aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/backend/nodes/outfuncs.c30
-rw-r--r--src/backend/optimizer/README5
-rw-r--r--src/backend/optimizer/path/allpaths.c6
-rw-r--r--src/backend/optimizer/path/clausesel.c4
-rw-r--r--src/backend/optimizer/plan/planagg.c6
-rw-r--r--src/backend/optimizer/plan/planner.c89
-rw-r--r--src/backend/optimizer/plan/subselect.c233
-rw-r--r--src/backend/optimizer/prep/prepjointree.c5
-rw-r--r--src/backend/optimizer/prep/preptlist.c4
-rw-r--r--src/backend/optimizer/prep/prepunion.c7
-rw-r--r--src/backend/optimizer/util/clauses.c13
-rw-r--r--src/backend/utils/adt/selfuncs.c6
-rw-r--r--src/include/nodes/nodes.h4
-rw-r--r--src/include/nodes/primnodes.h9
-rw-r--r--src/include/nodes/relation.h65
-rw-r--r--src/include/optimizer/clauses.h4
-rw-r--r--src/include/optimizer/planner.h12
-rw-r--r--src/include/optimizer/subselect.h14
18 files changed, 293 insertions, 223 deletions
diff --git a/src/backend/nodes/outfuncs.c b/src/backend/nodes/outfuncs.c
index a173cf59dff..0600f63b556 100644
--- a/src/backend/nodes/outfuncs.c
+++ b/src/backend/nodes/outfuncs.c
@@ -8,7 +8,7 @@
*
*
* 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
* Every node type that can appear in stored rules' parsetrees *must*
@@ -1226,13 +1226,26 @@ _outHashPath(StringInfo str, HashPath *node)
}
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
_outPlannerInfo(StringInfo str, PlannerInfo *node)
{
WRITE_NODE_TYPE("PLANNERINFO");
/* NB: this isn't a complete set of fields */
WRITE_NODE_FIELD(parse);
+ WRITE_NODE_FIELD(glob);
+ WRITE_UINT_FIELD(query_level);
WRITE_NODE_FIELD(join_rel_list);
+ WRITE_NODE_FIELD(init_plans);
WRITE_NODE_FIELD(eq_classes);
WRITE_NODE_FIELD(canon_pathkeys);
WRITE_NODE_FIELD(left_join_clauses);
@@ -1416,6 +1429,15 @@ _outAppendRelInfo(StringInfo str, AppendRelInfo *node)
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.
@@ -2195,6 +2217,9 @@ _outNode(StringInfo str, void *obj)
case T_HashPath:
_outHashPath(str, obj);
break;
+ case T_PlannerGlobal:
+ _outPlannerGlobal(str, obj);
+ break;
case T_PlannerInfo:
_outPlannerInfo(str, obj);
break;
@@ -2228,6 +2253,9 @@ _outNode(StringInfo str, void *obj)
case T_AppendRelInfo:
_outAppendRelInfo(str, obj);
break;
+ case T_PlannerParamItem:
+ _outPlannerParamItem(str, obj);
+ break;
case T_CreateStmt:
_outCreateStmt(str, obj);
diff --git a/src/backend/optimizer/README b/src/backend/optimizer/README
index 60505814fd4..6f9d008cbff 100644
--- a/src/backend/optimizer/README
+++ b/src/backend/optimizer/README
@@ -317,7 +317,10 @@ planner()
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
diff --git a/src/backend/optimizer/path/allpaths.c b/src/backend/optimizer/path/allpaths.c
index 43891a18459..1cb1d86be1b 100644
--- a/src/backend/optimizer/path/allpaths.c
+++ b/src/backend/optimizer/path/allpaths.c
@@ -8,7 +8,7 @@
*
*
* 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,
tuple_fraction = root->tuple_fraction;
/* 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);
/* Copy number of output rows from subplan */
diff --git a/src/backend/optimizer/path/clausesel.c b/src/backend/optimizer/path/clausesel.c
index f80e18a2020..405ab6fcc3a 100644
--- a/src/backend/optimizer/path/clausesel.c
+++ b/src/backend/optimizer/path/clausesel.c
@@ -8,7 +8,7 @@
*
*
* 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,
else if (IsA(clause, 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))
{
diff --git a/src/backend/optimizer/plan/planagg.c b/src/backend/optimizer/plan/planagg.c
index 77ad0176db2..be26d17a28a 100644
--- a/src/backend/optimizer/plan/planagg.c
+++ b/src/backend/optimizer/plan/planagg.c
@@ -8,7 +8,7 @@
*
*
* 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)
*/
memcpy(&subroot, root, sizeof(PlannerInfo));
subroot.parse = subparse = (Query *) copyObject(root->parse);
+ subroot.init_plans = NIL;
subparse->commandType = CMD_SELECT;
subparse->resultRelation = 0;
subparse->resultRelations = NIL;
@@ -524,6 +525,9 @@ make_agg_subplan(PlannerInfo *root, MinMaxAggInfo *info)
info->param = SS_make_initplan_from_plan(&subroot, plan,
exprType((Node *) tle->expr),
-1);
+
+ /* Make sure the InitPlan gets into the outer list */
+ root->init_plans = list_concat(root->init_plans, subroot.init_plans);
}
/*
diff --git a/src/backend/optimizer/plan/planner.c b/src/backend/optimizer/plan/planner.c
index ae9c10fc6b6..f4a940175ea 100644
--- a/src/backend/optimizer/plan/planner.c
+++ b/src/backend/optimizer/plan/planner.c
@@ -8,7 +8,7 @@
*
*
* 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 @@
#include "utils/syscache.h"
-ParamListInfo PlannerBoundParamList = NULL; /* current boundParams */
-
-
/* Expression kind codes for preprocess_expression */
#define EXPRKIND_QUAL 0
#define EXPRKIND_TARGET 1
@@ -86,35 +83,21 @@ Plan *
planner(Query *parse, bool isCursor, int cursorOptions,
ParamListInfo boundParams)
{
+ PlannerGlobal *glob;
double tuple_fraction;
Plan *result_plan;
- Index save_PlannerQueryLevel;
- List *save_PlannerParamList;
- ParamListInfo save_PlannerBoundParamList;
/*
- * The planner can be called recursively (an example is when
- * eval_const_expressions tries to pre-evaluate an SQL function). So,
- * these global state variables must be saved and restored.
- *
- * 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.
+ * Set up global state for this planner invocation. This data is needed
+ * across all levels of sub-Query that might exist in the given command,
+ * so we keep it in a separate struct that's linked to by each per-Query
+ * PlannerInfo.
*/
- save_PlannerQueryLevel = PlannerQueryLevel;
- save_PlannerParamList = PlannerParamList;
- save_PlannerBoundParamList = PlannerBoundParamList;
+ glob = makeNode(PlannerGlobal);
- /* Initialize state for handling outer-level references and params */
- PlannerQueryLevel = 0; /* will be 1 in top-level subquery_planner */
- PlannerParamList = NIL;
- PlannerBoundParamList = boundParams;
+ glob->boundParams = boundParams;
+ glob->paramlist = NIL;
+ glob->next_plan_id = 0;
/* Determine what fraction of the plan is likely to be scanned */
if (isCursor)
@@ -134,10 +117,7 @@ planner(Query *parse, bool isCursor, int cursorOptions,
}
/* primary planning entry point (may recurse for subqueries) */
- result_plan = subquery_planner(parse, tuple_fraction, NULL);
-
- /* check we popped out the right number of levels */
- Assert(PlannerQueryLevel == 0);
+ result_plan = subquery_planner(glob, parse, 1, tuple_fraction, NULL);
/*
* If creating a plan for a scrollable cursor, make sure it can run
@@ -153,12 +133,7 @@ planner(Query *parse, bool isCursor, int cursorOptions,
result_plan = set_plan_references(result_plan, parse->rtable);
/* executor wants to know total number of Params used overall */
- result_plan->nParamExec = list_length(PlannerParamList);
-
- /* restore state for outer planner, if any */
- PlannerQueryLevel = save_PlannerQueryLevel;
- PlannerParamList = save_PlannerParamList;
- PlannerBoundParamList = save_PlannerBoundParamList;
+ result_plan->nParamExec = list_length(glob->paramlist);
return result_plan;
}
@@ -169,7 +144,9 @@ planner(Query *parse, bool isCursor, int cursorOptions,
* Invokes the planner on a subquery. We recurse to here for each
* 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.
+ * 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 interpreted as explained for grouping_planner, below.
*
@@ -189,24 +166,23 @@ planner(Query *parse, bool isCursor, int cursorOptions,
*--------------------
*/
Plan *
-subquery_planner(Query *parse, double tuple_fraction,
+subquery_planner(PlannerGlobal *glob, Query *parse,
+ Index level, double tuple_fraction,
List **subquery_pathkeys)
{
- List *saved_initplan = PlannerInitPlan;
- int saved_planid = PlannerPlanId;
+ int saved_plan_id = glob->next_plan_id;
PlannerInfo *root;
Plan *plan;
List *newHaving;
ListCell *l;
- /* Set up for a new level of subquery */
- PlannerQueryLevel++;
- PlannerInitPlan = NIL;
-
/* Create a PlannerInfo data structure for this subquery */
root = makeNode(PlannerInfo);
root->parse = parse;
+ root->glob = glob;
+ root->query_level = level;
root->planner_cxt = CurrentMemoryContext;
+ root->init_plans = NIL;
root->eq_classes = NIL;
root->in_info_list = NIL;
root->append_rel_list = NIL;
@@ -396,18 +372,13 @@ subquery_planner(Query *parse, double tuple_fraction,
* initPlan list and extParam/allParam sets for plan nodes, and attach the
* initPlans to the top plan node.
*/
- if (PlannerPlanId != saved_planid || PlannerQueryLevel > 1)
- SS_finalize_plan(plan, parse->rtable);
+ if (root->glob->next_plan_id != saved_plan_id || root->query_level > 1)
+ SS_finalize_plan(root, plan);
/* Return sort ordering info if caller wants it */
if (subquery_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;
}
@@ -460,7 +431,7 @@ preprocess_expression(PlannerInfo *root, Node *expr, int kind)
if (kind != EXPRKIND_VALUES &&
(root->parse->jointree->fromlist != NIL ||
kind == EXPRKIND_QUAL ||
- PlannerQueryLevel > 1))
+ root->query_level > 1))
expr = eval_const_expressions(expr);
/*
@@ -478,7 +449,7 @@ preprocess_expression(PlannerInfo *root, Node *expr, int kind)
/* Expand SubLinks to SubPlans */
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
@@ -486,8 +457,8 @@ preprocess_expression(PlannerInfo *root, Node *expr, int kind)
*/
/* Replace uplevel vars with Param nodes (this IS possible in VALUES) */
- if (PlannerQueryLevel > 1)
- expr = SS_replace_correlation_vars(expr);
+ if (root->query_level > 1)
+ expr = SS_replace_correlation_vars(root, expr);
/*
* If it's a qual or havingQual, convert it to implicit-AND format. (We
@@ -590,6 +561,7 @@ inheritance_planner(PlannerInfo *root)
subroot.in_info_list = (List *)
adjust_appendrel_attrs((Node *) root->in_info_list,
appinfo);
+ subroot.init_plans = NIL;
/* There shouldn't be any OJ info to translate, as yet */
Assert(subroot.oj_info_list == NIL);
@@ -612,6 +584,9 @@ inheritance_planner(PlannerInfo *root)
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 */
resultRelations = lappend_int(resultRelations, appinfo->child_relid);
@@ -1201,7 +1176,7 @@ preprocess_limit(PlannerInfo *root, double tuple_fraction,
*/
if (parse->limitCount)
{
- est = estimate_expression_value(parse->limitCount);
+ est = estimate_expression_value(root, parse->limitCount);
if (est && IsA(est, Const))
{
if (((Const *) est)->constisnull)
@@ -1224,7 +1199,7 @@ preprocess_limit(PlannerInfo *root, double tuple_fraction,
if (parse->limitOffset)
{
- est = estimate_expression_value(parse->limitOffset);
+ est = estimate_expression_value(root, parse->limitOffset);
if (est && IsA(est, Const))
{
if (((Const *) est)->constisnull)
diff --git a/src/backend/optimizer/plan/subselect.c b/src/backend/optimizer/plan/subselect.c
index af035d9b104..b62aeb853d8 100644
--- a/src/backend/optimizer/plan/subselect.c
+++ b/src/backend/optimizer/plan/subselect.c
@@ -7,7 +7,7 @@
* Portions Copyright (c) 1994, Regents of the University of California
*
* IDENTIFICATION
- * $PostgreSQL: pgsql/src/backend/optimizer/plan/subselect.c,v 1.119 2007/02/19 02:23:12 tgl Exp $
+ * $PostgreSQL: pgsql/src/backend/optimizer/plan/subselect.c,v 1.120 2007/02/19 07:03:30 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -31,52 +31,19 @@
#include "utils/syscache.h"
-Index PlannerQueryLevel; /* level of current query */
-List *PlannerInitPlan; /* init subplans for current query */
-List *PlannerParamList; /* to keep track of cross-level Params */
-
-int PlannerPlanId = 0; /* to assign unique ID to subquery plans */
-
-/*
- * PlannerParamList 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
-{
- Node *item; /* the Var, Aggref, or Param */
- Index abslevel; /* its absolute query level */
-} PlannerParamItem;
-
-
typedef struct convert_testexpr_context
{
+ PlannerInfo *root;
int rtindex; /* RT index for Vars, or 0 for Params */
List *righthandIds; /* accumulated list of Vars or Param IDs */
} convert_testexpr_context;
+typedef struct process_sublinks_context
+{
+ PlannerInfo *root;
+ bool isTopQual;
+} process_sublinks_context;
+
typedef struct finalize_primnode_context
{
Bitmapset *paramids; /* Set of PARAM_EXEC paramids found */
@@ -84,15 +51,17 @@ typedef struct finalize_primnode_context
} finalize_primnode_context;
-static Node *convert_testexpr(Node *testexpr,
- int rtindex,
- List **righthandIds);
+static Node *convert_testexpr(PlannerInfo *root,
+ Node *testexpr,
+ int rtindex,
+ List **righthandIds);
static Node *convert_testexpr_mutator(Node *node,
convert_testexpr_context *context);
static bool subplan_is_hashable(SubLink *slink, SubPlan *node);
static bool hash_ok_operator(OpExpr *expr);
-static Node *replace_correlation_vars_mutator(Node *node, void *context);
-static Node *process_sublinks_mutator(Node *node, bool *isTopQual);
+static Node *replace_correlation_vars_mutator(Node *node, PlannerInfo *root);
+static Node *process_sublinks_mutator(Node *node,
+ process_sublinks_context *context);
static Bitmapset *finalize_plan(Plan *plan, List *rtable,
Bitmapset *outer_params,
Bitmapset *valid_params);
@@ -104,7 +73,7 @@ static bool finalize_primnode(Node *node, finalize_primnode_context *context);
* which is expected to have varlevelsup > 0 (ie, it is not local).
*/
static Param *
-replace_outer_var(Var *var)
+replace_outer_var(PlannerInfo *root, Var *var)
{
Param *retval;
ListCell *ppl;
@@ -112,11 +81,11 @@ replace_outer_var(Var *var)
Index abslevel;
int i;
- Assert(var->varlevelsup > 0 && var->varlevelsup < PlannerQueryLevel);
- abslevel = PlannerQueryLevel - var->varlevelsup;
+ Assert(var->varlevelsup > 0 && var->varlevelsup < root->query_level);
+ abslevel = root->query_level - var->varlevelsup;
/*
- * If there's already a PlannerParamList entry for this same Var, just use
+ * If there's already a paramlist entry for this same Var, just use
* it. NOTE: in sufficiently complex querytrees, it is possible for the
* same varno/abslevel to refer to different RTEs in different parts of
* the parsetree, so that different fields might end up sharing the same
@@ -130,7 +99,7 @@ replace_outer_var(Var *var)
* a subplan's args list.
*/
i = 0;
- foreach(ppl, PlannerParamList)
+ foreach(ppl, root->glob->paramlist)
{
pitem = (PlannerParamItem *) lfirst(ppl);
if (pitem->abslevel == abslevel && IsA(pitem->item, Var))
@@ -152,11 +121,11 @@ replace_outer_var(Var *var)
var = (Var *) copyObject(var);
var->varlevelsup = 0;
- pitem = (PlannerParamItem *) palloc(sizeof(PlannerParamItem));
+ pitem = makeNode(PlannerParamItem);
pitem->item = (Node *) var;
pitem->abslevel = abslevel;
- PlannerParamList = lappend(PlannerParamList, pitem);
+ root->glob->paramlist = lappend(root->glob->paramlist, pitem);
/* i is already the correct index for the new item */
}
@@ -174,15 +143,15 @@ replace_outer_var(Var *var)
* which is expected to have agglevelsup > 0 (ie, it is not local).
*/
static Param *
-replace_outer_agg(Aggref *agg)
+replace_outer_agg(PlannerInfo *root, Aggref *agg)
{
Param *retval;
PlannerParamItem *pitem;
Index abslevel;
int i;
- Assert(agg->agglevelsup > 0 && agg->agglevelsup < PlannerQueryLevel);
- abslevel = PlannerQueryLevel - agg->agglevelsup;
+ Assert(agg->agglevelsup > 0 && agg->agglevelsup < root->query_level);
+ abslevel = root->query_level - agg->agglevelsup;
/*
* It does not seem worthwhile to try to match duplicate outer aggs. Just
@@ -192,12 +161,12 @@ replace_outer_agg(Aggref *agg)
IncrementVarSublevelsUp((Node *) agg, -((int) agg->agglevelsup), 0);
Assert(agg->agglevelsup == 0);
- pitem = (PlannerParamItem *) palloc(sizeof(PlannerParamItem));
+ pitem = makeNode(PlannerParamItem);
pitem->item = (Node *) agg;
pitem->abslevel = abslevel;
- PlannerParamList = lappend(PlannerParamList, pitem);
- i = list_length(PlannerParamList) - 1;
+ root->glob->paramlist = lappend(root->glob->paramlist, pitem);
+ i = list_length(root->glob->paramlist) - 1;
retval = makeNode(Param);
retval->paramkind = PARAM_EXEC;
@@ -214,22 +183,22 @@ replace_outer_agg(Aggref *agg)
* This is used to allocate PARAM_EXEC slots for subplan outputs.
*/
static Param *
-generate_new_param(Oid paramtype, int32 paramtypmod)
+generate_new_param(PlannerInfo *root, Oid paramtype, int32 paramtypmod)
{
Param *retval;
PlannerParamItem *pitem;
retval = makeNode(Param);
retval->paramkind = PARAM_EXEC;
- retval->paramid = list_length(PlannerParamList);
+ retval->paramid = list_length(root->glob->paramlist);
retval->paramtype = paramtype;
retval->paramtypmod = paramtypmod;
- pitem = (PlannerParamItem *) palloc(sizeof(PlannerParamItem));
+ pitem = makeNode(PlannerParamItem);
pitem->item = (Node *) retval;
- pitem->abslevel = PlannerQueryLevel;
+ pitem->abslevel = root->query_level;
- PlannerParamList = lappend(PlannerParamList, pitem);
+ root->glob->paramlist = lappend(root->glob->paramlist, pitem);
return retval;
}
@@ -248,7 +217,7 @@ generate_new_param(Oid paramtype, int32 paramtypmod)
* tree containing InitPlan Param nodes.
*/
static Node *
-make_subplan(SubLink *slink, Node *testexpr, bool isTopQual)
+make_subplan(PlannerInfo *root, SubLink *slink, Node *testexpr, bool isTopQual)
{
SubPlan *node = makeNode(SubPlan);
Query *subquery = (Query *) (slink->subselect);
@@ -297,9 +266,13 @@ make_subplan(SubLink *slink, Node *testexpr, bool isTopQual)
/*
* Generate the plan for the subquery.
*/
- node->plan = plan = subquery_planner(subquery, tuple_fraction, NULL);
+ node->plan = plan = subquery_planner(root->glob, subquery,
+ root->query_level + 1,
+ tuple_fraction,
+ NULL);
- node->plan_id = PlannerPlanId++; /* Assign unique ID to this SubPlan */
+ /* Assign quasi-unique ID to this SubPlan */
+ node->plan_id = root->glob->next_plan_id++;
node->rtable = subquery->rtable;
@@ -323,9 +296,9 @@ make_subplan(SubLink *slink, Node *testexpr, bool isTopQual)
tmpset = bms_copy(plan->extParam);
while ((paramid = bms_first_member(tmpset)) >= 0)
{
- PlannerParamItem *pitem = list_nth(PlannerParamList, paramid);
+ PlannerParamItem *pitem = list_nth(root->glob->paramlist, paramid);
- if (pitem->abslevel == PlannerQueryLevel)
+ if (pitem->abslevel == root->query_level)
node->parParam = lappend_int(node->parParam, paramid);
}
bms_free(tmpset);
@@ -342,9 +315,9 @@ make_subplan(SubLink *slink, Node *testexpr, bool isTopQual)
{
Param *prm;
- prm = generate_new_param(BOOLOID, -1);
+ prm = generate_new_param(root, BOOLOID, -1);
node->setParam = list_make1_int(prm->paramid);
- PlannerInitPlan = lappend(PlannerInitPlan, node);
+ root->init_plans = lappend(root->init_plans, node);
result = (Node *) prm;
}
else if (node->parParam == NIL && slink->subLinkType == EXPR_SUBLINK)
@@ -353,10 +326,11 @@ make_subplan(SubLink *slink, Node *testexpr, bool isTopQual)
Param *prm;
Assert(!te->resjunk);
- prm = generate_new_param(exprType((Node *) te->expr),
+ prm = generate_new_param(root,
+ exprType((Node *) te->expr),
exprTypmod((Node *) te->expr));
node->setParam = list_make1_int(prm->paramid);
- PlannerInitPlan = lappend(PlannerInitPlan, node);
+ root->init_plans = lappend(root->init_plans, node);
result = (Node *) prm;
}
else if (node->parParam == NIL && slink->subLinkType == ARRAY_SUBLINK)
@@ -370,19 +344,22 @@ make_subplan(SubLink *slink, Node *testexpr, bool isTopQual)
if (!OidIsValid(arraytype))
elog(ERROR, "could not find array type for datatype %s",
format_type_be(exprType((Node *) te->expr)));
- prm = generate_new_param(arraytype, exprTypmod((Node *) te->expr));
+ prm = generate_new_param(root,
+ arraytype,
+ exprTypmod((Node *) te->expr));
node->setParam = list_make1_int(prm->paramid);
- PlannerInitPlan = lappend(PlannerInitPlan, node);
+ root->init_plans = lappend(root->init_plans, node);
result = (Node *) prm;
}
else if (node->parParam == NIL && slink->subLinkType == ROWCOMPARE_SUBLINK)
{
/* Adjust the Params */
- result = convert_testexpr(testexpr,
+ result = convert_testexpr(root,
+ testexpr,
0,
&node->paramIds);
node->setParam = list_copy(node->paramIds);
- PlannerInitPlan = lappend(PlannerInitPlan, node);
+ root->init_plans = lappend(root->init_plans, node);
/*
* The executable expression is returned to become part of the outer
@@ -395,7 +372,8 @@ make_subplan(SubLink *slink, Node *testexpr, bool isTopQual)
ListCell *l;
/* Adjust the Params */
- node->testexpr = convert_testexpr(testexpr,
+ node->testexpr = convert_testexpr(root,
+ testexpr,
0,
&node->paramIds);
@@ -442,7 +420,8 @@ make_subplan(SubLink *slink, Node *testexpr, bool isTopQual)
args = NIL;
foreach(l, node->parParam)
{
- PlannerParamItem *pitem = list_nth(PlannerParamList, lfirst_int(l));
+ PlannerParamItem *pitem = list_nth(root->glob->paramlist,
+ lfirst_int(l));
/*
* The Var or Aggref has already been adjusted to have the correct
@@ -477,13 +456,15 @@ make_subplan(SubLink *slink, Node *testexpr, bool isTopQual)
* any we find are for our own level of SubLink.
*/
static Node *
-convert_testexpr(Node *testexpr,
+convert_testexpr(PlannerInfo *root,
+ Node *testexpr,
int rtindex,
List **righthandIds)
{
Node *result;
convert_testexpr_context context;
+ context.root = root;
context.rtindex = rtindex;
context.righthandIds = NIL;
result = convert_testexpr_mutator(testexpr, &context);
@@ -536,7 +517,8 @@ convert_testexpr_mutator(Node *node,
/* Make the Param node representing the subplan's result */
Param *newparam;
- newparam = generate_new_param(param->paramtype,
+ newparam = generate_new_param(context->root,
+ param->paramtype,
param->paramtypmod);
/* Record its ID */
context->righthandIds = lappend_int(context->righthandIds,
@@ -765,7 +747,8 @@ convert_IN_to_join(PlannerInfo *root, SubLink *sublink)
* ininfo->sub_targetlist is filled with a list of Vars representing the
* subselect outputs.
*/
- result = convert_testexpr(sublink->testexpr,
+ result = convert_testexpr(root,
+ sublink->testexpr,
rtindex,
&ininfo->sub_targetlist);
@@ -795,30 +778,30 @@ convert_IN_to_join(PlannerInfo *root, SubLink *sublink)
* argument expressions, either in the parent or the child level.
*/
Node *
-SS_replace_correlation_vars(Node *expr)
+SS_replace_correlation_vars(PlannerInfo *root, Node *expr)
{
/* No setup needed for tree walk, so away we go */
- return replace_correlation_vars_mutator(expr, NULL);
+ return replace_correlation_vars_mutator(expr, root);
}
static Node *
-replace_correlation_vars_mutator(Node *node, void *context)
+replace_correlation_vars_mutator(Node *node, PlannerInfo *root)
{
if (node == NULL)
return NULL;
if (IsA(node, Var))
{
if (((Var *) node)->varlevelsup > 0)
- return (Node *) replace_outer_var((Var *) node);
+ return (Node *) replace_outer_var(root, (Var *) node);
}
if (IsA(node, Aggref))
{
if (((Aggref *) node)->agglevelsup > 0)
- return (Node *) replace_outer_agg((Aggref *) node);
+ return (Node *) replace_outer_agg(root, (Aggref *) node);
}
return expression_tree_mutator(node,
replace_correlation_vars_mutator,
- context);
+ (void *) root);
}
/*
@@ -829,16 +812,21 @@ replace_correlation_vars_mutator(Node *node, void *context)
* not distinguish FALSE from UNKNOWN return values.
*/
Node *
-SS_process_sublinks(Node *expr, bool isQual)
+SS_process_sublinks(PlannerInfo *root, Node *expr, bool isQual)
{
- /* The only context needed is the initial are-we-in-a-qual flag */
- return process_sublinks_mutator(expr, &isQual);
+ process_sublinks_context context;
+
+ context.root = root;
+ context.isTopQual = isQual;
+ return process_sublinks_mutator(expr, &context);
}
static Node *
-process_sublinks_mutator(Node *node, bool *isTopQual)
+process_sublinks_mutator(Node *node, process_sublinks_context *context)
{
- bool locTopQual;
+ process_sublinks_context locContext;
+
+ locContext.root = context->root;
if (node == NULL)
return NULL;
@@ -849,14 +837,18 @@ process_sublinks_mutator(Node *node, bool *isTopQual)
/*
* First, recursively process the lefthand-side expressions, if any.
+ * They're not top-level anymore.
*/
- locTopQual = false;
- testexpr = process_sublinks_mutator(sublink->testexpr, &locTopQual);
+ locContext.isTopQual = false;
+ testexpr = process_sublinks_mutator(sublink->testexpr, &locContext);
/*
* Now build the SubPlan node and make the expr to return.
*/
- return make_subplan(sublink, testexpr, *isTopQual);
+ return make_subplan(context->root,
+ sublink,
+ testexpr,
+ context->isTopQual);
}
/*
@@ -883,14 +875,13 @@ process_sublinks_mutator(Node *node, bool *isTopQual)
ListCell *l;
/* Still at qual top-level */
- locTopQual = *isTopQual;
+ locContext.isTopQual = context->isTopQual;
foreach(l, ((BoolExpr *) node)->args)
{
Node *newarg;
- newarg = process_sublinks_mutator(lfirst(l),
- (void *) &locTopQual);
+ newarg = process_sublinks_mutator(lfirst(l), &locContext);
if (and_clause(newarg))
newargs = list_concat(newargs, ((BoolExpr *) newarg)->args);
else
@@ -900,7 +891,7 @@ process_sublinks_mutator(Node *node, bool *isTopQual)
}
/* otherwise not at qual top-level */
- locTopQual = false;
+ locContext.isTopQual = false;
if (or_clause(node))
{
@@ -911,8 +902,7 @@ process_sublinks_mutator(Node *node, bool *isTopQual)
{
Node *newarg;
- newarg = process_sublinks_mutator(lfirst(l),
- (void *) &locTopQual);
+ newarg = process_sublinks_mutator(lfirst(l), &locContext);
if (or_clause(newarg))
newargs = list_concat(newargs, ((BoolExpr *) newarg)->args);
else
@@ -923,7 +913,7 @@ process_sublinks_mutator(Node *node, bool *isTopQual)
return expression_tree_mutator(node,
process_sublinks_mutator,
- (void *) &locTopQual);
+ (void *) &locContext);
}
/*
@@ -934,7 +924,7 @@ process_sublinks_mutator(Node *node, bool *isTopQual)
* to the top plan node.
*/
void
-SS_finalize_plan(Plan *plan, List *rtable)
+SS_finalize_plan(PlannerInfo *root, Plan *plan)
{
Bitmapset *outer_params,
*valid_params,
@@ -951,17 +941,17 @@ SS_finalize_plan(Plan *plan, List *rtable)
*/
outer_params = valid_params = NULL;
paramid = 0;
- foreach(l, PlannerParamList)
+ foreach(l, root->glob->paramlist)
{
PlannerParamItem *pitem = (PlannerParamItem *) lfirst(l);
- if (pitem->abslevel < PlannerQueryLevel)
+ if (pitem->abslevel < root->query_level)
{
/* valid outer-level parameter */
outer_params = bms_add_member(outer_params, paramid);
valid_params = bms_add_member(valid_params, paramid);
}
- else if (pitem->abslevel == PlannerQueryLevel &&
+ else if (pitem->abslevel == root->query_level &&
IsA(pitem->item, Param))
{
/* valid local parameter (i.e., a setParam of my child) */
@@ -974,7 +964,7 @@ SS_finalize_plan(Plan *plan, List *rtable)
/*
* Now recurse through plan tree.
*/
- (void) finalize_plan(plan, rtable, outer_params, valid_params);
+ (void) finalize_plan(plan, root->parse->rtable, outer_params, valid_params);
bms_free(outer_params);
bms_free(valid_params);
@@ -991,8 +981,8 @@ SS_finalize_plan(Plan *plan, List *rtable)
* top node. This is a conservative overestimate, since in fact each
* initPlan might be executed later than plan startup, or even not at all.
*/
- plan->initPlan = PlannerInitPlan;
- PlannerInitPlan = NIL; /* make sure they're not attached twice */
+ plan->initPlan = root->init_plans;
+ root->init_plans = NIL; /* make sure they're not attached twice */
initExtParam = initSetParam = NULL;
initplan_cost = 0;
@@ -1287,25 +1277,27 @@ Param *
SS_make_initplan_from_plan(PlannerInfo *root, Plan *plan,
Oid resulttype, int32 resulttypmod)
{
- List *saved_initplan = PlannerInitPlan;
+ List *saved_init_plans;
SubPlan *node;
Param *prm;
/*
* Set up for a new level of subquery. This is just to keep
- * SS_finalize_plan from becoming confused.
+ * SS_finalize_plan from becoming confused; we don't bother with making
+ * a whole new PlannerInfo struct.
*/
- PlannerQueryLevel++;
- PlannerInitPlan = NIL;
+ root->query_level++;
+ saved_init_plans = root->init_plans;
+ root->init_plans = NIL;
/*
* Build extParam/allParam sets for plan nodes.
*/
- SS_finalize_plan(plan, root->parse->rtable);
+ SS_finalize_plan(root, plan);
/* Return to outer subquery context */
- PlannerQueryLevel--;
- PlannerInitPlan = saved_initplan;
+ root->query_level--;
+ root->init_plans = saved_init_plans;
/*
* Create a SubPlan node and add it to the outer list of InitPlans.
@@ -1313,11 +1305,12 @@ SS_make_initplan_from_plan(PlannerInfo *root, Plan *plan,
node = makeNode(SubPlan);
node->subLinkType = EXPR_SUBLINK;
node->plan = plan;
- node->plan_id = PlannerPlanId++; /* Assign unique ID to this SubPlan */
+ /* Assign quasi-unique ID to this SubPlan */
+ node->plan_id = root->glob->next_plan_id++;
node->rtable = root->parse->rtable;
- PlannerInitPlan = lappend(PlannerInitPlan, node);
+ root->init_plans = lappend(root->init_plans, node);
/*
* The node can't have any inputs (since it's an initplan), so the
@@ -1327,7 +1320,7 @@ SS_make_initplan_from_plan(PlannerInfo *root, Plan *plan,
/*
* Make a Param that will be the subplan's output.
*/
- prm = generate_new_param(resulttype, resulttypmod);
+ prm = generate_new_param(root, resulttype, resulttypmod);
node->setParam = list_make1_int(prm->paramid);
return prm;
diff --git a/src/backend/optimizer/prep/prepjointree.c b/src/backend/optimizer/prep/prepjointree.c
index ce6f9cc38e4..1519c01e60e 100644
--- a/src/backend/optimizer/prep/prepjointree.c
+++ b/src/backend/optimizer/prep/prepjointree.c
@@ -15,7 +15,7 @@
*
*
* 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,
*/
subroot = makeNode(PlannerInfo);
subroot->parse = subquery;
+ subroot->glob = root->glob;
+ subroot->query_level = root->query_level;
subroot->planner_cxt = CurrentMemoryContext;
+ subroot->init_plans = NIL;
subroot->in_info_list = NIL;
subroot->append_rel_list = NIL;
diff --git a/src/backend/optimizer/prep/preptlist.c b/src/backend/optimizer/prep/preptlist.c
index b8d98cc9e3c..310b57392cd 100644
--- a/src/backend/optimizer/prep/preptlist.c
+++ b/src/backend/optimizer/prep/preptlist.c
@@ -16,7 +16,7 @@
* Portions Copyright (c) 1994, Regents of the University of California
*
* 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)
/*
* Currently the executor only supports FOR UPDATE/SHARE at top level
*/
- if (PlannerQueryLevel > 1)
+ if (root->query_level > 1)
ereport(ERROR,
(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
errmsg("SELECT FOR UPDATE/SHARE is not allowed in subqueries")));
diff --git a/src/backend/optimizer/prep/prepunion.c b/src/backend/optimizer/prep/prepunion.c
index 5ee03b75cff..2f06e1bf532 100644
--- a/src/backend/optimizer/prep/prepunion.c
+++ b/src/backend/optimizer/prep/prepunion.c
@@ -22,7 +22,7 @@
*
*
* 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,
/*
* 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
diff --git a/src/backend/optimizer/util/clauses.c b/src/backend/optimizer/util/clauses.c
index 528f02ed111..f90d5500197 100644
--- a/src/backend/optimizer/util/clauses.c
+++ b/src/backend/optimizer/util/clauses.c
@@ -8,7 +8,7 @@
*
*
* 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
* AUTHOR DATE MAJOR EVENT
@@ -49,6 +49,7 @@
typedef struct
{
+ ParamListInfo boundParams;
List *active_fns;
Node *case_val;
bool estimate;
@@ -1578,6 +1579,7 @@ eval_const_expressions(Node *node)
{
eval_const_expressions_context context;
+ context.boundParams = NULL; /* don't use any bound params */
context.active_fns = NIL; /* nothing being recursively simplified */
context.case_val = NULL; /* no CASE being examined */
context.estimate = false; /* safe transformations only */
@@ -1601,10 +1603,11 @@ eval_const_expressions(Node *node)
*--------------------
*/
Node *
-estimate_expression_value(Node *node)
+estimate_expression_value(PlannerInfo *root, Node *node)
{
eval_const_expressions_context context;
+ context.boundParams = root->glob->boundParams; /* bound Params */
context.active_fns = NIL; /* nothing being recursively simplified */
context.case_val = NULL; /* no CASE being examined */
context.estimate = true; /* unsafe transformations OK */
@@ -1623,11 +1626,11 @@ eval_const_expressions_mutator(Node *node,
/* Look to see if we've been given a value for this Param */
if (param->paramkind == PARAM_EXTERN &&
- PlannerBoundParamList != NULL &&
+ context->boundParams != NULL &&
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))
{
diff --git a/src/backend/utils/adt/selfuncs.c b/src/backend/utils/adt/selfuncs.c
index 7908ab15167..c6b8e8481c4 100644
--- a/src/backend/utils/adt/selfuncs.c
+++ b/src/backend/utils/adt/selfuncs.c
@@ -15,7 +15,7 @@
*
*
* 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,
if (vardata->rel && rdata.rel == NULL)
{
*varonleft = true;
- *other = estimate_expression_value(rdata.var);
+ *other = estimate_expression_value(root, rdata.var);
/* Assume we need no ReleaseVariableStats(rdata) here */
return true;
}
@@ -3419,7 +3419,7 @@ get_restriction_variable(PlannerInfo *root, List *args, int varRelid,
if (vardata->rel == NULL && rdata.rel)
{
*varonleft = false;
- *other = estimate_expression_value(vardata->var);
+ *other = estimate_expression_value(root, vardata->var);
/* Assume we need no ReleaseVariableStats(*vardata) here */
*vardata = rdata;
return true;
diff --git a/src/include/nodes/nodes.h b/src/include/nodes/nodes.h
index 2452f792940..44175591e75 100644
--- a/src/include/nodes/nodes.h
+++ b/src/include/nodes/nodes.h
@@ -7,7 +7,7 @@
* Portions Copyright (c) 1996-2007, PostgreSQL Global Development Group
* 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
* TAGS FOR PLANNER NODES (relation.h)
*/
T_PlannerInfo = 500,
+ T_PlannerGlobal,
T_RelOptInfo,
T_IndexOptInfo,
T_Path,
@@ -198,6 +199,7 @@ typedef enum NodeTag
T_OuterJoinInfo,
T_InClauseInfo,
T_AppendRelInfo,
+ T_PlannerParamItem,
/*
* TAGS FOR MEMORY NODES (memnodes.h)
diff --git a/src/include/nodes/primnodes.h b/src/include/nodes/primnodes.h
index 298ac0d95d6..caa689e2623 100644
--- a/src/include/nodes/primnodes.h
+++ b/src/include/nodes/primnodes.h
@@ -10,7 +10,7 @@
* Portions Copyright (c) 1996-2007, PostgreSQL Global Development Group
* 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
List *paramIds; /* IDs of Params embedded in the above */
/* The subselect, transformed to a Plan: */
struct Plan *plan; /* subselect plan itself */
- int plan_id; /* dummy thing because of we haven't equal
- * funcs for plan nodes... actually, we could
- * put *plan itself somewhere else (TopPlan
- * node ?)... */
+ int plan_id; /* kluge because we haven't equal-funcs for
+ * plan nodes... we compare this instead of
+ * subselect plan */
List *rtable; /* range table for subselect */
/* Information about execution strategy: */
bool useHashTable; /* TRUE to store subselect output in a hash
diff --git a/src/include/nodes/relation.h b/src/include/nodes/relation.h
index dac7d959bbd..6de06ebc918 100644
--- a/src/include/nodes/relation.h
+++ b/src/include/nodes/relation.h
@@ -7,7 +7,7 @@
* Portions Copyright (c) 1996-2007, PostgreSQL Global Development Group
* 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 @@
#include "access/sdir.h"
#include "nodes/bitmapset.h"
+#include "nodes/params.h"
#include "nodes/parsenodes.h"
#include "storage/block.h"
@@ -47,6 +48,27 @@ typedef struct 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
* Per-query information for planning/optimization
*
@@ -62,6 +84,10 @@ typedef struct PlannerInfo
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
* comments for RelOptInfo for more info). It is indexed by rangetable
@@ -84,6 +110,8 @@ typedef struct PlannerInfo
List *join_rel_list; /* list of join-relation RelOptInfos */
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 *canon_pathkeys; /* list of "canonical" PathKeys */
@@ -1109,4 +1137,39 @@ typedef struct AppendRelInfo
Oid parent_reloid; /* OID of parent relation */
} 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 */
diff --git a/src/include/optimizer/clauses.h b/src/include/optimizer/clauses.h
index 50011259142..bd4a7964355 100644
--- a/src/include/optimizer/clauses.h
+++ b/src/include/optimizer/clauses.h
@@ -7,7 +7,7 @@
* Portions Copyright (c) 1996-2007, PostgreSQL Global Development Group
* 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);
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) (),
void *context);
diff --git a/src/include/optimizer/planner.h b/src/include/optimizer/planner.h
index 6567e5b8b77..44d03602694 100644
--- a/src/include/optimizer/planner.h
+++ b/src/include/optimizer/planner.h
@@ -7,23 +7,21 @@
* Portions Copyright (c) 1996-2007, PostgreSQL Global Development Group
* 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
#define PLANNER_H
-#include "nodes/params.h"
-#include "nodes/parsenodes.h"
#include "nodes/plannodes.h"
+#include "nodes/relation.h"
-extern ParamListInfo PlannerBoundParamList; /* current boundParams */
-
extern Plan *planner(Query *parse, bool isCursor, int cursorOptions,
ParamListInfo boundParams);
-extern Plan *subquery_planner(Query *parse, double tuple_fraction,
- List **subquery_pathkeys);
+extern Plan *subquery_planner(PlannerGlobal *glob, Query *parse,
+ Index level, double tuple_fraction,
+ List **subquery_pathkeys);
#endif /* PLANNER_H */
diff --git a/src/include/optimizer/subselect.h b/src/include/optimizer/subselect.h
index 8a4328bd1f2..17c94bf6099 100644
--- a/src/include/optimizer/subselect.h
+++ b/src/include/optimizer/subselect.h
@@ -5,7 +5,7 @@
* Portions Copyright (c) 1996-2007, PostgreSQL Global Development Group
* 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 @@
#include "nodes/plannodes.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 *SS_replace_correlation_vars(Node *expr);
-extern Node *SS_process_sublinks(Node *expr, bool isQual);
-extern void SS_finalize_plan(Plan *plan, List *rtable);
+extern Node *SS_replace_correlation_vars(PlannerInfo *root, Node *expr);
+extern Node *SS_process_sublinks(PlannerInfo *root, Node *expr, bool isQual);
+extern void SS_finalize_plan(PlannerInfo *root, Plan *plan);
extern Param *SS_make_initplan_from_plan(PlannerInfo *root, Plan *plan,
Oid resulttype, int32 resulttypmod);