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