Line data Source code
1 : /*-------------------------------------------------------------------------
2 : *
3 : * subselect.c
4 : * Planning routines for subselects and parameters.
5 : *
6 : * Portions Copyright (c) 1996-2017, PostgreSQL Global Development Group
7 : * Portions Copyright (c) 1994, Regents of the University of California
8 : *
9 : * IDENTIFICATION
10 : * src/backend/optimizer/plan/subselect.c
11 : *
12 : *-------------------------------------------------------------------------
13 : */
14 : #include "postgres.h"
15 :
16 : #include "access/htup_details.h"
17 : #include "catalog/pg_operator.h"
18 : #include "catalog/pg_type.h"
19 : #include "executor/executor.h"
20 : #include "miscadmin.h"
21 : #include "nodes/makefuncs.h"
22 : #include "nodes/nodeFuncs.h"
23 : #include "optimizer/clauses.h"
24 : #include "optimizer/cost.h"
25 : #include "optimizer/pathnode.h"
26 : #include "optimizer/planmain.h"
27 : #include "optimizer/planner.h"
28 : #include "optimizer/prep.h"
29 : #include "optimizer/subselect.h"
30 : #include "optimizer/var.h"
31 : #include "parser/parse_relation.h"
32 : #include "rewrite/rewriteManip.h"
33 : #include "utils/builtins.h"
34 : #include "utils/lsyscache.h"
35 : #include "utils/syscache.h"
36 :
37 :
38 : typedef struct convert_testexpr_context
39 : {
40 : PlannerInfo *root;
41 : List *subst_nodes; /* Nodes to substitute for Params */
42 : } convert_testexpr_context;
43 :
44 : typedef struct process_sublinks_context
45 : {
46 : PlannerInfo *root;
47 : bool isTopQual;
48 : } process_sublinks_context;
49 :
50 : typedef struct finalize_primnode_context
51 : {
52 : PlannerInfo *root;
53 : Bitmapset *paramids; /* Non-local PARAM_EXEC paramids found */
54 : } finalize_primnode_context;
55 :
56 :
57 : static Node *build_subplan(PlannerInfo *root, Plan *plan, PlannerInfo *subroot,
58 : List *plan_params,
59 : SubLinkType subLinkType, int subLinkId,
60 : Node *testexpr, bool adjust_testexpr,
61 : bool unknownEqFalse);
62 : static List *generate_subquery_params(PlannerInfo *root, List *tlist,
63 : List **paramIds);
64 : static List *generate_subquery_vars(PlannerInfo *root, List *tlist,
65 : Index varno);
66 : static Node *convert_testexpr(PlannerInfo *root,
67 : Node *testexpr,
68 : List *subst_nodes);
69 : static Node *convert_testexpr_mutator(Node *node,
70 : convert_testexpr_context *context);
71 : static bool subplan_is_hashable(Plan *plan);
72 : static bool testexpr_is_hashable(Node *testexpr);
73 : static bool hash_ok_operator(OpExpr *expr);
74 : static bool simplify_EXISTS_query(PlannerInfo *root, Query *query);
75 : static Query *convert_EXISTS_to_ANY(PlannerInfo *root, Query *subselect,
76 : Node **testexpr, List **paramIds);
77 : static Node *replace_correlation_vars_mutator(Node *node, PlannerInfo *root);
78 : static Node *process_sublinks_mutator(Node *node,
79 : process_sublinks_context *context);
80 : static Bitmapset *finalize_plan(PlannerInfo *root,
81 : Plan *plan,
82 : int gather_param,
83 : Bitmapset *valid_params,
84 : Bitmapset *scan_params);
85 : static bool finalize_primnode(Node *node, finalize_primnode_context *context);
86 : static bool finalize_agg_primnode(Node *node, finalize_primnode_context *context);
87 :
88 :
89 : /*
90 : * Select a PARAM_EXEC number to identify the given Var as a parameter for
91 : * the current subquery, or for a nestloop's inner scan.
92 : * If the Var already has a param in the current context, return that one.
93 : */
94 : static int
95 4544 : assign_param_for_var(PlannerInfo *root, Var *var)
96 : {
97 : ListCell *ppl;
98 : PlannerParamItem *pitem;
99 : Index levelsup;
100 :
101 : /* Find the query level the Var belongs to */
102 7084 : for (levelsup = var->varlevelsup; levelsup > 0; levelsup--)
103 2540 : root = root->parent_root;
104 :
105 : /* If there's already a matching PlannerParamItem there, just use it */
106 7018 : foreach(ppl, root->plan_params)
107 : {
108 3764 : pitem = (PlannerParamItem *) lfirst(ppl);
109 3764 : if (IsA(pitem->item, Var))
110 : {
111 3760 : Var *pvar = (Var *) pitem->item;
112 :
113 : /*
114 : * This comparison must match _equalVar(), except for ignoring
115 : * varlevelsup. Note that _equalVar() ignores the location.
116 : */
117 6393 : if (pvar->varno == var->varno &&
118 3923 : pvar->varattno == var->varattno &&
119 2580 : pvar->vartype == var->vartype &&
120 2580 : pvar->vartypmod == var->vartypmod &&
121 2580 : pvar->varcollid == var->varcollid &&
122 2580 : pvar->varnoold == var->varnoold &&
123 1290 : pvar->varoattno == var->varoattno)
124 1290 : return pitem->paramId;
125 : }
126 : }
127 :
128 : /* Nope, so make a new one */
129 3254 : var = copyObject(var);
130 3254 : var->varlevelsup = 0;
131 :
132 3254 : pitem = makeNode(PlannerParamItem);
133 3254 : pitem->item = (Node *) var;
134 3254 : pitem->paramId = root->glob->nParamExec++;
135 :
136 3254 : root->plan_params = lappend(root->plan_params, pitem);
137 :
138 3254 : return pitem->paramId;
139 : }
140 :
141 : /*
142 : * Generate a Param node to replace the given Var,
143 : * which is expected to have varlevelsup > 0 (ie, it is not local).
144 : */
145 : static Param *
146 2509 : replace_outer_var(PlannerInfo *root, Var *var)
147 : {
148 : Param *retval;
149 : int i;
150 :
151 2509 : Assert(var->varlevelsup > 0 && var->varlevelsup < root->query_level);
152 :
153 : /* Find the Var in the appropriate plan_params, or add it if not present */
154 2509 : i = assign_param_for_var(root, var);
155 :
156 2509 : retval = makeNode(Param);
157 2509 : retval->paramkind = PARAM_EXEC;
158 2509 : retval->paramid = i;
159 2509 : retval->paramtype = var->vartype;
160 2509 : retval->paramtypmod = var->vartypmod;
161 2509 : retval->paramcollid = var->varcollid;
162 2509 : retval->location = var->location;
163 :
164 2509 : return retval;
165 : }
166 :
167 : /*
168 : * Generate a Param node to replace the given Var, which will be supplied
169 : * from an upper NestLoop join node.
170 : *
171 : * This is effectively the same as replace_outer_var, except that we expect
172 : * the Var to be local to the current query level.
173 : */
174 : Param *
175 2035 : assign_nestloop_param_var(PlannerInfo *root, Var *var)
176 : {
177 : Param *retval;
178 : int i;
179 :
180 2035 : Assert(var->varlevelsup == 0);
181 :
182 2035 : i = assign_param_for_var(root, var);
183 :
184 2035 : retval = makeNode(Param);
185 2035 : retval->paramkind = PARAM_EXEC;
186 2035 : retval->paramid = i;
187 2035 : retval->paramtype = var->vartype;
188 2035 : retval->paramtypmod = var->vartypmod;
189 2035 : retval->paramcollid = var->varcollid;
190 2035 : retval->location = var->location;
191 :
192 2035 : return retval;
193 : }
194 :
195 : /*
196 : * Select a PARAM_EXEC number to identify the given PlaceHolderVar as a
197 : * parameter for the current subquery, or for a nestloop's inner scan.
198 : * If the PHV already has a param in the current context, return that one.
199 : *
200 : * This is just like assign_param_for_var, except for PlaceHolderVars.
201 : */
202 : static int
203 24 : assign_param_for_placeholdervar(PlannerInfo *root, PlaceHolderVar *phv)
204 : {
205 : ListCell *ppl;
206 : PlannerParamItem *pitem;
207 : Index levelsup;
208 :
209 : /* Find the query level the PHV belongs to */
210 31 : for (levelsup = phv->phlevelsup; levelsup > 0; levelsup--)
211 7 : root = root->parent_root;
212 :
213 : /* If there's already a matching PlannerParamItem there, just use it */
214 43 : foreach(ppl, root->plan_params)
215 : {
216 26 : pitem = (PlannerParamItem *) lfirst(ppl);
217 26 : if (IsA(pitem->item, PlaceHolderVar))
218 : {
219 11 : PlaceHolderVar *pphv = (PlaceHolderVar *) pitem->item;
220 :
221 : /* We assume comparing the PHIDs is sufficient */
222 11 : if (pphv->phid == phv->phid)
223 7 : return pitem->paramId;
224 : }
225 : }
226 :
227 : /* Nope, so make a new one */
228 17 : phv = copyObject(phv);
229 17 : if (phv->phlevelsup != 0)
230 : {
231 7 : IncrementVarSublevelsUp((Node *) phv, -((int) phv->phlevelsup), 0);
232 7 : Assert(phv->phlevelsup == 0);
233 : }
234 :
235 17 : pitem = makeNode(PlannerParamItem);
236 17 : pitem->item = (Node *) phv;
237 17 : pitem->paramId = root->glob->nParamExec++;
238 :
239 17 : root->plan_params = lappend(root->plan_params, pitem);
240 :
241 17 : return pitem->paramId;
242 : }
243 :
244 : /*
245 : * Generate a Param node to replace the given PlaceHolderVar,
246 : * which is expected to have phlevelsup > 0 (ie, it is not local).
247 : *
248 : * This is just like replace_outer_var, except for PlaceHolderVars.
249 : */
250 : static Param *
251 7 : replace_outer_placeholdervar(PlannerInfo *root, PlaceHolderVar *phv)
252 : {
253 : Param *retval;
254 : int i;
255 :
256 7 : Assert(phv->phlevelsup > 0 && phv->phlevelsup < root->query_level);
257 :
258 : /* Find the PHV in the appropriate plan_params, or add it if not present */
259 7 : i = assign_param_for_placeholdervar(root, phv);
260 :
261 7 : retval = makeNode(Param);
262 7 : retval->paramkind = PARAM_EXEC;
263 7 : retval->paramid = i;
264 7 : retval->paramtype = exprType((Node *) phv->phexpr);
265 7 : retval->paramtypmod = exprTypmod((Node *) phv->phexpr);
266 7 : retval->paramcollid = exprCollation((Node *) phv->phexpr);
267 7 : retval->location = -1;
268 :
269 7 : return retval;
270 : }
271 :
272 : /*
273 : * Generate a Param node to replace the given PlaceHolderVar, which will be
274 : * supplied from an upper NestLoop join node.
275 : *
276 : * This is just like assign_nestloop_param_var, except for PlaceHolderVars.
277 : */
278 : Param *
279 17 : assign_nestloop_param_placeholdervar(PlannerInfo *root, PlaceHolderVar *phv)
280 : {
281 : Param *retval;
282 : int i;
283 :
284 17 : Assert(phv->phlevelsup == 0);
285 :
286 17 : i = assign_param_for_placeholdervar(root, phv);
287 :
288 17 : retval = makeNode(Param);
289 17 : retval->paramkind = PARAM_EXEC;
290 17 : retval->paramid = i;
291 17 : retval->paramtype = exprType((Node *) phv->phexpr);
292 17 : retval->paramtypmod = exprTypmod((Node *) phv->phexpr);
293 17 : retval->paramcollid = exprCollation((Node *) phv->phexpr);
294 17 : retval->location = -1;
295 :
296 17 : return retval;
297 : }
298 :
299 : /*
300 : * Generate a Param node to replace the given Aggref
301 : * which is expected to have agglevelsup > 0 (ie, it is not local).
302 : */
303 : static Param *
304 6 : replace_outer_agg(PlannerInfo *root, Aggref *agg)
305 : {
306 : Param *retval;
307 : PlannerParamItem *pitem;
308 : Index levelsup;
309 :
310 6 : Assert(agg->agglevelsup > 0 && agg->agglevelsup < root->query_level);
311 :
312 : /* Find the query level the Aggref belongs to */
313 12 : for (levelsup = agg->agglevelsup; levelsup > 0; levelsup--)
314 6 : root = root->parent_root;
315 :
316 : /*
317 : * It does not seem worthwhile to try to match duplicate outer aggs. Just
318 : * make a new slot every time.
319 : */
320 6 : agg = copyObject(agg);
321 6 : IncrementVarSublevelsUp((Node *) agg, -((int) agg->agglevelsup), 0);
322 6 : Assert(agg->agglevelsup == 0);
323 :
324 6 : pitem = makeNode(PlannerParamItem);
325 6 : pitem->item = (Node *) agg;
326 6 : pitem->paramId = root->glob->nParamExec++;
327 :
328 6 : root->plan_params = lappend(root->plan_params, pitem);
329 :
330 6 : retval = makeNode(Param);
331 6 : retval->paramkind = PARAM_EXEC;
332 6 : retval->paramid = pitem->paramId;
333 6 : retval->paramtype = agg->aggtype;
334 6 : retval->paramtypmod = -1;
335 6 : retval->paramcollid = agg->aggcollid;
336 6 : retval->location = agg->location;
337 :
338 6 : return retval;
339 : }
340 :
341 : /*
342 : * Generate a Param node to replace the given GroupingFunc expression which is
343 : * expected to have agglevelsup > 0 (ie, it is not local).
344 : */
345 : static Param *
346 4 : replace_outer_grouping(PlannerInfo *root, GroupingFunc *grp)
347 : {
348 : Param *retval;
349 : PlannerParamItem *pitem;
350 : Index levelsup;
351 :
352 4 : Assert(grp->agglevelsup > 0 && grp->agglevelsup < root->query_level);
353 :
354 : /* Find the query level the GroupingFunc belongs to */
355 9 : for (levelsup = grp->agglevelsup; levelsup > 0; levelsup--)
356 5 : root = root->parent_root;
357 :
358 : /*
359 : * It does not seem worthwhile to try to match duplicate outer aggs. Just
360 : * make a new slot every time.
361 : */
362 4 : grp = copyObject(grp);
363 4 : IncrementVarSublevelsUp((Node *) grp, -((int) grp->agglevelsup), 0);
364 4 : Assert(grp->agglevelsup == 0);
365 :
366 4 : pitem = makeNode(PlannerParamItem);
367 4 : pitem->item = (Node *) grp;
368 4 : pitem->paramId = root->glob->nParamExec++;
369 :
370 4 : root->plan_params = lappend(root->plan_params, pitem);
371 :
372 4 : retval = makeNode(Param);
373 4 : retval->paramkind = PARAM_EXEC;
374 4 : retval->paramid = pitem->paramId;
375 4 : retval->paramtype = exprType((Node *) grp);
376 4 : retval->paramtypmod = -1;
377 4 : retval->paramcollid = InvalidOid;
378 4 : retval->location = grp->location;
379 :
380 4 : return retval;
381 : }
382 :
383 : /*
384 : * Generate a new Param node that will not conflict with any other.
385 : *
386 : * This is used to create Params representing subplan outputs.
387 : * We don't need to build a PlannerParamItem for such a Param, but we do
388 : * need to record the PARAM_EXEC slot number as being allocated.
389 : */
390 : static Param *
391 622 : generate_new_param(PlannerInfo *root, Oid paramtype, int32 paramtypmod,
392 : Oid paramcollation)
393 : {
394 : Param *retval;
395 :
396 622 : retval = makeNode(Param);
397 622 : retval->paramkind = PARAM_EXEC;
398 622 : retval->paramid = root->glob->nParamExec++;
399 622 : retval->paramtype = paramtype;
400 622 : retval->paramtypmod = paramtypmod;
401 622 : retval->paramcollid = paramcollation;
402 622 : retval->location = -1;
403 :
404 622 : return retval;
405 : }
406 :
407 : /*
408 : * Assign a (nonnegative) PARAM_EXEC ID for a special parameter (one that
409 : * is not actually used to carry a value at runtime). Such parameters are
410 : * used for special runtime signaling purposes, such as connecting a
411 : * recursive union node to its worktable scan node or forcing plan
412 : * re-evaluation within the EvalPlanQual mechanism. No actual Param node
413 : * exists with this ID, however.
414 : */
415 : int
416 4880 : SS_assign_special_param(PlannerInfo *root)
417 : {
418 4880 : return root->glob->nParamExec++;
419 : }
420 :
421 : /*
422 : * Get the datatype/typmod/collation of the first column of the plan's output.
423 : *
424 : * This information is stored for ARRAY_SUBLINK execution and for
425 : * exprType()/exprTypmod()/exprCollation(), which have no way to get at the
426 : * plan associated with a SubPlan node. We really only need the info for
427 : * EXPR_SUBLINK and ARRAY_SUBLINK subplans, but for consistency we save it
428 : * always.
429 : */
430 : static void
431 1927 : get_first_col_type(Plan *plan, Oid *coltype, int32 *coltypmod,
432 : Oid *colcollation)
433 : {
434 : /* In cases such as EXISTS, tlist might be empty; arbitrarily use VOID */
435 1927 : if (plan->targetlist)
436 : {
437 1772 : TargetEntry *tent = linitial_node(TargetEntry, plan->targetlist);
438 :
439 1772 : if (!tent->resjunk)
440 : {
441 1772 : *coltype = exprType((Node *) tent->expr);
442 1772 : *coltypmod = exprTypmod((Node *) tent->expr);
443 1772 : *colcollation = exprCollation((Node *) tent->expr);
444 3699 : return;
445 : }
446 : }
447 155 : *coltype = VOIDOID;
448 155 : *coltypmod = -1;
449 155 : *colcollation = InvalidOid;
450 : }
451 :
452 : /*
453 : * Convert a SubLink (as created by the parser) into a SubPlan.
454 : *
455 : * We are given the SubLink's contained query, type, ID, and testexpr. We are
456 : * also told if this expression appears at top level of a WHERE/HAVING qual.
457 : *
458 : * Note: we assume that the testexpr has been AND/OR flattened (actually,
459 : * it's been through eval_const_expressions), but not converted to
460 : * implicit-AND form; and any SubLinks in it should already have been
461 : * converted to SubPlans. The subquery is as yet untouched, however.
462 : *
463 : * The result is whatever we need to substitute in place of the SubLink node
464 : * in the executable expression. If we're going to do the subplan as a
465 : * regular subplan, this will be the constructed SubPlan node. If we're going
466 : * to do the subplan as an InitPlan, the SubPlan node instead goes into
467 : * root->init_plans, and what we return here is an expression tree
468 : * representing the InitPlan's result: usually just a Param node representing
469 : * a single scalar result, but possibly a row comparison tree containing
470 : * multiple Param nodes, or for a MULTIEXPR subquery a simple NULL constant
471 : * (since the real output Params are elsewhere in the tree, and the MULTIEXPR
472 : * subquery itself is in a resjunk tlist entry whose value is uninteresting).
473 : */
474 : static Node *
475 1627 : make_subplan(PlannerInfo *root, Query *orig_subquery,
476 : SubLinkType subLinkType, int subLinkId,
477 : Node *testexpr, bool isTopQual)
478 : {
479 : Query *subquery;
480 1627 : bool simple_exists = false;
481 : double tuple_fraction;
482 : PlannerInfo *subroot;
483 : RelOptInfo *final_rel;
484 : Path *best_path;
485 : Plan *plan;
486 : List *plan_params;
487 : Node *result;
488 :
489 : /*
490 : * Copy the source Query node. This is a quick and dirty kluge to resolve
491 : * the fact that the parser can generate trees with multiple links to the
492 : * same sub-Query node, but the planner wants to scribble on the Query.
493 : * Try to clean this up when we do querytree redesign...
494 : */
495 1627 : subquery = copyObject(orig_subquery);
496 :
497 : /*
498 : * If it's an EXISTS subplan, we might be able to simplify it.
499 : */
500 1627 : if (subLinkType == EXISTS_SUBLINK)
501 123 : simple_exists = simplify_EXISTS_query(root, subquery);
502 :
503 : /*
504 : * For an EXISTS subplan, tell lower-level planner to expect that only the
505 : * first tuple will be retrieved. For ALL and ANY subplans, we will be
506 : * able to stop evaluating if the test condition fails or matches, so very
507 : * often not all the tuples will be retrieved; for lack of a better idea,
508 : * specify 50% retrieval. For EXPR, MULTIEXPR, and ROWCOMPARE subplans,
509 : * use default behavior (we're only expecting one row out, anyway).
510 : *
511 : * NOTE: if you change these numbers, also change cost_subplan() in
512 : * path/costsize.c.
513 : *
514 : * XXX If an ANY subplan is uncorrelated, build_subplan may decide to hash
515 : * its output. In that case it would've been better to specify full
516 : * retrieval. At present, however, we can only check hashability after
517 : * we've made the subplan :-(. (Determining whether it'll fit in work_mem
518 : * is the really hard part.) Therefore, we don't want to be too
519 : * optimistic about the percentage of tuples retrieved, for fear of
520 : * selecting a plan that's bad for the materialization case.
521 : */
522 1627 : if (subLinkType == EXISTS_SUBLINK)
523 123 : tuple_fraction = 1.0; /* just like a LIMIT 1 */
524 1504 : else if (subLinkType == ALL_SUBLINK ||
525 : subLinkType == ANY_SUBLINK)
526 41 : tuple_fraction = 0.5; /* 50% */
527 : else
528 1463 : tuple_fraction = 0.0; /* default behavior */
529 :
530 : /* plan_params should not be in use in current query level */
531 1627 : Assert(root->plan_params == NIL);
532 :
533 : /* Generate Paths for the subquery */
534 1627 : subroot = subquery_planner(root->glob, subquery,
535 : root,
536 : false, tuple_fraction);
537 :
538 : /* Isolate the params needed by this specific subplan */
539 1627 : plan_params = root->plan_params;
540 1627 : root->plan_params = NIL;
541 :
542 : /*
543 : * Select best Path and turn it into a Plan. At least for now, there
544 : * seems no reason to postpone doing that.
545 : */
546 1627 : final_rel = fetch_upper_rel(subroot, UPPERREL_FINAL, NULL);
547 1627 : best_path = get_cheapest_fractional_path(final_rel, tuple_fraction);
548 :
549 1627 : plan = create_plan(subroot, best_path);
550 :
551 : /* And convert to SubPlan or InitPlan format. */
552 1627 : result = build_subplan(root, plan, subroot, plan_params,
553 : subLinkType, subLinkId,
554 : testexpr, true, isTopQual);
555 :
556 : /*
557 : * If it's a correlated EXISTS with an unimportant targetlist, we might be
558 : * able to transform it to the equivalent of an IN and then implement it
559 : * by hashing. We don't have enough information yet to tell which way is
560 : * likely to be better (it depends on the expected number of executions of
561 : * the EXISTS qual, and we are much too early in planning the outer query
562 : * to be able to guess that). So we generate both plans, if possible, and
563 : * leave it to the executor to decide which to use.
564 : */
565 1627 : if (simple_exists && IsA(result, SubPlan))
566 : {
567 : Node *newtestexpr;
568 : List *paramIds;
569 :
570 : /* Make a second copy of the original subquery */
571 84 : subquery = copyObject(orig_subquery);
572 : /* and re-simplify */
573 84 : simple_exists = simplify_EXISTS_query(root, subquery);
574 84 : Assert(simple_exists);
575 : /* See if it can be converted to an ANY query */
576 84 : subquery = convert_EXISTS_to_ANY(root, subquery,
577 : &newtestexpr, ¶mIds);
578 84 : if (subquery)
579 : {
580 : /* Generate Paths for the ANY subquery; we'll need all rows */
581 84 : subroot = subquery_planner(root->glob, subquery,
582 : root,
583 : false, 0.0);
584 :
585 : /* Isolate the params needed by this specific subplan */
586 84 : plan_params = root->plan_params;
587 84 : root->plan_params = NIL;
588 :
589 : /* Select best Path and turn it into a Plan */
590 84 : final_rel = fetch_upper_rel(subroot, UPPERREL_FINAL, NULL);
591 84 : best_path = final_rel->cheapest_total_path;
592 :
593 84 : plan = create_plan(subroot, best_path);
594 :
595 : /* Now we can check if it'll fit in work_mem */
596 : /* XXX can we check this at the Path stage? */
597 84 : if (subplan_is_hashable(plan))
598 : {
599 : SubPlan *hashplan;
600 : AlternativeSubPlan *asplan;
601 :
602 : /* OK, convert to SubPlan format. */
603 84 : hashplan = castNode(SubPlan,
604 : build_subplan(root, plan, subroot,
605 : plan_params,
606 : ANY_SUBLINK, 0,
607 : newtestexpr,
608 : false, true));
609 : /* Check we got what we expected */
610 84 : Assert(hashplan->parParam == NIL);
611 84 : Assert(hashplan->useHashTable);
612 : /* build_subplan won't have filled in paramIds */
613 84 : hashplan->paramIds = paramIds;
614 :
615 : /* Leave it to the executor to decide which plan to use */
616 84 : asplan = makeNode(AlternativeSubPlan);
617 84 : asplan->subplans = list_make2(result, hashplan);
618 84 : result = (Node *) asplan;
619 : }
620 : }
621 : }
622 :
623 1627 : return result;
624 : }
625 :
626 : /*
627 : * Build a SubPlan node given the raw inputs --- subroutine for make_subplan
628 : *
629 : * Returns either the SubPlan, or a replacement expression if we decide to
630 : * make it an InitPlan, as explained in the comments for make_subplan.
631 : */
632 : static Node *
633 1711 : build_subplan(PlannerInfo *root, Plan *plan, PlannerInfo *subroot,
634 : List *plan_params,
635 : SubLinkType subLinkType, int subLinkId,
636 : Node *testexpr, bool adjust_testexpr,
637 : bool unknownEqFalse)
638 : {
639 : Node *result;
640 : SubPlan *splan;
641 : bool isInitPlan;
642 : ListCell *lc;
643 :
644 : /*
645 : * Initialize the SubPlan node. Note plan_id, plan_name, and cost fields
646 : * are set further down.
647 : */
648 1711 : splan = makeNode(SubPlan);
649 1711 : splan->subLinkType = subLinkType;
650 1711 : splan->testexpr = NULL;
651 1711 : splan->paramIds = NIL;
652 1711 : get_first_col_type(plan, &splan->firstColType, &splan->firstColTypmod,
653 : &splan->firstColCollation);
654 1711 : splan->useHashTable = false;
655 1711 : splan->unknownEqFalse = unknownEqFalse;
656 1711 : splan->parallel_safe = plan->parallel_safe;
657 1711 : splan->setParam = NIL;
658 1711 : splan->parParam = NIL;
659 1711 : splan->args = NIL;
660 :
661 : /*
662 : * Make parParam and args lists of param IDs and expressions that current
663 : * query level will pass to this child plan.
664 : */
665 3904 : foreach(lc, plan_params)
666 : {
667 2193 : PlannerParamItem *pitem = (PlannerParamItem *) lfirst(lc);
668 2193 : Node *arg = pitem->item;
669 :
670 : /*
671 : * The Var, PlaceHolderVar, or Aggref has already been adjusted to
672 : * have the correct varlevelsup, phlevelsup, or agglevelsup.
673 : *
674 : * If it's a PlaceHolderVar or Aggref, its arguments might contain
675 : * SubLinks, which have not yet been processed (see the comments for
676 : * SS_replace_correlation_vars). Do that now.
677 : */
678 4384 : if (IsA(arg, PlaceHolderVar) ||
679 2191 : IsA(arg, Aggref))
680 8 : arg = SS_process_sublinks(root, arg, false);
681 :
682 2193 : splan->parParam = lappend_int(splan->parParam, pitem->paramId);
683 2193 : splan->args = lappend(splan->args, arg);
684 : }
685 :
686 : /*
687 : * Un-correlated or undirect correlated plans of EXISTS, EXPR, ARRAY,
688 : * ROWCOMPARE, or MULTIEXPR types can be used as initPlans. For EXISTS,
689 : * EXPR, or ARRAY, we return a Param referring to the result of evaluating
690 : * the initPlan. For ROWCOMPARE, we must modify the testexpr tree to
691 : * contain PARAM_EXEC Params instead of the PARAM_SUBLINK Params emitted
692 : * by the parser, and then return that tree. For MULTIEXPR, we return a
693 : * null constant: the resjunk targetlist item containing the SubLink does
694 : * not need to return anything useful, since the referencing Params are
695 : * elsewhere.
696 : */
697 1711 : if (splan->parParam == NIL && subLinkType == EXISTS_SUBLINK)
698 38 : {
699 : Param *prm;
700 :
701 38 : Assert(testexpr == NULL);
702 38 : prm = generate_new_param(root, BOOLOID, -1, InvalidOid);
703 38 : splan->setParam = list_make1_int(prm->paramid);
704 38 : isInitPlan = true;
705 38 : result = (Node *) prm;
706 : }
707 1673 : else if (splan->parParam == NIL && subLinkType == EXPR_SUBLINK)
708 307 : {
709 307 : TargetEntry *te = linitial(plan->targetlist);
710 : Param *prm;
711 :
712 307 : Assert(!te->resjunk);
713 307 : Assert(testexpr == NULL);
714 921 : prm = generate_new_param(root,
715 307 : exprType((Node *) te->expr),
716 307 : exprTypmod((Node *) te->expr),
717 307 : exprCollation((Node *) te->expr));
718 307 : splan->setParam = list_make1_int(prm->paramid);
719 307 : isInitPlan = true;
720 307 : result = (Node *) prm;
721 : }
722 1366 : else if (splan->parParam == NIL && subLinkType == ARRAY_SUBLINK)
723 8 : {
724 8 : TargetEntry *te = linitial(plan->targetlist);
725 : Oid arraytype;
726 : Param *prm;
727 :
728 8 : Assert(!te->resjunk);
729 8 : Assert(testexpr == NULL);
730 8 : arraytype = get_promoted_array_type(exprType((Node *) te->expr));
731 8 : if (!OidIsValid(arraytype))
732 0 : elog(ERROR, "could not find array type for datatype %s",
733 : format_type_be(exprType((Node *) te->expr)));
734 16 : prm = generate_new_param(root,
735 : arraytype,
736 8 : exprTypmod((Node *) te->expr),
737 8 : exprCollation((Node *) te->expr));
738 8 : splan->setParam = list_make1_int(prm->paramid);
739 8 : isInitPlan = true;
740 8 : result = (Node *) prm;
741 : }
742 1358 : else if (splan->parParam == NIL && subLinkType == ROWCOMPARE_SUBLINK)
743 0 : {
744 : /* Adjust the Params */
745 : List *params;
746 :
747 0 : Assert(testexpr != NULL);
748 0 : params = generate_subquery_params(root,
749 : plan->targetlist,
750 : &splan->paramIds);
751 0 : result = convert_testexpr(root,
752 : testexpr,
753 : params);
754 0 : splan->setParam = list_copy(splan->paramIds);
755 0 : isInitPlan = true;
756 :
757 : /*
758 : * The executable expression is returned to become part of the outer
759 : * plan's expression tree; it is not kept in the initplan node.
760 : */
761 : }
762 1358 : else if (subLinkType == MULTIEXPR_SUBLINK)
763 : {
764 : /*
765 : * Whether it's an initplan or not, it needs to set a PARAM_EXEC Param
766 : * for each output column.
767 : */
768 : List *params;
769 :
770 9 : Assert(testexpr == NULL);
771 9 : params = generate_subquery_params(root,
772 : plan->targetlist,
773 : &splan->setParam);
774 :
775 : /*
776 : * Save the list of replacement Params in the n'th cell of
777 : * root->multiexpr_params; setrefs.c will use it to replace
778 : * PARAM_MULTIEXPR Params.
779 : */
780 27 : while (list_length(root->multiexpr_params) < subLinkId)
781 9 : root->multiexpr_params = lappend(root->multiexpr_params, NIL);
782 9 : lc = list_nth_cell(root->multiexpr_params, subLinkId - 1);
783 9 : Assert(lfirst(lc) == NIL);
784 9 : lfirst(lc) = params;
785 :
786 : /* It can be an initplan if there are no parParams. */
787 9 : if (splan->parParam == NIL)
788 : {
789 4 : isInitPlan = true;
790 4 : result = (Node *) makeNullConst(RECORDOID, -1, InvalidOid);
791 : }
792 : else
793 : {
794 5 : isInitPlan = false;
795 5 : result = (Node *) splan;
796 : }
797 : }
798 : else
799 : {
800 : /*
801 : * Adjust the Params in the testexpr, unless caller said it's not
802 : * needed.
803 : */
804 1349 : if (testexpr && adjust_testexpr)
805 41 : {
806 : List *params;
807 :
808 41 : params = generate_subquery_params(root,
809 : plan->targetlist,
810 : &splan->paramIds);
811 41 : splan->testexpr = convert_testexpr(root,
812 : testexpr,
813 : params);
814 : }
815 : else
816 1308 : splan->testexpr = testexpr;
817 :
818 : /*
819 : * We can't convert subplans of ALL_SUBLINK or ANY_SUBLINK types to
820 : * initPlans, even when they are uncorrelated or undirect correlated,
821 : * because we need to scan the output of the subplan for each outer
822 : * tuple. But if it's a not-direct-correlated IN (= ANY) test, we
823 : * might be able to use a hashtable to avoid comparing all the tuples.
824 : */
825 1472 : if (subLinkType == ANY_SUBLINK &&
826 234 : splan->parParam == NIL &&
827 222 : subplan_is_hashable(plan) &&
828 111 : testexpr_is_hashable(splan->testexpr))
829 111 : splan->useHashTable = true;
830 :
831 : /*
832 : * Otherwise, we have the option to tack a Material node onto the top
833 : * of the subplan, to reduce the cost of reading it repeatedly. This
834 : * is pointless for a direct-correlated subplan, since we'd have to
835 : * recompute its results each time anyway. For uncorrelated/undirect
836 : * correlated subplans, we add Material unless the subplan's top plan
837 : * node would materialize its output anyway. Also, if enable_material
838 : * is false, then the user does not want us to materialize anything
839 : * unnecessarily, so we don't.
840 : */
841 1240 : else if (splan->parParam == NIL && enable_material &&
842 2 : !ExecMaterializesOutput(nodeTag(plan)))
843 2 : plan = materialize_finished_plan(plan);
844 :
845 1349 : result = (Node *) splan;
846 1349 : isInitPlan = false;
847 : }
848 :
849 : /*
850 : * Add the subplan and its PlannerInfo to the global lists.
851 : */
852 1711 : root->glob->subplans = lappend(root->glob->subplans, plan);
853 1711 : root->glob->subroots = lappend(root->glob->subroots, subroot);
854 1711 : splan->plan_id = list_length(root->glob->subplans);
855 :
856 1711 : if (isInitPlan)
857 357 : root->init_plans = lappend(root->init_plans, splan);
858 :
859 : /*
860 : * A parameterless subplan (not initplan) should be prepared to handle
861 : * REWIND efficiently. If it has direct parameters then there's no point
862 : * since it'll be reset on each scan anyway; and if it's an initplan then
863 : * there's no point since it won't get re-run without parameter changes
864 : * anyway. The input of a hashed subplan doesn't need REWIND either.
865 : */
866 1711 : if (splan->parParam == NIL && !isInitPlan && !splan->useHashTable)
867 2 : root->glob->rewindPlanIDs = bms_add_member(root->glob->rewindPlanIDs,
868 : splan->plan_id);
869 :
870 : /* Label the subplan for EXPLAIN purposes */
871 1711 : splan->plan_name = palloc(32 + 12 * list_length(splan->setParam));
872 1711 : sprintf(splan->plan_name, "%s %d",
873 : isInitPlan ? "InitPlan" : "SubPlan",
874 : splan->plan_id);
875 1711 : if (splan->setParam)
876 : {
877 362 : char *ptr = splan->plan_name + strlen(splan->plan_name);
878 :
879 362 : ptr += sprintf(ptr, " (returns ");
880 733 : foreach(lc, splan->setParam)
881 : {
882 371 : ptr += sprintf(ptr, "$%d%s",
883 : lfirst_int(lc),
884 371 : lnext(lc) ? "," : ")");
885 : }
886 : }
887 :
888 : /* Lastly, fill in the cost estimates for use later */
889 1711 : cost_subplan(root, splan, plan);
890 :
891 1711 : return result;
892 : }
893 :
894 : /*
895 : * generate_subquery_params: build a list of Params representing the output
896 : * columns of a sublink's sub-select, given the sub-select's targetlist.
897 : *
898 : * We also return an integer list of the paramids of the Params.
899 : */
900 : static List *
901 50 : generate_subquery_params(PlannerInfo *root, List *tlist, List **paramIds)
902 : {
903 : List *result;
904 : List *ids;
905 : ListCell *lc;
906 :
907 50 : result = ids = NIL;
908 114 : foreach(lc, tlist)
909 : {
910 64 : TargetEntry *tent = (TargetEntry *) lfirst(lc);
911 : Param *param;
912 :
913 64 : if (tent->resjunk)
914 1 : continue;
915 :
916 189 : param = generate_new_param(root,
917 63 : exprType((Node *) tent->expr),
918 63 : exprTypmod((Node *) tent->expr),
919 63 : exprCollation((Node *) tent->expr));
920 63 : result = lappend(result, param);
921 63 : ids = lappend_int(ids, param->paramid);
922 : }
923 :
924 50 : *paramIds = ids;
925 50 : return result;
926 : }
927 :
928 : /*
929 : * generate_subquery_vars: build a list of Vars representing the output
930 : * columns of a sublink's sub-select, given the sub-select's targetlist.
931 : * The Vars have the specified varno (RTE index).
932 : */
933 : static List *
934 49 : generate_subquery_vars(PlannerInfo *root, List *tlist, Index varno)
935 : {
936 : List *result;
937 : ListCell *lc;
938 :
939 49 : result = NIL;
940 103 : foreach(lc, tlist)
941 : {
942 54 : TargetEntry *tent = (TargetEntry *) lfirst(lc);
943 : Var *var;
944 :
945 54 : if (tent->resjunk)
946 0 : continue;
947 :
948 54 : var = makeVarFromTargetEntry(varno, tent);
949 54 : result = lappend(result, var);
950 : }
951 :
952 49 : return result;
953 : }
954 :
955 : /*
956 : * convert_testexpr: convert the testexpr given by the parser into
957 : * actually executable form. This entails replacing PARAM_SUBLINK Params
958 : * with Params or Vars representing the results of the sub-select. The
959 : * nodes to be substituted are passed in as the List result from
960 : * generate_subquery_params or generate_subquery_vars.
961 : */
962 : static Node *
963 90 : convert_testexpr(PlannerInfo *root,
964 : Node *testexpr,
965 : List *subst_nodes)
966 : {
967 : convert_testexpr_context context;
968 :
969 90 : context.root = root;
970 90 : context.subst_nodes = subst_nodes;
971 90 : return convert_testexpr_mutator(testexpr, &context);
972 : }
973 :
974 : static Node *
975 461 : convert_testexpr_mutator(Node *node,
976 : convert_testexpr_context *context)
977 : {
978 461 : if (node == NULL)
979 3 : return NULL;
980 458 : if (IsA(node, Param))
981 : {
982 99 : Param *param = (Param *) node;
983 :
984 99 : if (param->paramkind == PARAM_SUBLINK)
985 : {
986 198 : if (param->paramid <= 0 ||
987 99 : param->paramid > list_length(context->subst_nodes))
988 0 : elog(ERROR, "unexpected PARAM_SUBLINK ID: %d", param->paramid);
989 :
990 : /*
991 : * We copy the list item to avoid having doubly-linked
992 : * substructure in the modified parse tree. This is probably
993 : * unnecessary when it's a Param, but be safe.
994 : */
995 99 : return (Node *) copyObject(list_nth(context->subst_nodes,
996 : param->paramid - 1));
997 : }
998 : }
999 359 : if (IsA(node, SubLink))
1000 : {
1001 : /*
1002 : * If we come across a nested SubLink, it is neither necessary nor
1003 : * correct to recurse into it: any PARAM_SUBLINKs we might find inside
1004 : * belong to the inner SubLink not the outer. So just return it as-is.
1005 : *
1006 : * This reasoning depends on the assumption that nothing will pull
1007 : * subexpressions into or out of the testexpr field of a SubLink, at
1008 : * least not without replacing PARAM_SUBLINKs first. If we did want
1009 : * to do that we'd need to rethink the parser-output representation
1010 : * altogether, since currently PARAM_SUBLINKs are only unique per
1011 : * SubLink not globally across the query. The whole point of
1012 : * replacing them with Vars or PARAM_EXEC nodes is to make them
1013 : * globally unique before they escape from the SubLink's testexpr.
1014 : *
1015 : * Note: this can't happen when called during SS_process_sublinks,
1016 : * because that recursively processes inner SubLinks first. It can
1017 : * happen when called from convert_ANY_sublink_to_join, though.
1018 : */
1019 2 : return node;
1020 : }
1021 357 : return expression_tree_mutator(node,
1022 : convert_testexpr_mutator,
1023 : (void *) context);
1024 : }
1025 :
1026 : /*
1027 : * subplan_is_hashable: can we implement an ANY subplan by hashing?
1028 : */
1029 : static bool
1030 195 : subplan_is_hashable(Plan *plan)
1031 : {
1032 : double subquery_size;
1033 :
1034 : /*
1035 : * The estimated size of the subquery result must fit in work_mem. (Note:
1036 : * we use heap tuple overhead here even though the tuples will actually be
1037 : * stored as MinimalTuples; this provides some fudge factor for hashtable
1038 : * overhead.)
1039 : */
1040 390 : subquery_size = plan->plan_rows *
1041 195 : (MAXALIGN(plan->plan_width) + MAXALIGN(SizeofHeapTupleHeader));
1042 195 : if (subquery_size > work_mem * 1024L)
1043 0 : return false;
1044 :
1045 195 : return true;
1046 : }
1047 :
1048 : /*
1049 : * testexpr_is_hashable: is an ANY SubLink's test expression hashable?
1050 : */
1051 : static bool
1052 111 : testexpr_is_hashable(Node *testexpr)
1053 : {
1054 : /*
1055 : * The testexpr must be a single OpExpr, or an AND-clause containing only
1056 : * OpExprs.
1057 : *
1058 : * The combining operators must be hashable and strict. The need for
1059 : * hashability is obvious, since we want to use hashing. Without
1060 : * strictness, behavior in the presence of nulls is too unpredictable. We
1061 : * actually must assume even more than plain strictness: they can't yield
1062 : * NULL for non-null inputs, either (see nodeSubplan.c). However, hash
1063 : * indexes and hash joins assume that too.
1064 : */
1065 111 : if (testexpr && IsA(testexpr, OpExpr))
1066 : {
1067 77 : if (hash_ok_operator((OpExpr *) testexpr))
1068 77 : return true;
1069 : }
1070 34 : else if (and_clause(testexpr))
1071 : {
1072 : ListCell *l;
1073 :
1074 102 : foreach(l, ((BoolExpr *) testexpr)->args)
1075 : {
1076 68 : Node *andarg = (Node *) lfirst(l);
1077 :
1078 68 : if (!IsA(andarg, OpExpr))
1079 0 : return false;
1080 68 : if (!hash_ok_operator((OpExpr *) andarg))
1081 0 : return false;
1082 : }
1083 34 : return true;
1084 : }
1085 :
1086 0 : return false;
1087 : }
1088 :
1089 : /*
1090 : * Check expression is hashable + strict
1091 : *
1092 : * We could use op_hashjoinable() and op_strict(), but do it like this to
1093 : * avoid a redundant cache lookup.
1094 : */
1095 : static bool
1096 399 : hash_ok_operator(OpExpr *expr)
1097 : {
1098 399 : Oid opid = expr->opno;
1099 :
1100 : /* quick out if not a binary operator */
1101 399 : if (list_length(expr->args) != 2)
1102 0 : return false;
1103 399 : if (opid == ARRAY_EQ_OP)
1104 : {
1105 : /* array_eq is strict, but must check input type to ensure hashable */
1106 : /* XXX record_eq will need same treatment when it becomes hashable */
1107 0 : Node *leftarg = linitial(expr->args);
1108 :
1109 0 : return op_hashjoinable(opid, exprType(leftarg));
1110 : }
1111 : else
1112 : {
1113 : /* else must look up the operator properties */
1114 : HeapTuple tup;
1115 : Form_pg_operator optup;
1116 :
1117 399 : tup = SearchSysCache1(OPEROID, ObjectIdGetDatum(opid));
1118 399 : if (!HeapTupleIsValid(tup))
1119 0 : elog(ERROR, "cache lookup failed for operator %u", opid);
1120 399 : optup = (Form_pg_operator) GETSTRUCT(tup);
1121 399 : if (!optup->oprcanhash || !func_strict(optup->oprcode))
1122 : {
1123 1 : ReleaseSysCache(tup);
1124 1 : return false;
1125 : }
1126 398 : ReleaseSysCache(tup);
1127 398 : return true;
1128 : }
1129 : }
1130 :
1131 :
1132 : /*
1133 : * SS_process_ctes: process a query's WITH list
1134 : *
1135 : * We plan each interesting WITH item and convert it to an initplan.
1136 : * A side effect is to fill in root->cte_plan_ids with a list that
1137 : * parallels root->parse->cteList and provides the subplan ID for
1138 : * each CTE's initplan.
1139 : */
1140 : void
1141 116 : SS_process_ctes(PlannerInfo *root)
1142 : {
1143 : ListCell *lc;
1144 :
1145 116 : Assert(root->cte_plan_ids == NIL);
1146 :
1147 254 : foreach(lc, root->parse->cteList)
1148 : {
1149 138 : CommonTableExpr *cte = (CommonTableExpr *) lfirst(lc);
1150 138 : CmdType cmdType = ((Query *) cte->ctequery)->commandType;
1151 : Query *subquery;
1152 : PlannerInfo *subroot;
1153 : RelOptInfo *final_rel;
1154 : Path *best_path;
1155 : Plan *plan;
1156 : SubPlan *splan;
1157 : int paramid;
1158 :
1159 : /*
1160 : * Ignore SELECT CTEs that are not actually referenced anywhere.
1161 : */
1162 138 : if (cte->cterefcount == 0 && cmdType == CMD_SELECT)
1163 : {
1164 : /* Make a dummy entry in cte_plan_ids */
1165 1 : root->cte_plan_ids = lappend_int(root->cte_plan_ids, -1);
1166 1 : continue;
1167 : }
1168 :
1169 : /*
1170 : * Copy the source Query node. Probably not necessary, but let's keep
1171 : * this similar to make_subplan.
1172 : */
1173 137 : subquery = (Query *) copyObject(cte->ctequery);
1174 :
1175 : /* plan_params should not be in use in current query level */
1176 137 : Assert(root->plan_params == NIL);
1177 :
1178 : /*
1179 : * Generate Paths for the CTE query. Always plan for full retrieval
1180 : * --- we don't have enough info to predict otherwise.
1181 : */
1182 137 : subroot = subquery_planner(root->glob, subquery,
1183 : root,
1184 137 : cte->cterecursive, 0.0);
1185 :
1186 : /*
1187 : * Since the current query level doesn't yet contain any RTEs, it
1188 : * should not be possible for the CTE to have requested parameters of
1189 : * this level.
1190 : */
1191 137 : if (root->plan_params)
1192 0 : elog(ERROR, "unexpected outer reference in CTE query");
1193 :
1194 : /*
1195 : * Select best Path and turn it into a Plan. At least for now, there
1196 : * seems no reason to postpone doing that.
1197 : */
1198 137 : final_rel = fetch_upper_rel(subroot, UPPERREL_FINAL, NULL);
1199 137 : best_path = final_rel->cheapest_total_path;
1200 :
1201 137 : plan = create_plan(subroot, best_path);
1202 :
1203 : /*
1204 : * Make a SubPlan node for it. This is just enough unlike
1205 : * build_subplan that we can't share code.
1206 : *
1207 : * Note plan_id, plan_name, and cost fields are set further down.
1208 : */
1209 137 : splan = makeNode(SubPlan);
1210 137 : splan->subLinkType = CTE_SUBLINK;
1211 137 : splan->testexpr = NULL;
1212 137 : splan->paramIds = NIL;
1213 137 : get_first_col_type(plan, &splan->firstColType, &splan->firstColTypmod,
1214 : &splan->firstColCollation);
1215 137 : splan->useHashTable = false;
1216 137 : splan->unknownEqFalse = false;
1217 :
1218 : /*
1219 : * CTE scans are not considered for parallelism (cf
1220 : * set_rel_consider_parallel), and even if they were, initPlans aren't
1221 : * parallel-safe.
1222 : */
1223 137 : splan->parallel_safe = false;
1224 137 : splan->setParam = NIL;
1225 137 : splan->parParam = NIL;
1226 137 : splan->args = NIL;
1227 :
1228 : /*
1229 : * The node can't have any inputs (since it's an initplan), so the
1230 : * parParam and args lists remain empty. (It could contain references
1231 : * to earlier CTEs' output param IDs, but CTE outputs are not
1232 : * propagated via the args list.)
1233 : */
1234 :
1235 : /*
1236 : * Assign a param ID to represent the CTE's output. No ordinary
1237 : * "evaluation" of this param slot ever happens, but we use the param
1238 : * ID for setParam/chgParam signaling just as if the CTE plan were
1239 : * returning a simple scalar output. (Also, the executor abuses the
1240 : * ParamExecData slot for this param ID for communication among
1241 : * multiple CteScan nodes that might be scanning this CTE.)
1242 : */
1243 137 : paramid = SS_assign_special_param(root);
1244 137 : splan->setParam = list_make1_int(paramid);
1245 :
1246 : /*
1247 : * Add the subplan and its PlannerInfo to the global lists.
1248 : */
1249 137 : root->glob->subplans = lappend(root->glob->subplans, plan);
1250 137 : root->glob->subroots = lappend(root->glob->subroots, subroot);
1251 137 : splan->plan_id = list_length(root->glob->subplans);
1252 :
1253 137 : root->init_plans = lappend(root->init_plans, splan);
1254 :
1255 137 : root->cte_plan_ids = lappend_int(root->cte_plan_ids, splan->plan_id);
1256 :
1257 : /* Label the subplan for EXPLAIN purposes */
1258 137 : splan->plan_name = psprintf("CTE %s", cte->ctename);
1259 :
1260 : /* Lastly, fill in the cost estimates for use later */
1261 137 : cost_subplan(root, splan, plan);
1262 : }
1263 116 : }
1264 :
1265 : /*
1266 : * convert_ANY_sublink_to_join: try to convert an ANY SubLink to a join
1267 : *
1268 : * The caller has found an ANY SubLink at the top level of one of the query's
1269 : * qual clauses, but has not checked the properties of the SubLink further.
1270 : * Decide whether it is appropriate to process this SubLink in join style.
1271 : * If so, form a JoinExpr and return it. Return NULL if the SubLink cannot
1272 : * be converted to a join.
1273 : *
1274 : * The only non-obvious input parameter is available_rels: this is the set
1275 : * of query rels that can safely be referenced in the sublink expression.
1276 : * (We must restrict this to avoid changing the semantics when a sublink
1277 : * is present in an outer join's ON qual.) The conversion must fail if
1278 : * the converted qual would reference any but these parent-query relids.
1279 : *
1280 : * On success, the returned JoinExpr has larg = NULL and rarg = the jointree
1281 : * item representing the pulled-up subquery. The caller must set larg to
1282 : * represent the relation(s) on the lefthand side of the new join, and insert
1283 : * the JoinExpr into the upper query's jointree at an appropriate place
1284 : * (typically, where the lefthand relation(s) had been). Note that the
1285 : * passed-in SubLink must also be removed from its original position in the
1286 : * query quals, since the quals of the returned JoinExpr replace it.
1287 : * (Notionally, we replace the SubLink with a constant TRUE, then elide the
1288 : * redundant constant from the qual.)
1289 : *
1290 : * On success, the caller is also responsible for recursively applying
1291 : * pull_up_sublinks processing to the rarg and quals of the returned JoinExpr.
1292 : * (On failure, there is no need to do anything, since pull_up_sublinks will
1293 : * be applied when we recursively plan the sub-select.)
1294 : *
1295 : * Side effects of a successful conversion include adding the SubLink's
1296 : * subselect to the query's rangetable, so that it can be referenced in
1297 : * the JoinExpr's rarg.
1298 : */
1299 : JoinExpr *
1300 61 : convert_ANY_sublink_to_join(PlannerInfo *root, SubLink *sublink,
1301 : Relids available_rels)
1302 : {
1303 : JoinExpr *result;
1304 61 : Query *parse = root->parse;
1305 61 : Query *subselect = (Query *) sublink->subselect;
1306 : Relids upper_varnos;
1307 : int rtindex;
1308 : RangeTblEntry *rte;
1309 : RangeTblRef *rtr;
1310 : List *subquery_vars;
1311 : Node *quals;
1312 : ParseState *pstate;
1313 :
1314 61 : Assert(sublink->subLinkType == ANY_SUBLINK);
1315 :
1316 : /*
1317 : * The sub-select must not refer to any Vars of the parent query. (Vars of
1318 : * higher levels should be okay, though.)
1319 : */
1320 61 : if (contain_vars_of_level((Node *) subselect, 1))
1321 10 : return NULL;
1322 :
1323 : /*
1324 : * The test expression must contain some Vars of the parent query, else
1325 : * it's not gonna be a join. (Note that it won't have Vars referring to
1326 : * the subquery, rather Params.)
1327 : */
1328 51 : upper_varnos = pull_varnos(sublink->testexpr);
1329 51 : if (bms_is_empty(upper_varnos))
1330 2 : return NULL;
1331 :
1332 : /*
1333 : * However, it can't refer to anything outside available_rels.
1334 : */
1335 49 : if (!bms_is_subset(upper_varnos, available_rels))
1336 0 : return NULL;
1337 :
1338 : /*
1339 : * The combining operators and left-hand expressions mustn't be volatile.
1340 : */
1341 49 : if (contain_volatile_functions(sublink->testexpr))
1342 0 : return NULL;
1343 :
1344 : /* Create a dummy ParseState for addRangeTableEntryForSubquery */
1345 49 : pstate = make_parsestate(NULL);
1346 :
1347 : /*
1348 : * Okay, pull up the sub-select into upper range table.
1349 : *
1350 : * We rely here on the assumption that the outer query has no references
1351 : * to the inner (necessarily true, other than the Vars that we build
1352 : * below). Therefore this is a lot easier than what pull_up_subqueries has
1353 : * to go through.
1354 : */
1355 49 : rte = addRangeTableEntryForSubquery(pstate,
1356 : subselect,
1357 : makeAlias("ANY_subquery", NIL),
1358 : false,
1359 : false);
1360 49 : parse->rtable = lappend(parse->rtable, rte);
1361 49 : rtindex = list_length(parse->rtable);
1362 :
1363 : /*
1364 : * Form a RangeTblRef for the pulled-up sub-select.
1365 : */
1366 49 : rtr = makeNode(RangeTblRef);
1367 49 : rtr->rtindex = rtindex;
1368 :
1369 : /*
1370 : * Build a list of Vars representing the subselect outputs.
1371 : */
1372 49 : subquery_vars = generate_subquery_vars(root,
1373 : subselect->targetList,
1374 : rtindex);
1375 :
1376 : /*
1377 : * Build the new join's qual expression, replacing Params with these Vars.
1378 : */
1379 49 : quals = convert_testexpr(root, sublink->testexpr, subquery_vars);
1380 :
1381 : /*
1382 : * And finally, build the JoinExpr node.
1383 : */
1384 49 : result = makeNode(JoinExpr);
1385 49 : result->jointype = JOIN_SEMI;
1386 49 : result->isNatural = false;
1387 49 : result->larg = NULL; /* caller must fill this in */
1388 49 : result->rarg = (Node *) rtr;
1389 49 : result->usingClause = NIL;
1390 49 : result->quals = quals;
1391 49 : result->alias = NULL;
1392 49 : result->rtindex = 0; /* we don't need an RTE for it */
1393 :
1394 49 : return result;
1395 : }
1396 :
1397 : /*
1398 : * convert_EXISTS_sublink_to_join: try to convert an EXISTS SubLink to a join
1399 : *
1400 : * The API of this function is identical to convert_ANY_sublink_to_join's,
1401 : * except that we also support the case where the caller has found NOT EXISTS,
1402 : * so we need an additional input parameter "under_not".
1403 : */
1404 : JoinExpr *
1405 228 : convert_EXISTS_sublink_to_join(PlannerInfo *root, SubLink *sublink,
1406 : bool under_not, Relids available_rels)
1407 : {
1408 : JoinExpr *result;
1409 228 : Query *parse = root->parse;
1410 228 : Query *subselect = (Query *) sublink->subselect;
1411 : Node *whereClause;
1412 : int rtoffset;
1413 : int varno;
1414 : Relids clause_varnos;
1415 : Relids upper_varnos;
1416 :
1417 228 : Assert(sublink->subLinkType == EXISTS_SUBLINK);
1418 :
1419 : /*
1420 : * Can't flatten if it contains WITH. (We could arrange to pull up the
1421 : * WITH into the parent query's cteList, but that risks changing the
1422 : * semantics, since a WITH ought to be executed once per associated query
1423 : * call.) Note that convert_ANY_sublink_to_join doesn't have to reject
1424 : * this case, since it just produces a subquery RTE that doesn't have to
1425 : * get flattened into the parent query.
1426 : */
1427 228 : if (subselect->cteList)
1428 0 : return NULL;
1429 :
1430 : /*
1431 : * Copy the subquery so we can modify it safely (see comments in
1432 : * make_subplan).
1433 : */
1434 228 : subselect = copyObject(subselect);
1435 :
1436 : /*
1437 : * See if the subquery can be simplified based on the knowledge that it's
1438 : * being used in EXISTS(). If we aren't able to get rid of its
1439 : * targetlist, we have to fail, because the pullup operation leaves us
1440 : * with noplace to evaluate the targetlist.
1441 : */
1442 228 : if (!simplify_EXISTS_query(root, subselect))
1443 1 : return NULL;
1444 :
1445 : /*
1446 : * The subquery must have a nonempty jointree, else we won't have a join.
1447 : */
1448 227 : if (subselect->jointree->fromlist == NIL)
1449 0 : return NULL;
1450 :
1451 : /*
1452 : * Separate out the WHERE clause. (We could theoretically also remove
1453 : * top-level plain JOIN/ON clauses, but it's probably not worth the
1454 : * trouble.)
1455 : */
1456 227 : whereClause = subselect->jointree->quals;
1457 227 : subselect->jointree->quals = NULL;
1458 :
1459 : /*
1460 : * The rest of the sub-select must not refer to any Vars of the parent
1461 : * query. (Vars of higher levels should be okay, though.)
1462 : */
1463 227 : if (contain_vars_of_level((Node *) subselect, 1))
1464 0 : return NULL;
1465 :
1466 : /*
1467 : * On the other hand, the WHERE clause must contain some Vars of the
1468 : * parent query, else it's not gonna be a join.
1469 : */
1470 227 : if (!contain_vars_of_level(whereClause, 1))
1471 8 : return NULL;
1472 :
1473 : /*
1474 : * We don't risk optimizing if the WHERE clause is volatile, either.
1475 : */
1476 219 : if (contain_volatile_functions(whereClause))
1477 0 : return NULL;
1478 :
1479 : /*
1480 : * Prepare to pull up the sub-select into top range table.
1481 : *
1482 : * We rely here on the assumption that the outer query has no references
1483 : * to the inner (necessarily true). Therefore this is a lot easier than
1484 : * what pull_up_subqueries has to go through.
1485 : *
1486 : * In fact, it's even easier than what convert_ANY_sublink_to_join has to
1487 : * do. The machinations of simplify_EXISTS_query ensured that there is
1488 : * nothing interesting in the subquery except an rtable and jointree, and
1489 : * even the jointree FromExpr no longer has quals. So we can just append
1490 : * the rtable to our own and use the FromExpr in our jointree. But first,
1491 : * adjust all level-zero varnos in the subquery to account for the rtable
1492 : * merger.
1493 : */
1494 219 : rtoffset = list_length(parse->rtable);
1495 219 : OffsetVarNodes((Node *) subselect, rtoffset, 0);
1496 219 : OffsetVarNodes(whereClause, rtoffset, 0);
1497 :
1498 : /*
1499 : * Upper-level vars in subquery will now be one level closer to their
1500 : * parent than before; in particular, anything that had been level 1
1501 : * becomes level zero.
1502 : */
1503 219 : IncrementVarSublevelsUp((Node *) subselect, -1, 1);
1504 219 : IncrementVarSublevelsUp(whereClause, -1, 1);
1505 :
1506 : /*
1507 : * Now that the WHERE clause is adjusted to match the parent query
1508 : * environment, we can easily identify all the level-zero rels it uses.
1509 : * The ones <= rtoffset belong to the upper query; the ones > rtoffset do
1510 : * not.
1511 : */
1512 219 : clause_varnos = pull_varnos(whereClause);
1513 219 : upper_varnos = NULL;
1514 879 : while ((varno = bms_first_member(clause_varnos)) >= 0)
1515 : {
1516 441 : if (varno <= rtoffset)
1517 222 : upper_varnos = bms_add_member(upper_varnos, varno);
1518 : }
1519 219 : bms_free(clause_varnos);
1520 219 : Assert(!bms_is_empty(upper_varnos));
1521 :
1522 : /*
1523 : * Now that we've got the set of upper-level varnos, we can make the last
1524 : * check: only available_rels can be referenced.
1525 : */
1526 219 : if (!bms_is_subset(upper_varnos, available_rels))
1527 0 : return NULL;
1528 :
1529 : /* Now we can attach the modified subquery rtable to the parent */
1530 219 : parse->rtable = list_concat(parse->rtable, subselect->rtable);
1531 :
1532 : /*
1533 : * And finally, build the JoinExpr node.
1534 : */
1535 219 : result = makeNode(JoinExpr);
1536 219 : result->jointype = under_not ? JOIN_ANTI : JOIN_SEMI;
1537 219 : result->isNatural = false;
1538 219 : result->larg = NULL; /* caller must fill this in */
1539 : /* flatten out the FromExpr node if it's useless */
1540 219 : if (list_length(subselect->jointree->fromlist) == 1)
1541 219 : result->rarg = (Node *) linitial(subselect->jointree->fromlist);
1542 : else
1543 0 : result->rarg = (Node *) subselect->jointree;
1544 219 : result->usingClause = NIL;
1545 219 : result->quals = whereClause;
1546 219 : result->alias = NULL;
1547 219 : result->rtindex = 0; /* we don't need an RTE for it */
1548 :
1549 219 : return result;
1550 : }
1551 :
1552 : /*
1553 : * simplify_EXISTS_query: remove any useless stuff in an EXISTS's subquery
1554 : *
1555 : * The only thing that matters about an EXISTS query is whether it returns
1556 : * zero or more than zero rows. Therefore, we can remove certain SQL features
1557 : * that won't affect that. The only part that is really likely to matter in
1558 : * typical usage is simplifying the targetlist: it's a common habit to write
1559 : * "SELECT * FROM" even though there is no need to evaluate any columns.
1560 : *
1561 : * Note: by suppressing the targetlist we could cause an observable behavioral
1562 : * change, namely that any errors that might occur in evaluating the tlist
1563 : * won't occur, nor will other side-effects of volatile functions. This seems
1564 : * unlikely to bother anyone in practice.
1565 : *
1566 : * Returns TRUE if was able to discard the targetlist, else FALSE.
1567 : */
1568 : static bool
1569 435 : simplify_EXISTS_query(PlannerInfo *root, Query *query)
1570 : {
1571 : /*
1572 : * We don't try to simplify at all if the query uses set operations,
1573 : * aggregates, grouping sets, SRFs, modifying CTEs, HAVING, OFFSET, or FOR
1574 : * UPDATE/SHARE; none of these seem likely in normal usage and their
1575 : * possible effects are complex. (Note: we could ignore an "OFFSET 0"
1576 : * clause, but that traditionally is used as an optimization fence, so we
1577 : * don't.)
1578 : */
1579 870 : if (query->commandType != CMD_SELECT ||
1580 870 : query->setOperations ||
1581 870 : query->hasAggs ||
1582 870 : query->groupingSets ||
1583 870 : query->hasWindowFuncs ||
1584 870 : query->hasTargetSRFs ||
1585 870 : query->hasModifyingCTE ||
1586 870 : query->havingQual ||
1587 870 : query->limitOffset ||
1588 435 : query->rowMarks)
1589 0 : return false;
1590 :
1591 : /*
1592 : * LIMIT with a constant positive (or NULL) value doesn't affect the
1593 : * semantics of EXISTS, so let's ignore such clauses. This is worth doing
1594 : * because people accustomed to certain other DBMSes may be in the habit
1595 : * of writing EXISTS(SELECT ... LIMIT 1) as an optimization. If there's a
1596 : * LIMIT with anything else as argument, though, we can't simplify.
1597 : */
1598 435 : if (query->limitCount)
1599 : {
1600 : /*
1601 : * The LIMIT clause has not yet been through eval_const_expressions,
1602 : * so we have to apply that here. It might seem like this is a waste
1603 : * of cycles, since the only case plausibly worth worrying about is
1604 : * "LIMIT 1" ... but what we'll actually see is "LIMIT int8(1::int4)",
1605 : * so we have to fold constants or we're not going to recognize it.
1606 : */
1607 4 : Node *node = eval_const_expressions(root, query->limitCount);
1608 : Const *limit;
1609 :
1610 : /* Might as well update the query if we simplified the clause. */
1611 4 : query->limitCount = node;
1612 :
1613 4 : if (!IsA(node, Const))
1614 0 : return false;
1615 :
1616 4 : limit = (Const *) node;
1617 4 : Assert(limit->consttype == INT8OID);
1618 4 : if (!limit->constisnull && DatumGetInt64(limit->constvalue) <= 0)
1619 2 : return false;
1620 :
1621 : /* Whether or not the targetlist is safe, we can drop the LIMIT. */
1622 2 : query->limitCount = NULL;
1623 : }
1624 :
1625 : /*
1626 : * Otherwise, we can throw away the targetlist, as well as any GROUP,
1627 : * WINDOW, DISTINCT, and ORDER BY clauses; none of those clauses will
1628 : * change a nonzero-rows result to zero rows or vice versa. (Furthermore,
1629 : * since our parsetree representation of these clauses depends on the
1630 : * targetlist, we'd better throw them away if we drop the targetlist.)
1631 : */
1632 433 : query->targetList = NIL;
1633 433 : query->groupClause = NIL;
1634 433 : query->windowClause = NIL;
1635 433 : query->distinctClause = NIL;
1636 433 : query->sortClause = NIL;
1637 433 : query->hasDistinctOn = false;
1638 :
1639 433 : return true;
1640 : }
1641 :
1642 : /*
1643 : * convert_EXISTS_to_ANY: try to convert EXISTS to a hashable ANY sublink
1644 : *
1645 : * The subselect is expected to be a fresh copy that we can munge up,
1646 : * and to have been successfully passed through simplify_EXISTS_query.
1647 : *
1648 : * On success, the modified subselect is returned, and we store a suitable
1649 : * upper-level test expression at *testexpr, plus a list of the subselect's
1650 : * output Params at *paramIds. (The test expression is already Param-ified
1651 : * and hence need not go through convert_testexpr, which is why we have to
1652 : * deal with the Param IDs specially.)
1653 : *
1654 : * On failure, returns NULL.
1655 : */
1656 : static Query *
1657 84 : convert_EXISTS_to_ANY(PlannerInfo *root, Query *subselect,
1658 : Node **testexpr, List **paramIds)
1659 : {
1660 : Node *whereClause;
1661 : List *leftargs,
1662 : *rightargs,
1663 : *opids,
1664 : *opcollations,
1665 : *newWhere,
1666 : *tlist,
1667 : *testlist,
1668 : *paramids;
1669 : ListCell *lc,
1670 : *rc,
1671 : *oc,
1672 : *cc;
1673 : AttrNumber resno;
1674 :
1675 : /*
1676 : * Query must not require a targetlist, since we have to insert a new one.
1677 : * Caller should have dealt with the case already.
1678 : */
1679 84 : Assert(subselect->targetList == NIL);
1680 :
1681 : /*
1682 : * Separate out the WHERE clause. (We could theoretically also remove
1683 : * top-level plain JOIN/ON clauses, but it's probably not worth the
1684 : * trouble.)
1685 : */
1686 84 : whereClause = subselect->jointree->quals;
1687 84 : subselect->jointree->quals = NULL;
1688 :
1689 : /*
1690 : * The rest of the sub-select must not refer to any Vars of the parent
1691 : * query. (Vars of higher levels should be okay, though.)
1692 : *
1693 : * Note: we need not check for Aggrefs separately because we know the
1694 : * sub-select is as yet unoptimized; any uplevel Aggref must therefore
1695 : * contain an uplevel Var reference. This is not the case below ...
1696 : */
1697 84 : if (contain_vars_of_level((Node *) subselect, 1))
1698 0 : return NULL;
1699 :
1700 : /*
1701 : * We don't risk optimizing if the WHERE clause is volatile, either.
1702 : */
1703 84 : if (contain_volatile_functions(whereClause))
1704 0 : return NULL;
1705 :
1706 : /*
1707 : * Clean up the WHERE clause by doing const-simplification etc on it.
1708 : * Aside from simplifying the processing we're about to do, this is
1709 : * important for being able to pull chunks of the WHERE clause up into the
1710 : * parent query. Since we are invoked partway through the parent's
1711 : * preprocess_expression() work, earlier steps of preprocess_expression()
1712 : * wouldn't get applied to the pulled-up stuff unless we do them here. For
1713 : * the parts of the WHERE clause that get put back into the child query,
1714 : * this work is partially duplicative, but it shouldn't hurt.
1715 : *
1716 : * Note: we do not run flatten_join_alias_vars. This is OK because any
1717 : * parent aliases were flattened already, and we're not going to pull any
1718 : * child Vars (of any description) into the parent.
1719 : *
1720 : * Note: passing the parent's root to eval_const_expressions is
1721 : * technically wrong, but we can get away with it since only the
1722 : * boundParams (if any) are used, and those would be the same in a
1723 : * subroot.
1724 : */
1725 84 : whereClause = eval_const_expressions(root, whereClause);
1726 84 : whereClause = (Node *) canonicalize_qual((Expr *) whereClause);
1727 84 : whereClause = (Node *) make_ands_implicit((Expr *) whereClause);
1728 :
1729 : /*
1730 : * We now have a flattened implicit-AND list of clauses, which we try to
1731 : * break apart into "outervar = innervar" hash clauses. Anything that
1732 : * can't be broken apart just goes back into the newWhere list. Note that
1733 : * we aren't trying hard yet to ensure that we have only outer or only
1734 : * inner on each side; we'll check that if we get to the end.
1735 : */
1736 84 : leftargs = rightargs = opids = opcollations = newWhere = NIL;
1737 287 : foreach(lc, (List *) whereClause)
1738 : {
1739 203 : OpExpr *expr = (OpExpr *) lfirst(lc);
1740 :
1741 346 : if (IsA(expr, OpExpr) &&
1742 143 : hash_ok_operator(expr))
1743 : {
1744 142 : Node *leftarg = (Node *) linitial(expr->args);
1745 142 : Node *rightarg = (Node *) lsecond(expr->args);
1746 :
1747 142 : if (contain_vars_of_level(leftarg, 1))
1748 : {
1749 3 : leftargs = lappend(leftargs, leftarg);
1750 3 : rightargs = lappend(rightargs, rightarg);
1751 3 : opids = lappend_oid(opids, expr->opno);
1752 3 : opcollations = lappend_oid(opcollations, expr->inputcollid);
1753 3 : continue;
1754 : }
1755 139 : if (contain_vars_of_level(rightarg, 1))
1756 : {
1757 : /*
1758 : * We must commute the clause to put the outer var on the
1759 : * left, because the hashing code in nodeSubplan.c expects
1760 : * that. This probably shouldn't ever fail, since hashable
1761 : * operators ought to have commutators, but be paranoid.
1762 : */
1763 111 : expr->opno = get_commutator(expr->opno);
1764 111 : if (OidIsValid(expr->opno) && hash_ok_operator(expr))
1765 : {
1766 111 : leftargs = lappend(leftargs, rightarg);
1767 111 : rightargs = lappend(rightargs, leftarg);
1768 111 : opids = lappend_oid(opids, expr->opno);
1769 111 : opcollations = lappend_oid(opcollations, expr->inputcollid);
1770 111 : continue;
1771 : }
1772 : /* If no commutator, no chance to optimize the WHERE clause */
1773 0 : return NULL;
1774 : }
1775 : }
1776 : /* Couldn't handle it as a hash clause */
1777 89 : newWhere = lappend(newWhere, expr);
1778 : }
1779 :
1780 : /*
1781 : * If we didn't find anything we could convert, fail.
1782 : */
1783 84 : if (leftargs == NIL)
1784 0 : return NULL;
1785 :
1786 : /*
1787 : * There mustn't be any parent Vars or Aggs in the stuff that we intend to
1788 : * put back into the child query. Note: you might think we don't need to
1789 : * check for Aggs separately, because an uplevel Agg must contain an
1790 : * uplevel Var in its argument. But it is possible that the uplevel Var
1791 : * got optimized away by eval_const_expressions. Consider
1792 : *
1793 : * SUM(CASE WHEN false THEN uplevelvar ELSE 0 END)
1794 : */
1795 168 : if (contain_vars_of_level((Node *) newWhere, 1) ||
1796 84 : contain_vars_of_level((Node *) rightargs, 1))
1797 0 : return NULL;
1798 87 : if (root->parse->hasAggs &&
1799 6 : (contain_aggs_of_level((Node *) newWhere, 1) ||
1800 3 : contain_aggs_of_level((Node *) rightargs, 1)))
1801 0 : return NULL;
1802 :
1803 : /*
1804 : * And there can't be any child Vars in the stuff we intend to pull up.
1805 : * (Note: we'd need to check for child Aggs too, except we know the child
1806 : * has no aggs at all because of simplify_EXISTS_query's check. The same
1807 : * goes for window functions.)
1808 : */
1809 84 : if (contain_vars_of_level((Node *) leftargs, 0))
1810 0 : return NULL;
1811 :
1812 : /*
1813 : * Also reject sublinks in the stuff we intend to pull up. (It might be
1814 : * possible to support this, but doesn't seem worth the complication.)
1815 : */
1816 84 : if (contain_subplans((Node *) leftargs))
1817 0 : return NULL;
1818 :
1819 : /*
1820 : * Okay, adjust the sublevelsup in the stuff we're pulling up.
1821 : */
1822 84 : IncrementVarSublevelsUp((Node *) leftargs, -1, 1);
1823 :
1824 : /*
1825 : * Put back any child-level-only WHERE clauses.
1826 : */
1827 84 : if (newWhere)
1828 58 : subselect->jointree->quals = (Node *) make_ands_explicit(newWhere);
1829 :
1830 : /*
1831 : * Build a new targetlist for the child that emits the expressions we
1832 : * need. Concurrently, build a testexpr for the parent using Params to
1833 : * reference the child outputs. (Since we generate Params directly here,
1834 : * there will be no need to convert the testexpr in build_subplan.)
1835 : */
1836 84 : tlist = testlist = paramids = NIL;
1837 84 : resno = 1;
1838 : /* there's no "forfour" so we have to chase one of the lists manually */
1839 84 : cc = list_head(opcollations);
1840 198 : forthree(lc, leftargs, rc, rightargs, oc, opids)
1841 : {
1842 114 : Node *leftarg = (Node *) lfirst(lc);
1843 114 : Node *rightarg = (Node *) lfirst(rc);
1844 114 : Oid opid = lfirst_oid(oc);
1845 114 : Oid opcollation = lfirst_oid(cc);
1846 : Param *param;
1847 :
1848 114 : cc = lnext(cc);
1849 114 : param = generate_new_param(root,
1850 : exprType(rightarg),
1851 : exprTypmod(rightarg),
1852 : exprCollation(rightarg));
1853 114 : tlist = lappend(tlist,
1854 114 : makeTargetEntry((Expr *) rightarg,
1855 114 : resno++,
1856 : NULL,
1857 : false));
1858 114 : testlist = lappend(testlist,
1859 114 : make_opclause(opid, BOOLOID, false,
1860 : (Expr *) leftarg, (Expr *) param,
1861 : InvalidOid, opcollation));
1862 114 : paramids = lappend_int(paramids, param->paramid);
1863 : }
1864 :
1865 : /* Put everything where it should go, and we're done */
1866 84 : subselect->targetList = tlist;
1867 84 : *testexpr = (Node *) make_ands_explicit(testlist);
1868 84 : *paramIds = paramids;
1869 :
1870 84 : return subselect;
1871 : }
1872 :
1873 :
1874 : /*
1875 : * Replace correlation vars (uplevel vars) with Params.
1876 : *
1877 : * Uplevel PlaceHolderVars and aggregates are replaced, too.
1878 : *
1879 : * Note: it is critical that this runs immediately after SS_process_sublinks.
1880 : * Since we do not recurse into the arguments of uplevel PHVs and aggregates,
1881 : * they will get copied to the appropriate subplan args list in the parent
1882 : * query with uplevel vars not replaced by Params, but only adjusted in level
1883 : * (see replace_outer_placeholdervar and replace_outer_agg). That's exactly
1884 : * what we want for the vars of the parent level --- but if a PHV's or
1885 : * aggregate's argument contains any further-up variables, they have to be
1886 : * replaced with Params in their turn. That will happen when the parent level
1887 : * runs SS_replace_correlation_vars. Therefore it must do so after expanding
1888 : * its sublinks to subplans. And we don't want any steps in between, else
1889 : * those steps would never get applied to the argument expressions, either in
1890 : * the parent or the child level.
1891 : *
1892 : * Another fairly tricky thing going on here is the handling of SubLinks in
1893 : * the arguments of uplevel PHVs/aggregates. Those are not touched inside the
1894 : * intermediate query level, either. Instead, SS_process_sublinks recurses on
1895 : * them after copying the PHV or Aggref expression into the parent plan level
1896 : * (this is actually taken care of in build_subplan).
1897 : */
1898 : Node *
1899 5968 : SS_replace_correlation_vars(PlannerInfo *root, Node *expr)
1900 : {
1901 : /* No setup needed for tree walk, so away we go */
1902 5968 : return replace_correlation_vars_mutator(expr, root);
1903 : }
1904 :
1905 : static Node *
1906 46007 : replace_correlation_vars_mutator(Node *node, PlannerInfo *root)
1907 : {
1908 46007 : if (node == NULL)
1909 1518 : return NULL;
1910 44489 : if (IsA(node, Var))
1911 : {
1912 11867 : if (((Var *) node)->varlevelsup > 0)
1913 2509 : return (Node *) replace_outer_var(root, (Var *) node);
1914 : }
1915 41980 : if (IsA(node, PlaceHolderVar))
1916 : {
1917 7 : if (((PlaceHolderVar *) node)->phlevelsup > 0)
1918 7 : return (Node *) replace_outer_placeholdervar(root,
1919 : (PlaceHolderVar *) node);
1920 : }
1921 41973 : if (IsA(node, Aggref))
1922 : {
1923 320 : if (((Aggref *) node)->agglevelsup > 0)
1924 6 : return (Node *) replace_outer_agg(root, (Aggref *) node);
1925 : }
1926 41967 : if (IsA(node, GroupingFunc))
1927 : {
1928 8 : if (((GroupingFunc *) node)->agglevelsup > 0)
1929 4 : return (Node *) replace_outer_grouping(root, (GroupingFunc *) node);
1930 : }
1931 41963 : return expression_tree_mutator(node,
1932 : replace_correlation_vars_mutator,
1933 : (void *) root);
1934 : }
1935 :
1936 : /*
1937 : * Expand SubLinks to SubPlans in the given expression.
1938 : *
1939 : * The isQual argument tells whether or not this expression is a WHERE/HAVING
1940 : * qualifier expression. If it is, any sublinks appearing at top level need
1941 : * not distinguish FALSE from UNKNOWN return values.
1942 : */
1943 : Node *
1944 3618 : SS_process_sublinks(PlannerInfo *root, Node *expr, bool isQual)
1945 : {
1946 : process_sublinks_context context;
1947 :
1948 3618 : context.root = root;
1949 3618 : context.isTopQual = isQual;
1950 3618 : return process_sublinks_mutator(expr, &context);
1951 : }
1952 :
1953 : static Node *
1954 53309 : process_sublinks_mutator(Node *node, process_sublinks_context *context)
1955 : {
1956 : process_sublinks_context locContext;
1957 :
1958 53309 : locContext.root = context->root;
1959 :
1960 53309 : if (node == NULL)
1961 2545 : return NULL;
1962 50764 : if (IsA(node, SubLink))
1963 : {
1964 1627 : SubLink *sublink = (SubLink *) node;
1965 : Node *testexpr;
1966 :
1967 : /*
1968 : * First, recursively process the lefthand-side expressions, if any.
1969 : * They're not top-level anymore.
1970 : */
1971 1627 : locContext.isTopQual = false;
1972 1627 : testexpr = process_sublinks_mutator(sublink->testexpr, &locContext);
1973 :
1974 : /*
1975 : * Now build the SubPlan node and make the expr to return.
1976 : */
1977 3254 : return make_subplan(context->root,
1978 1627 : (Query *) sublink->subselect,
1979 : sublink->subLinkType,
1980 : sublink->subLinkId,
1981 : testexpr,
1982 1627 : context->isTopQual);
1983 : }
1984 :
1985 : /*
1986 : * Don't recurse into the arguments of an outer PHV or aggregate here. Any
1987 : * SubLinks in the arguments have to be dealt with at the outer query
1988 : * level; they'll be handled when build_subplan collects the PHV or Aggref
1989 : * into the arguments to be passed down to the current subplan.
1990 : */
1991 49137 : if (IsA(node, PlaceHolderVar))
1992 : {
1993 6 : if (((PlaceHolderVar *) node)->phlevelsup > 0)
1994 1 : return node;
1995 : }
1996 49131 : else if (IsA(node, Aggref))
1997 : {
1998 59 : if (((Aggref *) node)->agglevelsup > 0)
1999 2 : return node;
2000 : }
2001 :
2002 : /*
2003 : * We should never see a SubPlan expression in the input (since this is
2004 : * the very routine that creates 'em to begin with). We shouldn't find
2005 : * ourselves invoked directly on a Query, either.
2006 : */
2007 49134 : Assert(!IsA(node, SubPlan));
2008 49134 : Assert(!IsA(node, AlternativeSubPlan));
2009 49134 : Assert(!IsA(node, Query));
2010 :
2011 : /*
2012 : * Because make_subplan() could return an AND or OR clause, we have to
2013 : * take steps to preserve AND/OR flatness of a qual. We assume the input
2014 : * has been AND/OR flattened and so we need no recursion here.
2015 : *
2016 : * (Due to the coding here, we will not get called on the List subnodes of
2017 : * an AND; and the input is *not* yet in implicit-AND format. So no check
2018 : * is needed for a bare List.)
2019 : *
2020 : * Anywhere within the top-level AND/OR clause structure, we can tell
2021 : * make_subplan() that NULL and FALSE are interchangeable. So isTopQual
2022 : * propagates down in both cases. (Note that this is unlike the meaning
2023 : * of "top level qual" used in most other places in Postgres.)
2024 : */
2025 49134 : if (and_clause(node))
2026 : {
2027 516 : List *newargs = NIL;
2028 : ListCell *l;
2029 :
2030 : /* Still at qual top-level */
2031 516 : locContext.isTopQual = context->isTopQual;
2032 :
2033 2010 : foreach(l, ((BoolExpr *) node)->args)
2034 : {
2035 : Node *newarg;
2036 :
2037 1494 : newarg = process_sublinks_mutator(lfirst(l), &locContext);
2038 1494 : if (and_clause(newarg))
2039 0 : newargs = list_concat(newargs, ((BoolExpr *) newarg)->args);
2040 : else
2041 1494 : newargs = lappend(newargs, newarg);
2042 : }
2043 516 : return (Node *) make_andclause(newargs);
2044 : }
2045 :
2046 48618 : if (or_clause(node))
2047 : {
2048 59 : List *newargs = NIL;
2049 : ListCell *l;
2050 :
2051 : /* Still at qual top-level */
2052 59 : locContext.isTopQual = context->isTopQual;
2053 :
2054 214 : foreach(l, ((BoolExpr *) node)->args)
2055 : {
2056 : Node *newarg;
2057 :
2058 155 : newarg = process_sublinks_mutator(lfirst(l), &locContext);
2059 155 : if (or_clause(newarg))
2060 0 : newargs = list_concat(newargs, ((BoolExpr *) newarg)->args);
2061 : else
2062 155 : newargs = lappend(newargs, newarg);
2063 : }
2064 59 : return (Node *) make_orclause(newargs);
2065 : }
2066 :
2067 : /*
2068 : * If we recurse down through anything other than an AND or OR node, we
2069 : * are definitely not at top qual level anymore.
2070 : */
2071 48559 : locContext.isTopQual = false;
2072 :
2073 48559 : return expression_tree_mutator(node,
2074 : process_sublinks_mutator,
2075 : (void *) &locContext);
2076 : }
2077 :
2078 : /*
2079 : * SS_identify_outer_params - identify the Params available from outer levels
2080 : *
2081 : * This must be run after SS_replace_correlation_vars and SS_process_sublinks
2082 : * processing is complete in a given query level as well as all of its
2083 : * descendant levels (which means it's most practical to do it at the end of
2084 : * processing the query level). We compute the set of paramIds that outer
2085 : * levels will make available to this level+descendants, and record it in
2086 : * root->outer_params for use while computing extParam/allParam sets in final
2087 : * plan cleanup. (We can't just compute it then, because the upper levels'
2088 : * plan_params lists are transient and will be gone by then.)
2089 : */
2090 : void
2091 25328 : SS_identify_outer_params(PlannerInfo *root)
2092 : {
2093 : Bitmapset *outer_params;
2094 : PlannerInfo *proot;
2095 : ListCell *l;
2096 :
2097 : /*
2098 : * If no parameters have been assigned anywhere in the tree, we certainly
2099 : * don't need to do anything here.
2100 : */
2101 25328 : if (root->glob->nParamExec == 0)
2102 42953 : return;
2103 :
2104 : /*
2105 : * Scan all query levels above this one to see which parameters are due to
2106 : * be available from them, either because lower query levels have
2107 : * requested them (via plan_params) or because they will be available from
2108 : * initPlans of those levels.
2109 : */
2110 7703 : outer_params = NULL;
2111 9743 : for (proot = root->parent_root; proot != NULL; proot = proot->parent_root)
2112 : {
2113 : /* Include ordinary Var/PHV/Aggref params */
2114 4339 : foreach(l, proot->plan_params)
2115 : {
2116 2299 : PlannerParamItem *pitem = (PlannerParamItem *) lfirst(l);
2117 :
2118 2299 : outer_params = bms_add_member(outer_params, pitem->paramId);
2119 : }
2120 : /* Include any outputs of outer-level initPlans */
2121 2201 : foreach(l, proot->init_plans)
2122 : {
2123 161 : SubPlan *initsubplan = (SubPlan *) lfirst(l);
2124 : ListCell *l2;
2125 :
2126 322 : foreach(l2, initsubplan->setParam)
2127 : {
2128 161 : outer_params = bms_add_member(outer_params, lfirst_int(l2));
2129 : }
2130 : }
2131 : /* Include worktable ID, if a recursive query is being planned */
2132 2040 : if (proot->wt_param_id >= 0)
2133 101 : outer_params = bms_add_member(outer_params, proot->wt_param_id);
2134 : }
2135 7703 : root->outer_params = outer_params;
2136 : }
2137 :
2138 : /*
2139 : * SS_charge_for_initplans - account for initplans in Path costs & parallelism
2140 : *
2141 : * If any initPlans have been created in the current query level, they will
2142 : * get attached to the Plan tree created from whichever Path we select from
2143 : * the given rel. Increment all that rel's Paths' costs to account for them,
2144 : * and make sure the paths get marked as parallel-unsafe, since we can't
2145 : * currently transmit initPlans to parallel workers.
2146 : *
2147 : * This is separate from SS_attach_initplans because we might conditionally
2148 : * create more initPlans during create_plan(), depending on which Path we
2149 : * select. However, Paths that would generate such initPlans are expected
2150 : * to have included their cost already.
2151 : */
2152 : void
2153 25328 : SS_charge_for_initplans(PlannerInfo *root, RelOptInfo *final_rel)
2154 : {
2155 : Cost initplan_cost;
2156 : ListCell *lc;
2157 :
2158 : /* Nothing to do if no initPlans */
2159 25328 : if (root->init_plans == NIL)
2160 50250 : return;
2161 :
2162 : /*
2163 : * Compute the cost increment just once, since it will be the same for all
2164 : * Paths. We assume each initPlan gets run once during top plan startup.
2165 : * This is a conservative overestimate, since in fact an initPlan might be
2166 : * executed later than plan startup, or even not at all.
2167 : */
2168 406 : initplan_cost = 0;
2169 900 : foreach(lc, root->init_plans)
2170 : {
2171 494 : SubPlan *initsubplan = (SubPlan *) lfirst(lc);
2172 :
2173 494 : initplan_cost += initsubplan->startup_cost + initsubplan->per_call_cost;
2174 : }
2175 :
2176 : /*
2177 : * Now adjust the costs and parallel_safe flags.
2178 : */
2179 814 : foreach(lc, final_rel->pathlist)
2180 : {
2181 408 : Path *path = (Path *) lfirst(lc);
2182 :
2183 408 : path->startup_cost += initplan_cost;
2184 408 : path->total_cost += initplan_cost;
2185 408 : path->parallel_safe = false;
2186 : }
2187 :
2188 : /* We needn't do set_cheapest() here, caller will do it */
2189 : }
2190 :
2191 : /*
2192 : * SS_attach_initplans - attach initplans to topmost plan node
2193 : *
2194 : * Attach any initplans created in the current query level to the specified
2195 : * plan node, which should normally be the topmost node for the query level.
2196 : * (In principle the initPlans could go in any node at or above where they're
2197 : * referenced; but there seems no reason to put them any lower than the
2198 : * topmost node, so we don't bother to track exactly where they came from.)
2199 : * We do not touch the plan node's cost; the initplans should have been
2200 : * accounted for in path costing.
2201 : */
2202 : void
2203 25224 : SS_attach_initplans(PlannerInfo *root, Plan *plan)
2204 : {
2205 25224 : plan->initPlan = root->init_plans;
2206 25224 : }
2207 :
2208 : /*
2209 : * SS_finalize_plan - do final parameter processing for a completed Plan.
2210 : *
2211 : * This recursively computes the extParam and allParam sets for every Plan
2212 : * node in the given plan tree. (Oh, and RangeTblFunction.funcparams too.)
2213 : *
2214 : * We assume that SS_finalize_plan has already been run on any initplans or
2215 : * subplans the plan tree could reference.
2216 : */
2217 : void
2218 8755 : SS_finalize_plan(PlannerInfo *root, Plan *plan)
2219 : {
2220 : /* No setup needed, just recurse through plan tree. */
2221 8755 : (void) finalize_plan(root, plan, -1, root->outer_params, NULL);
2222 8755 : }
2223 :
2224 : /*
2225 : * Recursive processing of all nodes in the plan tree
2226 : *
2227 : * gather_param is the rescan_param of an ancestral Gather/GatherMerge,
2228 : * or -1 if there is none.
2229 : *
2230 : * valid_params is the set of param IDs supplied by outer plan levels
2231 : * that are valid to reference in this plan node or its children.
2232 : *
2233 : * scan_params is a set of param IDs to force scan plan nodes to reference.
2234 : * This is for EvalPlanQual support, and is always NULL at the top of the
2235 : * recursion.
2236 : *
2237 : * The return value is the computed allParam set for the given Plan node.
2238 : * This is just an internal notational convenience: we can add a child
2239 : * plan's allParams to the set of param IDs of interest to this level
2240 : * in the same statement that recurses to that child.
2241 : *
2242 : * Do not scribble on caller's values of valid_params or scan_params!
2243 : *
2244 : * Note: although we attempt to deal with initPlans anywhere in the tree, the
2245 : * logic is not really right. The problem is that a plan node might return an
2246 : * output Param of its initPlan as a targetlist item, in which case it's valid
2247 : * for the parent plan level to reference that same Param; the parent's usage
2248 : * will be converted into a Var referencing the child plan node by setrefs.c.
2249 : * But this function would see the parent's reference as out of scope and
2250 : * complain about it. For now, this does not matter because the planner only
2251 : * attaches initPlans to the topmost plan node in a query level, so the case
2252 : * doesn't arise. If we ever merge this processing into setrefs.c, maybe it
2253 : * can be handled more cleanly.
2254 : */
2255 : static Bitmapset *
2256 55528 : finalize_plan(PlannerInfo *root, Plan *plan,
2257 : int gather_param,
2258 : Bitmapset *valid_params,
2259 : Bitmapset *scan_params)
2260 : {
2261 : finalize_primnode_context context;
2262 : int locally_added_param;
2263 : Bitmapset *nestloop_params;
2264 : Bitmapset *initExtParam;
2265 : Bitmapset *initSetParam;
2266 : Bitmapset *child_params;
2267 : ListCell *l;
2268 :
2269 55528 : if (plan == NULL)
2270 34578 : return NULL;
2271 :
2272 20950 : context.root = root;
2273 20950 : context.paramids = NULL; /* initialize set to empty */
2274 20950 : locally_added_param = -1; /* there isn't one */
2275 20950 : nestloop_params = NULL; /* there aren't any */
2276 :
2277 : /*
2278 : * Examine any initPlans to determine the set of external params they
2279 : * reference and the set of output params they supply. (We assume
2280 : * SS_finalize_plan was run on them already.)
2281 : */
2282 20950 : initExtParam = initSetParam = NULL;
2283 21523 : foreach(l, plan->initPlan)
2284 : {
2285 573 : SubPlan *initsubplan = (SubPlan *) lfirst(l);
2286 573 : Plan *initplan = planner_subplan_get_plan(root, initsubplan);
2287 : ListCell *l2;
2288 :
2289 573 : initExtParam = bms_add_members(initExtParam, initplan->extParam);
2290 1150 : foreach(l2, initsubplan->setParam)
2291 : {
2292 577 : initSetParam = bms_add_member(initSetParam, lfirst_int(l2));
2293 : }
2294 : }
2295 :
2296 : /* Any setParams are validly referenceable in this node and children */
2297 20950 : if (initSetParam)
2298 477 : valid_params = bms_union(valid_params, initSetParam);
2299 :
2300 : /*
2301 : * When we call finalize_primnode, context.paramids sets are automatically
2302 : * merged together. But when recursing to self, we have to do it the hard
2303 : * way. We want the paramids set to include params in subplans as well as
2304 : * at this level.
2305 : */
2306 :
2307 : /* Find params in targetlist and qual */
2308 20950 : finalize_primnode((Node *) plan->targetlist, &context);
2309 20950 : finalize_primnode((Node *) plan->qual, &context);
2310 :
2311 : /*
2312 : * If it's a parallel-aware scan node, mark it as dependent on the parent
2313 : * Gather/GatherMerge's rescan Param.
2314 : */
2315 20950 : if (plan->parallel_aware)
2316 : {
2317 41 : if (gather_param < 0)
2318 0 : elog(ERROR, "parallel-aware plan node is not below a Gather");
2319 41 : context.paramids =
2320 41 : bms_add_member(context.paramids, gather_param);
2321 : }
2322 :
2323 : /* Check additional node-type-specific fields */
2324 20950 : switch (nodeTag(plan))
2325 : {
2326 : case T_Result:
2327 3670 : finalize_primnode(((Result *) plan)->resconstantqual,
2328 : &context);
2329 3670 : break;
2330 :
2331 : case T_SeqScan:
2332 3172 : context.paramids = bms_add_members(context.paramids, scan_params);
2333 3172 : break;
2334 :
2335 : case T_SampleScan:
2336 7 : finalize_primnode((Node *) ((SampleScan *) plan)->tablesample,
2337 : &context);
2338 7 : context.paramids = bms_add_members(context.paramids, scan_params);
2339 7 : break;
2340 :
2341 : case T_IndexScan:
2342 2482 : finalize_primnode((Node *) ((IndexScan *) plan)->indexqual,
2343 : &context);
2344 2482 : finalize_primnode((Node *) ((IndexScan *) plan)->indexorderby,
2345 : &context);
2346 :
2347 : /*
2348 : * we need not look at indexqualorig, since it will have the same
2349 : * param references as indexqual. Likewise, we can ignore
2350 : * indexorderbyorig.
2351 : */
2352 2482 : context.paramids = bms_add_members(context.paramids, scan_params);
2353 2482 : break;
2354 :
2355 : case T_IndexOnlyScan:
2356 333 : finalize_primnode((Node *) ((IndexOnlyScan *) plan)->indexqual,
2357 : &context);
2358 333 : finalize_primnode((Node *) ((IndexOnlyScan *) plan)->indexorderby,
2359 : &context);
2360 :
2361 : /*
2362 : * we need not look at indextlist, since it cannot contain Params.
2363 : */
2364 333 : context.paramids = bms_add_members(context.paramids, scan_params);
2365 333 : break;
2366 :
2367 : case T_BitmapIndexScan:
2368 338 : finalize_primnode((Node *) ((BitmapIndexScan *) plan)->indexqual,
2369 : &context);
2370 :
2371 : /*
2372 : * we need not look at indexqualorig, since it will have the same
2373 : * param references as indexqual.
2374 : */
2375 338 : break;
2376 :
2377 : case T_BitmapHeapScan:
2378 337 : finalize_primnode((Node *) ((BitmapHeapScan *) plan)->bitmapqualorig,
2379 : &context);
2380 337 : context.paramids = bms_add_members(context.paramids, scan_params);
2381 337 : break;
2382 :
2383 : case T_TidScan:
2384 57 : finalize_primnode((Node *) ((TidScan *) plan)->tidquals,
2385 : &context);
2386 57 : context.paramids = bms_add_members(context.paramids, scan_params);
2387 57 : break;
2388 :
2389 : case T_SubqueryScan:
2390 : {
2391 360 : SubqueryScan *sscan = (SubqueryScan *) plan;
2392 : RelOptInfo *rel;
2393 :
2394 : /* We must run SS_finalize_plan on the subquery */
2395 360 : rel = find_base_rel(root, sscan->scan.scanrelid);
2396 360 : SS_finalize_plan(rel->subroot, sscan->subplan);
2397 :
2398 : /* Now we can add its extParams to the parent's params */
2399 360 : context.paramids = bms_add_members(context.paramids,
2400 360 : sscan->subplan->extParam);
2401 : /* We need scan_params too, though */
2402 360 : context.paramids = bms_add_members(context.paramids,
2403 : scan_params);
2404 : }
2405 360 : break;
2406 :
2407 : case T_FunctionScan:
2408 : {
2409 629 : FunctionScan *fscan = (FunctionScan *) plan;
2410 : ListCell *lc;
2411 :
2412 : /*
2413 : * Call finalize_primnode independently on each function
2414 : * expression, so that we can record which params are
2415 : * referenced in each, in order to decide which need
2416 : * re-evaluating during rescan.
2417 : */
2418 1262 : foreach(lc, fscan->functions)
2419 : {
2420 633 : RangeTblFunction *rtfunc = (RangeTblFunction *) lfirst(lc);
2421 : finalize_primnode_context funccontext;
2422 :
2423 633 : funccontext = context;
2424 633 : funccontext.paramids = NULL;
2425 :
2426 633 : finalize_primnode(rtfunc->funcexpr, &funccontext);
2427 :
2428 : /* remember results for execution */
2429 633 : rtfunc->funcparams = funccontext.paramids;
2430 :
2431 : /* add the function's params to the overall set */
2432 633 : context.paramids = bms_add_members(context.paramids,
2433 633 : funccontext.paramids);
2434 : }
2435 :
2436 629 : context.paramids = bms_add_members(context.paramids,
2437 : scan_params);
2438 : }
2439 629 : break;
2440 :
2441 : case T_TableFuncScan:
2442 22 : finalize_primnode((Node *) ((TableFuncScan *) plan)->tablefunc,
2443 : &context);
2444 22 : context.paramids = bms_add_members(context.paramids, scan_params);
2445 22 : break;
2446 :
2447 : case T_ValuesScan:
2448 233 : finalize_primnode((Node *) ((ValuesScan *) plan)->values_lists,
2449 : &context);
2450 233 : context.paramids = bms_add_members(context.paramids, scan_params);
2451 233 : break;
2452 :
2453 : case T_CteScan:
2454 : {
2455 : /*
2456 : * You might think we should add the node's cteParam to
2457 : * paramids, but we shouldn't because that param is just a
2458 : * linkage mechanism for multiple CteScan nodes for the same
2459 : * CTE; it is never used for changed-param signaling. What we
2460 : * have to do instead is to find the referenced CTE plan and
2461 : * incorporate its external paramids, so that the correct
2462 : * things will happen if the CTE references outer-level
2463 : * variables. See test cases for bug #4902. (We assume
2464 : * SS_finalize_plan was run on the CTE plan already.)
2465 : */
2466 162 : int plan_id = ((CteScan *) plan)->ctePlanId;
2467 : Plan *cteplan;
2468 :
2469 : /* so, do this ... */
2470 162 : if (plan_id < 1 || plan_id > list_length(root->glob->subplans))
2471 0 : elog(ERROR, "could not find plan for CteScan referencing plan ID %d",
2472 : plan_id);
2473 162 : cteplan = (Plan *) list_nth(root->glob->subplans, plan_id - 1);
2474 162 : context.paramids =
2475 162 : bms_add_members(context.paramids, cteplan->extParam);
2476 :
2477 : #ifdef NOT_USED
2478 : /* ... but not this */
2479 : context.paramids =
2480 : bms_add_member(context.paramids,
2481 : ((CteScan *) plan)->cteParam);
2482 : #endif
2483 :
2484 162 : context.paramids = bms_add_members(context.paramids,
2485 : scan_params);
2486 : }
2487 162 : break;
2488 :
2489 : case T_WorkTableScan:
2490 40 : context.paramids =
2491 40 : bms_add_member(context.paramids,
2492 : ((WorkTableScan *) plan)->wtParam);
2493 40 : context.paramids = bms_add_members(context.paramids, scan_params);
2494 40 : break;
2495 :
2496 : case T_NamedTuplestoreScan:
2497 37 : context.paramids = bms_add_members(context.paramids, scan_params);
2498 37 : break;
2499 :
2500 : case T_ForeignScan:
2501 : {
2502 0 : ForeignScan *fscan = (ForeignScan *) plan;
2503 :
2504 0 : finalize_primnode((Node *) fscan->fdw_exprs,
2505 : &context);
2506 0 : finalize_primnode((Node *) fscan->fdw_recheck_quals,
2507 : &context);
2508 :
2509 : /* We assume fdw_scan_tlist cannot contain Params */
2510 0 : context.paramids = bms_add_members(context.paramids,
2511 : scan_params);
2512 : }
2513 0 : break;
2514 :
2515 : case T_CustomScan:
2516 : {
2517 0 : CustomScan *cscan = (CustomScan *) plan;
2518 : ListCell *lc;
2519 :
2520 0 : finalize_primnode((Node *) cscan->custom_exprs,
2521 : &context);
2522 : /* We assume custom_scan_tlist cannot contain Params */
2523 0 : context.paramids =
2524 0 : bms_add_members(context.paramids, scan_params);
2525 :
2526 : /* child nodes if any */
2527 0 : foreach(lc, cscan->custom_plans)
2528 : {
2529 0 : context.paramids =
2530 0 : bms_add_members(context.paramids,
2531 0 : finalize_plan(root,
2532 0 : (Plan *) lfirst(lc),
2533 : gather_param,
2534 : valid_params,
2535 : scan_params));
2536 : }
2537 : }
2538 0 : break;
2539 :
2540 : case T_ModifyTable:
2541 : {
2542 4314 : ModifyTable *mtplan = (ModifyTable *) plan;
2543 : ListCell *l;
2544 :
2545 : /* Force descendant scan nodes to reference epqParam */
2546 4314 : locally_added_param = mtplan->epqParam;
2547 4314 : valid_params = bms_add_member(bms_copy(valid_params),
2548 : locally_added_param);
2549 4314 : scan_params = bms_add_member(bms_copy(scan_params),
2550 : locally_added_param);
2551 4314 : finalize_primnode((Node *) mtplan->returningLists,
2552 : &context);
2553 4314 : finalize_primnode((Node *) mtplan->onConflictSet,
2554 : &context);
2555 4314 : finalize_primnode((Node *) mtplan->onConflictWhere,
2556 : &context);
2557 : /* exclRelTlist contains only Vars, doesn't need examination */
2558 8744 : foreach(l, mtplan->plans)
2559 : {
2560 4430 : context.paramids =
2561 4430 : bms_add_members(context.paramids,
2562 4430 : finalize_plan(root,
2563 4430 : (Plan *) lfirst(l),
2564 : gather_param,
2565 : valid_params,
2566 : scan_params));
2567 : }
2568 : }
2569 4314 : break;
2570 :
2571 : case T_Append:
2572 : {
2573 : ListCell *l;
2574 :
2575 529 : foreach(l, ((Append *) plan)->appendplans)
2576 : {
2577 389 : context.paramids =
2578 389 : bms_add_members(context.paramids,
2579 389 : finalize_plan(root,
2580 389 : (Plan *) lfirst(l),
2581 : gather_param,
2582 : valid_params,
2583 : scan_params));
2584 : }
2585 : }
2586 140 : break;
2587 :
2588 : case T_MergeAppend:
2589 : {
2590 : ListCell *l;
2591 :
2592 70 : foreach(l, ((MergeAppend *) plan)->mergeplans)
2593 : {
2594 52 : context.paramids =
2595 52 : bms_add_members(context.paramids,
2596 52 : finalize_plan(root,
2597 52 : (Plan *) lfirst(l),
2598 : gather_param,
2599 : valid_params,
2600 : scan_params));
2601 : }
2602 : }
2603 18 : break;
2604 :
2605 : case T_BitmapAnd:
2606 : {
2607 : ListCell *l;
2608 :
2609 0 : foreach(l, ((BitmapAnd *) plan)->bitmapplans)
2610 : {
2611 0 : context.paramids =
2612 0 : bms_add_members(context.paramids,
2613 0 : finalize_plan(root,
2614 0 : (Plan *) lfirst(l),
2615 : gather_param,
2616 : valid_params,
2617 : scan_params));
2618 : }
2619 : }
2620 0 : break;
2621 :
2622 : case T_BitmapOr:
2623 : {
2624 : ListCell *l;
2625 :
2626 3 : foreach(l, ((BitmapOr *) plan)->bitmapplans)
2627 : {
2628 2 : context.paramids =
2629 2 : bms_add_members(context.paramids,
2630 2 : finalize_plan(root,
2631 2 : (Plan *) lfirst(l),
2632 : gather_param,
2633 : valid_params,
2634 : scan_params));
2635 : }
2636 : }
2637 1 : break;
2638 :
2639 : case T_NestLoop:
2640 : {
2641 : ListCell *l;
2642 :
2643 1605 : finalize_primnode((Node *) ((Join *) plan)->joinqual,
2644 : &context);
2645 : /* collect set of params that will be passed to right child */
2646 2717 : foreach(l, ((NestLoop *) plan)->nestParams)
2647 : {
2648 1112 : NestLoopParam *nlp = (NestLoopParam *) lfirst(l);
2649 :
2650 1112 : nestloop_params = bms_add_member(nestloop_params,
2651 : nlp->paramno);
2652 : }
2653 : }
2654 1605 : break;
2655 :
2656 : case T_MergeJoin:
2657 36 : finalize_primnode((Node *) ((Join *) plan)->joinqual,
2658 : &context);
2659 36 : finalize_primnode((Node *) ((MergeJoin *) plan)->mergeclauses,
2660 : &context);
2661 36 : break;
2662 :
2663 : case T_HashJoin:
2664 408 : finalize_primnode((Node *) ((Join *) plan)->joinqual,
2665 : &context);
2666 408 : finalize_primnode((Node *) ((HashJoin *) plan)->hashclauses,
2667 : &context);
2668 408 : break;
2669 :
2670 : case T_Limit:
2671 167 : finalize_primnode(((Limit *) plan)->limitOffset,
2672 : &context);
2673 167 : finalize_primnode(((Limit *) plan)->limitCount,
2674 : &context);
2675 167 : break;
2676 :
2677 : case T_RecursiveUnion:
2678 : /* child nodes are allowed to reference wtParam */
2679 40 : locally_added_param = ((RecursiveUnion *) plan)->wtParam;
2680 40 : valid_params = bms_add_member(bms_copy(valid_params),
2681 : locally_added_param);
2682 : /* wtParam does *not* get added to scan_params */
2683 40 : break;
2684 :
2685 : case T_LockRows:
2686 : /* Force descendant scan nodes to reference epqParam */
2687 328 : locally_added_param = ((LockRows *) plan)->epqParam;
2688 328 : valid_params = bms_add_member(bms_copy(valid_params),
2689 : locally_added_param);
2690 328 : scan_params = bms_add_member(bms_copy(scan_params),
2691 : locally_added_param);
2692 328 : break;
2693 :
2694 : case T_Agg:
2695 : {
2696 404 : Agg *agg = (Agg *) plan;
2697 :
2698 : /*
2699 : * AGG_HASHED plans need to know which Params are referenced
2700 : * in aggregate calls. Do a separate scan to identify them.
2701 : */
2702 404 : if (agg->aggstrategy == AGG_HASHED)
2703 : {
2704 : finalize_primnode_context aggcontext;
2705 :
2706 40 : aggcontext.root = root;
2707 40 : aggcontext.paramids = NULL;
2708 40 : finalize_agg_primnode((Node *) agg->plan.targetlist,
2709 : &aggcontext);
2710 40 : finalize_agg_primnode((Node *) agg->plan.qual,
2711 : &aggcontext);
2712 40 : agg->aggParams = aggcontext.paramids;
2713 : }
2714 : }
2715 404 : break;
2716 :
2717 : case T_WindowAgg:
2718 8 : finalize_primnode(((WindowAgg *) plan)->startOffset,
2719 : &context);
2720 8 : finalize_primnode(((WindowAgg *) plan)->endOffset,
2721 : &context);
2722 8 : break;
2723 :
2724 : case T_Gather:
2725 : /* child nodes are allowed to reference rescan_param, if any */
2726 23 : locally_added_param = ((Gather *) plan)->rescan_param;
2727 23 : if (locally_added_param >= 0)
2728 : {
2729 23 : valid_params = bms_add_member(bms_copy(valid_params),
2730 : locally_added_param);
2731 :
2732 : /*
2733 : * We currently don't support nested Gathers. The issue so
2734 : * far as this function is concerned would be how to identify
2735 : * which child nodes depend on which Gather.
2736 : */
2737 23 : Assert(gather_param < 0);
2738 : /* Pass down rescan_param to child parallel-aware nodes */
2739 23 : gather_param = locally_added_param;
2740 : }
2741 : /* rescan_param does *not* get added to scan_params */
2742 23 : break;
2743 :
2744 : case T_GatherMerge:
2745 : /* child nodes are allowed to reference rescan_param, if any */
2746 8 : locally_added_param = ((GatherMerge *) plan)->rescan_param;
2747 8 : if (locally_added_param >= 0)
2748 : {
2749 8 : valid_params = bms_add_member(bms_copy(valid_params),
2750 : locally_added_param);
2751 :
2752 : /*
2753 : * We currently don't support nested Gathers. The issue so
2754 : * far as this function is concerned would be how to identify
2755 : * which child nodes depend on which Gather.
2756 : */
2757 8 : Assert(gather_param < 0);
2758 : /* Pass down rescan_param to child parallel-aware nodes */
2759 8 : gather_param = locally_added_param;
2760 : }
2761 : /* rescan_param does *not* get added to scan_params */
2762 8 : break;
2763 :
2764 : case T_ProjectSet:
2765 : case T_Hash:
2766 : case T_Material:
2767 : case T_Sort:
2768 : case T_Unique:
2769 : case T_SetOp:
2770 : case T_Group:
2771 : /* no node-type-specific fields need fixing */
2772 1571 : break;
2773 :
2774 : default:
2775 0 : elog(ERROR, "unrecognized node type: %d",
2776 : (int) nodeTag(plan));
2777 : }
2778 :
2779 : /* Process left and right child plans, if any */
2780 20950 : child_params = finalize_plan(root,
2781 20950 : plan->lefttree,
2782 : gather_param,
2783 : valid_params,
2784 : scan_params);
2785 20950 : context.paramids = bms_add_members(context.paramids, child_params);
2786 :
2787 20950 : if (nestloop_params)
2788 : {
2789 : /* right child can reference nestloop_params as well as valid_params */
2790 2030 : child_params = finalize_plan(root,
2791 1015 : plan->righttree,
2792 : gather_param,
2793 : bms_union(nestloop_params, valid_params),
2794 : scan_params);
2795 : /* ... and they don't count as parameters used at my level */
2796 1015 : child_params = bms_difference(child_params, nestloop_params);
2797 1015 : bms_free(nestloop_params);
2798 : }
2799 : else
2800 : {
2801 : /* easy case */
2802 19935 : child_params = finalize_plan(root,
2803 19935 : plan->righttree,
2804 : gather_param,
2805 : valid_params,
2806 : scan_params);
2807 : }
2808 20950 : context.paramids = bms_add_members(context.paramids, child_params);
2809 :
2810 : /*
2811 : * Any locally generated parameter doesn't count towards its generating
2812 : * plan node's external dependencies. (Note: if we changed valid_params
2813 : * and/or scan_params, we leak those bitmapsets; not worth the notational
2814 : * trouble to clean them up.)
2815 : */
2816 20950 : if (locally_added_param >= 0)
2817 : {
2818 4713 : context.paramids = bms_del_member(context.paramids,
2819 : locally_added_param);
2820 : }
2821 :
2822 : /* Now we have all the paramids referenced in this node and children */
2823 :
2824 20950 : if (!bms_is_subset(context.paramids, valid_params))
2825 0 : elog(ERROR, "plan should not reference subplan's variable");
2826 :
2827 : /*
2828 : * The plan node's allParam and extParam fields should include all its
2829 : * referenced paramids, plus contributions from any child initPlans.
2830 : * However, any setParams of the initPlans should not be present in the
2831 : * parent node's extParams, only in its allParams. (It's possible that
2832 : * some initPlans have extParams that are setParams of other initPlans.)
2833 : */
2834 :
2835 : /* allParam must include initplans' extParams and setParams */
2836 20950 : plan->allParam = bms_union(context.paramids, initExtParam);
2837 20950 : plan->allParam = bms_add_members(plan->allParam, initSetParam);
2838 : /* extParam must include any initplan extParams */
2839 20950 : plan->extParam = bms_union(context.paramids, initExtParam);
2840 : /* but not any initplan setParams */
2841 20950 : plan->extParam = bms_del_members(plan->extParam, initSetParam);
2842 :
2843 : /*
2844 : * For speed at execution time, make sure extParam/allParam are actually
2845 : * NULL if they are empty sets.
2846 : */
2847 20950 : if (bms_is_empty(plan->extParam))
2848 13897 : plan->extParam = NULL;
2849 20950 : if (bms_is_empty(plan->allParam))
2850 13444 : plan->allParam = NULL;
2851 :
2852 20950 : return plan->allParam;
2853 : }
2854 :
2855 : /*
2856 : * finalize_primnode: add IDs of all PARAM_EXEC params appearing in the given
2857 : * expression tree to the result set.
2858 : */
2859 : static bool
2860 272727 : finalize_primnode(Node *node, finalize_primnode_context *context)
2861 : {
2862 272727 : if (node == NULL)
2863 46673 : return false;
2864 226054 : if (IsA(node, Param))
2865 : {
2866 4611 : if (((Param *) node)->paramkind == PARAM_EXEC)
2867 : {
2868 4322 : int paramid = ((Param *) node)->paramid;
2869 :
2870 4322 : context->paramids = bms_add_member(context->paramids, paramid);
2871 : }
2872 4611 : return false; /* no more to do here */
2873 : }
2874 221443 : if (IsA(node, SubPlan))
2875 : {
2876 1699 : SubPlan *subplan = (SubPlan *) node;
2877 1699 : Plan *plan = planner_subplan_get_plan(context->root, subplan);
2878 : ListCell *lc;
2879 : Bitmapset *subparamids;
2880 :
2881 : /* Recurse into the testexpr, but not into the Plan */
2882 1699 : finalize_primnode(subplan->testexpr, context);
2883 :
2884 : /*
2885 : * Remove any param IDs of output parameters of the subplan that were
2886 : * referenced in the testexpr. These are not interesting for
2887 : * parameter change signaling since we always re-evaluate the subplan.
2888 : * Note that this wouldn't work too well if there might be uses of the
2889 : * same param IDs elsewhere in the plan, but that can't happen because
2890 : * generate_new_param never tries to merge params.
2891 : */
2892 1891 : foreach(lc, subplan->paramIds)
2893 : {
2894 192 : context->paramids = bms_del_member(context->paramids,
2895 : lfirst_int(lc));
2896 : }
2897 :
2898 : /* Also examine args list */
2899 1699 : finalize_primnode((Node *) subplan->args, context);
2900 :
2901 : /*
2902 : * Add params needed by the subplan to paramids, but excluding those
2903 : * we will pass down to it. (We assume SS_finalize_plan was run on
2904 : * the subplan already.)
2905 : */
2906 1699 : subparamids = bms_copy(plan->extParam);
2907 4396 : foreach(lc, subplan->parParam)
2908 : {
2909 2697 : subparamids = bms_del_member(subparamids, lfirst_int(lc));
2910 : }
2911 1699 : context->paramids = bms_join(context->paramids, subparamids);
2912 :
2913 1699 : return false; /* no more to do here */
2914 : }
2915 219744 : return expression_tree_walker(node, finalize_primnode,
2916 : (void *) context);
2917 : }
2918 :
2919 : /*
2920 : * finalize_agg_primnode: find all Aggref nodes in the given expression tree,
2921 : * and add IDs of all PARAM_EXEC params appearing within their aggregated
2922 : * arguments to the result set.
2923 : */
2924 : static bool
2925 280 : finalize_agg_primnode(Node *node, finalize_primnode_context *context)
2926 : {
2927 280 : if (node == NULL)
2928 41 : return false;
2929 239 : if (IsA(node, Aggref))
2930 : {
2931 24 : Aggref *agg = (Aggref *) node;
2932 :
2933 : /* we should not consider the direct arguments, if any */
2934 24 : finalize_primnode((Node *) agg->args, context);
2935 24 : finalize_primnode((Node *) agg->aggfilter, context);
2936 24 : return false; /* there can't be any Aggrefs below here */
2937 : }
2938 215 : return expression_tree_walker(node, finalize_agg_primnode,
2939 : (void *) context);
2940 : }
2941 :
2942 : /*
2943 : * SS_make_initplan_output_param - make a Param for an initPlan's output
2944 : *
2945 : * The plan is expected to return a scalar value of the given type/collation.
2946 : *
2947 : * Note that in some cases the initplan may not ever appear in the finished
2948 : * plan tree. If that happens, we'll have wasted a PARAM_EXEC slot, which
2949 : * is no big deal.
2950 : */
2951 : Param *
2952 92 : SS_make_initplan_output_param(PlannerInfo *root,
2953 : Oid resulttype, int32 resulttypmod,
2954 : Oid resultcollation)
2955 : {
2956 92 : return generate_new_param(root, resulttype, resulttypmod, resultcollation);
2957 : }
2958 :
2959 : /*
2960 : * SS_make_initplan_from_plan - given a plan tree, make it an InitPlan
2961 : *
2962 : * We build an EXPR_SUBLINK SubPlan node and put it into the initplan
2963 : * list for the outer query level. A Param that represents the initplan's
2964 : * output has already been assigned using SS_make_initplan_output_param.
2965 : */
2966 : void
2967 79 : SS_make_initplan_from_plan(PlannerInfo *root,
2968 : PlannerInfo *subroot, Plan *plan,
2969 : Param *prm)
2970 : {
2971 : SubPlan *node;
2972 :
2973 : /*
2974 : * Add the subplan and its PlannerInfo to the global lists.
2975 : */
2976 79 : root->glob->subplans = lappend(root->glob->subplans, plan);
2977 79 : root->glob->subroots = lappend(root->glob->subroots, subroot);
2978 :
2979 : /*
2980 : * Create a SubPlan node and add it to the outer list of InitPlans. Note
2981 : * it has to appear after any other InitPlans it might depend on (see
2982 : * comments in ExecReScan).
2983 : */
2984 79 : node = makeNode(SubPlan);
2985 79 : node->subLinkType = EXPR_SUBLINK;
2986 79 : node->plan_id = list_length(root->glob->subplans);
2987 79 : node->plan_name = psprintf("InitPlan %d (returns $%d)",
2988 : node->plan_id, prm->paramid);
2989 79 : get_first_col_type(plan, &node->firstColType, &node->firstColTypmod,
2990 : &node->firstColCollation);
2991 79 : node->setParam = list_make1_int(prm->paramid);
2992 :
2993 79 : root->init_plans = lappend(root->init_plans, node);
2994 :
2995 : /*
2996 : * The node can't have any inputs (since it's an initplan), so the
2997 : * parParam and args lists remain empty.
2998 : */
2999 :
3000 : /* Set costs of SubPlan using info from the plan tree */
3001 79 : cost_subplan(subroot, node, plan);
3002 79 : }
|