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