Make further use of new bitmapset code: executor's chgParam, extParam,

locParam lists can be converted to bitmapsets to speed updating.  Also,
replace 'locParam' with 'allParam', which contains all the paramIDs
relevant to the node (i.e., the union of extParam and locParam); this
saves a step during SetChangedParamList() without costing anything
elsewhere.
This commit is contained in:
Tom Lane 2003-02-09 00:30:41 +00:00
parent c15a4c2aef
commit 145014f811
17 changed files with 267 additions and 193 deletions

View File

@ -6,7 +6,7 @@
* 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 $
*
*-------------------------------------------------------------------------
*/
@ -55,7 +55,7 @@ ExecReScan(PlanState *node, ExprContext *exprCtxt)
InstrEndLoop(node->instrument);
/* If we have changed parameters, propagate that info */
if (node->chgParam != NIL)
if (node->chgParam != NULL)
{
List *lst;
@ -64,10 +64,10 @@ ExecReScan(PlanState *node, ExprContext *exprCtxt)
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)
@ -75,14 +75,14 @@ ExecReScan(PlanState *node, ExprContext *exprCtxt)
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))
@ -165,10 +165,10 @@ ExecReScan(PlanState *node, ExprContext *exprCtxt)
return;
}
if (node->chgParam != NIL)
if (node->chgParam != NULL)
{
freeList(node->chgParam);
node->chgParam = NIL;
bms_free(node->chgParam);
node->chgParam = NULL;
}
}

View File

@ -12,7 +12,7 @@
*
*
* 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 $
*
*-------------------------------------------------------------------------
*/
@ -282,7 +282,7 @@ ExecProcNode(PlanState *node)
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)
@ -504,10 +504,10 @@ ExecEndNode(PlanState *node)
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))

View File

@ -8,7 +8,7 @@
*
*
* 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 $
*
*-------------------------------------------------------------------------
*/
@ -874,25 +874,28 @@ ExecInsertIndexTuples(TupleTableSlot *slot,
}
}
/*
* UpdateChangedParamSet
* Add changed parameters to a plan node's chgParam set
*/
void
SetChangedParamList(PlanState *node, List *newchg)
UpdateChangedParamSet(PlanState *node, Bitmapset *newchg)
{
List *nl;
Bitmapset *parmset;
foreach(nl, newchg)
{
int paramId = lfirsti(nl);
/* 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);
}
/*

View File

@ -45,7 +45,7 @@
* 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 $
*
*-------------------------------------------------------------------------
*/
@ -1405,7 +1405,7 @@ ExecReScanAgg(AggState *node, ExprContext *exprCtxt)
* 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);
}

View File

@ -8,7 +8,7 @@
*
*
* 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 $
*
*-------------------------------------------------------------------------
*/
@ -361,14 +361,14 @@ ExecReScanAppend(AppendState *node, ExprContext *exprCtxt)
* 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;

View File

@ -7,7 +7,7 @@
* 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 $
*
*-------------------------------------------------------------------------
*/
@ -80,7 +80,7 @@ ExecHashSubPlan(SubPlanState *node,
* 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);
/*
@ -218,22 +218,18 @@ ExecScanSubPlan(SubPlanState *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;
int paramid = lfirsti(lst);
ParamExecData *prm = &(econtext->ecxt_param_exec_vals[paramid]);
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));
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);
@ -686,7 +682,12 @@ ExecInitSubPlan(SubPlanState *node, EState *estate)
/*
* 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)
{
@ -694,16 +695,11 @@ ExecInitSubPlan(SubPlanState *node, EState *estate)
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...
*/
}
/*
@ -884,7 +880,9 @@ ExecSetParamPlan(SubPlanState *node, ExprContext *econtext)
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);
@ -914,9 +912,13 @@ ExecSetParamPlan(SubPlanState *node, ExprContext *econtext)
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));
@ -928,7 +930,9 @@ ExecSetParamPlan(SubPlanState *node, ExprContext *econtext)
{
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);
@ -938,7 +942,8 @@ ExecSetParamPlan(SubPlanState *node, ExprContext *econtext)
{
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;
@ -979,12 +984,12 @@ ExecReScanSetParamPlan(SubPlanState *node, PlanState *parent)
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.
@ -995,10 +1000,10 @@ ExecReScanSetParamPlan(SubPlanState *node, PlanState *parent)
*/
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));
}

View File

@ -12,7 +12,7 @@
*
*
* 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 $
*
*-------------------------------------------------------------------------
*/
@ -261,10 +261,10 @@ ExecSubqueryReScan(SubqueryScanState *node, ExprContext *exprCtxt)
* 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

View File

@ -8,7 +8,7 @@
*
*
* 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 $
*
*-------------------------------------------------------------------------
*/
@ -349,7 +349,7 @@ ExecInitTidScan(TidScan *node, EState *estate)
Oid relid;
Oid reloid;
Relation currentRelation;
List *execParam = NIL;
Bitmapset *execParam = NULL;
/*
* create state structure

View File

@ -15,7 +15,7 @@
* 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 $
*
*-------------------------------------------------------------------------
*/
@ -120,8 +120,8 @@ CopyPlanFields(Plan *from, Plan *newnode)
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);
}

View File

@ -8,7 +8,7 @@
*
*
* 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*
@ -255,8 +255,8 @@ _outPlanInfo(StringInfo str, Plan *node)
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);
}

View File

@ -8,7 +8,7 @@
*
*
* 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 $
*
*-------------------------------------------------------------------------
*/
@ -268,14 +268,14 @@ subquery_planner(Query *parse, double tuple_fraction)
/*
* 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
@ -293,8 +293,8 @@ subquery_planner(Query *parse, double tuple_fraction)
{
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;
}

View File

@ -7,7 +7,7 @@
* 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 $
*
*-------------------------------------------------------------------------
*/
@ -57,10 +57,11 @@ int PlannerPlanId = 0; /* to assign unique ID to subquery plans */
*/
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,
@ -69,7 +70,10 @@ 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);
/*
@ -178,6 +182,8 @@ make_subplan(SubLink *slink, List *lefthand, bool isTopQual)
Query *subquery = (Query *) (slink->subselect);
double tuple_fraction;
Plan *plan;
Bitmapset *tmpset;
int paramid;
List *lst;
Node *result;
@ -246,15 +252,16 @@ make_subplan(SubLink *slink, List *lefthand, bool isTopQual)
* 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
@ -269,7 +276,7 @@ make_subplan(SubLink *slink, List *lefthand, bool isTopQual)
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;
}
@ -280,7 +287,7 @@ make_subplan(SubLink *slink, List *lefthand, bool isTopQual)
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;
}
@ -294,7 +301,7 @@ make_subplan(SubLink *slink, List *lefthand, bool isTopQual)
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
@ -387,8 +394,8 @@ make_subplan(SubLink *slink, List *lefthand, bool isTopQual)
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;
}
}
@ -769,44 +776,94 @@ process_sublinks_mutator(Node *node, bool *isTopQual)
/*
* 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
@ -816,7 +873,7 @@ SS_finalize_plan(Plan *plan, List *rtable)
case T_TidScan:
finalize_primnode((Node *) ((TidScan *) plan)->tideval,
&results);
&context);
break;
case T_SubqueryScan:
@ -828,7 +885,7 @@ SS_finalize_plan(Plan *plan, List *rtable)
* 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;
@ -839,39 +896,44 @@ SS_finalize_plan(Plan *plan, List *rtable)
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:
@ -885,50 +947,55 @@ SS_finalize_plan(Plan *plan, List *rtable)
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;
/*
* 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;
}
plan->extParam = extParam;
plan->locParam = locParam;
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;
@ -938,29 +1005,20 @@ finalize_primnode(Node *node, finalize_primnode_results *results)
{
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);
}

View File

@ -7,7 +7,7 @@
* 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 $
*
*-------------------------------------------------------------------------
*/
@ -160,7 +160,7 @@ extern TupleTableSlot *ExecInitExtraTupleSlot(EState *estate);
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
{

View File

@ -7,7 +7,7 @@
* 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 $
*
*-------------------------------------------------------------------------
*/
@ -18,6 +18,7 @@
#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"
@ -616,7 +617,7 @@ typedef struct PlanState
/*
* 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.

View File

@ -7,7 +7,7 @@
* 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 $
*
*-------------------------------------------------------------------------
*/
@ -15,6 +15,7 @@
#define PLANNODES_H
#include "access/sdir.h"
#include "nodes/bitmapset.h"
#include "nodes/primnodes.h"
@ -65,14 +66,17 @@ typedef struct Plan
/*
* 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

View File

@ -10,7 +10,7 @@
* 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 $
*
*-------------------------------------------------------------------------
*/
@ -435,9 +435,11 @@ typedef struct SubLink
* 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
{
@ -449,6 +451,7 @@ 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

View File

@ -5,7 +5,7 @@
* 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 $
*
*-------------------------------------------------------------------------
*/
@ -22,6 +22,6 @@ extern int PlannerPlanId; /* to assign unique ID to subquery plans */
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 */