56
56
static Node *build_subplan(PlannerInfo *root, Plan *plan,
57
57
List *rtable, List *rowmarks,
58
59
SubLinkType subLinkType, Node *testexpr,
59
60
bool adjust_testexpr, bool unknownEqFalse);
60
61
static List *generate_subquery_params(PlannerInfo *root, List *tlist,
86
* Select a PARAM_EXEC number to identify the given Var.
87
* If the Var already has a param slot, return that one.
87
* Select a PARAM_EXEC number to identify the given Var as a parameter for
88
* the current subquery, or for a nestloop's inner scan.
89
* If the Var already has a param in the current context, return that one.
90
92
assign_param_for_var(PlannerInfo *root, Var *var)
93
95
PlannerParamItem *pitem;
97
abslevel = root->query_level - var->varlevelsup;
99
/* If there's already a paramlist entry for this same Var, just use it */
101
foreach(ppl, root->glob->paramlist)
98
/* Find the query level the Var belongs to */
99
for (levelsup = var->varlevelsup; levelsup > 0; levelsup--)
100
root = root->parent_root;
102
/* If there's already a matching PlannerParamItem there, just use it */
103
foreach(ppl, root->plan_params)
103
105
pitem = (PlannerParamItem *) lfirst(ppl);
104
if (pitem->abslevel == abslevel && IsA(pitem->item, Var))
106
if (IsA(pitem->item, Var))
106
108
Var *pvar = (Var *) pitem->item;
111
* This comparison must match _equalVar(), except for ignoring
112
* varlevelsup. Note that _equalVar() ignores the location.
108
114
if (pvar->varno == var->varno &&
109
115
pvar->varattno == var->varattno &&
110
116
pvar->vartype == var->vartype &&
111
pvar->vartypmod == var->vartypmod)
117
pvar->vartypmod == var->vartypmod &&
118
pvar->varcollid == var->varcollid &&
119
pvar->varnoold == var->varnoold &&
120
pvar->varoattno == var->varoattno)
121
return pitem->paramId;
117
125
/* Nope, so make a new one */
121
129
pitem = makeNode(PlannerParamItem);
122
130
pitem->item = (Node *) var;
123
pitem->abslevel = abslevel;
125
root->glob->paramlist = lappend(root->glob->paramlist, pitem);
127
/* i is already the correct list index for the new item */
131
pitem->paramId = root->glob->nParamExec++;
133
root->plan_params = lappend(root->plan_params, pitem);
135
return pitem->paramId;
141
148
Assert(var->varlevelsup > 0 && var->varlevelsup < root->query_level);
144
* Find the Var in root->glob->paramlist, or add it if not present.
146
* NOTE: in sufficiently complex querytrees, it is possible for the same
147
* varno/abslevel to refer to different RTEs in different parts of the
148
* parsetree, so that different fields might end up sharing the same Param
149
* number. As long as we check the vartype/typmod as well, I believe that
150
* this sort of aliasing will cause no trouble. The correct field should
151
* get stored into the Param slot at execution in each part of the tree.
150
/* Find the Var in the appropriate plan_params, or add it if not present */
153
151
i = assign_param_for_var(root, var);
155
153
retval = makeNode(Param);
167
165
* Generate a Param node to replace the given Var, which will be supplied
168
166
* from an upper NestLoop join node.
170
* Because we allow nestloop and subquery Params to alias each other,
171
* this is effectively the same as replace_outer_var, except that we expect
168
* This is effectively the same as replace_outer_var, except that we expect
172
169
* the Var to be local to the current query level.
187
184
retval->paramtype = var->vartype;
188
185
retval->paramtypmod = var->vartypmod;
189
186
retval->paramcollid = var->varcollid;
190
retval->location = -1;
187
retval->location = var->location;
196
* Select a PARAM_EXEC number to identify the given PlaceHolderVar.
197
* If the PlaceHolderVar already has a param slot, return that one.
193
* Select a PARAM_EXEC number to identify the given PlaceHolderVar as a
194
* parameter for the current subquery, or for a nestloop's inner scan.
195
* If the PHV already has a param in the current context, return that one.
199
197
* This is just like assign_param_for_var, except for PlaceHolderVars.
205
203
PlannerParamItem *pitem;
209
abslevel = root->query_level - phv->phlevelsup;
211
/* If there's already a paramlist entry for this same PHV, just use it */
213
foreach(ppl, root->glob->paramlist)
206
/* Find the query level the PHV belongs to */
207
for (levelsup = phv->phlevelsup; levelsup > 0; levelsup--)
208
root = root->parent_root;
210
/* If there's already a matching PlannerParamItem there, just use it */
211
foreach(ppl, root->plan_params)
215
213
pitem = (PlannerParamItem *) lfirst(ppl);
216
if (pitem->abslevel == abslevel && IsA(pitem->item, PlaceHolderVar))
214
if (IsA(pitem->item, PlaceHolderVar))
218
216
PlaceHolderVar *pphv = (PlaceHolderVar *) pitem->item;
220
218
/* We assume comparing the PHIDs is sufficient */
221
219
if (pphv->phid == phv->phid)
220
return pitem->paramId;
227
224
/* Nope, so make a new one */
235
232
pitem = makeNode(PlannerParamItem);
236
233
pitem->item = (Node *) phv;
237
pitem->abslevel = abslevel;
239
root->glob->paramlist = lappend(root->glob->paramlist, pitem);
241
/* i is already the correct list index for the new item */
234
pitem->paramId = root->glob->nParamExec++;
236
root->plan_params = lappend(root->plan_params, pitem);
238
return pitem->paramId;
257
253
Assert(phv->phlevelsup > 0 && phv->phlevelsup < root->query_level);
260
* Find the PlaceHolderVar in root->glob->paramlist, or add it if not
255
/* Find the PHV in the appropriate plan_params, or add it if not present */
263
256
i = assign_param_for_placeholdervar(root, phv);
265
258
retval = makeNode(Param);
311
304
PlannerParamItem *pitem;
315
307
Assert(agg->agglevelsup > 0 && agg->agglevelsup < root->query_level);
316
abslevel = root->query_level - agg->agglevelsup;
309
/* Find the query level the Aggref belongs to */
310
for (levelsup = agg->agglevelsup; levelsup > 0; levelsup--)
311
root = root->parent_root;
319
314
* It does not seem worthwhile to try to match duplicate outer aggs. Just
326
321
pitem = makeNode(PlannerParamItem);
327
322
pitem->item = (Node *) agg;
328
pitem->abslevel = abslevel;
323
pitem->paramId = root->glob->nParamExec++;
330
root->glob->paramlist = lappend(root->glob->paramlist, pitem);
331
i = list_length(root->glob->paramlist) - 1;
325
root->plan_params = lappend(root->plan_params, pitem);
333
327
retval = makeNode(Param);
334
328
retval->paramkind = PARAM_EXEC;
329
retval->paramid = pitem->paramId;
336
330
retval->paramtype = agg->aggtype;
337
331
retval->paramtypmod = -1;
338
332
retval->paramcollid = agg->aggcollid;
339
retval->location = -1;
333
retval->location = agg->location;
345
339
* Generate a new Param node that will not conflict with any other.
347
* This is used to allocate PARAM_EXEC slots for subplan outputs.
341
* This is used to create Params representing subplan outputs.
342
* We don't need to build a PlannerParamItem for such a Param, but we do
343
* need to record the PARAM_EXEC slot number as being allocated.
350
346
generate_new_param(PlannerInfo *root, Oid paramtype, int32 paramtypmod,
351
347
Oid paramcollation)
354
PlannerParamItem *pitem;
356
351
retval = makeNode(Param);
357
352
retval->paramkind = PARAM_EXEC;
358
retval->paramid = list_length(root->glob->paramlist);
353
retval->paramid = root->glob->nParamExec++;
359
354
retval->paramtype = paramtype;
360
355
retval->paramtypmod = paramtypmod;
361
356
retval->paramcollid = paramcollation;
362
357
retval->location = -1;
364
pitem = makeNode(PlannerParamItem);
365
pitem->item = (Node *) retval;
366
pitem->abslevel = root->query_level;
368
root->glob->paramlist = lappend(root->glob->paramlist, pitem);
375
364
* is not actually used to carry a value at runtime). Such parameters are
376
365
* used for special runtime signaling purposes, such as connecting a
377
366
* recursive union node to its worktable scan node or forcing plan
378
* re-evaluation within the EvalPlanQual mechanism.
367
* re-evaluation within the EvalPlanQual mechanism. No actual Param node
368
* exists with this ID, however.
381
371
SS_assign_special_param(PlannerInfo *root)
385
/* We generate a Param of datatype INTERNAL */
386
param = generate_new_param(root, INTERNALOID, -1, InvalidOid);
387
/* ... but the caller only cares about its ID */
388
return param->paramid;
373
return root->glob->nParamExec++;
497
486
false, tuple_fraction,
489
/* Isolate the params needed by this specific subplan */
490
plan_params = root->plan_params;
491
root->plan_params = NIL;
500
493
/* And convert to SubPlan or InitPlan format. */
501
494
result = build_subplan(root, plan,
502
495
subroot->parse->rtable, subroot->rowMarks,
503
497
subLinkType, testexpr, true, isTopQual);
572
571
build_subplan(PlannerInfo *root, Plan *plan, List *rtable, List *rowmarks,
573
573
SubLinkType subLinkType, Node *testexpr,
574
574
bool adjust_testexpr, bool unknownEqFalse)
583
582
* Initialize the SubPlan node. Note plan_id, plan_name, and cost fields
599
598
* Make parParam and args lists of param IDs and expressions that current
600
599
* query level will pass to this child plan.
602
tmpset = bms_copy(plan->extParam);
603
while ((paramid = bms_first_member(tmpset)) >= 0)
601
foreach(lc, plan_params)
605
PlannerParamItem *pitem = list_nth(root->glob->paramlist, paramid);
607
if (pitem->abslevel == root->query_level)
612
* The Var, PlaceHolderVar, or Aggref has already been adjusted to
613
* have the correct varlevelsup, phlevelsup, or agglevelsup. We
614
* probably don't even need to copy it again, but be safe.
616
arg = copyObject(pitem->item);
619
* If it's a PlaceHolderVar or Aggref, its arguments might contain
620
* SubLinks, which have not yet been processed (see the comments
621
* for SS_replace_correlation_vars). Do that now.
623
if (IsA(arg, PlaceHolderVar) ||
625
arg = SS_process_sublinks(root, arg, false);
627
splan->parParam = lappend_int(splan->parParam, paramid);
628
splan->args = lappend(splan->args, arg);
603
PlannerParamItem *pitem = (PlannerParamItem *) lfirst(lc);
604
Node *arg = pitem->item;
607
* The Var, PlaceHolderVar, or Aggref has already been adjusted to
608
* have the correct varlevelsup, phlevelsup, or agglevelsup.
610
* If it's a PlaceHolderVar or Aggref, its arguments might contain
611
* SubLinks, which have not yet been processed (see the comments for
612
* SS_replace_correlation_vars). Do that now.
614
if (IsA(arg, PlaceHolderVar) ||
616
arg = SS_process_sublinks(root, arg, false);
618
splan->parParam = lappend_int(splan->parParam, pitem->paramId);
619
splan->args = lappend(splan->args, arg);
634
623
* Un-correlated or undirect correlated plans of EXISTS, EXPR, ARRAY, or
1071
1058
subquery = (Query *) copyObject(cte->ctequery);
1060
/* plan_params should not be in use in current query level */
1061
Assert(root->plan_params == NIL);
1074
1064
* Generate the plan for the CTE query. Always plan for full
1075
1065
* retrieval --- we don't have enough info to predict otherwise.
1073
* Since the current query level doesn't yet contain any RTEs, it
1074
* should not be possible for the CTE to have requested parameters of
1077
if (root->plan_params)
1078
elog(ERROR, "unexpected outer reference in CTE query");
1083
1081
* Make a SubPlan node for it. This is just enough unlike
1084
1082
* build_subplan that we can't share code.
1098
1096
splan->args = NIL;
1101
* Make parParam and args lists of param IDs and expressions that
1102
* current query level will pass to this child plan. Even though this
1103
* is an initplan, there could be side-references to earlier
1104
* initplan's outputs, specifically their CTE output parameters.
1099
* The node can't have any inputs (since it's an initplan), so the
1100
* parParam and args lists remain empty. (It could contain references
1101
* to earlier CTEs' output param IDs, but CTE outputs are not
1102
* propagated via the args list.)
1106
tmpset = bms_copy(plan->extParam);
1107
while ((paramid = bms_first_member(tmpset)) >= 0)
1109
PlannerParamItem *pitem = list_nth(root->glob->paramlist, paramid);
1111
if (pitem->abslevel == root->query_level)
1113
prm = (Param *) pitem->item;
1114
if (!IsA(prm, Param) ||
1115
prm->paramtype != INTERNALOID)
1116
elog(ERROR, "bogus local parameter passed to WITH query");
1118
splan->parParam = lappend_int(splan->parParam, paramid);
1119
splan->args = lappend(splan->args, copyObject(prm));
1125
* Assign a param to represent the query output. We only really care
1126
* about reserving a parameter ID number.
1106
* Assign a param ID to represent the CTE's output. No ordinary
1107
* "evaluation" of this param slot ever happens, but we use the param
1108
* ID for setParam/chgParam signaling just as if the CTE plan were
1109
* returning a simple scalar output. (Also, the executor abuses the
1110
* ParamExecData slot for this param ID for communication among
1111
* multiple CteScan nodes that might be scanning this CTE.)
1128
prm = generate_new_param(root, INTERNALOID, -1, InvalidOid);
1129
splan->setParam = list_make1_int(prm->paramid);
1113
paramid = SS_assign_special_param(root);
1114
splan->setParam = list_make1_int(paramid);
1132
1117
* Add the subplan and its rtable to the global lists.
1973
1958
* Now determine the set of params that are validly referenceable in this
1974
1959
* query level; to wit, those available from outer query levels plus the
1975
* output parameters of any initPlans. (We do not include output
1960
* output parameters of any local initPlans. (We do not include output
1976
1961
* parameters of regular subplans. Those should only appear within the
1977
1962
* testexpr of SubPlan nodes, and are taken care of locally within
1978
1963
* finalize_primnode. Likewise, special parameters that are generated by
1979
1964
* nodes such as ModifyTable are handled within finalize_plan.)
1981
* Note: this is a bit overly generous since some parameters of upper
1982
* query levels might belong to query subtrees that don't include this
1983
* query, or might be nestloop params that won't be passed down at all.
1984
* However, valid_params is only a debugging crosscheck, so it doesn't
1985
* seem worth expending lots of cycles to try to be exact.
1987
1966
valid_params = bms_copy(initSetParam);
1989
foreach(l, root->glob->paramlist)
1967
for (proot = root->parent_root; proot != NULL; proot = proot->parent_root)
1991
PlannerParamItem *pitem = (PlannerParamItem *) lfirst(l);
1993
if (pitem->abslevel < root->query_level)
1995
/* valid outer-level parameter */
1996
valid_params = bms_add_member(valid_params, paramid);
1969
/* Include ordinary Var/PHV/Aggref params */
1970
foreach(l, proot->plan_params)
1972
PlannerParamItem *pitem = (PlannerParamItem *) lfirst(l);
1974
valid_params = bms_add_member(valid_params, pitem->paramId);
1976
/* Include any outputs of outer-level initPlans */
1977
foreach(l, proot->init_plans)
1979
SubPlan *initsubplan = (SubPlan *) lfirst(l);
1982
foreach(l2, initsubplan->setParam)
1984
valid_params = bms_add_member(valid_params, lfirst_int(l2));
1987
/* Include worktable ID, if a recursive query is being planned */
1988
if (proot->wt_param_id >= 0)
1989
valid_params = bms_add_member(valid_params, proot->wt_param_id);