* Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
- * $Header: /cvsroot/pgsql/src/backend/executor/execAmi.c,v 1.68 2002/12/14 00:17:50 tgl Exp $
+ * $Header: /cvsroot/pgsql/src/backend/executor/execAmi.c,v 1.69 2003/02/09 00:30:39 tgl Exp $
*
*-------------------------------------------------------------------------
*/
InstrEndLoop(node->instrument);
/* If we have changed parameters, propagate that info */
- if (node->chgParam != NIL)
+ if (node->chgParam != NULL)
{
List *lst;
SubPlanState *sstate = (SubPlanState *) lfirst(lst);
PlanState *splan = sstate->planstate;
- if (splan->plan->extParam != NIL) /* don't care about child
- * locParam */
- SetChangedParamList(splan, node->chgParam);
- if (splan->chgParam != NIL)
+ if (splan->plan->extParam != NULL) /* don't care about child
+ * local Params */
+ UpdateChangedParamSet(splan, node->chgParam);
+ if (splan->chgParam != NULL)
ExecReScanSetParamPlan(sstate, node);
}
foreach(lst, node->subPlan)
SubPlanState *sstate = (SubPlanState *) lfirst(lst);
PlanState *splan = sstate->planstate;
- if (splan->plan->extParam != NIL)
- SetChangedParamList(splan, node->chgParam);
+ if (splan->plan->extParam != NULL)
+ UpdateChangedParamSet(splan, node->chgParam);
}
/* Well. Now set chgParam for left/right trees. */
if (node->lefttree != NULL)
- SetChangedParamList(node->lefttree, node->chgParam);
+ UpdateChangedParamSet(node->lefttree, node->chgParam);
if (node->righttree != NULL)
- SetChangedParamList(node->righttree, node->chgParam);
+ UpdateChangedParamSet(node->righttree, node->chgParam);
}
switch (nodeTag(node))
return;
}
- if (node->chgParam != NIL)
+ if (node->chgParam != NULL)
{
- freeList(node->chgParam);
- node->chgParam = NIL;
+ bms_free(node->chgParam);
+ node->chgParam = NULL;
}
}
*
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/backend/executor/execProcnode.c,v 1.34 2002/12/14 00:17:50 tgl Exp $
+ * $Header: /cvsroot/pgsql/src/backend/executor/execProcnode.c,v 1.35 2003/02/09 00:30:39 tgl Exp $
*
*-------------------------------------------------------------------------
*/
if (node == NULL)
return NULL;
- if (node->chgParam != NIL) /* something changed */
+ if (node->chgParam != NULL) /* something changed */
ExecReScan(node, NULL); /* let ReScan handle this */
if (node->instrument)
foreach(subp, node->subPlan)
ExecEndSubPlan((SubPlanState *) lfirst(subp));
- if (node->chgParam != NIL)
+ if (node->chgParam != NULL)
{
- freeList(node->chgParam);
- node->chgParam = NIL;
+ bms_free(node->chgParam);
+ node->chgParam = NULL;
}
switch (nodeTag(node))
*
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/backend/executor/execUtils.c,v 1.96 2003/01/23 05:10:39 tgl Exp $
+ * $Header: /cvsroot/pgsql/src/backend/executor/execUtils.c,v 1.97 2003/02/09 00:30:39 tgl Exp $
*
*-------------------------------------------------------------------------
*/
}
}
+/*
+ * UpdateChangedParamSet
+ * Add changed parameters to a plan node's chgParam set
+ */
void
-SetChangedParamList(PlanState *node, List *newchg)
+UpdateChangedParamSet(PlanState *node, Bitmapset *newchg)
{
- List *nl;
-
- foreach(nl, newchg)
- {
- int paramId = lfirsti(nl);
+ Bitmapset *parmset;
- /* if this node doesn't depend on a param ... */
- if (!intMember(paramId, node->plan->extParam) &&
- !intMember(paramId, node->plan->locParam))
- continue;
- /* if this param is already in list of changed ones ... */
- if (intMember(paramId, node->chgParam))
- continue;
- /* else - add this param to the list */
- node->chgParam = lappendi(node->chgParam, paramId);
- }
+ /*
+ * The plan node only depends on params listed in its allParam set.
+ * Don't include anything else into its chgParam set.
+ */
+ parmset = bms_intersect(node->plan->allParam, newchg);
+ /*
+ * Keep node->chgParam == NULL if there's not actually any members;
+ * this allows the simplest possible tests in executor node files.
+ */
+ if (!bms_is_empty(parmset))
+ node->chgParam = bms_join(node->chgParam, parmset);
+ else
+ bms_free(parmset);
}
/*
* Portions Copyright (c) 1994, Regents of the University of California
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/backend/executor/nodeAgg.c,v 1.103 2003/02/04 00:48:23 tgl Exp $
+ * $Header: /cvsroot/pgsql/src/backend/executor/nodeAgg.c,v 1.104 2003/02/09 00:30:39 tgl Exp $
*
*-------------------------------------------------------------------------
*/
* if chgParam of subnode is not null then plan will be re-scanned by
* first ExecProcNode.
*/
- if (((PlanState *) node)->lefttree->chgParam == NIL)
+ if (((PlanState *) node)->lefttree->chgParam == NULL)
ExecReScan(((PlanState *) node)->lefttree, exprCtxt);
}
*
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/backend/executor/nodeAppend.c,v 1.51 2002/12/05 15:50:33 tgl Exp $
+ * $Header: /cvsroot/pgsql/src/backend/executor/nodeAppend.c,v 1.52 2003/02/09 00:30:39 tgl Exp $
*
*-------------------------------------------------------------------------
*/
* ExecReScan doesn't know about my subplans, so I have to do
* changed-parameter signaling myself.
*/
- if (node->ps.chgParam != NIL)
- SetChangedParamList(subnode, node->ps.chgParam);
+ if (node->ps.chgParam != NULL)
+ UpdateChangedParamSet(subnode, node->ps.chgParam);
/*
* if chgParam of subnode is not null then plan will be re-scanned
* by first ExecProcNode.
*/
- if (subnode->chgParam == NIL)
+ if (subnode->chgParam == NULL)
{
/* make sure estate is correct for this subnode (needed??) */
node->as_whichplan = i;
* Portions Copyright (c) 1994, Regents of the University of California
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/backend/executor/nodeSubplan.c,v 1.43 2003/01/12 04:03:34 tgl Exp $
+ * $Header: /cvsroot/pgsql/src/backend/executor/nodeSubplan.c,v 1.44 2003/02/09 00:30:39 tgl Exp $
*
*-------------------------------------------------------------------------
*/
* If first time through or we need to rescan the subplan, build
* the hash table.
*/
- if (node->hashtable == NULL || planstate->chgParam != NIL)
+ if (node->hashtable == NULL || planstate->chgParam != NULL)
buildSubPlanHash(node);
/*
* Set Params of this plan from parent plan correlation Vars
*/
pvar = node->args;
- if (subplan->parParam != NIL)
+ foreach(lst, subplan->parParam)
{
- foreach(lst, subplan->parParam)
- {
- ParamExecData *prm;
-
- prm = &(econtext->ecxt_param_exec_vals[lfirsti(lst)]);
- Assert(pvar != NIL);
- prm->value = ExecEvalExprSwitchContext((ExprState *) lfirst(pvar),
- econtext,
- &(prm->isnull),
- NULL);
- pvar = lnext(pvar);
- }
- planstate->chgParam = nconc(planstate->chgParam,
- listCopy(subplan->parParam));
+ int paramid = lfirsti(lst);
+ ParamExecData *prm = &(econtext->ecxt_param_exec_vals[paramid]);
+
+ Assert(pvar != NIL);
+ prm->value = ExecEvalExprSwitchContext((ExprState *) lfirst(pvar),
+ econtext,
+ &(prm->isnull),
+ NULL);
+ pvar = lnext(pvar);
+ planstate->chgParam = bms_add_member(planstate->chgParam, paramid);
}
Assert(pvar == NIL);
/*
* If this plan is un-correlated or undirect correlated one and want
- * to set params for parent plan then prepare parameters.
+ * to set params for parent plan then mark parameters as needing
+ * evaluation.
+ *
+ * Note that in the case of un-correlated subqueries we don't care
+ * about setting parent->chgParam here: indices take care about
+ * it, for others - it doesn't matter...
*/
if (subplan->setParam != NIL)
{
foreach(lst, subplan->setParam)
{
- ParamExecData *prm = &(estate->es_param_exec_vals[lfirsti(lst)]);
+ int paramid = lfirsti(lst);
+ ParamExecData *prm = &(estate->es_param_exec_vals[paramid]);
prm->execPlan = node;
}
-
- /*
- * Note that in the case of un-correlated subqueries we don't care
- * about setting parent->chgParam here: indices take care about
- * it, for others - it doesn't matter...
- */
}
/*
if (subLinkType == EXISTS_SUBLINK)
{
- ParamExecData *prm = &(econtext->ecxt_param_exec_vals[lfirsti(subplan->setParam)]);
+ /* There can be only one param... */
+ int paramid = lfirsti(subplan->setParam);
+ ParamExecData *prm = &(econtext->ecxt_param_exec_vals[paramid]);
prm->execPlan = NULL;
prm->value = BoolGetDatum(true);
node->curTuple = tup;
MemoryContextSwitchTo(node->sub_estate->es_query_cxt);
+ /*
+ * Now set all the setParam params from the columns of the tuple
+ */
foreach(lst, subplan->setParam)
{
- ParamExecData *prm = &(econtext->ecxt_param_exec_vals[lfirsti(lst)]);
+ int paramid = lfirsti(lst);
+ ParamExecData *prm = &(econtext->ecxt_param_exec_vals[paramid]);
prm->execPlan = NULL;
prm->value = heap_getattr(tup, i, tdesc, &(prm->isnull));
{
if (subLinkType == EXISTS_SUBLINK)
{
- ParamExecData *prm = &(econtext->ecxt_param_exec_vals[lfirsti(subplan->setParam)]);
+ /* There can be only one param... */
+ int paramid = lfirsti(subplan->setParam);
+ ParamExecData *prm = &(econtext->ecxt_param_exec_vals[paramid]);
prm->execPlan = NULL;
prm->value = BoolGetDatum(false);
{
foreach(lst, subplan->setParam)
{
- ParamExecData *prm = &(econtext->ecxt_param_exec_vals[lfirsti(lst)]);
+ int paramid = lfirsti(lst);
+ ParamExecData *prm = &(econtext->ecxt_param_exec_vals[paramid]);
prm->execPlan = NULL;
prm->value = (Datum) 0;
EState *estate = parent->state;
List *lst;
- if (subplan->parParam != NULL)
+ if (subplan->parParam != NIL)
elog(ERROR, "ExecReScanSetParamPlan: direct correlated subquery unsupported, yet");
- if (subplan->setParam == NULL)
- elog(ERROR, "ExecReScanSetParamPlan: setParam list is NULL");
- if (planstate->plan->extParam == NULL)
- elog(ERROR, "ExecReScanSetParamPlan: extParam list of plan is NULL");
+ if (subplan->setParam == NIL)
+ elog(ERROR, "ExecReScanSetParamPlan: setParam list is empty");
+ if (bms_is_empty(planstate->plan->extParam))
+ elog(ERROR, "ExecReScanSetParamPlan: extParam set of plan is empty");
/*
* Don't actually re-scan: ExecSetParamPlan does it if needed.
*/
foreach(lst, subplan->setParam)
{
- ParamExecData *prm = &(estate->es_param_exec_vals[lfirsti(lst)]);
+ int paramid = lfirsti(lst);
+ ParamExecData *prm = &(estate->es_param_exec_vals[paramid]);
prm->execPlan = node;
+ parent->chgParam = bms_add_member(parent->chgParam, paramid);
}
-
- parent->chgParam = nconc(parent->chgParam, listCopy(subplan->setParam));
}
*
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/backend/executor/nodeSubqueryscan.c,v 1.17 2003/01/12 22:01:38 tgl Exp $
+ * $Header: /cvsroot/pgsql/src/backend/executor/nodeSubqueryscan.c,v 1.18 2003/02/09 00:30:39 tgl Exp $
*
*-------------------------------------------------------------------------
*/
* ExecReScan doesn't know about my subplan, so I have to do
* changed-parameter signaling myself. This is just as well,
* because the subplan has its own memory context in which its
- * chgParam lists live.
+ * chgParam state lives.
*/
if (node->ss.ps.chgParam != NULL)
- SetChangedParamList(node->subplan, node->ss.ps.chgParam);
+ UpdateChangedParamSet(node->subplan, node->ss.ps.chgParam);
/*
* if chgParam of subnode is not null then plan will be re-scanned by
*
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/backend/executor/nodeTidscan.c,v 1.32 2003/02/03 15:07:07 tgl Exp $
+ * $Header: /cvsroot/pgsql/src/backend/executor/nodeTidscan.c,v 1.33 2003/02/09 00:30:39 tgl Exp $
*
*-------------------------------------------------------------------------
*/
Oid relid;
Oid reloid;
Relation currentRelation;
- List *execParam = NIL;
+ Bitmapset *execParam = NULL;
/*
* create state structure
* Portions Copyright (c) 1994, Regents of the University of California
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/backend/nodes/copyfuncs.c,v 1.240 2003/02/08 20:20:53 tgl Exp $
+ * $Header: /cvsroot/pgsql/src/backend/nodes/copyfuncs.c,v 1.241 2003/02/09 00:30:39 tgl Exp $
*
*-------------------------------------------------------------------------
*/
COPY_NODE_FIELD(lefttree);
COPY_NODE_FIELD(righttree);
COPY_NODE_FIELD(initPlan);
- COPY_INTLIST_FIELD(extParam);
- COPY_INTLIST_FIELD(locParam);
+ COPY_BITMAPSET_FIELD(extParam);
+ COPY_BITMAPSET_FIELD(allParam);
COPY_SCALAR_FIELD(nParamExec);
}
*
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/backend/nodes/outfuncs.c,v 1.196 2003/02/08 20:20:54 tgl Exp $
+ * $Header: /cvsroot/pgsql/src/backend/nodes/outfuncs.c,v 1.197 2003/02/09 00:30:39 tgl Exp $
*
* NOTES
* Every node type that can appear in stored rules' parsetrees *must*
WRITE_NODE_FIELD(lefttree);
WRITE_NODE_FIELD(righttree);
WRITE_NODE_FIELD(initPlan);
- WRITE_INTLIST_FIELD(extParam);
- WRITE_INTLIST_FIELD(locParam);
+ WRITE_BITMAPSET_FIELD(extParam);
+ WRITE_BITMAPSET_FIELD(allParam);
WRITE_INT_FIELD(nParamExec);
}
*
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/backend/optimizer/plan/planner.c,v 1.144 2003/02/04 00:50:00 tgl Exp $
+ * $Header: /cvsroot/pgsql/src/backend/optimizer/plan/planner.c,v 1.145 2003/02/09 00:30:39 tgl Exp $
*
*-------------------------------------------------------------------------
*/
/*
* If any subplans were generated, or if we're inside a subplan, build
- * initPlan, extParam and locParam lists for plan nodes.
+ * initPlan list and extParam/allParam sets for plan nodes.
*/
if (PlannerPlanId != saved_planid || PlannerQueryLevel > 1)
{
Cost initplan_cost = 0;
- /* Prepare extParam/locParam data for all nodes in tree */
- (void) SS_finalize_plan(plan, parse->rtable);
+ /* Prepare extParam/allParam sets for all nodes in tree */
+ SS_finalize_plan(plan, parse->rtable);
/*
* SS_finalize_plan doesn't handle initPlans, so we have to manually
{
SubPlan *initplan = (SubPlan *) lfirst(lst);
- plan->extParam = set_unioni(plan->extParam,
- initplan->plan->extParam);
+ plan->extParam = bms_add_members(plan->extParam,
+ initplan->plan->extParam);
initplan_cost += initplan->plan->total_cost;
}
* Portions Copyright (c) 1994, Regents of the University of California
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/backend/optimizer/plan/subselect.c,v 1.70 2003/02/08 20:20:54 tgl Exp $
+ * $Header: /cvsroot/pgsql/src/backend/optimizer/plan/subselect.c,v 1.71 2003/02/09 00:30:39 tgl Exp $
*
*-------------------------------------------------------------------------
*/
*/
-typedef struct finalize_primnode_results
+typedef struct finalize_primnode_context
{
- List *paramids; /* List of PARAM_EXEC paramids found */
-} finalize_primnode_results;
+ Bitmapset *paramids; /* Set of PARAM_EXEC paramids found */
+ Bitmapset *outer_params; /* Set of accessible outer paramids */
+} finalize_primnode_context;
static List *convert_sublink_opers(List *lefthand, List *operOids,
static bool subplan_is_hashable(SubLink *slink, SubPlan *node);
static Node *replace_correlation_vars_mutator(Node *node, void *context);
static Node *process_sublinks_mutator(Node *node, bool *isTopQual);
-static bool finalize_primnode(Node *node, finalize_primnode_results *results);
+static Bitmapset *finalize_plan(Plan *plan, List *rtable,
+ Bitmapset *outer_params,
+ Bitmapset *valid_params);
+static bool finalize_primnode(Node *node, finalize_primnode_context *context);
/*
Query *subquery = (Query *) (slink->subselect);
double tuple_fraction;
Plan *plan;
+ Bitmapset *tmpset;
+ int paramid;
List *lst;
Node *result;
* Make parParam list of params that current query level will pass to
* this child plan.
*/
- foreach(lst, plan->extParam)
+ tmpset = bms_copy(plan->extParam);
+ while ((paramid = bms_first_member(tmpset)) >= 0)
{
- int paramid = lfirsti(lst);
Var *var = nth(paramid, PlannerParamVar);
/* note varlevelsup is absolute level number */
if (var->varlevelsup == PlannerQueryLevel)
node->parParam = lappendi(node->parParam, paramid);
}
+ bms_free(tmpset);
/*
* Un-correlated or undirect correlated plans of EXISTS, EXPR, or
Param *prm;
prm = generate_new_param(BOOLOID, -1);
- node->setParam = lappendi(node->setParam, prm->paramid);
+ node->setParam = makeListi1(prm->paramid);
PlannerInitPlan = lappend(PlannerInitPlan, node);
result = (Node *) prm;
}
Assert(!te->resdom->resjunk);
prm = generate_new_param(te->resdom->restype, te->resdom->restypmod);
- node->setParam = lappendi(node->setParam, prm->paramid);
+ node->setParam = makeListi1(prm->paramid);
PlannerInitPlan = lappend(PlannerInitPlan, node);
result = (Node *) prm;
}
plan->targetlist,
0,
&node->paramIds);
- node->setParam = nconc(node->setParam, listCopy(node->paramIds));
+ node->setParam = listCopy(node->paramIds);
PlannerInitPlan = lappend(PlannerInitPlan, node);
/*
* The executable expressions are returned to become part of the
matplan->plan_rows = plan->plan_rows;
matplan->plan_width = plan->plan_width;
/* parameter kluge --- see comments above */
- matplan->extParam = listCopy(plan->extParam);
- matplan->locParam = listCopy(plan->locParam);
+ matplan->extParam = bms_copy(plan->extParam);
+ matplan->allParam = bms_copy(plan->allParam);
node->plan = plan = matplan;
}
}
/*
* SS_finalize_plan - do final sublink processing for a completed Plan.
*
- * This recursively computes and sets the extParam and locParam lists
- * for every Plan node in the given tree.
+ * This recursively computes the extParam and allParam sets
+ * for every Plan node in the given plan tree.
*/
-List *
+void
SS_finalize_plan(Plan *plan, List *rtable)
{
- List *extParam = NIL;
- List *locParam = NIL;
- finalize_primnode_results results;
+ Bitmapset *outer_params = NULL;
+ Bitmapset *valid_params = NULL;
+ int paramid;
+ List *lst;
+
+ /*
+ * First, scan the param list to discover the sets of params that
+ * are available from outer query levels and my own query level.
+ * We do this once to save time in the per-plan recursion steps.
+ */
+ paramid = 0;
+ foreach(lst, PlannerParamVar)
+ {
+ Var *var = (Var *) lfirst(lst);
+
+ /* note varlevelsup is absolute level number */
+ if (var->varlevelsup < PlannerQueryLevel)
+ {
+ /* valid outer-level parameter */
+ outer_params = bms_add_member(outer_params, paramid);
+ valid_params = bms_add_member(valid_params, paramid);
+ }
+ else if (var->varlevelsup == PlannerQueryLevel &&
+ var->varno == 0 && var->varattno == 0)
+ {
+ /* valid local parameter (i.e., a setParam of my child) */
+ valid_params = bms_add_member(valid_params, paramid);
+ }
+
+ paramid++;
+ }
+
+ /*
+ * Now recurse through plan tree.
+ */
+ (void) finalize_plan(plan, rtable, outer_params, valid_params);
+
+ bms_free(outer_params);
+ bms_free(valid_params);
+}
+
+/*
+ * Recursive processing of all nodes in the plan tree
+ *
+ * The return value is the computed allParam set for the given Plan node.
+ * This is just an internal notational convenience.
+ */
+static Bitmapset *
+finalize_plan(Plan *plan, List *rtable,
+ Bitmapset *outer_params, Bitmapset *valid_params)
+{
+ finalize_primnode_context context;
List *lst;
if (plan == NULL)
- return NIL;
+ return NULL;
- results.paramids = NIL; /* initialize list to NIL */
+ context.paramids = NULL; /* initialize set to empty */
+ context.outer_params = outer_params;
/*
- * When we call finalize_primnode, results.paramids lists are
+ * When we call finalize_primnode, context.paramids sets are
* automatically merged together. But when recursing to self, we have
- * to do it the hard way. We want the paramids list to include params
+ * to do it the hard way. We want the paramids set to include params
* in subplans as well as at this level.
*/
/* Find params in targetlist and qual */
- finalize_primnode((Node *) plan->targetlist, &results);
- finalize_primnode((Node *) plan->qual, &results);
+ finalize_primnode((Node *) plan->targetlist, &context);
+ finalize_primnode((Node *) plan->qual, &context);
/* Check additional node-type-specific fields */
switch (nodeTag(plan))
{
case T_Result:
finalize_primnode(((Result *) plan)->resconstantqual,
- &results);
+ &context);
break;
case T_IndexScan:
finalize_primnode((Node *) ((IndexScan *) plan)->indxqual,
- &results);
+ &context);
/*
* we need not look at indxqualorig, since it will have the
case T_TidScan:
finalize_primnode((Node *) ((TidScan *) plan)->tideval,
- &results);
+ &context);
break;
case T_SubqueryScan:
* subplan's extParams list, which represents the params it
* needs from my level and higher levels.
*/
- results.paramids = set_unioni(results.paramids,
+ context.paramids = bms_add_members(context.paramids,
((SubqueryScan *) plan)->subplan->extParam);
break;
rte = rt_fetch(((FunctionScan *) plan)->scan.scanrelid,
rtable);
Assert(rte->rtekind == RTE_FUNCTION);
- finalize_primnode(rte->funcexpr, &results);
+ finalize_primnode(rte->funcexpr, &context);
}
break;
case T_Append:
foreach(lst, ((Append *) plan)->appendplans)
- results.paramids = set_unioni(results.paramids,
- SS_finalize_plan((Plan *) lfirst(lst),
- rtable));
+ {
+ context.paramids =
+ bms_add_members(context.paramids,
+ finalize_plan((Plan *) lfirst(lst),
+ rtable,
+ outer_params,
+ valid_params));
+ }
break;
case T_NestLoop:
finalize_primnode((Node *) ((Join *) plan)->joinqual,
- &results);
+ &context);
break;
case T_MergeJoin:
finalize_primnode((Node *) ((Join *) plan)->joinqual,
- &results);
+ &context);
finalize_primnode((Node *) ((MergeJoin *) plan)->mergeclauses,
- &results);
+ &context);
break;
case T_HashJoin:
finalize_primnode((Node *) ((Join *) plan)->joinqual,
- &results);
+ &context);
finalize_primnode((Node *) ((HashJoin *) plan)->hashclauses,
- &results);
+ &context);
break;
case T_Hash:
finalize_primnode((Node *) ((Hash *) plan)->hashkeys,
- &results);
+ &context);
break;
case T_Agg:
break;
default:
- elog(ERROR, "SS_finalize_plan: node %d unsupported",
+ elog(ERROR, "finalize_plan: node %d unsupported",
nodeTag(plan));
}
/* Process left and right child plans, if any */
- results.paramids = set_unioni(results.paramids,
- SS_finalize_plan(plan->lefttree,
- rtable));
- results.paramids = set_unioni(results.paramids,
- SS_finalize_plan(plan->righttree,
- rtable));
+ context.paramids = bms_add_members(context.paramids,
+ finalize_plan(plan->lefttree,
+ rtable,
+ outer_params,
+ valid_params));
+
+ context.paramids = bms_add_members(context.paramids,
+ finalize_plan(plan->righttree,
+ rtable,
+ outer_params,
+ valid_params));
/* Now we have all the paramids */
- foreach(lst, results.paramids)
- {
- int paramid = lfirsti(lst);
- Var *var = nth(paramid, PlannerParamVar);
+ if (!bms_is_subset(context.paramids, valid_params))
+ elog(ERROR, "finalize_plan: plan shouldn't reference subplan's variable");
- /* note varlevelsup is absolute level number */
- if (var->varlevelsup < PlannerQueryLevel)
- extParam = lappendi(extParam, paramid);
- else if (var->varlevelsup > PlannerQueryLevel)
- elog(ERROR, "SS_finalize_plan: plan shouldn't reference subplan's variable");
- else
- {
- Assert(var->varno == 0 && var->varattno == 0);
- locParam = lappendi(locParam, paramid);
- }
- }
+ plan->extParam = bms_intersect(context.paramids, outer_params);
+ plan->allParam = context.paramids;
- plan->extParam = extParam;
- plan->locParam = locParam;
+ /*
+ * For speed at execution time, make sure extParam/allParam are actually
+ * NULL if they are empty sets.
+ */
+ if (bms_is_empty(plan->extParam))
+ {
+ bms_free(plan->extParam);
+ plan->extParam = NULL;
+ }
+ if (bms_is_empty(plan->allParam))
+ {
+ bms_free(plan->allParam);
+ plan->allParam = NULL;
+ }
- return results.paramids;
+ return plan->allParam;
}
/*
- * finalize_primnode: build lists of params appearing
- * in the given expression tree. NOTE: items are added to list passed in,
- * so caller must initialize list to NIL before first call!
+ * finalize_primnode: add IDs of all PARAM_EXEC params appearing in the given
+ * expression tree to the result set.
*/
static bool
-finalize_primnode(Node *node, finalize_primnode_results *results)
+finalize_primnode(Node *node, finalize_primnode_context *context)
{
if (node == NULL)
return false;
{
int paramid = (int) ((Param *) node)->paramid;
- if (!intMember(paramid, results->paramids))
- results->paramids = lconsi(paramid, results->paramids);
+ context->paramids = bms_add_member(context->paramids, paramid);
}
return false; /* no more to do here */
}
if (is_subplan(node))
{
SubPlan *subplan = (SubPlan *) node;
- List *lst;
- /* Check extParam list for params to add to paramids */
- foreach(lst, subplan->plan->extParam)
- {
- int paramid = lfirsti(lst);
- Var *var = nth(paramid, PlannerParamVar);
-
- /* note varlevelsup is absolute level number */
- if (var->varlevelsup < PlannerQueryLevel &&
- !intMember(paramid, results->paramids))
- results->paramids = lconsi(paramid, results->paramids);
- }
+ /* Add outer-level params needed by the subplan to paramids */
+ context->paramids = bms_join(context->paramids,
+ bms_intersect(subplan->plan->extParam,
+ context->outer_params));
/* fall through to recurse into subplan args */
}
return expression_tree_walker(node, finalize_primnode,
- (void *) results);
+ (void *) context);
}
* Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
- * $Id: executor.h,v 1.88 2003/02/03 15:07:07 tgl Exp $
+ * $Id: executor.h,v 1.89 2003/02/09 00:30:39 tgl Exp $
*
*-------------------------------------------------------------------------
*/
extern TupleTableSlot *ExecInitNullTupleSlot(EState *estate,
TupleDesc tupType);
extern TupleDesc ExecTypeFromTL(List *targetList, bool hasoid);
-extern void SetChangedParamList(PlanState *node, List *newchg);
+extern void UpdateChangedParamSet(PlanState *node, Bitmapset *newchg);
typedef struct TupOutputState
{
* Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
- * $Id: execnodes.h,v 1.93 2003/02/03 21:15:44 tgl Exp $
+ * $Id: execnodes.h,v 1.94 2003/02/09 00:30:39 tgl Exp $
*
*-------------------------------------------------------------------------
*/
#include "executor/hashjoin.h"
#include "executor/tuptable.h"
#include "fmgr.h"
+#include "nodes/bitmapset.h"
#include "nodes/params.h"
#include "nodes/plannodes.h"
#include "utils/tuplestore.h"
/*
* State for management of parameter-change-driven rescanning
*/
- List *chgParam; /* integer list of IDs of changed Params */
+ Bitmapset *chgParam; /* set of IDs of changed Params */
/*
* Other run-time state needed by most if not all node types.
* Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
- * $Id: plannodes.h,v 1.63 2002/12/12 15:49:40 tgl Exp $
+ * $Id: plannodes.h,v 1.64 2003/02/09 00:30:40 tgl Exp $
*
*-------------------------------------------------------------------------
*/
#define PLANNODES_H
#include "access/sdir.h"
+#include "nodes/bitmapset.h"
#include "nodes/primnodes.h"
/*
* Information for management of parameter-change-driven rescanning
+ *
+ * extParam includes the paramIDs of all external PARAM_EXEC params
+ * affecting this plan node or its children. setParam params from
+ * the node's initPlans are not included, but their extParams are.
+ *
+ * allParam includes all the extParam paramIDs, plus the IDs of local
+ * params that affect the node (i.e., the setParams of its initplans).
+ * These are _all_ the PARAM_EXEC params that affect this node.
*/
- List *extParam; /* indices of _all_ _external_ PARAM_EXEC
- * for this plan in global
- * es_param_exec_vals. Params from
- * setParam from initPlan-s are not
- * included, but their execParam-s are
- * here!!! */
- List *locParam; /* someones from setParam-s */
+ Bitmapset *extParam;
+ Bitmapset *allParam;
/*
* We really need in some TopPlan node to store range table and
* Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
- * $Id: primnodes.h,v 1.78 2003/02/03 21:15:44 tgl Exp $
+ * $Id: primnodes.h,v 1.79 2003/02/09 00:30:40 tgl Exp $
*
*-------------------------------------------------------------------------
*/
* expressions to be evaluated in the outer-query context (currently these
* args are always just Vars, but in principle they could be any expression).
* The values are assigned to the global PARAM_EXEC params indexed by parParam
- * (the parParam and args lists must have the same length). setParam is a
+ * (the parParam and args lists must have the same ordering). setParam is a
* list of the PARAM_EXEC params that are computed by the sub-select, if it
- * is an initplan.
+ * is an initplan; they are listed in order by sub-select output column
+ * position. (parParam and setParam are integer Lists, not Bitmapsets,
+ * because their ordering is significant.)
*/
typedef struct SubPlan
{
/* The combining operators, transformed to executable expressions: */
List *exprs; /* list of OpExpr expression trees */
List *paramIds; /* IDs of Params embedded in the above */
+ /* Note: paramIds has a one-to-one correspondence to the exprs list */
/* The subselect, transformed to a Plan: */
struct Plan *plan; /* subselect plan itself */
int plan_id; /* dummy thing because of we haven't equal
* Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
- * $Id: subselect.h,v 1.17 2003/01/20 18:55:05 tgl Exp $
+ * $Id: subselect.h,v 1.18 2003/02/09 00:30:41 tgl Exp $
*
*-------------------------------------------------------------------------
*/
extern Node *convert_IN_to_join(Query *parse, SubLink *sublink);
extern Node *SS_replace_correlation_vars(Node *expr);
extern Node *SS_process_sublinks(Node *expr, bool isQual);
-extern List *SS_finalize_plan(Plan *plan, List *rtable);
+extern void SS_finalize_plan(Plan *plan, List *rtable);
#endif /* SUBSELECT_H */