Commit 7c5e5439 authored by Tom Lane's avatar Tom Lane

Get rid of some old and crufty global variables in the planner. When

this code was last gone over, there wasn't really any alternative to
globals because we didn't have the PlannerInfo struct being passed all
through the planner code.  Now that we do, we can restructure things
to avoid non-reentrancy.  I'm fooling with this because otherwise I'd
have had to add another global variable for the planned compact
range table list.
parent 90c301aa
...@@ -8,7 +8,7 @@ ...@@ -8,7 +8,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $PostgreSQL: pgsql/src/backend/nodes/outfuncs.c,v 1.298 2007/02/19 02:23:12 tgl Exp $ * $PostgreSQL: pgsql/src/backend/nodes/outfuncs.c,v 1.299 2007/02/19 07:03:27 tgl Exp $
* *
* NOTES * NOTES
* Every node type that can appear in stored rules' parsetrees *must* * Every node type that can appear in stored rules' parsetrees *must*
...@@ -1225,6 +1225,16 @@ _outHashPath(StringInfo str, HashPath *node) ...@@ -1225,6 +1225,16 @@ _outHashPath(StringInfo str, HashPath *node)
WRITE_NODE_FIELD(path_hashclauses); WRITE_NODE_FIELD(path_hashclauses);
} }
static void
_outPlannerGlobal(StringInfo str, PlannerGlobal *node)
{
WRITE_NODE_TYPE("PLANNERGLOBAL");
/* NB: this isn't a complete set of fields */
WRITE_NODE_FIELD(paramlist);
WRITE_INT_FIELD(next_plan_id);
}
static void static void
_outPlannerInfo(StringInfo str, PlannerInfo *node) _outPlannerInfo(StringInfo str, PlannerInfo *node)
{ {
...@@ -1232,7 +1242,10 @@ _outPlannerInfo(StringInfo str, PlannerInfo *node) ...@@ -1232,7 +1242,10 @@ _outPlannerInfo(StringInfo str, PlannerInfo *node)
/* NB: this isn't a complete set of fields */ /* NB: this isn't a complete set of fields */
WRITE_NODE_FIELD(parse); WRITE_NODE_FIELD(parse);
WRITE_NODE_FIELD(glob);
WRITE_UINT_FIELD(query_level);
WRITE_NODE_FIELD(join_rel_list); WRITE_NODE_FIELD(join_rel_list);
WRITE_NODE_FIELD(init_plans);
WRITE_NODE_FIELD(eq_classes); WRITE_NODE_FIELD(eq_classes);
WRITE_NODE_FIELD(canon_pathkeys); WRITE_NODE_FIELD(canon_pathkeys);
WRITE_NODE_FIELD(left_join_clauses); WRITE_NODE_FIELD(left_join_clauses);
...@@ -1416,6 +1429,15 @@ _outAppendRelInfo(StringInfo str, AppendRelInfo *node) ...@@ -1416,6 +1429,15 @@ _outAppendRelInfo(StringInfo str, AppendRelInfo *node)
WRITE_OID_FIELD(parent_reloid); WRITE_OID_FIELD(parent_reloid);
} }
static void
_outPlannerParamItem(StringInfo str, PlannerParamItem *node)
{
WRITE_NODE_TYPE("PLANNERPARAMITEM");
WRITE_NODE_FIELD(item);
WRITE_UINT_FIELD(abslevel);
}
/***************************************************************************** /*****************************************************************************
* *
* Stuff from parsenodes.h. * Stuff from parsenodes.h.
...@@ -2195,6 +2217,9 @@ _outNode(StringInfo str, void *obj) ...@@ -2195,6 +2217,9 @@ _outNode(StringInfo str, void *obj)
case T_HashPath: case T_HashPath:
_outHashPath(str, obj); _outHashPath(str, obj);
break; break;
case T_PlannerGlobal:
_outPlannerGlobal(str, obj);
break;
case T_PlannerInfo: case T_PlannerInfo:
_outPlannerInfo(str, obj); _outPlannerInfo(str, obj);
break; break;
...@@ -2228,6 +2253,9 @@ _outNode(StringInfo str, void *obj) ...@@ -2228,6 +2253,9 @@ _outNode(StringInfo str, void *obj)
case T_AppendRelInfo: case T_AppendRelInfo:
_outAppendRelInfo(str, obj); _outAppendRelInfo(str, obj);
break; break;
case T_PlannerParamItem:
_outPlannerParamItem(str, obj);
break;
case T_CreateStmt: case T_CreateStmt:
_outCreateStmt(str, obj); _outCreateStmt(str, obj);
......
...@@ -317,7 +317,10 @@ planner() ...@@ -317,7 +317,10 @@ planner()
Optimizer Data Structures Optimizer Data Structures
------------------------- -------------------------
PlannerInfo - global information for planning a particular Query PlannerGlobal - global information for a single planner invocation
PlannerInfo - information for planning a particular Query (we make
a separate PlannerInfo node for each sub-Query)
RelOptInfo - a relation or joined relations RelOptInfo - a relation or joined relations
......
...@@ -8,7 +8,7 @@ ...@@ -8,7 +8,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $PostgreSQL: pgsql/src/backend/optimizer/path/allpaths.c,v 1.158 2007/01/28 18:50:40 tgl Exp $ * $PostgreSQL: pgsql/src/backend/optimizer/path/allpaths.c,v 1.159 2007/02/19 07:03:28 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -517,7 +517,9 @@ set_subquery_pathlist(PlannerInfo *root, RelOptInfo *rel, ...@@ -517,7 +517,9 @@ set_subquery_pathlist(PlannerInfo *root, RelOptInfo *rel,
tuple_fraction = root->tuple_fraction; tuple_fraction = root->tuple_fraction;
/* Generate the plan for the subquery */ /* Generate the plan for the subquery */
rel->subplan = subquery_planner(subquery, tuple_fraction, rel->subplan = subquery_planner(root->glob, subquery,
root->query_level + 1,
tuple_fraction,
&subquery_pathkeys); &subquery_pathkeys);
/* Copy number of output rows from subplan */ /* Copy number of output rows from subplan */
......
...@@ -8,7 +8,7 @@ ...@@ -8,7 +8,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $PostgreSQL: pgsql/src/backend/optimizer/path/clausesel.c,v 1.83 2007/01/05 22:19:31 momjian Exp $ * $PostgreSQL: pgsql/src/backend/optimizer/path/clausesel.c,v 1.84 2007/02/19 07:03:28 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -537,7 +537,7 @@ clause_selectivity(PlannerInfo *root, ...@@ -537,7 +537,7 @@ clause_selectivity(PlannerInfo *root,
else if (IsA(clause, Param)) else if (IsA(clause, Param))
{ {
/* see if we can replace the Param */ /* see if we can replace the Param */
Node *subst = estimate_expression_value(clause); Node *subst = estimate_expression_value(root, clause);
if (IsA(subst, Const)) if (IsA(subst, Const))
{ {
......
...@@ -8,7 +8,7 @@ ...@@ -8,7 +8,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $PostgreSQL: pgsql/src/backend/optimizer/plan/planagg.c,v 1.26 2007/02/06 06:50:26 tgl Exp $ * $PostgreSQL: pgsql/src/backend/optimizer/plan/planagg.c,v 1.27 2007/02/19 07:03:29 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -450,6 +450,7 @@ make_agg_subplan(PlannerInfo *root, MinMaxAggInfo *info) ...@@ -450,6 +450,7 @@ make_agg_subplan(PlannerInfo *root, MinMaxAggInfo *info)
*/ */
memcpy(&subroot, root, sizeof(PlannerInfo)); memcpy(&subroot, root, sizeof(PlannerInfo));
subroot.parse = subparse = (Query *) copyObject(root->parse); subroot.parse = subparse = (Query *) copyObject(root->parse);
subroot.init_plans = NIL;
subparse->commandType = CMD_SELECT; subparse->commandType = CMD_SELECT;
subparse->resultRelation = 0; subparse->resultRelation = 0;
subparse->resultRelations = NIL; subparse->resultRelations = NIL;
...@@ -524,6 +525,9 @@ make_agg_subplan(PlannerInfo *root, MinMaxAggInfo *info) ...@@ -524,6 +525,9 @@ make_agg_subplan(PlannerInfo *root, MinMaxAggInfo *info)
info->param = SS_make_initplan_from_plan(&subroot, plan, info->param = SS_make_initplan_from_plan(&subroot, plan,
exprType((Node *) tle->expr), exprType((Node *) tle->expr),
-1); -1);
/* Make sure the InitPlan gets into the outer list */
root->init_plans = list_concat(root->init_plans, subroot.init_plans);
} }
/* /*
......
...@@ -8,7 +8,7 @@ ...@@ -8,7 +8,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $PostgreSQL: pgsql/src/backend/optimizer/plan/planner.c,v 1.212 2007/01/20 20:45:39 tgl Exp $ * $PostgreSQL: pgsql/src/backend/optimizer/plan/planner.c,v 1.213 2007/02/19 07:03:29 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -42,9 +42,6 @@ ...@@ -42,9 +42,6 @@
#include "utils/syscache.h" #include "utils/syscache.h"
ParamListInfo PlannerBoundParamList = NULL; /* current boundParams */
/* Expression kind codes for preprocess_expression */ /* Expression kind codes for preprocess_expression */
#define EXPRKIND_QUAL 0 #define EXPRKIND_QUAL 0
#define EXPRKIND_TARGET 1 #define EXPRKIND_TARGET 1
...@@ -86,35 +83,21 @@ Plan * ...@@ -86,35 +83,21 @@ Plan *
planner(Query *parse, bool isCursor, int cursorOptions, planner(Query *parse, bool isCursor, int cursorOptions,
ParamListInfo boundParams) ParamListInfo boundParams)
{ {
PlannerGlobal *glob;
double tuple_fraction; double tuple_fraction;
Plan *result_plan; Plan *result_plan;
Index save_PlannerQueryLevel;
List *save_PlannerParamList;
ParamListInfo save_PlannerBoundParamList;
/* /*
* The planner can be called recursively (an example is when * Set up global state for this planner invocation. This data is needed
* eval_const_expressions tries to pre-evaluate an SQL function). So, * across all levels of sub-Query that might exist in the given command,
* these global state variables must be saved and restored. * so we keep it in a separate struct that's linked to by each per-Query
* * PlannerInfo.
* Query level and the param list cannot be moved into the per-query
* PlannerInfo structure since their whole purpose is communication across
* multiple sub-queries. Also, boundParams is explicitly info from outside
* the query, and so is likewise better handled as a global variable.
*
* Note we do NOT save and restore PlannerPlanId: it exists to assign
* unique IDs to SubPlan nodes, and we want those IDs to be unique for the
* life of a backend. Also, PlannerInitPlan is saved/restored in
* subquery_planner, not here.
*/ */
save_PlannerQueryLevel = PlannerQueryLevel; glob = makeNode(PlannerGlobal);
save_PlannerParamList = PlannerParamList;
save_PlannerBoundParamList = PlannerBoundParamList;
/* Initialize state for handling outer-level references and params */ glob->boundParams = boundParams;
PlannerQueryLevel = 0; /* will be 1 in top-level subquery_planner */ glob->paramlist = NIL;
PlannerParamList = NIL; glob->next_plan_id = 0;
PlannerBoundParamList = boundParams;
/* Determine what fraction of the plan is likely to be scanned */ /* Determine what fraction of the plan is likely to be scanned */
if (isCursor) if (isCursor)
...@@ -134,10 +117,7 @@ planner(Query *parse, bool isCursor, int cursorOptions, ...@@ -134,10 +117,7 @@ planner(Query *parse, bool isCursor, int cursorOptions,
} }
/* primary planning entry point (may recurse for subqueries) */ /* primary planning entry point (may recurse for subqueries) */
result_plan = subquery_planner(parse, tuple_fraction, NULL); result_plan = subquery_planner(glob, parse, 1, tuple_fraction, NULL);
/* check we popped out the right number of levels */
Assert(PlannerQueryLevel == 0);
/* /*
* If creating a plan for a scrollable cursor, make sure it can run * If creating a plan for a scrollable cursor, make sure it can run
...@@ -153,12 +133,7 @@ planner(Query *parse, bool isCursor, int cursorOptions, ...@@ -153,12 +133,7 @@ planner(Query *parse, bool isCursor, int cursorOptions,
result_plan = set_plan_references(result_plan, parse->rtable); result_plan = set_plan_references(result_plan, parse->rtable);
/* executor wants to know total number of Params used overall */ /* executor wants to know total number of Params used overall */
result_plan->nParamExec = list_length(PlannerParamList); result_plan->nParamExec = list_length(glob->paramlist);
/* restore state for outer planner, if any */
PlannerQueryLevel = save_PlannerQueryLevel;
PlannerParamList = save_PlannerParamList;
PlannerBoundParamList = save_PlannerBoundParamList;
return result_plan; return result_plan;
} }
...@@ -169,7 +144,9 @@ planner(Query *parse, bool isCursor, int cursorOptions, ...@@ -169,7 +144,9 @@ planner(Query *parse, bool isCursor, int cursorOptions,
* Invokes the planner on a subquery. We recurse to here for each * Invokes the planner on a subquery. We recurse to here for each
* sub-SELECT found in the query tree. * sub-SELECT found in the query tree.
* *
* glob is the global state for the current planner run.
* parse is the querytree produced by the parser & rewriter. * parse is the querytree produced by the parser & rewriter.
* level is the current recursion depth (1 at the top-level Query).
* tuple_fraction is the fraction of tuples we expect will be retrieved. * tuple_fraction is the fraction of tuples we expect will be retrieved.
* tuple_fraction is interpreted as explained for grouping_planner, below. * tuple_fraction is interpreted as explained for grouping_planner, below.
* *
...@@ -189,24 +166,23 @@ planner(Query *parse, bool isCursor, int cursorOptions, ...@@ -189,24 +166,23 @@ planner(Query *parse, bool isCursor, int cursorOptions,
*-------------------- *--------------------
*/ */
Plan * Plan *
subquery_planner(Query *parse, double tuple_fraction, subquery_planner(PlannerGlobal *glob, Query *parse,
Index level, double tuple_fraction,
List **subquery_pathkeys) List **subquery_pathkeys)
{ {
List *saved_initplan = PlannerInitPlan; int saved_plan_id = glob->next_plan_id;
int saved_planid = PlannerPlanId;
PlannerInfo *root; PlannerInfo *root;
Plan *plan; Plan *plan;
List *newHaving; List *newHaving;
ListCell *l; ListCell *l;
/* Set up for a new level of subquery */
PlannerQueryLevel++;
PlannerInitPlan = NIL;
/* Create a PlannerInfo data structure for this subquery */ /* Create a PlannerInfo data structure for this subquery */
root = makeNode(PlannerInfo); root = makeNode(PlannerInfo);
root->parse = parse; root->parse = parse;
root->glob = glob;
root->query_level = level;
root->planner_cxt = CurrentMemoryContext; root->planner_cxt = CurrentMemoryContext;
root->init_plans = NIL;
root->eq_classes = NIL; root->eq_classes = NIL;
root->in_info_list = NIL; root->in_info_list = NIL;
root->append_rel_list = NIL; root->append_rel_list = NIL;
...@@ -396,18 +372,13 @@ subquery_planner(Query *parse, double tuple_fraction, ...@@ -396,18 +372,13 @@ subquery_planner(Query *parse, double tuple_fraction,
* initPlan list and extParam/allParam sets for plan nodes, and attach the * initPlan list and extParam/allParam sets for plan nodes, and attach the
* initPlans to the top plan node. * initPlans to the top plan node.
*/ */
if (PlannerPlanId != saved_planid || PlannerQueryLevel > 1) if (root->glob->next_plan_id != saved_plan_id || root->query_level > 1)
SS_finalize_plan(plan, parse->rtable); SS_finalize_plan(root, plan);
/* Return sort ordering info if caller wants it */ /* Return sort ordering info if caller wants it */
if (subquery_pathkeys) if (subquery_pathkeys)
*subquery_pathkeys = root->query_pathkeys; *subquery_pathkeys = root->query_pathkeys;
/* Return to outer subquery context */
PlannerQueryLevel--;
PlannerInitPlan = saved_initplan;
/* we do NOT restore PlannerPlanId; that's not an oversight! */
return plan; return plan;
} }
...@@ -460,7 +431,7 @@ preprocess_expression(PlannerInfo *root, Node *expr, int kind) ...@@ -460,7 +431,7 @@ preprocess_expression(PlannerInfo *root, Node *expr, int kind)
if (kind != EXPRKIND_VALUES && if (kind != EXPRKIND_VALUES &&
(root->parse->jointree->fromlist != NIL || (root->parse->jointree->fromlist != NIL ||
kind == EXPRKIND_QUAL || kind == EXPRKIND_QUAL ||
PlannerQueryLevel > 1)) root->query_level > 1))
expr = eval_const_expressions(expr); expr = eval_const_expressions(expr);
/* /*
...@@ -478,7 +449,7 @@ preprocess_expression(PlannerInfo *root, Node *expr, int kind) ...@@ -478,7 +449,7 @@ preprocess_expression(PlannerInfo *root, Node *expr, int kind)
/* Expand SubLinks to SubPlans */ /* Expand SubLinks to SubPlans */
if (root->parse->hasSubLinks) if (root->parse->hasSubLinks)
expr = SS_process_sublinks(expr, (kind == EXPRKIND_QUAL)); expr = SS_process_sublinks(root, expr, (kind == EXPRKIND_QUAL));
/* /*
* XXX do not insert anything here unless you have grokked the comments in * XXX do not insert anything here unless you have grokked the comments in
...@@ -486,8 +457,8 @@ preprocess_expression(PlannerInfo *root, Node *expr, int kind) ...@@ -486,8 +457,8 @@ preprocess_expression(PlannerInfo *root, Node *expr, int kind)
*/ */
/* Replace uplevel vars with Param nodes (this IS possible in VALUES) */ /* Replace uplevel vars with Param nodes (this IS possible in VALUES) */
if (PlannerQueryLevel > 1) if (root->query_level > 1)
expr = SS_replace_correlation_vars(expr); expr = SS_replace_correlation_vars(root, expr);
/* /*
* If it's a qual or havingQual, convert it to implicit-AND format. (We * If it's a qual or havingQual, convert it to implicit-AND format. (We
...@@ -590,6 +561,7 @@ inheritance_planner(PlannerInfo *root) ...@@ -590,6 +561,7 @@ inheritance_planner(PlannerInfo *root)
subroot.in_info_list = (List *) subroot.in_info_list = (List *)
adjust_appendrel_attrs((Node *) root->in_info_list, adjust_appendrel_attrs((Node *) root->in_info_list,
appinfo); appinfo);
subroot.init_plans = NIL;
/* There shouldn't be any OJ info to translate, as yet */ /* There shouldn't be any OJ info to translate, as yet */
Assert(subroot.oj_info_list == NIL); Assert(subroot.oj_info_list == NIL);
...@@ -612,6 +584,9 @@ inheritance_planner(PlannerInfo *root) ...@@ -612,6 +584,9 @@ inheritance_planner(PlannerInfo *root)
subplans = lappend(subplans, subplan); subplans = lappend(subplans, subplan);
/* Make sure any initplans from this rel get into the outer list */
root->init_plans = list_concat(root->init_plans, subroot.init_plans);
/* Build target-relations list for the executor */ /* Build target-relations list for the executor */
resultRelations = lappend_int(resultRelations, appinfo->child_relid); resultRelations = lappend_int(resultRelations, appinfo->child_relid);
...@@ -1201,7 +1176,7 @@ preprocess_limit(PlannerInfo *root, double tuple_fraction, ...@@ -1201,7 +1176,7 @@ preprocess_limit(PlannerInfo *root, double tuple_fraction,
*/ */
if (parse->limitCount) if (parse->limitCount)
{ {
est = estimate_expression_value(parse->limitCount); est = estimate_expression_value(root, parse->limitCount);
if (est && IsA(est, Const)) if (est && IsA(est, Const))
{ {
if (((Const *) est)->constisnull) if (((Const *) est)->constisnull)
...@@ -1224,7 +1199,7 @@ preprocess_limit(PlannerInfo *root, double tuple_fraction, ...@@ -1224,7 +1199,7 @@ preprocess_limit(PlannerInfo *root, double tuple_fraction,
if (parse->limitOffset) if (parse->limitOffset)
{ {
est = estimate_expression_value(parse->limitOffset); est = estimate_expression_value(root, parse->limitOffset);
if (est && IsA(est, Const)) if (est && IsA(est, Const))
{ {
if (((Const *) est)->constisnull) if (((Const *) est)->constisnull)
......
This diff is collapsed.
...@@ -15,7 +15,7 @@ ...@@ -15,7 +15,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $PostgreSQL: pgsql/src/backend/optimizer/prep/prepjointree.c,v 1.46 2007/01/20 20:45:39 tgl Exp $ * $PostgreSQL: pgsql/src/backend/optimizer/prep/prepjointree.c,v 1.47 2007/02/19 07:03:30 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -292,7 +292,10 @@ pull_up_simple_subquery(PlannerInfo *root, Node *jtnode, RangeTblEntry *rte, ...@@ -292,7 +292,10 @@ pull_up_simple_subquery(PlannerInfo *root, Node *jtnode, RangeTblEntry *rte,
*/ */
subroot = makeNode(PlannerInfo); subroot = makeNode(PlannerInfo);
subroot->parse = subquery; subroot->parse = subquery;
subroot->glob = root->glob;
subroot->query_level = root->query_level;
subroot->planner_cxt = CurrentMemoryContext; subroot->planner_cxt = CurrentMemoryContext;
subroot->init_plans = NIL;
subroot->in_info_list = NIL; subroot->in_info_list = NIL;
subroot->append_rel_list = NIL; subroot->append_rel_list = NIL;
......
...@@ -16,7 +16,7 @@ ...@@ -16,7 +16,7 @@
* Portions Copyright (c) 1994, Regents of the University of California * Portions Copyright (c) 1994, Regents of the University of California
* *
* IDENTIFICATION * IDENTIFICATION
* $PostgreSQL: pgsql/src/backend/optimizer/prep/preptlist.c,v 1.85 2007/01/05 22:19:32 momjian Exp $ * $PostgreSQL: pgsql/src/backend/optimizer/prep/preptlist.c,v 1.86 2007/02/19 07:03:30 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -124,7 +124,7 @@ preprocess_targetlist(PlannerInfo *root, List *tlist) ...@@ -124,7 +124,7 @@ preprocess_targetlist(PlannerInfo *root, List *tlist)
/* /*
* Currently the executor only supports FOR UPDATE/SHARE at top level * Currently the executor only supports FOR UPDATE/SHARE at top level
*/ */
if (PlannerQueryLevel > 1) if (root->query_level > 1)
ereport(ERROR, ereport(ERROR,
(errcode(ERRCODE_FEATURE_NOT_SUPPORTED), (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
errmsg("SELECT FOR UPDATE/SHARE is not allowed in subqueries"))); errmsg("SELECT FOR UPDATE/SHARE is not allowed in subqueries")));
......
...@@ -22,7 +22,7 @@ ...@@ -22,7 +22,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $PostgreSQL: pgsql/src/backend/optimizer/prep/prepunion.c,v 1.137 2007/01/22 20:00:39 tgl Exp $ * $PostgreSQL: pgsql/src/backend/optimizer/prep/prepunion.c,v 1.138 2007/02/19 07:03:30 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -177,7 +177,10 @@ recurse_set_operations(Node *setOp, PlannerInfo *root, ...@@ -177,7 +177,10 @@ recurse_set_operations(Node *setOp, PlannerInfo *root,
/* /*
* Generate plan for primitive subquery * Generate plan for primitive subquery
*/ */
subplan = subquery_planner(subquery, tuple_fraction, NULL); subplan = subquery_planner(root->glob, subquery,
root->query_level + 1,
tuple_fraction,
NULL);
/* /*
* Add a SubqueryScan with the caller-requested targetlist * Add a SubqueryScan with the caller-requested targetlist
......
...@@ -8,7 +8,7 @@ ...@@ -8,7 +8,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $PostgreSQL: pgsql/src/backend/optimizer/util/clauses.c,v 1.234 2007/02/16 23:32:08 tgl Exp $ * $PostgreSQL: pgsql/src/backend/optimizer/util/clauses.c,v 1.235 2007/02/19 07:03:30 tgl Exp $
* *
* HISTORY * HISTORY
* AUTHOR DATE MAJOR EVENT * AUTHOR DATE MAJOR EVENT
...@@ -49,6 +49,7 @@ ...@@ -49,6 +49,7 @@
typedef struct typedef struct
{ {
ParamListInfo boundParams;
List *active_fns; List *active_fns;
Node *case_val; Node *case_val;
bool estimate; bool estimate;
...@@ -1578,6 +1579,7 @@ eval_const_expressions(Node *node) ...@@ -1578,6 +1579,7 @@ eval_const_expressions(Node *node)
{ {
eval_const_expressions_context context; eval_const_expressions_context context;
context.boundParams = NULL; /* don't use any bound params */
context.active_fns = NIL; /* nothing being recursively simplified */ context.active_fns = NIL; /* nothing being recursively simplified */
context.case_val = NULL; /* no CASE being examined */ context.case_val = NULL; /* no CASE being examined */
context.estimate = false; /* safe transformations only */ context.estimate = false; /* safe transformations only */
...@@ -1601,10 +1603,11 @@ eval_const_expressions(Node *node) ...@@ -1601,10 +1603,11 @@ eval_const_expressions(Node *node)
*-------------------- *--------------------
*/ */
Node * Node *
estimate_expression_value(Node *node) estimate_expression_value(PlannerInfo *root, Node *node)
{ {
eval_const_expressions_context context; eval_const_expressions_context context;
context.boundParams = root->glob->boundParams; /* bound Params */
context.active_fns = NIL; /* nothing being recursively simplified */ context.active_fns = NIL; /* nothing being recursively simplified */
context.case_val = NULL; /* no CASE being examined */ context.case_val = NULL; /* no CASE being examined */
context.estimate = true; /* unsafe transformations OK */ context.estimate = true; /* unsafe transformations OK */
...@@ -1623,11 +1626,11 @@ eval_const_expressions_mutator(Node *node, ...@@ -1623,11 +1626,11 @@ eval_const_expressions_mutator(Node *node,
/* Look to see if we've been given a value for this Param */ /* Look to see if we've been given a value for this Param */
if (param->paramkind == PARAM_EXTERN && if (param->paramkind == PARAM_EXTERN &&
PlannerBoundParamList != NULL && context->boundParams != NULL &&
param->paramid > 0 && param->paramid > 0 &&
param->paramid <= PlannerBoundParamList->numParams) param->paramid <= context->boundParams->numParams)
{ {
ParamExternData *prm = &PlannerBoundParamList->params[param->paramid - 1]; ParamExternData *prm = &context->boundParams->params[param->paramid - 1];
if (OidIsValid(prm->ptype)) if (OidIsValid(prm->ptype))
{ {
......
...@@ -15,7 +15,7 @@ ...@@ -15,7 +15,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $PostgreSQL: pgsql/src/backend/utils/adt/selfuncs.c,v 1.225 2007/01/31 16:54:51 teodor Exp $ * $PostgreSQL: pgsql/src/backend/utils/adt/selfuncs.c,v 1.226 2007/02/19 07:03:31 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -3411,7 +3411,7 @@ get_restriction_variable(PlannerInfo *root, List *args, int varRelid, ...@@ -3411,7 +3411,7 @@ get_restriction_variable(PlannerInfo *root, List *args, int varRelid,
if (vardata->rel && rdata.rel == NULL) if (vardata->rel && rdata.rel == NULL)
{ {
*varonleft = true; *varonleft = true;
*other = estimate_expression_value(rdata.var); *other = estimate_expression_value(root, rdata.var);
/* Assume we need no ReleaseVariableStats(rdata) here */ /* Assume we need no ReleaseVariableStats(rdata) here */
return true; return true;
} }
...@@ -3419,7 +3419,7 @@ get_restriction_variable(PlannerInfo *root, List *args, int varRelid, ...@@ -3419,7 +3419,7 @@ get_restriction_variable(PlannerInfo *root, List *args, int varRelid,
if (vardata->rel == NULL && rdata.rel) if (vardata->rel == NULL && rdata.rel)
{ {
*varonleft = false; *varonleft = false;
*other = estimate_expression_value(vardata->var); *other = estimate_expression_value(root, vardata->var);
/* Assume we need no ReleaseVariableStats(*vardata) here */ /* Assume we need no ReleaseVariableStats(*vardata) here */
*vardata = rdata; *vardata = rdata;
return true; return true;
......
...@@ -7,7 +7,7 @@ ...@@ -7,7 +7,7 @@
* Portions Copyright (c) 1996-2007, PostgreSQL Global Development Group * Portions Copyright (c) 1996-2007, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California * Portions Copyright (c) 1994, Regents of the University of California
* *
* $PostgreSQL: pgsql/src/include/nodes/nodes.h,v 1.194 2007/02/03 14:06:55 petere Exp $ * $PostgreSQL: pgsql/src/include/nodes/nodes.h,v 1.195 2007/02/19 07:03:31 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -175,6 +175,7 @@ typedef enum NodeTag ...@@ -175,6 +175,7 @@ typedef enum NodeTag
* TAGS FOR PLANNER NODES (relation.h) * TAGS FOR PLANNER NODES (relation.h)
*/ */
T_PlannerInfo = 500, T_PlannerInfo = 500,
T_PlannerGlobal,
T_RelOptInfo, T_RelOptInfo,
T_IndexOptInfo, T_IndexOptInfo,
T_Path, T_Path,
...@@ -198,6 +199,7 @@ typedef enum NodeTag ...@@ -198,6 +199,7 @@ typedef enum NodeTag
T_OuterJoinInfo, T_OuterJoinInfo,
T_InClauseInfo, T_InClauseInfo,
T_AppendRelInfo, T_AppendRelInfo,
T_PlannerParamItem,
/* /*
* TAGS FOR MEMORY NODES (memnodes.h) * TAGS FOR MEMORY NODES (memnodes.h)
......
...@@ -10,7 +10,7 @@ ...@@ -10,7 +10,7 @@
* Portions Copyright (c) 1996-2007, PostgreSQL Global Development Group * Portions Copyright (c) 1996-2007, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California * Portions Copyright (c) 1994, Regents of the University of California
* *
* $PostgreSQL: pgsql/src/include/nodes/primnodes.h,v 1.124 2007/02/03 14:06:56 petere Exp $ * $PostgreSQL: pgsql/src/include/nodes/primnodes.h,v 1.125 2007/02/19 07:03:31 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -442,10 +442,9 @@ typedef struct SubPlan ...@@ -442,10 +442,9 @@ typedef struct SubPlan
List *paramIds; /* IDs of Params embedded in the above */ List *paramIds; /* IDs of Params embedded in the above */
/* The subselect, transformed to a Plan: */ /* The subselect, transformed to a Plan: */
struct Plan *plan; /* subselect plan itself */ struct Plan *plan; /* subselect plan itself */
int plan_id; /* dummy thing because of we haven't equal int plan_id; /* kluge because we haven't equal-funcs for
* funcs for plan nodes... actually, we could * plan nodes... we compare this instead of
* put *plan itself somewhere else (TopPlan * subselect plan */
* node ?)... */
List *rtable; /* range table for subselect */ List *rtable; /* range table for subselect */
/* Information about execution strategy: */ /* Information about execution strategy: */
bool useHashTable; /* TRUE to store subselect output in a hash bool useHashTable; /* TRUE to store subselect output in a hash
......
...@@ -7,7 +7,7 @@ ...@@ -7,7 +7,7 @@
* Portions Copyright (c) 1996-2007, PostgreSQL Global Development Group * Portions Copyright (c) 1996-2007, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California * Portions Copyright (c) 1994, Regents of the University of California
* *
* $PostgreSQL: pgsql/src/include/nodes/relation.h,v 1.135 2007/02/16 20:57:19 tgl Exp $ * $PostgreSQL: pgsql/src/include/nodes/relation.h,v 1.136 2007/02/19 07:03:33 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -16,6 +16,7 @@ ...@@ -16,6 +16,7 @@
#include "access/sdir.h" #include "access/sdir.h"
#include "nodes/bitmapset.h" #include "nodes/bitmapset.h"
#include "nodes/params.h"
#include "nodes/parsenodes.h" #include "nodes/parsenodes.h"
#include "storage/block.h" #include "storage/block.h"
...@@ -46,6 +47,27 @@ typedef struct QualCost ...@@ -46,6 +47,27 @@ typedef struct QualCost
} QualCost; } QualCost;
/*----------
* PlannerGlobal
* Global information for planning/optimization
*
* PlannerGlobal holds state for an entire planner invocation; this state
* is shared across all levels of sub-Queries that exist in the command being
* planned.
*----------
*/
typedef struct PlannerGlobal
{
NodeTag type;
ParamListInfo boundParams; /* Param values provided to planner() */
List *paramlist; /* to keep track of cross-level Params */
int next_plan_id; /* hack for distinguishing SubPlans */
} PlannerGlobal;
/*---------- /*----------
* PlannerInfo * PlannerInfo
* Per-query information for planning/optimization * Per-query information for planning/optimization
...@@ -62,6 +84,10 @@ typedef struct PlannerInfo ...@@ -62,6 +84,10 @@ typedef struct PlannerInfo
Query *parse; /* the Query being planned */ Query *parse; /* the Query being planned */
PlannerGlobal *glob; /* global info for current planner run */
Index query_level; /* 1 at the outermost Query */
/* /*
* simple_rel_array holds pointers to "base rels" and "other rels" (see * simple_rel_array holds pointers to "base rels" and "other rels" (see
* comments for RelOptInfo for more info). It is indexed by rangetable * comments for RelOptInfo for more info). It is indexed by rangetable
...@@ -84,6 +110,8 @@ typedef struct PlannerInfo ...@@ -84,6 +110,8 @@ typedef struct PlannerInfo
List *join_rel_list; /* list of join-relation RelOptInfos */ List *join_rel_list; /* list of join-relation RelOptInfos */
struct HTAB *join_rel_hash; /* optional hashtable for join relations */ struct HTAB *join_rel_hash; /* optional hashtable for join relations */
List *init_plans; /* init subplans for query */
List *eq_classes; /* list of active EquivalenceClasses */ List *eq_classes; /* list of active EquivalenceClasses */
List *canon_pathkeys; /* list of "canonical" PathKeys */ List *canon_pathkeys; /* list of "canonical" PathKeys */
...@@ -1109,4 +1137,39 @@ typedef struct AppendRelInfo ...@@ -1109,4 +1137,39 @@ typedef struct AppendRelInfo
Oid parent_reloid; /* OID of parent relation */ Oid parent_reloid; /* OID of parent relation */
} AppendRelInfo; } AppendRelInfo;
/*
* glob->paramlist keeps track of the PARAM_EXEC slots that we have decided
* we need for the query. At runtime these slots are used to pass values
* either down into subqueries (for outer references in subqueries) or up out
* of subqueries (for the results of a subplan). The n'th entry in the list
* (n counts from 0) corresponds to Param->paramid = n.
*
* Each paramlist item shows the absolute query level it is associated with,
* where the outermost query is level 1 and nested subqueries have higher
* numbers. The item the parameter slot represents can be one of three kinds:
*
* A Var: the slot represents a variable of that level that must be passed
* down because subqueries have outer references to it. The varlevelsup
* value in the Var will always be zero.
*
* An Aggref (with an expression tree representing its argument): the slot
* represents an aggregate expression that is an outer reference for some
* subquery. The Aggref itself has agglevelsup = 0, and its argument tree
* is adjusted to match in level.
*
* A Param: the slot holds the result of a subplan (it is a setParam item
* for that subplan). The absolute level shown for such items corresponds
* to the parent query of the subplan.
*
* Note: we detect duplicate Var parameters and coalesce them into one slot,
* but we do not do this for Aggref or Param slots.
*/
typedef struct PlannerParamItem
{
NodeTag type;
Node *item; /* the Var, Aggref, or Param */
Index abslevel; /* its absolute query level */
} PlannerParamItem;
#endif /* RELATION_H */ #endif /* RELATION_H */
...@@ -7,7 +7,7 @@ ...@@ -7,7 +7,7 @@
* Portions Copyright (c) 1996-2007, PostgreSQL Global Development Group * Portions Copyright (c) 1996-2007, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California * Portions Copyright (c) 1994, Regents of the University of California
* *
* $PostgreSQL: pgsql/src/include/optimizer/clauses.h,v 1.86 2007/01/22 01:35:22 tgl Exp $ * $PostgreSQL: pgsql/src/include/optimizer/clauses.h,v 1.87 2007/02/19 07:03:34 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -77,7 +77,7 @@ extern void set_coercionform_dontcare(Node *node); ...@@ -77,7 +77,7 @@ extern void set_coercionform_dontcare(Node *node);
extern Node *eval_const_expressions(Node *node); extern Node *eval_const_expressions(Node *node);
extern Node *estimate_expression_value(Node *node); extern Node *estimate_expression_value(PlannerInfo *root, Node *node);
extern bool expression_tree_walker(Node *node, bool (*walker) (), extern bool expression_tree_walker(Node *node, bool (*walker) (),
void *context); void *context);
......
...@@ -7,23 +7,21 @@ ...@@ -7,23 +7,21 @@
* Portions Copyright (c) 1996-2007, PostgreSQL Global Development Group * Portions Copyright (c) 1996-2007, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California * Portions Copyright (c) 1994, Regents of the University of California
* *
* $PostgreSQL: pgsql/src/include/optimizer/planner.h,v 1.36 2007/01/05 22:19:56 momjian Exp $ * $PostgreSQL: pgsql/src/include/optimizer/planner.h,v 1.37 2007/02/19 07:03:34 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
#ifndef PLANNER_H #ifndef PLANNER_H
#define PLANNER_H #define PLANNER_H
#include "nodes/params.h"
#include "nodes/parsenodes.h"
#include "nodes/plannodes.h" #include "nodes/plannodes.h"
#include "nodes/relation.h"
extern ParamListInfo PlannerBoundParamList; /* current boundParams */
extern Plan *planner(Query *parse, bool isCursor, int cursorOptions, extern Plan *planner(Query *parse, bool isCursor, int cursorOptions,
ParamListInfo boundParams); ParamListInfo boundParams);
extern Plan *subquery_planner(Query *parse, double tuple_fraction, extern Plan *subquery_planner(PlannerGlobal *glob, Query *parse,
List **subquery_pathkeys); Index level, double tuple_fraction,
List **subquery_pathkeys);
#endif /* PLANNER_H */ #endif /* PLANNER_H */
...@@ -5,7 +5,7 @@ ...@@ -5,7 +5,7 @@
* Portions Copyright (c) 1996-2007, PostgreSQL Global Development Group * Portions Copyright (c) 1996-2007, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California * Portions Copyright (c) 1994, Regents of the University of California
* *
* $PostgreSQL: pgsql/src/include/optimizer/subselect.h,v 1.28 2007/01/05 22:19:56 momjian Exp $ * $PostgreSQL: pgsql/src/include/optimizer/subselect.h,v 1.29 2007/02/19 07:03:34 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -15,16 +15,10 @@ ...@@ -15,16 +15,10 @@
#include "nodes/plannodes.h" #include "nodes/plannodes.h"
#include "nodes/relation.h" #include "nodes/relation.h"
extern Index PlannerQueryLevel; /* level of current query */
extern List *PlannerInitPlan; /* init subplans for current query */
extern List *PlannerParamList; /* to keep track of cross-level Params */
extern int PlannerPlanId; /* to assign unique ID to subquery plans */
extern Node *convert_IN_to_join(PlannerInfo *root, SubLink *sublink); extern Node *convert_IN_to_join(PlannerInfo *root, SubLink *sublink);
extern Node *SS_replace_correlation_vars(Node *expr); extern Node *SS_replace_correlation_vars(PlannerInfo *root, Node *expr);
extern Node *SS_process_sublinks(Node *expr, bool isQual); extern Node *SS_process_sublinks(PlannerInfo *root, Node *expr, bool isQual);
extern void SS_finalize_plan(Plan *plan, List *rtable); extern void SS_finalize_plan(PlannerInfo *root, Plan *plan);
extern Param *SS_make_initplan_from_plan(PlannerInfo *root, Plan *plan, extern Param *SS_make_initplan_from_plan(PlannerInfo *root, Plan *plan,
Oid resulttype, int32 resulttypmod); Oid resulttype, int32 resulttypmod);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment