Age Owner TLA Line data Source code
1 : /*-------------------------------------------------------------------------
2 : *
3 : * setrefs.c
4 : * Post-processing of a completed plan tree: fix references to subplan
5 : * vars, compute regproc values for operators, etc
6 : *
7 : * Portions Copyright (c) 1996-2023, PostgreSQL Global Development Group
8 : * Portions Copyright (c) 1994, Regents of the University of California
9 : *
10 : *
11 : * IDENTIFICATION
12 : * src/backend/optimizer/plan/setrefs.c
13 : *
14 : *-------------------------------------------------------------------------
15 : */
16 : #include "postgres.h"
17 :
18 : #include "access/transam.h"
19 : #include "catalog/pg_type.h"
20 : #include "nodes/makefuncs.h"
21 : #include "nodes/nodeFuncs.h"
22 : #include "optimizer/optimizer.h"
23 : #include "optimizer/pathnode.h"
24 : #include "optimizer/planmain.h"
25 : #include "optimizer/planner.h"
26 : #include "optimizer/tlist.h"
27 : #include "parser/parse_relation.h"
28 : #include "tcop/utility.h"
29 : #include "utils/lsyscache.h"
30 : #include "utils/syscache.h"
31 :
32 :
33 : typedef enum
34 : {
35 : NRM_EQUAL, /* expect exact match of nullingrels */
36 : NRM_SUBSET, /* actual Var may have a subset of input */
37 : NRM_SUPERSET /* actual Var may have a superset of input */
38 : } NullingRelsMatch;
39 :
40 : typedef struct
41 : {
42 : int varno; /* RT index of Var */
43 : AttrNumber varattno; /* attr number of Var */
44 : AttrNumber resno; /* TLE position of Var */
45 : #ifdef USE_ASSERT_CHECKING
46 : Bitmapset *varnullingrels; /* Var's varnullingrels */
47 : #endif
48 : } tlist_vinfo;
49 :
50 : typedef struct
51 : {
52 : List *tlist; /* underlying target list */
53 : int num_vars; /* number of plain Var tlist entries */
54 : bool has_ph_vars; /* are there PlaceHolderVar entries? */
55 : bool has_non_vars; /* are there other entries? */
56 : tlist_vinfo vars[FLEXIBLE_ARRAY_MEMBER]; /* has num_vars entries */
57 : } indexed_tlist;
58 :
59 : typedef struct
60 : {
61 : PlannerInfo *root;
62 : int rtoffset;
63 : double num_exec;
64 : } fix_scan_expr_context;
65 :
66 : typedef struct
67 : {
68 : PlannerInfo *root;
69 : indexed_tlist *outer_itlist;
70 : indexed_tlist *inner_itlist;
71 : Index acceptable_rel;
72 : int rtoffset;
73 : NullingRelsMatch nrm_match;
74 : double num_exec;
75 : } fix_join_expr_context;
76 :
77 : typedef struct
78 : {
79 : PlannerInfo *root;
80 : indexed_tlist *subplan_itlist;
81 : int newvarno;
82 : int rtoffset;
83 : NullingRelsMatch nrm_match;
84 : double num_exec;
85 : } fix_upper_expr_context;
86 :
87 : typedef struct
88 : {
89 : PlannerInfo *root;
90 : indexed_tlist *subplan_itlist;
91 : int newvarno;
92 : } fix_windowagg_cond_context;
93 :
94 : /* Context info for flatten_rtes_walker() */
95 : typedef struct
96 : {
97 : PlannerGlobal *glob;
98 : Query *query;
99 : } flatten_rtes_walker_context;
100 :
101 : /*
102 : * Selecting the best alternative in an AlternativeSubPlan expression requires
103 : * estimating how many times that expression will be evaluated. For an
104 : * expression in a plan node's targetlist, the plan's estimated number of
105 : * output rows is clearly what to use, but for an expression in a qual it's
106 : * far less clear. Since AlternativeSubPlans aren't heavily used, we don't
107 : * want to expend a lot of cycles making such estimates. What we use is twice
108 : * the number of output rows. That's not entirely unfounded: we know that
109 : * clause_selectivity() would fall back to a default selectivity estimate
110 : * of 0.5 for any SubPlan, so if the qual containing the SubPlan is the last
111 : * to be applied (which it likely would be, thanks to order_qual_clauses()),
112 : * this matches what we could have estimated in a far more laborious fashion.
113 : * Obviously there are many other scenarios, but it's probably not worth the
114 : * trouble to try to improve on this estimate, especially not when we don't
115 : * have a better estimate for the selectivity of the SubPlan qual itself.
116 : */
117 : #define NUM_EXEC_TLIST(parentplan) ((parentplan)->plan_rows)
118 : #define NUM_EXEC_QUAL(parentplan) ((parentplan)->plan_rows * 2.0)
119 :
120 : /*
121 : * Check if a Const node is a regclass value. We accept plain OID too,
122 : * since a regclass Const will get folded to that type if it's an argument
123 : * to oideq or similar operators. (This might result in some extraneous
124 : * values in a plan's list of relation dependencies, but the worst result
125 : * would be occasional useless replans.)
126 : */
127 : #define ISREGCLASSCONST(con) \
128 : (((con)->consttype == REGCLASSOID || (con)->consttype == OIDOID) && \
129 : !(con)->constisnull)
130 :
131 : #define fix_scan_list(root, lst, rtoffset, num_exec) \
132 : ((List *) fix_scan_expr(root, (Node *) (lst), rtoffset, num_exec))
133 :
134 : static void add_rtes_to_flat_rtable(PlannerInfo *root, bool recursing);
135 : static void flatten_unplanned_rtes(PlannerGlobal *glob, RangeTblEntry *rte);
136 : static bool flatten_rtes_walker(Node *node, flatten_rtes_walker_context *cxt);
137 : static void add_rte_to_flat_rtable(PlannerGlobal *glob, List *rteperminfos,
138 : RangeTblEntry *rte);
139 : static Plan *set_plan_refs(PlannerInfo *root, Plan *plan, int rtoffset);
140 : static Plan *set_indexonlyscan_references(PlannerInfo *root,
141 : IndexOnlyScan *plan,
142 : int rtoffset);
143 : static Plan *set_subqueryscan_references(PlannerInfo *root,
144 : SubqueryScan *plan,
145 : int rtoffset);
146 : static Plan *clean_up_removed_plan_level(Plan *parent, Plan *child);
147 : static void set_foreignscan_references(PlannerInfo *root,
148 : ForeignScan *fscan,
149 : int rtoffset);
150 : static void set_customscan_references(PlannerInfo *root,
151 : CustomScan *cscan,
152 : int rtoffset);
153 : static Plan *set_append_references(PlannerInfo *root,
154 : Append *aplan,
155 : int rtoffset);
156 : static Plan *set_mergeappend_references(PlannerInfo *root,
157 : MergeAppend *mplan,
158 : int rtoffset);
159 : static void set_hash_references(PlannerInfo *root, Plan *plan, int rtoffset);
160 : static Relids offset_relid_set(Relids relids, int rtoffset);
161 : static Node *fix_scan_expr(PlannerInfo *root, Node *node,
162 : int rtoffset, double num_exec);
163 : static Node *fix_scan_expr_mutator(Node *node, fix_scan_expr_context *context);
164 : static bool fix_scan_expr_walker(Node *node, fix_scan_expr_context *context);
165 : static void set_join_references(PlannerInfo *root, Join *join, int rtoffset);
166 : static void set_upper_references(PlannerInfo *root, Plan *plan, int rtoffset);
167 : static void set_param_references(PlannerInfo *root, Plan *plan);
168 : static Node *convert_combining_aggrefs(Node *node, void *context);
169 : static void set_dummy_tlist_references(Plan *plan, int rtoffset);
170 : static indexed_tlist *build_tlist_index(List *tlist);
171 : static Var *search_indexed_tlist_for_var(Var *var,
172 : indexed_tlist *itlist,
173 : int newvarno,
174 : int rtoffset,
175 : NullingRelsMatch nrm_match);
176 : static Var *search_indexed_tlist_for_phv(PlaceHolderVar *phv,
177 : indexed_tlist *itlist,
178 : int newvarno,
179 : NullingRelsMatch nrm_match);
180 : static Var *search_indexed_tlist_for_non_var(Expr *node,
181 : indexed_tlist *itlist,
182 : int newvarno);
183 : static Var *search_indexed_tlist_for_sortgroupref(Expr *node,
184 : Index sortgroupref,
185 : indexed_tlist *itlist,
186 : int newvarno);
187 : static List *fix_join_expr(PlannerInfo *root,
188 : List *clauses,
189 : indexed_tlist *outer_itlist,
190 : indexed_tlist *inner_itlist,
191 : Index acceptable_rel,
192 : int rtoffset,
193 : NullingRelsMatch nrm_match,
194 : double num_exec);
195 : static Node *fix_join_expr_mutator(Node *node,
196 : fix_join_expr_context *context);
197 : static Node *fix_upper_expr(PlannerInfo *root,
198 : Node *node,
199 : indexed_tlist *subplan_itlist,
200 : int newvarno,
201 : int rtoffset,
202 : NullingRelsMatch nrm_match,
203 : double num_exec);
204 : static Node *fix_upper_expr_mutator(Node *node,
205 : fix_upper_expr_context *context);
206 : static List *set_returning_clause_references(PlannerInfo *root,
207 : List *rlist,
208 : Plan *topplan,
209 : Index resultRelation,
210 : int rtoffset);
211 : static List *set_windowagg_runcondition_references(PlannerInfo *root,
212 : List *runcondition,
213 : Plan *plan);
214 :
215 :
216 : /*****************************************************************************
217 : *
218 : * SUBPLAN REFERENCES
219 : *
220 : *****************************************************************************/
221 :
222 : /*
223 : * set_plan_references
224 : *
225 : * This is the final processing pass of the planner/optimizer. The plan
226 : * tree is complete; we just have to adjust some representational details
227 : * for the convenience of the executor:
228 : *
229 : * 1. We flatten the various subquery rangetables into a single list, and
230 : * zero out RangeTblEntry fields that are not useful to the executor.
231 : *
232 : * 2. We adjust Vars in scan nodes to be consistent with the flat rangetable.
233 : *
234 : * 3. We adjust Vars in upper plan nodes to refer to the outputs of their
235 : * subplans.
236 : *
237 : * 4. Aggrefs in Agg plan nodes need to be adjusted in some cases involving
238 : * partial aggregation or minmax aggregate optimization.
239 : *
240 : * 5. PARAM_MULTIEXPR Params are replaced by regular PARAM_EXEC Params,
241 : * now that we have finished planning all MULTIEXPR subplans.
242 : *
243 : * 6. AlternativeSubPlan expressions are replaced by just one of their
244 : * alternatives, using an estimate of how many times they'll be executed.
245 : *
246 : * 7. We compute regproc OIDs for operators (ie, we look up the function
247 : * that implements each op).
248 : *
249 : * 8. We create lists of specific objects that the plan depends on.
250 : * This will be used by plancache.c to drive invalidation of cached plans.
251 : * Relation dependencies are represented by OIDs, and everything else by
252 : * PlanInvalItems (this distinction is motivated by the shared-inval APIs).
253 : * Currently, relations, user-defined functions, and domains are the only
254 : * types of objects that are explicitly tracked this way.
255 : *
256 : * 9. We assign every plan node in the tree a unique ID.
257 : *
258 : * We also perform one final optimization step, which is to delete
259 : * SubqueryScan, Append, and MergeAppend plan nodes that aren't doing
260 : * anything useful. The reason for doing this last is that
261 : * it can't readily be done before set_plan_references, because it would
262 : * break set_upper_references: the Vars in the child plan's top tlist
263 : * wouldn't match up with the Vars in the outer plan tree. A SubqueryScan
264 : * serves a necessary function as a buffer between outer query and subquery
265 : * variable numbering ... but after we've flattened the rangetable this is
266 : * no longer a problem, since then there's only one rtindex namespace.
267 : * Likewise, Append and MergeAppend buffer between the parent and child vars
268 : * of an appendrel, but we don't need to worry about that once we've done
269 : * set_plan_references.
270 : *
271 : * set_plan_references recursively traverses the whole plan tree.
272 : *
273 : * The return value is normally the same Plan node passed in, but can be
274 : * different when the passed-in Plan is a node we decide isn't needed.
275 : *
276 : * The flattened rangetable entries are appended to root->glob->finalrtable.
277 : * Also, rowmarks entries are appended to root->glob->finalrowmarks, and the
278 : * RT indexes of ModifyTable result relations to root->glob->resultRelations,
279 : * and flattened AppendRelInfos are appended to root->glob->appendRelations.
280 : * Plan dependencies are appended to root->glob->relationOids (for relations)
281 : * and root->glob->invalItems (for everything else).
282 : *
283 : * Notice that we modify Plan nodes in-place, but use expression_tree_mutator
284 : * to process targetlist and qual expressions. We can assume that the Plan
285 : * nodes were just built by the planner and are not multiply referenced, but
286 : * it's not so safe to assume that for expression tree nodes.
287 : */
288 : Plan *
4236 tgl 289 GIC 225469 : set_plan_references(PlannerInfo *root, Plan *plan)
290 : {
291 : Plan *result;
292 225469 : PlannerGlobal *glob = root->glob;
5890 293 225469 : int rtoffset = list_length(glob->finalrtable);
294 : ListCell *lc;
295 :
296 : /*
297 : * Add all the query's RTEs to the flattened rangetable. The live ones
298 : * will have their rangetable indexes increased by rtoffset. (Additional
299 : * RTEs, not referenced by the Plan tree, might get added after those.)
300 : */
3623 301 225469 : add_rtes_to_flat_rtable(root, false);
302 :
303 : /*
304 : * Adjust RT indexes of PlanRowMarks and add to final rowmarks list
305 : */
4236 306 230557 : foreach(lc, root->rowMarks)
307 : {
2190 308 5088 : PlanRowMark *rc = lfirst_node(PlanRowMark, lc);
309 : PlanRowMark *newrc;
310 :
311 : /* flat copy is enough since all fields are scalars */
4913 312 5088 : newrc = (PlanRowMark *) palloc(sizeof(PlanRowMark));
313 5088 : memcpy(newrc, rc, sizeof(PlanRowMark));
314 :
315 : /* adjust indexes ... but *not* the rowmarkId */
4927 316 5088 : newrc->rti += rtoffset;
317 5088 : newrc->prti += rtoffset;
318 :
4927 tgl 319 CBC 5088 : glob->finalrowmarks = lappend(glob->finalrowmarks, newrc);
320 : }
321 :
1215 tgl 322 ECB : /*
323 : * Adjust RT indexes of AppendRelInfos and add to final appendrels list.
324 : * We assume the AppendRelInfos were built during planning and don't need
325 : * to be copied.
326 : */
1215 tgl 327 GIC 244924 : foreach(lc, root->append_rel_list)
328 : {
329 19455 : AppendRelInfo *appinfo = lfirst_node(AppendRelInfo, lc);
330 :
1215 tgl 331 ECB : /* adjust RT indexes */
1215 tgl 332 GIC 19455 : appinfo->parent_relid += rtoffset;
333 19455 : appinfo->child_relid += rtoffset;
334 :
335 : /*
1215 tgl 336 ECB : * Rather than adjust the translated_vars entries, just drop 'em.
337 : * Neither the executor nor EXPLAIN currently need that data.
338 : */
1215 tgl 339 GIC 19455 : appinfo->translated_vars = NIL;
340 :
341 19455 : glob->appendRelations = lappend(glob->appendRelations, appinfo);
1215 tgl 342 ECB : }
343 :
344 : /* If needed, create workspace for processing AlternativeSubPlans */
572 tgl 345 GIC 225469 : if (root->hasAlternativeSubPlans)
572 tgl 346 ECB : {
572 tgl 347 CBC 437 : root->isAltSubplan = (bool *)
572 tgl 348 GIC 437 : palloc0(list_length(glob->subplans) * sizeof(bool));
572 tgl 349 CBC 437 : root->isUsedSubplan = (bool *)
572 tgl 350 GIC 437 : palloc0(list_length(glob->subplans) * sizeof(bool));
351 : }
352 :
353 : /* Also fix up the information in PartitionPruneInfos. */
10 alvherre 354 GNC 225696 : foreach(lc, root->partPruneInfos)
355 : {
356 227 : PartitionPruneInfo *pruneinfo = lfirst(lc);
357 : ListCell *l;
358 :
359 227 : pruneinfo->root_parent_relids =
360 227 : offset_relid_set(pruneinfo->root_parent_relids, rtoffset);
361 460 : foreach(l, pruneinfo->prune_infos)
362 : {
363 233 : List *prune_infos = lfirst(l);
364 : ListCell *l2;
365 :
366 670 : foreach(l2, prune_infos)
367 : {
368 437 : PartitionedRelPruneInfo *pinfo = lfirst(l2);
369 :
370 : /* RT index of the table to which the pinfo belongs. */
371 437 : pinfo->rtindex += rtoffset;
372 : }
373 : }
374 : }
375 :
376 : /* Now fix the Plan tree */
572 tgl 377 GIC 225469 : result = set_plan_refs(root, plan, rtoffset);
378 :
379 : /*
572 tgl 380 ECB : * If we have AlternativeSubPlans, it is likely that we now have some
381 : * unreferenced subplans in glob->subplans. To avoid expending cycles on
382 : * those subplans later, get rid of them by setting those list entries to
383 : * NULL. (Note: we can't do this immediately upon processing an
384 : * AlternativeSubPlan, because there may be multiple copies of the
385 : * AlternativeSubPlan, and they can get resolved differently.)
386 : */
572 tgl 387 GIC 225469 : if (root->hasAlternativeSubPlans)
388 : {
389 2085 : foreach(lc, glob->subplans)
390 : {
391 1648 : int ndx = foreach_current_index(lc);
572 tgl 392 ECB :
393 : /*
394 : * If it was used by some AlternativeSubPlan in this query level,
395 : * but wasn't selected as best by any AlternativeSubPlan, then we
396 : * don't need it. Do not touch subplans that aren't parts of
397 : * AlternativeSubPlans.
398 : */
572 tgl 399 GIC 1648 : if (root->isAltSubplan[ndx] && !root->isUsedSubplan[ndx])
572 tgl 400 CBC 696 : lfirst(lc) = NULL;
572 tgl 401 ECB : }
402 : }
403 :
572 tgl 404 GIC 225469 : return result;
405 : }
406 :
3623 tgl 407 ECB : /*
408 : * Extract RangeTblEntries from the plan's rangetable, and add to flat rtable
409 : *
410 : * This can recurse into subquery plans; "recursing" is true if so.
411 : *
412 : * This also seems like a good place to add the query's RTEPermissionInfos to
413 : * the flat rteperminfos.
414 : */
415 : static void
3623 tgl 416 CBC 225547 : add_rtes_to_flat_rtable(PlannerInfo *root, bool recursing)
3623 tgl 417 ECB : {
3623 tgl 418 GIC 225547 : PlannerGlobal *glob = root->glob;
3623 tgl 419 ECB : Index rti;
420 : ListCell *lc;
421 :
422 : /*
423 : * Add the query's own RTEs to the flattened rangetable.
424 : *
425 : * At top level, we must add all RTEs so that their indexes in the
426 : * flattened rangetable match up with their original indexes. When
427 : * recursing, we only care about extracting relation RTEs (and subquery
428 : * RTEs that were once relation RTEs).
429 : */
3623 tgl 430 GIC 620224 : foreach(lc, root->parse->rtable)
431 : {
432 394677 : RangeTblEntry *rte = (RangeTblEntry *) lfirst(lc);
433 :
81 tgl 434 GNC 394677 : if (!recursing || rte->rtekind == RTE_RELATION ||
435 120 : (rte->rtekind == RTE_SUBQUERY && OidIsValid(rte->relid)))
124 alvherre 436 394557 : add_rte_to_flat_rtable(glob, root->parse->rteperminfos, rte);
437 : }
438 :
439 : /*
440 : * If there are any dead subqueries, they are not referenced in the Plan
441 : * tree, so we must add RTEs contained in them to the flattened rtable
442 : * separately. (If we failed to do this, the executor would not perform
443 : * expected permission checks for tables mentioned in such subqueries.)
444 : *
3623 tgl 445 ECB : * Note: this pass over the rangetable can't be combined with the previous
446 : * one, because that would mess up the numbering of the live RTEs in the
447 : * flattened rangetable.
448 : */
3623 tgl 449 CBC 225547 : rti = 1;
3623 tgl 450 GIC 620224 : foreach(lc, root->parse->rtable)
451 : {
452 394677 : RangeTblEntry *rte = (RangeTblEntry *) lfirst(lc);
453 :
454 : /*
455 : * We should ignore inheritance-parent RTEs: their contents have been
456 : * pulled up into our rangetable already. Also ignore any subquery
3623 tgl 457 ECB : * RTEs without matching RelOptInfos, as they likewise have been
458 : * pulled up.
459 : */
3403 tgl 460 GIC 394677 : if (rte->rtekind == RTE_SUBQUERY && !rte->inh &&
461 25998 : rti < root->simple_rel_array_size)
3623 tgl 462 ECB : {
3623 tgl 463 GIC 25998 : RelOptInfo *rel = root->simple_rel_array[rti];
464 :
465 25998 : if (rel != NULL)
466 : {
2118 467 10334 : Assert(rel->relid == rti); /* sanity check on array */
468 :
469 : /*
470 : * The subquery might never have been planned at all, if it
471 : * was excluded on the basis of self-contradictory constraints
472 : * in our query level. In this case apply
473 : * flatten_unplanned_rtes.
3623 tgl 474 ECB : *
475 : * If it was planned but the result rel is dummy, we assume
2589 476 : * that it has been omitted from our plan tree (see
477 : * set_subquery_pathlist), and recurse to pull up its RTEs.
478 : *
479 : * Otherwise, it should be represented by a SubqueryScan node
480 : * somewhere in our plan tree, and we'll pull up its RTEs when
481 : * we process that plan node.
482 : *
483 : * However, if we're recursing, then we should pull up RTEs
484 : * whether the subquery is dummy or not, because we've found
485 : * that some upper query level is treating this one as dummy,
486 : * and so we won't scan this level's plan tree at all.
487 : */
2589 tgl 488 CBC 10334 : if (rel->subroot == NULL)
3623 tgl 489 GIC 9 : flatten_unplanned_rtes(glob, rte);
2589 tgl 490 CBC 20626 : else if (recursing ||
2589 tgl 491 GIC 10301 : IS_DUMMY_REL(fetch_upper_rel(rel->subroot,
2589 tgl 492 ECB : UPPERREL_FINAL, NULL)))
3623 tgl 493 CBC 78 : add_rtes_to_flat_rtable(rel->subroot, true);
3623 tgl 494 ECB : }
495 : }
3623 tgl 496 GIC 394677 : rti++;
497 : }
498 225547 : }
499 :
500 : /*
501 : * Extract RangeTblEntries from a subquery that was never planned at all
502 : */
503 :
504 : static void
505 9 : flatten_unplanned_rtes(PlannerGlobal *glob, RangeTblEntry *rte)
506 : {
124 alvherre 507 GNC 9 : flatten_rtes_walker_context cxt = {glob, rte->subquery};
508 :
509 : /* Use query_tree_walker to find all RTEs in the parse tree */
3623 tgl 510 CBC 9 : (void) query_tree_walker(rte->subquery,
3623 tgl 511 ECB : flatten_rtes_walker,
512 : (void *) &cxt,
1535 513 : QTW_EXAMINE_RTES_BEFORE);
3623 tgl 514 GIC 9 : }
515 :
516 : static bool
124 alvherre 517 GNC 231 : flatten_rtes_walker(Node *node, flatten_rtes_walker_context *cxt)
518 : {
3623 tgl 519 GIC 231 : if (node == NULL)
520 129 : return false;
3623 tgl 521 CBC 102 : if (IsA(node, RangeTblEntry))
3623 tgl 522 ECB : {
3623 tgl 523 GIC 9 : RangeTblEntry *rte = (RangeTblEntry *) node;
3623 tgl 524 ECB :
525 : /* As above, we need only save relation RTEs and former relations */
81 tgl 526 GNC 9 : if (rte->rtekind == RTE_RELATION ||
81 tgl 527 UNC 0 : (rte->rtekind == RTE_SUBQUERY && OidIsValid(rte->relid)))
124 alvherre 528 GNC 9 : add_rte_to_flat_rtable(cxt->glob, cxt->query->rteperminfos, rte);
3623 tgl 529 CBC 9 : return false;
530 : }
3623 tgl 531 GIC 93 : if (IsA(node, Query))
532 : {
533 : /*
534 : * Recurse into subselects. Must update cxt->query to this query so
535 : * that the rtable and rteperminfos correspond with each other.
536 : */
55 tgl 537 GNC 3 : Query *save_query = cxt->query;
538 : bool result;
539 :
124 alvherre 540 3 : cxt->query = (Query *) node;
55 tgl 541 3 : result = query_tree_walker((Query *) node,
542 : flatten_rtes_walker,
543 : (void *) cxt,
544 : QTW_EXAMINE_RTES_BEFORE);
545 3 : cxt->query = save_query;
546 3 : return result;
547 : }
3623 tgl 548 GIC 90 : return expression_tree_walker(node, flatten_rtes_walker,
549 : (void *) cxt);
550 : }
551 :
552 : /*
553 : * Add (a copy of) the given RTE to the final rangetable and also the
554 : * corresponding RTEPermissionInfo, if any, to final rteperminfos.
555 : *
556 : * In the flat rangetable, we zero out substructure pointers that are not
557 : * needed by the executor; this reduces the storage space and copying cost
558 : * for cached plans. We keep only the ctename, alias, eref Alias fields,
559 : * which are needed by EXPLAIN, and perminfoindex which is needed by the
560 : * executor to fetch the RTE's RTEPermissionInfo.
3623 tgl 561 ECB : */
562 : static void
124 alvherre 563 GNC 394566 : add_rte_to_flat_rtable(PlannerGlobal *glob, List *rteperminfos,
564 : RangeTblEntry *rte)
3623 tgl 565 ECB : {
566 : RangeTblEntry *newrte;
567 :
568 : /* flat copy to duplicate all the scalar fields */
3623 tgl 569 GIC 394566 : newrte = (RangeTblEntry *) palloc(sizeof(RangeTblEntry));
3623 tgl 570 CBC 394566 : memcpy(newrte, rte, sizeof(RangeTblEntry));
571 :
572 : /* zap unneeded sub-structure */
2815 tgl 573 GIC 394566 : newrte->tablesample = NULL;
3623 574 394566 : newrte->subquery = NULL;
575 394566 : newrte->joinaliasvars = NIL;
1186 576 394566 : newrte->joinleftcols = NIL;
1186 tgl 577 CBC 394566 : newrte->joinrightcols = NIL;
739 peter 578 GIC 394566 : newrte->join_using_alias = NULL;
3426 tgl 579 CBC 394566 : newrte->functions = NIL;
2223 alvherre 580 GIC 394566 : newrte->tablefunc = NULL;
3623 tgl 581 394566 : newrte->values_lists = NIL;
2313 tgl 582 CBC 394566 : newrte->coltypes = NIL;
2313 tgl 583 GIC 394566 : newrte->coltypmods = NIL;
584 394566 : newrte->colcollations = NIL;
2819 585 394566 : newrte->securityQuals = NIL;
3623 tgl 586 ECB :
3623 tgl 587 GIC 394566 : glob->finalrtable = lappend(glob->finalrtable, newrte);
588 :
3623 tgl 589 ECB : /*
590 : * If it's a plain relation RTE (or a subquery that was once a view
591 : * reference), add the relation OID to relationOids.
592 : *
593 : * We do this even though the RTE might be unreferenced in the plan tree;
594 : * this would correspond to cases such as views that were expanded, child
595 : * tables that were eliminated by constraint exclusion, etc. Schema
596 : * invalidation on such a rel must still force rebuilding of the plan.
597 : *
598 : * Note we don't bother to avoid making duplicate list entries. We could,
599 : * but it would probably cost more cycles than it would save.
3623 tgl 600 EUB : */
81 tgl 601 GNC 394566 : if (newrte->rtekind == RTE_RELATION ||
602 177862 : (newrte->rtekind == RTE_SUBQUERY && OidIsValid(newrte->relid)))
3623 tgl 603 CBC 222493 : glob->relationOids = lappend_oid(glob->relationOids, newrte->relid);
604 :
605 : /*
606 : * Add a copy of the RTEPermissionInfo, if any, corresponding to this RTE
607 : * to the flattened global list.
608 : */
124 alvherre 609 GNC 394566 : if (rte->perminfoindex > 0)
610 : {
611 : RTEPermissionInfo *perminfo;
612 : RTEPermissionInfo *newperminfo;
613 :
614 : /* Get the existing one from this query's rteperminfos. */
615 205837 : perminfo = getRTEPermissionInfo(rteperminfos, newrte);
616 :
617 : /*
618 : * Add a new one to finalrteperminfos and copy the contents of the
619 : * existing one into it. Note that addRTEPermissionInfo() also
620 : * updates newrte->perminfoindex to point to newperminfo in
621 : * finalrteperminfos.
622 : */
623 205837 : newrte->perminfoindex = 0; /* expected by addRTEPermissionInfo() */
624 205837 : newperminfo = addRTEPermissionInfo(&glob->finalrteperminfos, newrte);
625 205837 : memcpy(newperminfo, perminfo, sizeof(RTEPermissionInfo));
626 : }
3623 tgl 627 GIC 394566 : }
3623 tgl 628 ECB :
629 : /*
630 : * set_plan_refs: recurse through the Plan nodes of a single subquery level
631 : */
632 : static Plan *
4236 tgl 633 GIC 1166644 : set_plan_refs(PlannerInfo *root, Plan *plan, int rtoffset)
9770 scrappy 634 ECB : {
635 : ListCell *l;
636 :
9345 bruce 637 CBC 1166644 : if (plan == NULL)
6531 tgl 638 681391 : return NULL;
639 :
640 : /* Assign this node a unique ID. */
2750 rhaas 641 GIC 485253 : plan->plan_node_id = root->glob->lastPlanNodeId++;
2750 rhaas 642 ECB :
8631 tgl 643 : /*
644 : * Plan-type-specific fixes
645 : */
8631 tgl 646 GIC 485253 : switch (nodeTag(plan))
647 : {
648 85442 : case T_SeqScan:
649 : {
5624 bruce 650 85442 : SeqScan *splan = (SeqScan *) plan;
651 :
609 peter 652 85442 : splan->scan.scanrelid += rtoffset;
653 85442 : splan->scan.plan.targetlist =
654 85442 : fix_scan_list(root, splan->scan.plan.targetlist,
655 : rtoffset, NUM_EXEC_TLIST(plan));
656 85442 : splan->scan.plan.qual =
657 85442 : fix_scan_list(root, splan->scan.plan.qual,
658 : rtoffset, NUM_EXEC_QUAL(plan));
659 : }
8631 tgl 660 CBC 85442 : break;
2886 simon 661 GIC 126 : case T_SampleScan:
662 : {
2878 bruce 663 126 : SampleScan *splan = (SampleScan *) plan;
664 :
2815 tgl 665 126 : splan->scan.scanrelid += rtoffset;
2815 tgl 666 CBC 126 : splan->scan.plan.targetlist =
924 667 126 : fix_scan_list(root, splan->scan.plan.targetlist,
668 : rtoffset, NUM_EXEC_TLIST(plan));
2815 tgl 669 GIC 126 : splan->scan.plan.qual =
924 tgl 670 CBC 126 : fix_scan_list(root, splan->scan.plan.qual,
924 tgl 671 ECB : rtoffset, NUM_EXEC_QUAL(plan));
2815 tgl 672 CBC 126 : splan->tablesample = (TableSampleClause *)
924 673 126 : fix_scan_expr(root, (Node *) splan->tablesample,
924 tgl 674 ECB : rtoffset, 1);
2886 simon 675 : }
2886 simon 676 CBC 126 : break;
8631 tgl 677 53055 : case T_IndexScan:
5890 tgl 678 ECB : {
5624 bruce 679 CBC 53055 : IndexScan *splan = (IndexScan *) plan;
5890 tgl 680 ECB :
5890 tgl 681 CBC 53055 : splan->scan.scanrelid += rtoffset;
682 53055 : splan->scan.plan.targetlist =
924 tgl 683 GIC 53055 : fix_scan_list(root, splan->scan.plan.targetlist,
924 tgl 684 ECB : rtoffset, NUM_EXEC_TLIST(plan));
5890 tgl 685 GIC 53055 : splan->scan.plan.qual =
924 686 53055 : fix_scan_list(root, splan->scan.plan.qual,
687 : rtoffset, NUM_EXEC_QUAL(plan));
5890 688 53055 : splan->indexqual =
924 689 53055 : fix_scan_list(root, splan->indexqual,
690 : rtoffset, 1);
5890 691 53055 : splan->indexqualorig =
924 692 53055 : fix_scan_list(root, splan->indexqualorig,
693 : rtoffset, NUM_EXEC_QUAL(plan));
4511 694 53055 : splan->indexorderby =
924 695 53055 : fix_scan_list(root, splan->indexorderby,
696 : rtoffset, 1);
4511 697 53055 : splan->indexorderbyorig =
924 tgl 698 CBC 53055 : fix_scan_list(root, splan->indexorderbyorig,
924 tgl 699 ECB : rtoffset, NUM_EXEC_QUAL(plan));
5890 700 : }
8344 tgl 701 GIC 53055 : break;
4198 702 6151 : case T_IndexOnlyScan:
703 : {
3955 bruce 704 6151 : IndexOnlyScan *splan = (IndexOnlyScan *) plan;
705 :
4198 tgl 706 CBC 6151 : return set_indexonlyscan_references(root, splan, rtoffset);
707 : }
708 : break;
6564 tgl 709 GIC 10632 : case T_BitmapIndexScan:
710 : {
5890 711 10632 : BitmapIndexScan *splan = (BitmapIndexScan *) plan;
5890 tgl 712 ECB :
5890 tgl 713 GIC 10632 : splan->scan.scanrelid += rtoffset;
714 : /* no need to fix targetlist and qual */
715 10632 : Assert(splan->scan.plan.targetlist == NIL);
716 10632 : Assert(splan->scan.plan.qual == NIL);
717 10632 : splan->indexqual =
924 718 10632 : fix_scan_list(root, splan->indexqual, rtoffset, 1);
5890 719 10632 : splan->indexqualorig =
924 tgl 720 CBC 10632 : fix_scan_list(root, splan->indexqualorig,
924 tgl 721 ECB : rtoffset, NUM_EXEC_QUAL(plan));
5890 722 : }
6564 tgl 723 GIC 10632 : break;
6564 tgl 724 CBC 10456 : case T_BitmapHeapScan:
725 : {
5890 tgl 726 GIC 10456 : BitmapHeapScan *splan = (BitmapHeapScan *) plan;
727 :
728 10456 : splan->scan.scanrelid += rtoffset;
729 10456 : splan->scan.plan.targetlist =
924 tgl 730 CBC 10456 : fix_scan_list(root, splan->scan.plan.targetlist,
731 : rtoffset, NUM_EXEC_TLIST(plan));
5890 tgl 732 GIC 10456 : splan->scan.plan.qual =
924 733 10456 : fix_scan_list(root, splan->scan.plan.qual,
924 tgl 734 ECB : rtoffset, NUM_EXEC_QUAL(plan));
5890 tgl 735 CBC 10456 : splan->bitmapqualorig =
924 tgl 736 GIC 10456 : fix_scan_list(root, splan->bitmapqualorig,
737 : rtoffset, NUM_EXEC_QUAL(plan));
5890 tgl 738 ECB : }
6564 tgl 739 GIC 10456 : break;
8344 740 318 : case T_TidScan:
741 : {
5624 bruce 742 318 : TidScan *splan = (TidScan *) plan;
5890 tgl 743 ECB :
5890 tgl 744 GIC 318 : splan->scan.scanrelid += rtoffset;
5890 tgl 745 CBC 318 : splan->scan.plan.targetlist =
924 tgl 746 GIC 318 : fix_scan_list(root, splan->scan.plan.targetlist,
924 tgl 747 ECB : rtoffset, NUM_EXEC_TLIST(plan));
5890 tgl 748 GIC 318 : splan->scan.plan.qual =
924 tgl 749 CBC 318 : fix_scan_list(root, splan->scan.plan.qual,
924 tgl 750 ECB : rtoffset, NUM_EXEC_QUAL(plan));
5890 tgl 751 CBC 318 : splan->tidquals =
924 tgl 752 GIC 318 : fix_scan_list(root, splan->tidquals,
924 tgl 753 ECB : rtoffset, 1);
5890 754 : }
8631 tgl 755 GIC 318 : break;
771 drowley 756 101 : case T_TidRangeScan:
771 drowley 757 ECB : {
771 drowley 758 CBC 101 : TidRangeScan *splan = (TidRangeScan *) plan;
759 :
760 101 : splan->scan.scanrelid += rtoffset;
771 drowley 761 GIC 101 : splan->scan.plan.targetlist =
771 drowley 762 CBC 101 : fix_scan_list(root, splan->scan.plan.targetlist,
771 drowley 763 ECB : rtoffset, NUM_EXEC_TLIST(plan));
771 drowley 764 CBC 101 : splan->scan.plan.qual =
771 drowley 765 GIC 101 : fix_scan_list(root, splan->scan.plan.qual,
771 drowley 766 ECB : rtoffset, NUM_EXEC_QUAL(plan));
771 drowley 767 CBC 101 : splan->tidrangequals =
771 drowley 768 GIC 101 : fix_scan_list(root, splan->tidrangequals,
771 drowley 769 ECB : rtoffset, 1);
770 : }
771 drowley 771 GIC 101 : break;
8227 tgl 772 10241 : case T_SubqueryScan:
6531 tgl 773 ECB : /* Needs special treatment, see comments below */
4236 tgl 774 CBC 10241 : return set_subqueryscan_references(root,
775 : (SubqueryScan *) plan,
5890 tgl 776 ECB : rtoffset);
7637 tgl 777 GIC 17700 : case T_FunctionScan:
5890 tgl 778 ECB : {
5890 tgl 779 CBC 17700 : FunctionScan *splan = (FunctionScan *) plan;
5890 tgl 780 ECB :
5890 tgl 781 GIC 17700 : splan->scan.scanrelid += rtoffset;
5890 tgl 782 CBC 17700 : splan->scan.plan.targetlist =
924 783 17700 : fix_scan_list(root, splan->scan.plan.targetlist,
784 : rtoffset, NUM_EXEC_TLIST(plan));
5890 785 17700 : splan->scan.plan.qual =
924 786 17700 : fix_scan_list(root, splan->scan.plan.qual,
787 : rtoffset, NUM_EXEC_QUAL(plan));
3426 788 17700 : splan->functions =
924 789 17700 : fix_scan_list(root, splan->functions, rtoffset, 1);
790 : }
7637 791 17700 : break;
2223 alvherre 792 108 : case T_TableFuncScan:
793 : {
794 108 : TableFuncScan *splan = (TableFuncScan *) plan;
2223 alvherre 795 ECB :
2223 alvherre 796 GIC 108 : splan->scan.scanrelid += rtoffset;
797 108 : splan->scan.plan.targetlist =
924 tgl 798 CBC 108 : fix_scan_list(root, splan->scan.plan.targetlist,
924 tgl 799 ECB : rtoffset, NUM_EXEC_TLIST(plan));
2223 alvherre 800 GIC 108 : splan->scan.plan.qual =
924 tgl 801 CBC 108 : fix_scan_list(root, splan->scan.plan.qual,
802 : rtoffset, NUM_EXEC_QUAL(plan));
2223 alvherre 803 108 : splan->tablefunc = (TableFunc *)
924 tgl 804 GIC 108 : fix_scan_expr(root, (Node *) splan->tablefunc,
805 : rtoffset, 1);
2223 alvherre 806 ECB : }
2223 alvherre 807 GIC 108 : break;
6094 mail 808 CBC 3553 : case T_ValuesScan:
809 : {
5890 tgl 810 3553 : ValuesScan *splan = (ValuesScan *) plan;
811 :
812 3553 : splan->scan.scanrelid += rtoffset;
813 3553 : splan->scan.plan.targetlist =
924 814 3553 : fix_scan_list(root, splan->scan.plan.targetlist,
924 tgl 815 ECB : rtoffset, NUM_EXEC_TLIST(plan));
5890 tgl 816 CBC 3553 : splan->scan.plan.qual =
924 817 3553 : fix_scan_list(root, splan->scan.plan.qual,
818 : rtoffset, NUM_EXEC_QUAL(plan));
5890 tgl 819 GIC 3553 : splan->values_lists =
924 tgl 820 CBC 3553 : fix_scan_list(root, splan->values_lists,
924 tgl 821 ECB : rtoffset, 1);
822 : }
6094 mail 823 CBC 3553 : break;
5300 tgl 824 GIC 1236 : case T_CteScan:
5300 tgl 825 ECB : {
5050 bruce 826 CBC 1236 : CteScan *splan = (CteScan *) plan;
5300 tgl 827 ECB :
5300 tgl 828 GIC 1236 : splan->scan.scanrelid += rtoffset;
5300 tgl 829 CBC 1236 : splan->scan.plan.targetlist =
924 830 1236 : fix_scan_list(root, splan->scan.plan.targetlist,
831 : rtoffset, NUM_EXEC_TLIST(plan));
5300 832 1236 : splan->scan.plan.qual =
924 833 1236 : fix_scan_list(root, splan->scan.plan.qual,
834 : rtoffset, NUM_EXEC_QUAL(plan));
835 : }
5300 836 1236 : break;
2200 kgrittn 837 219 : case T_NamedTuplestoreScan:
838 : {
839 219 : NamedTuplestoreScan *splan = (NamedTuplestoreScan *) plan;
840 :
841 219 : splan->scan.scanrelid += rtoffset;
842 219 : splan->scan.plan.targetlist =
924 tgl 843 219 : fix_scan_list(root, splan->scan.plan.targetlist,
844 : rtoffset, NUM_EXEC_TLIST(plan));
2200 kgrittn 845 219 : splan->scan.plan.qual =
924 tgl 846 219 : fix_scan_list(root, splan->scan.plan.qual,
847 : rtoffset, NUM_EXEC_QUAL(plan));
2200 kgrittn 848 ECB : }
2200 kgrittn 849 CBC 219 : break;
5300 tgl 850 GIC 354 : case T_WorkTableScan:
851 : {
5300 tgl 852 CBC 354 : WorkTableScan *splan = (WorkTableScan *) plan;
5890 tgl 853 ECB :
5300 tgl 854 GIC 354 : splan->scan.scanrelid += rtoffset;
5300 tgl 855 CBC 354 : splan->scan.plan.targetlist =
924 tgl 856 GIC 354 : fix_scan_list(root, splan->scan.plan.targetlist,
924 tgl 857 ECB : rtoffset, NUM_EXEC_TLIST(plan));
5300 tgl 858 CBC 354 : splan->scan.plan.qual =
924 859 354 : fix_scan_list(root, splan->scan.plan.qual,
860 : rtoffset, NUM_EXEC_QUAL(plan));
5300 tgl 861 ECB : }
5300 tgl 862 CBC 354 : break;
4431 tgl 863 GIC 943 : case T_ForeignScan:
2900 rhaas 864 CBC 943 : set_foreignscan_references(root, (ForeignScan *) plan, rtoffset);
4431 tgl 865 943 : break;
3075 rhaas 866 UIC 0 : case T_CustomScan:
2900 867 0 : set_customscan_references(root, (CustomScan *) plan, rtoffset);
3075 rhaas 868 LBC 0 : break;
3075 rhaas 869 ECB :
8631 tgl 870 GIC 48768 : case T_NestLoop:
8631 tgl 871 ECB : case T_MergeJoin:
872 : case T_HashJoin:
4236 tgl 873 GIC 48768 : set_join_references(root, (Join *) plan, rtoffset);
8631 tgl 874 CBC 48768 : break;
875 :
2720 rhaas 876 608 : case T_Gather:
877 : case T_GatherMerge:
1970 rhaas 878 ECB : {
1970 rhaas 879 CBC 608 : set_upper_references(root, plan, rtoffset);
880 608 : set_param_references(root, plan);
881 : }
2720 882 608 : break;
2720 rhaas 883 ECB :
7389 tgl 884 GIC 13953 : case T_Hash:
1346 andres 885 CBC 13953 : set_hash_references(root, plan, rtoffset);
886 13953 : break;
887 :
634 drowley 888 502 : case T_Memoize:
737 drowley 889 ECB : {
634 drowley 890 GIC 502 : Memoize *mplan = (Memoize *) plan;
737 drowley 891 ECB :
892 : /*
634 893 : * Memoize does not evaluate its targetlist. It just uses the
894 : * same targetlist from its outer subnode.
684 895 : */
684 drowley 896 GIC 502 : set_dummy_tlist_references(plan, rtoffset);
684 drowley 897 ECB :
634 drowley 898 CBC 502 : mplan->param_exprs = fix_scan_list(root, mplan->param_exprs,
899 : rtoffset,
634 drowley 900 ECB : NUM_EXEC_TLIST(plan));
737 drowley 901 CBC 502 : break;
902 : }
903 :
8631 tgl 904 28978 : case T_Material:
8631 tgl 905 ECB : case T_Sort:
906 : case T_IncrementalSort:
907 : case T_Unique:
908 : case T_SetOp:
8397 bruce 909 :
910 : /*
911 : * These plan types don't actually bother to evaluate their
912 : * targetlists, because they just return their unmodified input
3260 913 : * tuples. Even though the targetlist won't be used by the
5890 tgl 914 : * executor, we fix it up for possible use by EXPLAIN (not to
915 : * mention ease of debugging --- wrong varnos are very confusing).
916 : */
5889 tgl 917 CBC 28978 : set_dummy_tlist_references(plan, rtoffset);
918 :
919 : /*
6385 bruce 920 ECB : * Since these plan types don't check quals either, we should not
921 : * find any qual expression attached to them.
922 : */
6531 tgl 923 CBC 28978 : Assert(plan->qual == NIL);
8631 tgl 924 GIC 28978 : break;
4927 tgl 925 CBC 3359 : case T_LockRows:
4927 tgl 926 ECB : {
4927 tgl 927 CBC 3359 : LockRows *splan = (LockRows *) plan;
928 :
4927 tgl 929 ECB : /*
930 : * Like the plan types above, LockRows doesn't evaluate its
931 : * tlist or quals. But we have to fix up the RT indexes in
932 : * its rowmarks.
933 : */
4927 tgl 934 CBC 3359 : set_dummy_tlist_references(plan, rtoffset);
4927 tgl 935 GIC 3359 : Assert(splan->plan.qual == NIL);
4927 tgl 936 ECB :
4927 tgl 937 GIC 7693 : foreach(l, splan->rowMarks)
4927 tgl 938 ECB : {
4913 tgl 939 CBC 4334 : PlanRowMark *rc = (PlanRowMark *) lfirst(l);
4927 tgl 940 ECB :
4927 tgl 941 GIC 4334 : rc->rti += rtoffset;
4927 tgl 942 CBC 4334 : rc->prti += rtoffset;
4927 tgl 943 ECB : }
944 : }
4927 tgl 945 GIC 3359 : break;
6907 tgl 946 CBC 2391 : case T_Limit:
5890 tgl 947 ECB : {
5624 bruce 948 GIC 2391 : Limit *splan = (Limit *) plan;
5890 tgl 949 ECB :
950 : /*
951 : * Like the plan types above, Limit doesn't evaluate its tlist
952 : * or quals. It does have live expressions for limit/offset,
5624 bruce 953 : * however; and those cannot contain subplan variable refs, so
954 : * fix_scan_expr works for them.
5890 tgl 955 : */
5889 tgl 956 CBC 2391 : set_dummy_tlist_references(plan, rtoffset);
5890 tgl 957 GIC 2391 : Assert(splan->plan.qual == NIL);
958 :
5890 tgl 959 CBC 2391 : splan->limitOffset =
924 960 2391 : fix_scan_expr(root, splan->limitOffset, rtoffset, 1);
5890 961 2391 : splan->limitCount =
924 962 2391 : fix_scan_expr(root, splan->limitCount, rtoffset, 1);
5890 tgl 963 EUB : }
6907 tgl 964 GBC 2391 : break;
8631 965 18778 : case T_Agg:
966 : {
2478 tgl 967 CBC 18778 : Agg *agg = (Agg *) plan;
968 :
969 : /*
2478 tgl 970 ECB : * If this node is combining partial-aggregation results, we
971 : * must convert its Aggrefs to contain references to the
972 : * partial-aggregate subexpressions that will be available
973 : * from the child plan node.
974 : */
2478 tgl 975 GIC 18778 : if (DO_AGGSPLIT_COMBINE(agg->aggsplit))
2478 tgl 976 ECB : {
2478 tgl 977 CBC 419 : plan->targetlist = (List *)
2478 tgl 978 GIC 419 : convert_combining_aggrefs((Node *) plan->targetlist,
2478 tgl 979 ECB : NULL);
2478 tgl 980 GIC 419 : plan->qual = (List *)
2478 tgl 981 CBC 419 : convert_combining_aggrefs((Node *) plan->qual,
2478 tgl 982 ECB : NULL);
983 : }
984 :
2478 tgl 985 CBC 18778 : set_upper_references(root, plan, rtoffset);
986 : }
987 18778 : break;
8631 tgl 988 GIC 111 : case T_Group:
4236 989 111 : set_upper_references(root, plan, rtoffset);
8631 990 111 : break;
4804 991 1089 : case T_WindowAgg:
992 : {
4790 bruce 993 CBC 1089 : WindowAgg *wplan = (WindowAgg *) plan;
994 :
366 drowley 995 ECB : /*
996 : * Adjust the WindowAgg's run conditions by swapping the
997 : * WindowFuncs references out to instead reference the Var in
998 : * the scan slot so that when the executor evaluates the
999 : * runCondition, it receives the WindowFunc's value from the
1000 : * slot that the result has just been stored into rather than
1001 : * evaluating the WindowFunc all over again.
1002 : */
366 drowley 1003 GIC 1089 : wplan->runCondition = set_windowagg_runcondition_references(root,
1004 : wplan->runCondition,
1005 : (Plan *) wplan);
1006 :
4236 tgl 1007 1089 : set_upper_references(root, plan, rtoffset);
1008 :
1009 : /*
1010 : * Like Limit node limit/offset expressions, WindowAgg has
1011 : * frame offset expressions, which cannot contain subplan
1012 : * variable refs, so fix_scan_expr works for them.
1013 : */
4804 tgl 1014 CBC 1089 : wplan->startOffset =
924 tgl 1015 GIC 1089 : fix_scan_expr(root, wplan->startOffset, rtoffset, 1);
4804 1016 1089 : wplan->endOffset =
924 1017 1089 : fix_scan_expr(root, wplan->endOffset, rtoffset, 1);
366 drowley 1018 1089 : wplan->runCondition = fix_scan_list(root,
1019 : wplan->runCondition,
366 drowley 1020 ECB : rtoffset,
1021 : NUM_EXEC_TLIST(plan));
366 drowley 1022 CBC 1089 : wplan->runConditionOrig = fix_scan_list(root,
1023 : wplan->runConditionOrig,
366 drowley 1024 ECB : rtoffset,
1025 : NUM_EXEC_TLIST(plan));
1026 : }
4804 tgl 1027 GIC 1089 : break;
8631 1028 100857 : case T_Result:
1029 : {
5624 bruce 1030 100857 : Result *splan = (Result *) plan;
5890 tgl 1031 ECB :
1032 : /*
1033 : * Result may or may not have a subplan; if not, it's more
1034 : * like a scan node than an upper node.
1035 : */
5890 tgl 1036 CBC 100857 : if (splan->plan.lefttree != NULL)
4236 tgl 1037 GIC 4526 : set_upper_references(root, plan, rtoffset);
5890 tgl 1038 ECB : else
1039 : {
1040 : /*
1041 : * The tlist of a childless Result could contain
739 1042 : * unresolved ROWID_VAR Vars, in case it's representing a
1043 : * target relation which is completely empty because of
1044 : * constraint exclusion. Replace any such Vars by null
1045 : * constants, as though they'd been resolved for a leaf
1046 : * scan node that doesn't support them. We could have
1047 : * fix_scan_expr do this, but since the case is only
1048 : * expected to occur here, it seems safer to special-case
1049 : * it here and keep the assertions that ROWID_VARs
1050 : * shouldn't be seen by fix_scan_expr.
1051 : */
739 tgl 1052 GIC 271732 : foreach(l, splan->plan.targetlist)
739 tgl 1053 ECB : {
739 tgl 1054 CBC 175401 : TargetEntry *tle = (TargetEntry *) lfirst(l);
739 tgl 1055 GIC 175401 : Var *var = (Var *) tle->expr;
739 tgl 1056 ECB :
739 tgl 1057 CBC 175401 : if (var && IsA(var, Var) && var->varno == ROWID_VAR)
1058 36 : tle->expr = (Expr *) makeNullConst(var->vartype,
739 tgl 1059 ECB : var->vartypmod,
1060 : var->varcollid);
1061 : }
1062 :
5890 tgl 1063 GIC 96331 : splan->plan.targetlist =
924 tgl 1064 CBC 96331 : fix_scan_list(root, splan->plan.targetlist,
1065 : rtoffset, NUM_EXEC_TLIST(plan));
5890 tgl 1066 GIC 96331 : splan->plan.qual =
924 1067 96331 : fix_scan_list(root, splan->plan.qual,
1068 : rtoffset, NUM_EXEC_QUAL(plan));
1069 : }
1070 : /* resconstantqual can't contain any subplan variable refs */
5890 1071 100857 : splan->resconstantqual =
924 tgl 1072 CBC 100857 : fix_scan_expr(root, splan->resconstantqual, rtoffset, 1);
1073 : }
8631 1074 100857 : break;
2272 andres 1075 3246 : case T_ProjectSet:
2272 andres 1076 GIC 3246 : set_upper_references(root, plan, rtoffset);
2272 andres 1077 CBC 3246 : break;
4929 tgl 1078 52176 : case T_ModifyTable:
1079 : {
4929 tgl 1080 GIC 52176 : ModifyTable *splan = (ModifyTable *) plan;
377 alvherre 1081 52176 : Plan *subplan = outerPlan(splan);
4929 tgl 1082 ECB :
4001 tgl 1083 GIC 52176 : Assert(splan->plan.targetlist == NIL);
4929 tgl 1084 CBC 52176 : Assert(splan->plan.qual == NIL);
4929 tgl 1085 ECB :
3121 sfrost 1086 CBC 52176 : splan->withCheckOptionLists =
924 tgl 1087 52176 : fix_scan_list(root, splan->withCheckOptionLists,
924 tgl 1088 ECB : rtoffset, 1);
1089 :
4001 tgl 1090 CBC 52176 : if (splan->returningLists)
1091 : {
4001 tgl 1092 GIC 1124 : List *newRL = NIL;
1093 : ListCell *lcrl,
1094 : *lcrr;
1095 :
1096 : /*
1097 : * Pass each per-resultrel returningList through
1098 : * set_returning_clause_references().
1099 : */
4001 tgl 1100 CBC 1124 : Assert(list_length(splan->returningLists) == list_length(splan->resultRelations));
739 tgl 1101 GIC 2391 : forboth(lcrl, splan->returningLists,
1102 : lcrr, splan->resultRelations)
1103 : {
3955 bruce 1104 CBC 1267 : List *rlist = (List *) lfirst(lcrl);
3955 bruce 1105 GIC 1267 : Index resultrel = lfirst_int(lcrr);
1106 :
4001 tgl 1107 1267 : rlist = set_returning_clause_references(root,
1108 : rlist,
1109 : subplan,
1110 : resultrel,
4001 tgl 1111 ECB : rtoffset);
4001 tgl 1112 CBC 1267 : newRL = lappend(newRL, rlist);
4001 tgl 1113 ECB : }
4001 tgl 1114 CBC 1124 : splan->returningLists = newRL;
4001 tgl 1115 ECB :
1116 : /*
1117 : * Set up the visible plan targetlist as being the same as
1118 : * the first RETURNING list. This is for the use of
1119 : * EXPLAIN; the executor won't pay any attention to the
1120 : * targetlist. We postpone this step until here so that
1121 : * we don't have to do set_returning_clause_references()
1122 : * twice on identical targetlists.
1123 : */
4001 tgl 1124 CBC 1124 : splan->plan.targetlist = copyObject(linitial(newRL));
4001 tgl 1125 ECB : }
1126 :
2893 andres 1127 : /*
1128 : * We treat ModifyTable with ON CONFLICT as a form of 'pseudo
1129 : * join', where the inner side is the EXCLUDED tuple.
1130 : * Therefore use fix_join_expr to setup the relevant variables
1131 : * to INNER_VAR. We explicitly don't create any OUTER_VARs as
1132 : * those are already used by RETURNING and it seems better to
1133 : * be non-conflicting.
1134 : */
2893 andres 1135 GIC 52176 : if (splan->onConflictSet)
1136 : {
1137 : indexed_tlist *itlist;
1138 :
1139 483 : itlist = build_tlist_index(splan->exclRelTlist);
1140 :
1141 483 : splan->onConflictSet =
1142 966 : fix_join_expr(root, splan->onConflictSet,
1143 : NULL, itlist,
1144 483 : linitial_int(splan->resultRelations),
69 tgl 1145 GNC 483 : rtoffset, NRM_EQUAL, NUM_EXEC_QUAL(plan));
1146 :
2893 andres 1147 GIC 483 : splan->onConflictWhere = (Node *)
1148 966 : fix_join_expr(root, (List *) splan->onConflictWhere,
2893 andres 1149 ECB : NULL, itlist,
2893 andres 1150 GIC 483 : linitial_int(splan->resultRelations),
69 tgl 1151 GNC 483 : rtoffset, NRM_EQUAL, NUM_EXEC_QUAL(plan));
2888 andres 1152 ECB :
2828 andres 1153 GIC 483 : pfree(itlist);
2828 andres 1154 ECB :
2888 andres 1155 CBC 483 : splan->exclRelTlist =
924 tgl 1156 GIC 483 : fix_scan_list(root, splan->exclRelTlist, rtoffset, 1);
1157 : }
1158 :
1159 : /*
377 alvherre 1160 ECB : * The MERGE statement produces the target rows by performing
1161 : * a right join between the target relation and the source
1162 : * relation (which could be a plain relation or a subquery).
1163 : * The INSERT and UPDATE actions of the MERGE statement
1164 : * require access to the columns from the source relation. We
1165 : * arrange things so that the source relation attributes are
1166 : * available as INNER_VAR and the target relation attributes
1167 : * are available from the scan tuple.
1168 : */
377 alvherre 1169 CBC 52176 : if (splan->mergeActionLists != NIL)
1170 : {
377 alvherre 1171 ECB : ListCell *lca,
1172 : *lcr;
1173 :
1174 : /*
1175 : * Fix the targetList of individual action nodes so that
1176 : * the so-called "source relation" Vars are referenced as
1177 : * INNER_VAR. Note that for this to work correctly during
1178 : * execution, the ecxt_innertuple must be set to the tuple
1179 : * obtained by executing the subplan, which is what
1180 : * constitutes the "source relation".
1181 : *
1182 : * We leave the Vars from the result relation (i.e. the
1183 : * target relation) unchanged i.e. those Vars would be
1184 : * picked from the scan slot. So during execution, we must
1185 : * ensure that ecxt_scantuple is setup correctly to refer
1186 : * to the tuple from the target relation.
1187 : */
1188 : indexed_tlist *itlist;
1189 :
377 alvherre 1190 GIC 464 : itlist = build_tlist_index(subplan->targetlist);
1191 :
1192 992 : forboth(lca, splan->mergeActionLists,
1193 : lcr, splan->resultRelations)
1194 : {
1195 528 : List *mergeActionList = lfirst(lca);
1196 528 : Index resultrel = lfirst_int(lcr);
377 alvherre 1197 ECB :
377 alvherre 1198 CBC 1373 : foreach(l, mergeActionList)
1199 : {
377 alvherre 1200 GIC 845 : MergeAction *action = (MergeAction *) lfirst(l);
377 alvherre 1201 ECB :
1202 : /* Fix targetList of each action. */
377 alvherre 1203 GIC 845 : action->targetList = fix_join_expr(root,
377 alvherre 1204 ECB : action->targetList,
1205 : NULL, itlist,
1206 : resultrel,
1207 : rtoffset,
1208 : NRM_EQUAL,
1209 : NUM_EXEC_TLIST(plan));
1210 :
1211 : /* Fix quals too. */
377 alvherre 1212 CBC 845 : action->qual = (Node *) fix_join_expr(root,
377 alvherre 1213 GIC 845 : (List *) action->qual,
1214 : NULL, itlist,
1215 : resultrel,
1216 : rtoffset,
1217 : NRM_EQUAL,
1218 845 : NUM_EXEC_QUAL(plan));
1219 : }
1220 : }
1221 : }
1222 :
2973 tgl 1223 CBC 52176 : splan->nominalRelation += rtoffset;
1645 tgl 1224 GIC 52176 : if (splan->rootRelation)
1225 3586 : splan->rootRelation += rtoffset;
2893 andres 1226 52176 : splan->exclRelRTI += rtoffset;
1227 :
4929 tgl 1228 105434 : foreach(l, splan->resultRelations)
1229 : {
1230 53258 : lfirst_int(l) += rtoffset;
1231 : }
4913 1232 52910 : foreach(l, splan->rowMarks)
1233 : {
4913 tgl 1234 CBC 734 : PlanRowMark *rc = (PlanRowMark *) lfirst(l);
1235 :
4913 tgl 1236 GIC 734 : rc->rti += rtoffset;
1237 734 : rc->prti += rtoffset;
4913 tgl 1238 ECB : }
1239 :
4426 1240 : /*
1241 : * Append this ModifyTable node's final result relation RT
1242 : * index(es) to the global list for the plan.
1243 : */
4236 tgl 1244 CBC 104352 : root->glob->resultRelations =
4236 tgl 1245 GIC 52176 : list_concat(root->glob->resultRelations,
1336 tgl 1246 CBC 52176 : splan->resultRelations);
1645 1247 52176 : if (splan->rootRelation)
1248 : {
908 heikki.linnakangas 1249 3586 : root->glob->resultRelations =
1250 3586 : lappend_int(root->glob->resultRelations,
1645 tgl 1251 GIC 3586 : splan->rootRelation);
2169 rhaas 1252 ECB : }
1253 : }
4929 tgl 1254 CBC 52176 : break;
8631 1255 9105 : case T_Append:
1256 : /* Needs special treatment, see comments below */
1476 tgl 1257 GIC 9105 : return set_append_references(root,
1258 : (Append *) plan,
1259 : rtoffset);
4560 1260 194 : case T_MergeAppend:
1261 : /* Needs special treatment, see comments below */
1476 1262 194 : return set_mergeappend_references(root,
1263 : (MergeAppend *) plan,
1264 : rtoffset);
5300 1265 354 : case T_RecursiveUnion:
1266 : /* This doesn't evaluate targetlist or check quals either */
1267 354 : set_dummy_tlist_references(plan, rtoffset);
5300 tgl 1268 CBC 354 : Assert(plan->qual == NIL);
5300 tgl 1269 GIC 354 : break;
6564 1270 38 : case T_BitmapAnd:
1271 : {
5624 bruce 1272 38 : BitmapAnd *splan = (BitmapAnd *) plan;
1273 :
1274 : /* BitmapAnd works like Append, but has no tlist */
5890 tgl 1275 38 : Assert(splan->plan.targetlist == NIL);
1276 38 : Assert(splan->plan.qual == NIL);
1277 114 : foreach(l, splan->bitmapplans)
1278 : {
4236 1279 76 : lfirst(l) = set_plan_refs(root,
5890 1280 76 : (Plan *) lfirst(l),
1281 : rtoffset);
1282 : }
1283 : }
6564 1284 38 : break;
1285 111 : case T_BitmapOr:
1286 : {
5624 bruce 1287 111 : BitmapOr *splan = (BitmapOr *) plan;
1288 :
5890 tgl 1289 ECB : /* BitmapOr works like Append, but has no tlist */
5890 tgl 1290 GIC 111 : Assert(splan->plan.targetlist == NIL);
5890 tgl 1291 CBC 111 : Assert(splan->plan.qual == NIL);
5890 tgl 1292 GIC 360 : foreach(l, splan->bitmapplans)
1293 : {
4236 tgl 1294 CBC 249 : lfirst(l) = set_plan_refs(root,
5890 1295 249 : (Plan *) lfirst(l),
1296 : rtoffset);
5890 tgl 1297 ECB : }
1298 : }
6564 tgl 1299 CBC 111 : break;
8631 tgl 1300 UIC 0 : default:
7198 1301 0 : elog(ERROR, "unrecognized node type: %d",
7198 tgl 1302 ECB : (int) nodeTag(plan));
1303 : break;
1304 : }
1305 :
1306 : /*
1307 : * Now recurse into child plans, if any
1308 : *
1309 : * NOTE: it is essential that we recurse into child plans AFTER we set
1310 : * subplan references in this plan's tlist and quals. If we did the
8631 1311 : * reference-adjustments bottom-up, then we would fail to match this
6385 bruce 1312 : * plan's var nodes against the already-modified nodes of the children.
1313 : */
4236 tgl 1314 GIC 459562 : plan->lefttree = set_plan_refs(root, plan->lefttree, rtoffset);
1315 459562 : plan->righttree = set_plan_refs(root, plan->righttree, rtoffset);
1316 :
6531 tgl 1317 CBC 459562 : return plan;
1318 : }
1319 :
1320 : /*
1321 : * set_indexonlyscan_references
4198 tgl 1322 ECB : * Do set_plan_references processing on an IndexOnlyScan
1323 : *
1324 : * This is unlike the handling of a plain IndexScan because we have to
1325 : * convert Vars referencing the heap into Vars referencing the index.
1326 : * We can use the fix_upper_expr machinery for that, by working from a
1327 : * targetlist describing the index columns.
1328 : */
1329 : static Plan *
4198 tgl 1330 GIC 6151 : set_indexonlyscan_references(PlannerInfo *root,
4198 tgl 1331 ECB : IndexOnlyScan *plan,
1332 : int rtoffset)
1333 : {
1334 : indexed_tlist *index_itlist;
461 1335 : List *stripped_indextlist;
1336 : ListCell *lc;
1337 :
1338 : /*
1339 : * Vars in the plan node's targetlist, qual, and recheckqual must only
1340 : * reference columns that the index AM can actually return. To ensure
1341 : * this, remove non-returnable columns (which are marked as resjunk) from
1342 : * the indexed tlist. We can just drop them because the indexed_tlist
1343 : * machinery pays attention to TLE resnos, not physical list position.
1344 : */
461 tgl 1345 CBC 6151 : stripped_indextlist = NIL;
1346 13992 : foreach(lc, plan->indextlist)
1347 : {
1348 7841 : TargetEntry *indextle = (TargetEntry *) lfirst(lc);
461 tgl 1349 ECB :
461 tgl 1350 CBC 7841 : if (!indextle->resjunk)
461 tgl 1351 GIC 7815 : stripped_indextlist = lappend(stripped_indextlist, indextle);
1352 : }
4198 tgl 1353 ECB :
461 tgl 1354 CBC 6151 : index_itlist = build_tlist_index(stripped_indextlist);
1355 :
4198 1356 6151 : plan->scan.scanrelid += rtoffset;
4198 tgl 1357 GIC 6151 : plan->scan.plan.targetlist = (List *)
1358 6151 : fix_upper_expr(root,
4198 tgl 1359 CBC 6151 : (Node *) plan->scan.plan.targetlist,
1360 : index_itlist,
4198 tgl 1361 ECB : INDEX_VAR,
1362 : rtoffset,
1363 : NRM_EQUAL,
1364 : NUM_EXEC_TLIST((Plan *) plan));
4198 tgl 1365 CBC 6151 : plan->scan.plan.qual = (List *)
4198 tgl 1366 GIC 6151 : fix_upper_expr(root,
4198 tgl 1367 CBC 6151 : (Node *) plan->scan.plan.qual,
4198 tgl 1368 ECB : index_itlist,
1369 : INDEX_VAR,
924 1370 : rtoffset,
1371 : NRM_EQUAL,
924 tgl 1372 GIC 6151 : NUM_EXEC_QUAL((Plan *) plan));
461 tgl 1373 CBC 6151 : plan->recheckqual = (List *)
461 tgl 1374 GIC 6151 : fix_upper_expr(root,
1375 6151 : (Node *) plan->recheckqual,
461 tgl 1376 ECB : index_itlist,
1377 : INDEX_VAR,
1378 : rtoffset,
1379 : NRM_EQUAL,
461 tgl 1380 GIC 6151 : NUM_EXEC_QUAL((Plan *) plan));
4198 tgl 1381 ECB : /* indexqual is already transformed to reference index columns */
924 tgl 1382 CBC 6151 : plan->indexqual = fix_scan_list(root, plan->indexqual,
1383 : rtoffset, 1);
1384 : /* indexorderby is already transformed to reference index columns */
924 tgl 1385 GIC 6151 : plan->indexorderby = fix_scan_list(root, plan->indexorderby,
924 tgl 1386 ECB : rtoffset, 1);
4198 1387 : /* indextlist must NOT be transformed to reference index columns */
924 tgl 1388 GIC 6151 : plan->indextlist = fix_scan_list(root, plan->indextlist,
924 tgl 1389 ECB : rtoffset, NUM_EXEC_TLIST((Plan *) plan));
1390 :
4198 tgl 1391 GIC 6151 : pfree(index_itlist);
4198 tgl 1392 ECB :
4198 tgl 1393 CBC 6151 : return (Plan *) plan;
4198 tgl 1394 ECB : }
1395 :
6531 1396 : /*
1397 : * set_subqueryscan_references
1398 : * Do set_plan_references processing on a SubqueryScan
1399 : *
1400 : * We try to strip out the SubqueryScan entirely; if we can't, we have
1401 : * to do the normal processing on it.
6531 tgl 1402 EUB : */
1403 : static Plan *
4236 tgl 1404 GIC 10241 : set_subqueryscan_references(PlannerInfo *root,
1405 : SubqueryScan *plan,
1406 : int rtoffset)
1407 : {
1408 : RelOptInfo *rel;
1409 : Plan *result;
1410 :
1411 : /* Need to look up the subquery's RelOptInfo, since we need its subroot */
1412 10241 : rel = find_base_rel(root, plan->scan.scanrelid);
1413 :
1414 : /* Recursively process the subplan */
1415 10241 : plan->subplan = set_plan_references(rel->subroot, plan->subplan);
6531 tgl 1416 ECB :
6531 tgl 1417 CBC 10241 : if (trivial_subqueryscan(plan))
1418 : {
6531 tgl 1419 ECB : /*
1420 : * We can omit the SubqueryScan node and just pull up the subplan.
1421 : */
1476 tgl 1422 GIC 5540 : result = clean_up_removed_plan_level((Plan *) plan, plan->subplan);
1423 : }
1424 : else
1425 : {
1426 : /*
1427 : * Keep the SubqueryScan node. We have to do the processing that
1428 : * set_plan_references would otherwise have done on it. Notice we do
1429 : * not do set_upper_references() here, because a SubqueryScan will
1430 : * always have been created with correct references to its subplan's
1431 : * outputs to begin with.
6531 tgl 1432 ECB : */
5890 tgl 1433 GIC 4701 : plan->scan.scanrelid += rtoffset;
1434 4701 : plan->scan.plan.targetlist =
924 1435 4701 : fix_scan_list(root, plan->scan.plan.targetlist,
1436 : rtoffset, NUM_EXEC_TLIST((Plan *) plan));
5890 1437 4701 : plan->scan.plan.qual =
924 1438 4701 : fix_scan_list(root, plan->scan.plan.qual,
1439 : rtoffset, NUM_EXEC_QUAL((Plan *) plan));
1440 :
5890 1441 4701 : result = (Plan *) plan;
1442 : }
1443 :
6531 1444 10241 : return result;
1445 : }
1446 :
6531 tgl 1447 ECB : /*
1448 : * trivial_subqueryscan
1449 : * Detect whether a SubqueryScan can be deleted from the plan tree.
1450 : *
1451 : * We can delete it if it has no qual to check and the targetlist just
1452 : * regurgitates the output of the child plan.
368 efujita 1453 : *
1454 : * This can be called from mark_async_capable_plan(), a helper function for
1455 : * create_append_plan(), before set_subqueryscan_references(), to determine
304 1456 : * triviality of a SubqueryScan that is a child of an Append node. So we
1457 : * cache the result in the SubqueryScan node to avoid repeated computation.
1458 : *
1459 : * Note: when called from mark_async_capable_plan(), we determine the result
1460 : * before running finalize_plan() on the SubqueryScan node (if needed) and
1461 : * set_plan_references() on the subplan tree, but this would be safe, because
1462 : * 1) finalize_plan() doesn't modify the tlist or quals for the SubqueryScan
1463 : * node (or that for any plan node in the subplan tree), and
1464 : * 2) set_plan_references() modifies the tlist for every plan node in the
1465 : * subplan tree, but keeps const/resjunk columns as const/resjunk ones and
1466 : * preserves the length and order of the tlist, and
1467 : * 3) set_plan_references() might delete the topmost plan node like an Append
1468 : * or MergeAppend from the subplan tree and pull up the child plan node,
1469 : * but in that case, the tlist for the child plan node exactly matches the
1470 : * parent.
1471 : */
1472 : bool
6531 tgl 1473 GIC 15878 : trivial_subqueryscan(SubqueryScan *plan)
6531 tgl 1474 ECB : {
1475 : int attrno;
1476 : ListCell *lp,
1477 : *lc;
1478 :
1479 : /* We might have detected this already; in which case reuse the result */
368 efujita 1480 GIC 15878 : if (plan->scanstatus == SUBQUERY_SCAN_TRIVIAL)
1481 2470 : return true;
368 efujita 1482 CBC 13408 : if (plan->scanstatus == SUBQUERY_SCAN_NONTRIVIAL)
368 efujita 1483 GIC 3167 : return false;
368 efujita 1484 CBC 10241 : Assert(plan->scanstatus == SUBQUERY_SCAN_UNKNOWN);
1485 : /* Initially, mark the SubqueryScan as non-deletable from the plan tree */
368 efujita 1486 GIC 10241 : plan->scanstatus = SUBQUERY_SCAN_NONTRIVIAL;
368 efujita 1487 ECB :
6531 tgl 1488 GIC 10241 : if (plan->scan.plan.qual != NIL)
1489 284 : return false;
6531 tgl 1490 ECB :
6425 tgl 1491 GIC 19914 : if (list_length(plan->scan.plan.targetlist) !=
1492 9957 : list_length(plan->subplan->targetlist))
6425 tgl 1493 CBC 1390 : return false; /* tlists not same length */
1494 :
6531 1495 8567 : attrno = 1;
6531 tgl 1496 GIC 23697 : forboth(lp, plan->scan.plan.targetlist, lc, plan->subplan->targetlist)
1497 : {
1498 18157 : TargetEntry *ptle = (TargetEntry *) lfirst(lp);
1499 18157 : TargetEntry *ctle = (TargetEntry *) lfirst(lc);
1500 :
1501 18157 : if (ptle->resjunk != ctle->resjunk)
1502 3027 : return false; /* tlist doesn't match junk status */
1503 :
1504 : /*
1505 : * We accept either a Var referencing the corresponding element of the
6031 bruce 1506 ECB : * subplan tlist, or a Const equaling the subplan element. See
1507 : * generate_setop_tlist() for motivation.
1508 : */
6068 tgl 1509 GIC 18151 : if (ptle->expr && IsA(ptle->expr, Var))
1510 13855 : {
6031 bruce 1511 13947 : Var *var = (Var *) ptle->expr;
1512 :
6068 tgl 1513 13947 : Assert(var->varno == plan->scan.scanrelid);
6068 tgl 1514 CBC 13947 : Assert(var->varlevelsup == 0);
6068 tgl 1515 GIC 13947 : if (var->varattno != attrno)
1516 92 : return false; /* out of order */
6068 tgl 1517 ECB : }
6068 tgl 1518 GIC 4204 : else if (ptle->expr && IsA(ptle->expr, Const))
6068 tgl 1519 ECB : {
6068 tgl 1520 GIC 3704 : if (!equal(ptle->expr, ctle->expr))
1521 2429 : return false;
1522 : }
1523 : else
6068 tgl 1524 CBC 500 : return false;
1525 :
6531 tgl 1526 GIC 15130 : attrno++;
1527 : }
1528 :
1529 : /* Re-mark the SubqueryScan as deletable from the plan tree */
368 efujita 1530 5540 : plan->scanstatus = SUBQUERY_SCAN_TRIVIAL;
1531 :
6531 tgl 1532 5540 : return true;
1533 : }
1534 :
1476 tgl 1535 ECB : /*
1536 : * clean_up_removed_plan_level
1537 : * Do necessary cleanup when we strip out a SubqueryScan, Append, etc
1538 : *
1539 : * We are dropping the "parent" plan in favor of returning just its "child".
1540 : * A few small tweaks are needed.
1541 : */
1542 : static Plan *
1476 tgl 1543 CBC 8320 : clean_up_removed_plan_level(Plan *parent, Plan *child)
1544 : {
1545 : /* We have to be sure we don't lose any initplans */
1546 16640 : child->initPlan = list_concat(parent->initPlan,
1476 tgl 1547 GIC 8320 : child->initPlan);
1548 :
1549 : /*
1550 : * We also have to transfer the parent's column labeling info into the
1551 : * child, else columns sent to client will be improperly labeled if this
1552 : * is the topmost plan level. resjunk and so on may be important too.
1553 : */
1554 8320 : apply_tlist_labeling(child->targetlist, parent->targetlist);
1555 :
1556 8320 : return child;
1557 : }
1558 :
1559 : /*
1560 : * set_foreignscan_references
1561 : * Do set_plan_references processing on a ForeignScan
1562 : */
1563 : static void
2891 1564 943 : set_foreignscan_references(PlannerInfo *root,
1565 : ForeignScan *fscan,
1566 : int rtoffset)
1567 : {
1568 : /* Adjust scanrelid if it's valid */
1569 943 : if (fscan->scan.scanrelid > 0)
1570 695 : fscan->scan.scanrelid += rtoffset;
1571 :
1572 943 : if (fscan->fdw_scan_tlist != NIL || fscan->scan.scanrelid == 0)
1573 248 : {
1574 : /*
2588 rhaas 1575 ECB : * Adjust tlist, qual, fdw_exprs, fdw_recheck_quals to reference
1576 : * foreign scan tuple
1577 : */
2891 tgl 1578 GIC 248 : indexed_tlist *itlist = build_tlist_index(fscan->fdw_scan_tlist);
1579 :
1580 248 : fscan->scan.plan.targetlist = (List *)
1581 248 : fix_upper_expr(root,
2891 tgl 1582 CBC 248 : (Node *) fscan->scan.plan.targetlist,
2891 tgl 1583 ECB : itlist,
1584 : INDEX_VAR,
924 1585 : rtoffset,
1586 : NRM_EQUAL,
1587 : NUM_EXEC_TLIST((Plan *) fscan));
2891 tgl 1588 GIC 248 : fscan->scan.plan.qual = (List *)
2891 tgl 1589 CBC 248 : fix_upper_expr(root,
2891 tgl 1590 GIC 248 : (Node *) fscan->scan.plan.qual,
2891 tgl 1591 ECB : itlist,
1592 : INDEX_VAR,
1593 : rtoffset,
1594 : NRM_EQUAL,
924 tgl 1595 CBC 248 : NUM_EXEC_QUAL((Plan *) fscan));
2891 1596 248 : fscan->fdw_exprs = (List *)
1597 248 : fix_upper_expr(root,
2891 tgl 1598 GIC 248 : (Node *) fscan->fdw_exprs,
2891 tgl 1599 ECB : itlist,
1600 : INDEX_VAR,
1601 : rtoffset,
1602 : NRM_EQUAL,
924 tgl 1603 CBC 248 : NUM_EXEC_QUAL((Plan *) fscan));
2699 rhaas 1604 248 : fscan->fdw_recheck_quals = (List *)
2699 rhaas 1605 GIC 248 : fix_upper_expr(root,
2699 rhaas 1606 CBC 248 : (Node *) fscan->fdw_recheck_quals,
2699 rhaas 1607 ECB : itlist,
1608 : INDEX_VAR,
1609 : rtoffset,
1610 : NRM_EQUAL,
924 tgl 1611 GIC 248 : NUM_EXEC_QUAL((Plan *) fscan));
2891 1612 248 : pfree(itlist);
1613 : /* fdw_scan_tlist itself just needs fix_scan_list() adjustments */
1614 248 : fscan->fdw_scan_tlist =
924 tgl 1615 CBC 248 : fix_scan_list(root, fscan->fdw_scan_tlist,
924 tgl 1616 ECB : rtoffset, NUM_EXEC_TLIST((Plan *) fscan));
2891 1617 : }
1618 : else
1619 : {
2588 rhaas 1620 : /*
1621 : * Adjust tlist, qual, fdw_exprs, fdw_recheck_quals in the standard
1622 : * way
1623 : */
2891 tgl 1624 CBC 695 : fscan->scan.plan.targetlist =
924 tgl 1625 GIC 695 : fix_scan_list(root, fscan->scan.plan.targetlist,
924 tgl 1626 ECB : rtoffset, NUM_EXEC_TLIST((Plan *) fscan));
2891 tgl 1627 CBC 695 : fscan->scan.plan.qual =
924 tgl 1628 GIC 695 : fix_scan_list(root, fscan->scan.plan.qual,
1629 : rtoffset, NUM_EXEC_QUAL((Plan *) fscan));
2891 tgl 1630 CBC 695 : fscan->fdw_exprs =
924 tgl 1631 GIC 695 : fix_scan_list(root, fscan->fdw_exprs,
924 tgl 1632 ECB : rtoffset, NUM_EXEC_QUAL((Plan *) fscan));
2733 rhaas 1633 GIC 695 : fscan->fdw_recheck_quals =
924 tgl 1634 695 : fix_scan_list(root, fscan->fdw_recheck_quals,
1635 : rtoffset, NUM_EXEC_QUAL((Plan *) fscan));
2891 tgl 1636 ECB : }
1637 :
1215 tgl 1638 CBC 943 : fscan->fs_relids = offset_relid_set(fscan->fs_relids, rtoffset);
69 tgl 1639 GNC 943 : fscan->fs_base_relids = offset_relid_set(fscan->fs_base_relids, rtoffset);
1640 :
1641 : /* Adjust resultRelation if it's valid */
907 heikki.linnakangas 1642 GIC 943 : if (fscan->resultRelation > 0)
1643 104 : fscan->resultRelation += rtoffset;
2891 tgl 1644 943 : }
1645 :
1646 : /*
1647 : * set_customscan_references
1648 : * Do set_plan_references processing on a CustomScan
1649 : */
2891 tgl 1650 ECB : static void
2891 tgl 1651 UIC 0 : set_customscan_references(PlannerInfo *root,
1652 : CustomScan *cscan,
2891 tgl 1653 ECB : int rtoffset)
1654 : {
1655 : ListCell *lc;
1656 :
1657 : /* Adjust scanrelid if it's valid */
2891 tgl 1658 UIC 0 : if (cscan->scan.scanrelid > 0)
1659 0 : cscan->scan.scanrelid += rtoffset;
1660 :
2891 tgl 1661 LBC 0 : if (cscan->custom_scan_tlist != NIL || cscan->scan.scanrelid == 0)
2891 tgl 1662 UIC 0 : {
2891 tgl 1663 ECB : /* Adjust tlist, qual, custom_exprs to reference custom scan tuple */
2891 tgl 1664 UIC 0 : indexed_tlist *itlist = build_tlist_index(cscan->custom_scan_tlist);
1665 :
1666 0 : cscan->scan.plan.targetlist = (List *)
1667 0 : fix_upper_expr(root,
1668 0 : (Node *) cscan->scan.plan.targetlist,
1669 : itlist,
1670 : INDEX_VAR,
924 tgl 1671 ECB : rtoffset,
1672 : NRM_EQUAL,
1673 : NUM_EXEC_TLIST((Plan *) cscan));
2891 tgl 1674 UIC 0 : cscan->scan.plan.qual = (List *)
1675 0 : fix_upper_expr(root,
1676 0 : (Node *) cscan->scan.plan.qual,
2891 tgl 1677 ECB : itlist,
1678 : INDEX_VAR,
1679 : rtoffset,
1680 : NRM_EQUAL,
924 tgl 1681 LBC 0 : NUM_EXEC_QUAL((Plan *) cscan));
2891 1682 0 : cscan->custom_exprs = (List *)
2891 tgl 1683 UIC 0 : fix_upper_expr(root,
1684 0 : (Node *) cscan->custom_exprs,
1685 : itlist,
1686 : INDEX_VAR,
924 tgl 1687 ECB : rtoffset,
1688 : NRM_EQUAL,
924 tgl 1689 UIC 0 : NUM_EXEC_QUAL((Plan *) cscan));
2891 tgl 1690 LBC 0 : pfree(itlist);
2891 tgl 1691 ECB : /* custom_scan_tlist itself just needs fix_scan_list() adjustments */
2891 tgl 1692 LBC 0 : cscan->custom_scan_tlist =
924 tgl 1693 UIC 0 : fix_scan_list(root, cscan->custom_scan_tlist,
1694 : rtoffset, NUM_EXEC_TLIST((Plan *) cscan));
1695 : }
1696 : else
1697 : {
2891 tgl 1698 ECB : /* Adjust tlist, qual, custom_exprs in the standard way */
2891 tgl 1699 LBC 0 : cscan->scan.plan.targetlist =
924 1700 0 : fix_scan_list(root, cscan->scan.plan.targetlist,
1701 : rtoffset, NUM_EXEC_TLIST((Plan *) cscan));
2891 tgl 1702 UIC 0 : cscan->scan.plan.qual =
924 1703 0 : fix_scan_list(root, cscan->scan.plan.qual,
1704 : rtoffset, NUM_EXEC_QUAL((Plan *) cscan));
2891 tgl 1705 LBC 0 : cscan->custom_exprs =
924 1706 0 : fix_scan_list(root, cscan->custom_exprs,
924 tgl 1707 ECB : rtoffset, NUM_EXEC_QUAL((Plan *) cscan));
2891 1708 : }
1709 :
1710 : /* Adjust child plan-nodes recursively, if needed */
2819 tgl 1711 UIC 0 : foreach(lc, cscan->custom_plans)
1712 : {
2844 rhaas 1713 LBC 0 : lfirst(lc) = set_plan_refs(root, (Plan *) lfirst(lc), rtoffset);
2844 rhaas 1714 ECB : }
1715 :
1215 tgl 1716 LBC 0 : cscan->custom_relids = offset_relid_set(cscan->custom_relids, rtoffset);
2891 tgl 1717 UIC 0 : }
1718 :
1719 : /*
1720 : * register_partpruneinfo
1721 : * Subroutine for set_append_references and set_mergeappend_references
1722 : *
1723 : * Add the PartitionPruneInfo from root->partPruneInfos at the given index
1724 : * into PlannerGlobal->partPruneInfos and return its index there.
1725 : */
1726 : static int
10 alvherre 1727 GNC 212 : register_partpruneinfo(PlannerInfo *root, int part_prune_index)
1728 : {
1729 212 : PlannerGlobal *glob = root->glob;
1730 : PartitionPruneInfo *pruneinfo;
1731 :
1732 212 : Assert(part_prune_index >= 0 &&
1733 : part_prune_index < list_length(root->partPruneInfos));
1734 212 : pruneinfo = list_nth_node(PartitionPruneInfo, root->partPruneInfos,
1735 : part_prune_index);
1736 :
1737 212 : glob->partPruneInfos = lappend(glob->partPruneInfos, pruneinfo);
1738 :
1739 212 : return list_length(glob->partPruneInfos) - 1;
1740 : }
1741 :
1742 : /*
1743 : * set_append_references
1476 tgl 1744 ECB : * Do set_plan_references processing on an Append
1745 : *
1746 : * We try to strip out the Append entirely; if we can't, we have
1747 : * to do the normal processing on it.
1748 : */
1749 : static Plan *
1476 tgl 1750 GIC 9105 : set_append_references(PlannerInfo *root,
1751 : Append *aplan,
1752 : int rtoffset)
1753 : {
1754 : ListCell *l;
1755 :
1756 : /*
1476 tgl 1757 ECB : * Append, like Sort et al, doesn't actually evaluate its targetlist or
1758 : * check quals. If it's got exactly one child plan, then it's not doing
1759 : * anything useful at all, and we can strip it out.
1760 : */
1476 tgl 1761 CBC 9105 : Assert(aplan->plan.qual == NIL);
1762 :
1476 tgl 1763 ECB : /* First, we gotta recurse on the children */
1476 tgl 1764 CBC 30240 : foreach(l, aplan->appendplans)
1765 : {
1766 21135 : lfirst(l) = set_plan_refs(root, (Plan *) lfirst(l), rtoffset);
1476 tgl 1767 ECB : }
1768 :
1769 : /*
1770 : * See if it's safe to get rid of the Append entirely. For this to be
439 drowley 1771 : * safe, there must be only one child plan and that child plan's parallel
1772 : * awareness must match the Append's. The reason for the latter is that
1773 : * if the Append is parallel aware and the child is not, then the calling
1774 : * plan may execute the non-parallel aware child multiple times. (If you
1775 : * change these rules, update create_append_path to match.)
1776 : */
264 alvherre 1777 GNC 9105 : if (list_length(aplan->appendplans) == 1)
1778 : {
1779 2778 : Plan *p = (Plan *) linitial(aplan->appendplans);
1780 :
1781 2778 : if (p->parallel_aware == aplan->plan.parallel_aware)
1782 2778 : return clean_up_removed_plan_level((Plan *) aplan, p);
1783 : }
1784 :
1785 : /*
1786 : * Otherwise, clean up the Append as needed. It's okay to do this after
1476 tgl 1787 EUB : * recursing to the children, because set_dummy_tlist_references doesn't
1788 : * look at those.
1789 : */
1476 tgl 1790 GIC 6327 : set_dummy_tlist_references((Plan *) aplan, rtoffset);
1791 :
1215 1792 6327 : aplan->apprelids = offset_relid_set(aplan->apprelids, rtoffset);
1793 :
1794 : /*
1795 : * Add PartitionPruneInfo, if any, to PlannerGlobal and update the index.
1796 : */
129 alvherre 1797 GNC 6327 : if (aplan->part_prune_index >= 0)
10 1798 200 : aplan->part_prune_index =
1799 200 : register_partpruneinfo(root, aplan->part_prune_index);
1800 :
1476 tgl 1801 EUB : /* We don't need to recurse to lefttree or righttree ... */
1476 tgl 1802 GBC 6327 : Assert(aplan->plan.lefttree == NULL);
1803 6327 : Assert(aplan->plan.righttree == NULL);
1804 :
1476 tgl 1805 GIC 6327 : return (Plan *) aplan;
1806 : }
1807 :
1476 tgl 1808 EUB : /*
1809 : * set_mergeappend_references
1810 : * Do set_plan_references processing on a MergeAppend
1811 : *
1812 : * We try to strip out the MergeAppend entirely; if we can't, we have
1813 : * to do the normal processing on it.
1814 : */
1815 : static Plan *
1476 tgl 1816 GBC 194 : set_mergeappend_references(PlannerInfo *root,
1476 tgl 1817 EUB : MergeAppend *mplan,
1818 : int rtoffset)
1819 : {
1820 : ListCell *l;
1821 :
1822 : /*
1823 : * MergeAppend, like Sort et al, doesn't actually evaluate its targetlist
1824 : * or check quals. If it's got exactly one child plan, then it's not
1825 : * doing anything useful at all, and we can strip it out.
1826 : */
1476 tgl 1827 GBC 194 : Assert(mplan->plan.qual == NIL);
1828 :
1476 tgl 1829 EUB : /* First, we gotta recurse on the children */
1476 tgl 1830 GBC 785 : foreach(l, mplan->mergeplans)
1831 : {
1832 591 : lfirst(l) = set_plan_refs(root, (Plan *) lfirst(l), rtoffset);
1476 tgl 1833 EUB : }
1834 :
1835 : /*
1836 : * See if it's safe to get rid of the MergeAppend entirely. For this to
1837 : * be safe, there must be only one child plan and that child plan's
1838 : * parallel awareness must match the MergeAppend's. The reason for the
1839 : * latter is that if the MergeAppend is parallel aware and the child is
1840 : * not, then the calling plan may execute the non-parallel aware child
1841 : * multiple times. (If you change these rules, update
1842 : * create_merge_append_path to match.)
1843 : */
264 alvherre 1844 GNC 194 : if (list_length(mplan->mergeplans) == 1)
1845 : {
1846 2 : Plan *p = (Plan *) linitial(mplan->mergeplans);
1847 :
1848 2 : if (p->parallel_aware == mplan->plan.parallel_aware)
1849 2 : return clean_up_removed_plan_level((Plan *) mplan, p);
1850 : }
1851 :
1852 : /*
1853 : * Otherwise, clean up the MergeAppend as needed. It's okay to do this
1854 : * after recursing to the children, because set_dummy_tlist_references
1855 : * doesn't look at those.
1856 : */
1476 tgl 1857 GIC 192 : set_dummy_tlist_references((Plan *) mplan, rtoffset);
1476 tgl 1858 ECB :
1215 tgl 1859 GIC 192 : mplan->apprelids = offset_relid_set(mplan->apprelids, rtoffset);
1215 tgl 1860 ECB :
1861 : /*
1862 : * Add PartitionPruneInfo, if any, to PlannerGlobal and update the index.
1863 : */
129 alvherre 1864 GNC 192 : if (mplan->part_prune_index >= 0)
10 1865 12 : mplan->part_prune_index =
1866 12 : register_partpruneinfo(root, mplan->part_prune_index);
1867 :
1868 : /* We don't need to recurse to lefttree or righttree ... */
1476 tgl 1869 GIC 192 : Assert(mplan->plan.lefttree == NULL);
1870 192 : Assert(mplan->plan.righttree == NULL);
1871 :
1476 tgl 1872 CBC 192 : return (Plan *) mplan;
1873 : }
1874 :
1875 : /*
1876 : * set_hash_references
1877 : * Do set_plan_references processing on a Hash node
1878 : */
1879 : static void
1346 andres 1880 GIC 13953 : set_hash_references(PlannerInfo *root, Plan *plan, int rtoffset)
1881 : {
1882 13953 : Hash *hplan = (Hash *) plan;
1346 andres 1883 CBC 13953 : Plan *outer_plan = plan->lefttree;
1884 : indexed_tlist *outer_itlist;
1885 :
1346 andres 1886 ECB : /*
1887 : * Hash's hashkeys are used when feeding tuples into the hashtable,
1888 : * therefore have them reference Hash's outer plan (which itself is the
1889 : * inner plan of the HashJoin).
1890 : */
1346 andres 1891 GIC 13953 : outer_itlist = build_tlist_index(outer_plan->targetlist);
1892 13953 : hplan->hashkeys = (List *)
1893 13953 : fix_upper_expr(root,
1894 13953 : (Node *) hplan->hashkeys,
1895 : outer_itlist,
1896 : OUTER_VAR,
1897 : rtoffset,
1898 : NRM_EQUAL,
924 tgl 1899 13953 : NUM_EXEC_QUAL(plan));
1346 andres 1900 ECB :
1901 : /* Hash doesn't project */
1346 andres 1902 CBC 13953 : set_dummy_tlist_references(plan, rtoffset);
1903 :
1346 andres 1904 ECB : /* Hash nodes don't have their own quals */
1346 andres 1905 CBC 13953 : Assert(plan->qual == NIL);
1346 andres 1906 GIC 13953 : }
1907 :
1908 : /*
1909 : * offset_relid_set
1910 : * Apply rtoffset to the members of a Relids set.
1911 : */
1912 : static Relids
1215 tgl 1913 CBC 8632 : offset_relid_set(Relids relids, int rtoffset)
1914 : {
1915 8632 : Relids result = NULL;
1916 : int rtindex;
1917 :
1918 : /* If there's no offset to apply, we needn't recompute the value */
1215 tgl 1919 GIC 8632 : if (rtoffset == 0)
1215 tgl 1920 CBC 7716 : return relids;
1921 916 : rtindex = -1;
1922 2459 : while ((rtindex = bms_next_member(relids, rtindex)) >= 0)
1215 tgl 1923 GIC 1543 : result = bms_add_member(result, rtindex + rtoffset);
1924 916 : return result;
1215 tgl 1925 ECB : }
1926 :
1927 : /*
5823 1928 : * copyVar
1929 : * Copy a Var node.
1930 : *
1931 : * fix_scan_expr and friends do this enough times that it's worth having
1932 : * a bespoke routine instead of using the generic copyObject() function.
1933 : */
1934 : static inline Var *
5823 tgl 1935 GIC 683886 : copyVar(Var *var)
1936 : {
1937 683886 : Var *newvar = (Var *) palloc(sizeof(Var));
1938 :
5823 tgl 1939 CBC 683886 : *newvar = *var;
5823 tgl 1940 GIC 683886 : return newvar;
1941 : }
1942 :
1943 : /*
1944 : * fix_expr_common
1945 : * Do generic set_plan_references processing on an expression node
1946 : *
1947 : * This is code that is common to all variants of expression-fixing.
1948 : * We must look up operator opcode info for OpExpr and related nodes,
1949 : * add OIDs from regclass Const nodes into root->glob->relationOids, and
2768 tgl 1950 ECB : * add PlanInvalItems for user-defined functions into root->glob->invalItems.
1951 : * We also fill in column index lists for GROUPING() expressions.
1952 : *
5325 1953 : * We assume it's okay to update opcode info in-place. So this could possibly
1954 : * scribble on the planner's input data structures, but it's OK.
1955 : */
1956 : static void
4236 tgl 1957 GIC 5680440 : fix_expr_common(PlannerInfo *root, Node *node)
1958 : {
1959 : /* We assume callers won't call us on a NULL pointer */
5325 1960 5680440 : if (IsA(node, Aggref))
1961 : {
4236 1962 23280 : record_plan_function_dependency(root,
1963 : ((Aggref *) node)->aggfnoid);
1964 : }
5215 1965 5657160 : else if (IsA(node, WindowFunc))
1966 : {
4236 tgl 1967 CBC 1431 : record_plan_function_dependency(root,
1968 : ((WindowFunc *) node)->winfnoid);
5215 tgl 1969 ECB : }
5325 tgl 1970 GIC 5655729 : else if (IsA(node, FuncExpr))
5325 tgl 1971 ECB : {
4236 tgl 1972 CBC 123045 : record_plan_function_dependency(root,
1973 : ((FuncExpr *) node)->funcid);
1974 : }
5325 tgl 1975 GIC 5532684 : else if (IsA(node, OpExpr))
1976 : {
1977 316288 : set_opfuncid((OpExpr *) node);
4236 1978 316288 : record_plan_function_dependency(root,
1979 : ((OpExpr *) node)->opfuncid);
5325 tgl 1980 ECB : }
5325 tgl 1981 GIC 5216396 : else if (IsA(node, DistinctExpr))
5325 tgl 1982 ECB : {
5325 tgl 1983 GIC 359 : set_opfuncid((OpExpr *) node); /* rely on struct equivalence */
4236 1984 359 : record_plan_function_dependency(root,
1985 : ((DistinctExpr *) node)->opfuncid);
1986 : }
5325 tgl 1987 CBC 5216037 : else if (IsA(node, NullIfExpr))
5325 tgl 1988 ECB : {
5325 tgl 1989 CBC 64 : set_opfuncid((OpExpr *) node); /* rely on struct equivalence */
4236 tgl 1990 GIC 64 : record_plan_function_dependency(root,
1991 : ((NullIfExpr *) node)->opfuncid);
5325 tgl 1992 ECB : }
5325 tgl 1993 CBC 5215973 : else if (IsA(node, ScalarArrayOpExpr))
1994 : {
731 drowley 1995 13759 : ScalarArrayOpExpr *saop = (ScalarArrayOpExpr *) node;
1996 :
731 drowley 1997 GIC 13759 : set_sa_opfuncid(saop);
1998 13759 : record_plan_function_dependency(root, saop->opfuncid);
1999 :
2000 13759 : if (!OidIsValid(saop->hashfuncid))
2001 13536 : record_plan_function_dependency(root, saop->hashfuncid);
2002 :
641 drowley 2003 CBC 13759 : if (!OidIsValid(saop->negfuncid))
641 drowley 2004 GIC 13724 : record_plan_function_dependency(root, saop->negfuncid);
5325 tgl 2005 ECB : }
5325 tgl 2006 CBC 5202214 : else if (IsA(node, Const))
2007 : {
5325 tgl 2008 GIC 636620 : Const *con = (Const *) node;
2009 :
2010 : /* Check for regclass reference */
2011 636620 : if (ISREGCLASSCONST(con))
4236 2012 83828 : root->glob->relationOids =
2013 83828 : lappend_oid(root->glob->relationOids,
5325 tgl 2014 ECB : DatumGetObjectId(con->constvalue));
2015 : }
2885 andres 2016 CBC 4565594 : else if (IsA(node, GroupingFunc))
2885 andres 2017 ECB : {
2885 andres 2018 GIC 151 : GroupingFunc *g = (GroupingFunc *) node;
2019 151 : AttrNumber *grouping_map = root->grouping_map;
2020 :
2021 : /* If there are no grouping sets, we don't need this. */
2885 andres 2022 ECB :
2885 andres 2023 GIC 151 : Assert(grouping_map || g->cols == NIL);
2024 :
2885 andres 2025 CBC 151 : if (grouping_map)
2026 : {
2027 : ListCell *lc;
2028 106 : List *cols = NIL;
2885 andres 2029 ECB :
2885 andres 2030 GIC 294 : foreach(lc, g->refs)
2031 : {
2032 188 : cols = lappend_int(cols, grouping_map[lfirst_int(lc)]);
2033 : }
2034 :
2035 106 : Assert(!g->cols || equal(cols, g->cols));
2885 andres 2036 ECB :
2885 andres 2037 GIC 106 : if (!g->cols)
2885 andres 2038 CBC 106 : g->cols = cols;
2039 : }
2040 : }
5325 tgl 2041 GIC 5680440 : }
5325 tgl 2042 ECB :
3217 2043 : /*
2044 : * fix_param_node
2045 : * Do set_plan_references processing on a Param
2046 : *
2047 : * If it's a PARAM_MULTIEXPR, replace it with the appropriate Param from
2048 : * root->multiexpr_params; otherwise no change is needed.
2049 : * Just for paranoia's sake, we make a copy of the node in either case.
2050 : */
2051 : static Node *
3217 tgl 2052 GIC 35772 : fix_param_node(PlannerInfo *root, Param *p)
2053 : {
2054 35772 : if (p->paramkind == PARAM_MULTIEXPR)
2055 : {
2056 137 : int subqueryid = p->paramid >> 16;
2057 137 : int colno = p->paramid & 0xFFFF;
3217 tgl 2058 ECB : List *params;
2059 :
3217 tgl 2060 CBC 274 : if (subqueryid <= 0 ||
3217 tgl 2061 GIC 137 : subqueryid > list_length(root->multiexpr_params))
3217 tgl 2062 LBC 0 : elog(ERROR, "unexpected PARAM_MULTIEXPR ID: %d", p->paramid);
3217 tgl 2063 CBC 137 : params = (List *) list_nth(root->multiexpr_params, subqueryid - 1);
3217 tgl 2064 GIC 137 : if (colno <= 0 || colno > list_length(params))
3217 tgl 2065 UIC 0 : elog(ERROR, "unexpected PARAM_MULTIEXPR ID: %d", p->paramid);
3217 tgl 2066 GIC 137 : return copyObject(list_nth(params, colno - 1));
2067 : }
2222 peter_e 2068 35635 : return (Node *) copyObject(p);
2069 : }
2070 :
2071 : /*
2072 : * fix_alternative_subplan
2073 : * Do set_plan_references processing on an AlternativeSubPlan
2074 : *
2075 : * Choose one of the alternative implementations and return just that one,
2076 : * discarding the rest of the AlternativeSubPlan structure.
2077 : * Note: caller must still recurse into the result!
2078 : *
2079 : * We don't make any attempt to fix up cost estimates in the parent plan
572 tgl 2080 ECB : * node or higher-level nodes.
2081 : */
2082 : static Node *
924 tgl 2083 CBC 753 : fix_alternative_subplan(PlannerInfo *root, AlternativeSubPlan *asplan,
2084 : double num_exec)
924 tgl 2085 ECB : {
924 tgl 2086 GIC 753 : SubPlan *bestplan = NULL;
2087 753 : Cost bestcost = 0;
924 tgl 2088 ECB : ListCell *lc;
2089 :
2090 : /*
2091 : * Compute the estimated cost of each subplan assuming num_exec
2092 : * executions, and keep the cheapest one. In event of exact equality of
572 2093 : * estimates, we prefer the later plan; this is a bit arbitrary, but in
2094 : * current usage it biases us to break ties against fast-start subplans.
924 2095 : */
924 tgl 2096 GIC 753 : Assert(asplan->subplans != NIL);
2097 :
924 tgl 2098 CBC 2259 : foreach(lc, asplan->subplans)
2099 : {
2100 1506 : SubPlan *curplan = (SubPlan *) lfirst(lc);
924 tgl 2101 ECB : Cost curcost;
2102 :
924 tgl 2103 GIC 1506 : curcost = curplan->startup_cost + num_exec * curplan->per_call_cost;
572 tgl 2104 CBC 1506 : if (bestplan == NULL || curcost <= bestcost)
2105 : {
924 2106 1035 : bestplan = curplan;
2107 1035 : bestcost = curcost;
2108 : }
2109 :
572 tgl 2110 ECB : /* Also mark all subplans that are in AlternativeSubPlans */
572 tgl 2111 GIC 1506 : root->isAltSubplan[curplan->plan_id - 1] = true;
924 tgl 2112 ECB : }
2113 :
2114 : /* Mark the subplan we selected */
572 tgl 2115 GIC 753 : root->isUsedSubplan[bestplan->plan_id - 1] = true;
572 tgl 2116 ECB :
924 tgl 2117 GIC 753 : return (Node *) bestplan;
924 tgl 2118 ECB : }
2119 :
6531 2120 : /*
5890 2121 : * fix_scan_expr
2122 : * Do set_plan_references processing on a scan-level expression
6531 2123 : *
5659 2124 : * This consists of incrementing all Vars' varnos by rtoffset,
2125 : * replacing PARAM_MULTIEXPR Params, expanding PlaceHolderVars,
2589 2126 : * replacing Aggref nodes that should be replaced by initplan output Params,
924 2127 : * choosing the best implementation for AlternativeSubPlans,
2128 : * looking up operator opcode info for OpExpr and related nodes,
4236 2129 : * and adding OIDs from regclass Const nodes into root->glob->relationOids.
2130 : *
739 2131 : * 'node': the expression to be modified
2132 : * 'rtoffset': how much to increment varnos by
2133 : * 'num_exec': estimated number of executions of expression
2134 : *
2135 : * The expression tree is either copied-and-modified, or modified in-place
2136 : * if that seems safe.
2137 : */
2138 : static Node *
924 tgl 2139 CBC 997883 : fix_scan_expr(PlannerInfo *root, Node *node, int rtoffset, double num_exec)
2140 : {
5890 tgl 2141 ECB : fix_scan_expr_context context;
2142 :
4236 tgl 2143 GIC 997883 : context.root = root;
5890 2144 997883 : context.rtoffset = rtoffset;
924 2145 997883 : context.num_exec = num_exec;
5615 tgl 2146 ECB :
3217 tgl 2147 GIC 997883 : if (rtoffset != 0 ||
3217 tgl 2148 CBC 853676 : root->multiexpr_params != NIL ||
2589 tgl 2149 GIC 853400 : root->glob->lastPHId != 0 ||
924 2150 850105 : root->minmax_aggs != NIL ||
924 tgl 2151 CBC 849718 : root->hasAlternativeSubPlans)
2152 : {
5615 2153 153968 : return fix_scan_expr_mutator(node, &context);
2154 : }
5615 tgl 2155 ECB : else
2156 : {
2157 : /*
5283 2158 : * If rtoffset == 0, we don't need to change any Vars, and if there
2159 : * are no MULTIEXPR subqueries then we don't need to replace
3217 2160 : * PARAM_MULTIEXPR Params, and if there are no placeholders anywhere
2589 2161 : * we won't need to remove them, and if there are no minmax Aggrefs we
2162 : * won't need to replace them, and if there are no AlternativeSubPlans
2163 : * we won't need to remove them. Then it's OK to just scribble on the
3217 2164 : * input node tree instead of copying (since the only change, filling
2165 : * in any unset opfuncid fields, is harmless). This saves just enough
2166 : * cycles to be noticeable on trivial queries.
2167 : */
5615 tgl 2168 GIC 843915 : (void) fix_scan_expr_walker(node, &context);
2169 843915 : return node;
2170 : }
2171 : }
2172 :
2173 : static Node *
5624 bruce 2174 906677 : fix_scan_expr_mutator(Node *node, fix_scan_expr_context *context)
6531 tgl 2175 ECB : {
6531 tgl 2176 GIC 906677 : if (node == NULL)
5890 tgl 2177 CBC 60867 : return NULL;
6531 tgl 2178 GIC 845810 : if (IsA(node, Var))
6531 tgl 2179 ECB : {
5823 tgl 2180 CBC 284656 : Var *var = copyVar((Var *) node);
2181 :
6531 tgl 2182 GIC 284656 : Assert(var->varlevelsup == 0);
5624 bruce 2183 ECB :
5890 tgl 2184 : /*
739 tgl 2185 EUB : * We should not see Vars marked INNER_VAR, OUTER_VAR, or ROWID_VAR.
739 tgl 2186 ECB : * But an indexqual expression could contain INDEX_VAR Vars.
5890 2187 : */
4198 tgl 2188 GBC 284656 : Assert(var->varno != INNER_VAR);
4198 tgl 2189 CBC 284656 : Assert(var->varno != OUTER_VAR);
739 tgl 2190 GIC 284656 : Assert(var->varno != ROWID_VAR);
4198 tgl 2191 CBC 284656 : if (!IS_SPECIAL_VARNO(var->varno))
4198 tgl 2192 GIC 266849 : var->varno += context->rtoffset;
1186 2193 284656 : if (var->varnosyn > 0)
2194 284371 : var->varnosyn += context->rtoffset;
5890 2195 284656 : return (Node *) var;
2196 : }
3217 2197 561154 : if (IsA(node, Param))
2198 30330 : return fix_param_node(context->root, (Param *) node);
2589 2199 530824 : if (IsA(node, Aggref))
2200 : {
2201 206 : Aggref *aggref = (Aggref *) node;
2202 :
2203 : /* See if the Aggref should be replaced by a Param */
2204 397 : if (context->root->minmax_aggs != NIL &&
2205 191 : list_length(aggref->args) == 1)
2589 tgl 2206 ECB : {
2589 tgl 2207 GIC 191 : TargetEntry *curTarget = (TargetEntry *) linitial(aggref->args);
2208 : ListCell *lc;
2589 tgl 2209 ECB :
2589 tgl 2210 CBC 209 : foreach(lc, context->root->minmax_aggs)
2211 : {
2589 tgl 2212 GIC 209 : MinMaxAggInfo *mminfo = (MinMaxAggInfo *) lfirst(lc);
2213 :
2214 400 : if (mminfo->aggfnoid == aggref->aggfnoid &&
2215 191 : equal(mminfo->target, curTarget->expr))
2216 191 : return (Node *) copyObject(mminfo->param);
2217 : }
2218 : }
2589 tgl 2219 ECB : /* If no match, just fall through to process it normally */
2220 : }
5781 tgl 2221 CBC 530633 : if (IsA(node, CurrentOfExpr))
2222 : {
5781 tgl 2223 LBC 0 : CurrentOfExpr *cexpr = (CurrentOfExpr *) copyObject(node);
2224 :
571 tgl 2225 UIC 0 : Assert(!IS_SPECIAL_VARNO(cexpr->cvarno));
571 tgl 2226 LBC 0 : cexpr->cvarno += context->rtoffset;
5781 2227 0 : return (Node *) cexpr;
2228 : }
5283 tgl 2229 CBC 530633 : if (IsA(node, PlaceHolderVar))
5283 tgl 2230 ECB : {
2231 : /* At scan level, we should always just evaluate the contained expr */
5283 tgl 2232 GIC 516 : PlaceHolderVar *phv = (PlaceHolderVar *) node;
2233 :
2234 : /* XXX can we assert something about phnullingrels? */
5283 tgl 2235 CBC 516 : return fix_scan_expr_mutator((Node *) phv->phexpr, context);
2236 : }
924 tgl 2237 GIC 530117 : if (IsA(node, AlternativeSubPlan))
2238 135 : return fix_scan_expr_mutator(fix_alternative_subplan(context->root,
924 tgl 2239 ECB : (AlternativeSubPlan *) node,
2240 : context->num_exec),
2241 : context);
4236 tgl 2242 GIC 529982 : fix_expr_common(context->root, node);
5890 2243 529982 : return expression_tree_mutator(node, fix_scan_expr_mutator,
2244 : (void *) context);
2245 : }
2246 :
2247 : static bool
5615 2248 4445818 : fix_scan_expr_walker(Node *node, fix_scan_expr_context *context)
2249 : {
2250 4445818 : if (node == NULL)
2251 439235 : return false;
739 2252 4006583 : Assert(!(IsA(node, Var) && ((Var *) node)->varno == ROWID_VAR));
5283 2253 4006583 : Assert(!IsA(node, PlaceHolderVar));
924 2254 4006583 : Assert(!IsA(node, AlternativeSubPlan));
4236 2255 4006583 : fix_expr_common(context->root, node);
5615 2256 4006583 : return expression_tree_walker(node, fix_scan_expr_walker,
2257 : (void *) context);
2258 : }
2259 :
2260 : /*
2261 : * set_join_references
2262 : * Modify the target list and quals of a join node to reference its
4198 tgl 2263 ECB : * subplans, by setting the varnos to OUTER_VAR or INNER_VAR and setting
2264 : * attno values to the result domain number of either the corresponding
2265 : * outer or inner join tuple item. Also perform opcode lookup for these
2266 : * expressions, and add regclass OIDs to root->glob->relationOids.
9770 scrappy 2267 : */
2268 : static void
4236 tgl 2269 CBC 48768 : set_join_references(PlannerInfo *root, Join *join, int rtoffset)
2270 : {
7389 2271 48768 : Plan *outer_plan = join->plan.lefttree;
2272 48768 : Plan *inner_plan = join->plan.righttree;
6512 tgl 2273 ECB : indexed_tlist *outer_itlist;
2274 : indexed_tlist *inner_itlist;
7384 2275 :
6512 tgl 2276 GIC 48768 : outer_itlist = build_tlist_index(outer_plan->targetlist);
6512 tgl 2277 CBC 48768 : inner_itlist = build_tlist_index(inner_plan->targetlist);
2278 :
2279 : /*
2280 : * First process the joinquals (including merge or hash clauses). These
2281 : * are logically below the join so they can always use all values
2282 : * available from the input tlists. It's okay to also handle
2283 : * NestLoopParams now, because those couldn't refer to nullable
2284 : * subexpressions.
2285 : */
4236 tgl 2286 GIC 97536 : join->joinqual = fix_join_expr(root,
2287 : join->joinqual,
2288 : outer_itlist,
2289 : inner_itlist,
2290 : (Index) 0,
2291 : rtoffset,
2292 : NRM_EQUAL,
924 tgl 2293 CBC 48768 : NUM_EXEC_QUAL((Plan *) join));
7389 tgl 2294 ECB :
2295 : /* Now do join-type-specific stuff */
7389 tgl 2296 GIC 48768 : if (IsA(join, NestLoop))
2297 : {
4654 2298 32413 : NestLoop *nl = (NestLoop *) join;
4654 tgl 2299 ECB : ListCell *lc;
2300 :
4654 tgl 2301 CBC 50634 : foreach(lc, nl->nestParams)
4654 tgl 2302 ECB : {
4654 tgl 2303 CBC 18221 : NestLoopParam *nlp = (NestLoopParam *) lfirst(lc);
2304 :
2305 : /*
2306 : * Because we don't reparameterize parameterized paths to match
2307 : * the outer-join level at which they are used, Vars seen in the
2308 : * NestLoopParam expression may have nullingrels that are just a
2309 : * subset of those in the Vars actually available from the outer
2310 : * side. Not checking this exactly is a bit grotty, but the work
2311 : * needed to make things match up perfectly seems well out of
2312 : * proportion to the value.
2313 : */
4236 2314 36442 : nlp->paramval = (Var *) fix_upper_expr(root,
4654 tgl 2315 GIC 18221 : (Node *) nlp->paramval,
4654 tgl 2316 ECB : outer_itlist,
2317 : OUTER_VAR,
2318 : rtoffset,
2319 : NRM_SUBSET,
2320 : NUM_EXEC_TLIST(outer_plan));
2321 : /* Check we replaced any PlaceHolderVar with simple Var */
4175 tgl 2322 GIC 18221 : if (!(IsA(nlp->paramval, Var) &&
4175 tgl 2323 CBC 18221 : nlp->paramval->varno == OUTER_VAR))
4175 tgl 2324 LBC 0 : elog(ERROR, "NestLoopParam was not reduced to a simple Var");
4654 tgl 2325 ECB : }
7389 2326 : }
7389 tgl 2327 CBC 16355 : else if (IsA(join, MergeJoin))
7389 tgl 2328 ECB : {
7389 tgl 2329 CBC 2402 : MergeJoin *mj = (MergeJoin *) join;
7389 tgl 2330 ECB :
4236 tgl 2331 GIC 2402 : mj->mergeclauses = fix_join_expr(root,
5659 tgl 2332 ECB : mj->mergeclauses,
5890 2333 : outer_itlist,
2334 : inner_itlist,
2335 : (Index) 0,
924 2336 : rtoffset,
2337 : NRM_EQUAL,
924 tgl 2338 GIC 2402 : NUM_EXEC_QUAL((Plan *) join));
2339 : }
7389 tgl 2340 CBC 13953 : else if (IsA(join, HashJoin))
7389 tgl 2341 ECB : {
7389 tgl 2342 GIC 13953 : HashJoin *hj = (HashJoin *) join;
7389 tgl 2343 ECB :
4236 tgl 2344 GIC 27906 : hj->hashclauses = fix_join_expr(root,
2345 : hj->hashclauses,
5890 tgl 2346 ECB : outer_itlist,
2347 : inner_itlist,
2348 : (Index) 0,
2349 : rtoffset,
2350 : NRM_EQUAL,
924 tgl 2351 CBC 13953 : NUM_EXEC_QUAL((Plan *) join));
1346 andres 2352 ECB :
2353 : /*
2354 : * HashJoin's hashkeys are used to look for matching tuples from its
2355 : * outer plan (not the Hash node!) in the hashtable.
2356 : */
1346 andres 2357 GIC 13953 : hj->hashkeys = (List *) fix_upper_expr(root,
1346 andres 2358 CBC 13953 : (Node *) hj->hashkeys,
2359 : outer_itlist,
1346 andres 2360 EUB : OUTER_VAR,
2361 : rtoffset,
2362 : NRM_EQUAL,
924 tgl 2363 GBC 13953 : NUM_EXEC_QUAL((Plan *) join));
7389 tgl 2364 EUB : }
6512 2365 :
2366 : /*
2927 tgl 2367 ECB : * Now we need to fix up the targetlist and qpqual, which are logically
2368 : * above the join. This means that, if it's not an inner join, any Vars
2369 : * and PHVs appearing here should have nullingrels that include the
2370 : * effects of the outer join, ie they will have nullingrels equal to the
2371 : * input Vars' nullingrels plus the bit added by the outer join. We don't
2372 : * currently have enough info available here to identify what that should
2373 : * be, so we just tell fix_join_expr to accept superset nullingrels
2374 : * matches instead of exact ones.
2375 : */
2927 tgl 2376 GIC 48768 : join->plan.targetlist = fix_join_expr(root,
2377 : join->plan.targetlist,
2378 : outer_itlist,
2379 : inner_itlist,
2380 : (Index) 0,
2381 : rtoffset,
69 tgl 2382 GNC 48768 : (join->jointype == JOIN_INNER ? NRM_EQUAL : NRM_SUPERSET),
2383 : NUM_EXEC_TLIST((Plan *) join));
2927 tgl 2384 GIC 48768 : join->plan.qual = fix_join_expr(root,
2385 : join->plan.qual,
2386 : outer_itlist,
2387 : inner_itlist,
2927 tgl 2388 ECB : (Index) 0,
2389 : rtoffset,
69 tgl 2390 GNC 48768 : (join->jointype == JOIN_INNER ? NRM_EQUAL : NRM_SUPERSET),
924 tgl 2391 CBC 48768 : NUM_EXEC_QUAL((Plan *) join));
2927 tgl 2392 ECB :
6512 tgl 2393 GIC 48768 : pfree(outer_itlist);
2394 48768 : pfree(inner_itlist);
9770 scrappy 2395 48768 : }
9770 scrappy 2396 ECB :
9345 bruce 2397 : /*
2398 : * set_upper_references
2399 : * Update the targetlist and quals of an upper-level plan node
2400 : * to refer to the tuples returned by its lefttree subplan.
2401 : * Also perform opcode lookup for these expressions, and
2402 : * add regclass OIDs to root->glob->relationOids.
2403 : *
2404 : * This is used for single-input plan types like Agg, Group, Result.
2405 : *
8125 tgl 2406 : * In most cases, we have to match up individual Vars in the tlist and
2407 : * qual expressions with elements of the subplan's tlist (which was
2408 : * generated by flattening these selfsame expressions, so it should have all
2409 : * the required variables). There is an important exception, however:
2410 : * depending on where we are in the plan tree, sort/group columns may have
2411 : * been pushed into the subplan tlist unflattened. If these values are also
2412 : * needed in the output then we want to reference the subplan tlist element
2586 2413 : * rather than recomputing the expression.
2414 : */
2415 : static void
4236 tgl 2416 CBC 28358 : set_upper_references(PlannerInfo *root, Plan *plan, int rtoffset)
2417 : {
8631 2418 28358 : Plan *subplan = plan->lefttree;
2419 : indexed_tlist *subplan_itlist;
2420 : List *output_targetlist;
6892 neilc 2421 ECB : ListCell *l;
2422 :
5889 tgl 2423 CBC 28358 : subplan_itlist = build_tlist_index(subplan->targetlist);
2424 :
7831 tgl 2425 GIC 28358 : output_targetlist = NIL;
2426 77786 : foreach(l, plan->targetlist)
2427 : {
2428 49428 : TargetEntry *tle = (TargetEntry *) lfirst(l);
2429 : Node *newexpr;
2430 :
2431 : /* If it's a sort/group item, first try to match by sortref */
1991 2432 49428 : if (tle->ressortgroupref != 0)
2433 : {
4892 tgl 2434 ECB : newexpr = (Node *)
2222 peter_e 2435 CBC 8918 : search_indexed_tlist_for_sortgroupref(tle->expr,
2436 : tle->ressortgroupref,
2437 : subplan_itlist,
2438 : OUTER_VAR);
4892 tgl 2439 GIC 8918 : if (!newexpr)
4236 2440 1420 : newexpr = fix_upper_expr(root,
4892 2441 1420 : (Node *) tle->expr,
4892 tgl 2442 ECB : subplan_itlist,
4198 2443 : OUTER_VAR,
924 tgl 2444 EUB : rtoffset,
2445 : NRM_EQUAL,
2446 : NUM_EXEC_TLIST(plan));
2447 : }
4892 tgl 2448 ECB : else
4236 tgl 2449 GIC 40510 : newexpr = fix_upper_expr(root,
4892 tgl 2450 CBC 40510 : (Node *) tle->expr,
2451 : subplan_itlist,
4198 tgl 2452 ECB : OUTER_VAR,
2453 : rtoffset,
2454 : NRM_EQUAL,
2455 : NUM_EXEC_TLIST(plan));
6577 tgl 2456 GIC 49428 : tle = flatCopyTargetEntry(tle);
2457 49428 : tle->expr = (Expr *) newexpr;
2458 49428 : output_targetlist = lappend(output_targetlist, tle);
2459 : }
7831 tgl 2460 CBC 28358 : plan->targetlist = output_targetlist;
2461 :
8631 2462 28358 : plan->qual = (List *)
4236 tgl 2463 GIC 28358 : fix_upper_expr(root,
5659 tgl 2464 CBC 28358 : (Node *) plan->qual,
2465 : subplan_itlist,
4198 tgl 2466 ECB : OUTER_VAR,
2467 : rtoffset,
2468 : NRM_EQUAL,
924 tgl 2469 GIC 28358 : NUM_EXEC_QUAL(plan));
2470 :
6512 2471 28358 : pfree(subplan_itlist);
9770 scrappy 2472 28358 : }
2473 :
1970 rhaas 2474 ECB : /*
2475 : * set_param_references
2476 : * Initialize the initParam list in Gather or Gather merge node such that
2477 : * it contains reference of all the params that needs to be evaluated
2478 : * before execution of the node. It contains the initplan params that are
2479 : * being passed to the plan nodes below it.
2480 : */
2481 : static void
1970 rhaas 2482 GIC 608 : set_param_references(PlannerInfo *root, Plan *plan)
2483 : {
1058 tgl 2484 608 : Assert(IsA(plan, Gather) || IsA(plan, GatherMerge));
2485 :
1970 rhaas 2486 CBC 608 : if (plan->lefttree->extParam)
2487 : {
2488 : PlannerInfo *proot;
1970 rhaas 2489 GIC 596 : Bitmapset *initSetParam = NULL;
2490 : ListCell *l;
2491 :
2492 1279 : for (proot = root; proot != NULL; proot = proot->parent_root)
2493 : {
2494 722 : foreach(l, proot->init_plans)
2495 : {
2496 39 : SubPlan *initsubplan = (SubPlan *) lfirst(l);
2497 : ListCell *l2;
2498 :
1970 rhaas 2499 CBC 78 : foreach(l2, initsubplan->setParam)
2500 : {
1970 rhaas 2501 GIC 39 : initSetParam = bms_add_member(initSetParam, lfirst_int(l2));
2502 : }
2503 : }
2504 : }
1970 rhaas 2505 ECB :
2506 : /*
2507 : * Remember the list of all external initplan params that are used by
2508 : * the children of Gather or Gather merge node.
2509 : */
1970 rhaas 2510 GIC 596 : if (IsA(plan, Gather))
2511 458 : ((Gather *) plan)->initParam =
2512 458 : bms_intersect(plan->lefttree->extParam, initSetParam);
1970 rhaas 2513 ECB : else
1970 rhaas 2514 CBC 138 : ((GatherMerge *) plan)->initParam =
1970 rhaas 2515 GIC 138 : bms_intersect(plan->lefttree->extParam, initSetParam);
1970 rhaas 2516 ECB : }
1970 rhaas 2517 CBC 608 : }
1970 rhaas 2518 ECB :
2519 : /*
2520 : * Recursively scan an expression tree and convert Aggrefs to the proper
2521 : * intermediate form for combining aggregates. This means (1) replacing each
2522 : * one's argument list with a single argument that is the original Aggref
2523 : * modified to show partial aggregation and (2) changing the upper Aggref to
2524 : * show combining aggregation.
2525 : *
2526 : * After this step, set_upper_references will replace the partial Aggrefs
2527 : * with Vars referencing the lower Agg plan node's outputs, so that the final
2528 : * form seen by the executor is a combining Aggref with a Var as input.
2529 : *
2530 : * It's rather messy to postpone this step until setrefs.c; ideally it'd be
2531 : * done in createplan.c. The difficulty is that once we modify the Aggref
2532 : * expressions, they will no longer be equal() to their original form and
2533 : * so cross-plan-node-level matches will fail. So this has to happen after
2534 : * the plan node above the Agg has resolved its subplan references.
2535 : */
2536 : static Node *
2478 tgl 2537 GIC 2985 : convert_combining_aggrefs(Node *node, void *context)
2538 : {
2478 tgl 2539 CBC 2985 : if (node == NULL)
2478 tgl 2540 GIC 334 : return NULL;
2478 tgl 2541 CBC 2651 : if (IsA(node, Aggref))
2542 : {
2478 tgl 2543 GIC 695 : Aggref *orig_agg = (Aggref *) node;
2544 : Aggref *child_agg;
2545 : Aggref *parent_agg;
2575 rhaas 2546 ECB :
2547 : /* Assert we've not chosen to partial-ize any unsupported cases */
2451 tgl 2548 CBC 695 : Assert(orig_agg->aggorder == NIL);
2549 695 : Assert(orig_agg->aggdistinct == NIL);
2550 :
2478 tgl 2551 ECB : /*
2552 : * Since aggregate calls can't be nested, we needn't recurse into the
2553 : * arguments. But for safety, flat-copy the Aggref node itself rather
2554 : * than modifying it in-place.
2555 : */
2478 tgl 2556 GIC 695 : child_agg = makeNode(Aggref);
2557 695 : memcpy(child_agg, orig_agg, sizeof(Aggref));
2575 rhaas 2558 ECB :
2559 : /*
2560 : * For the parent Aggref, we want to copy all the fields of the
2561 : * original aggregate *except* the args list, which we'll replace
2451 tgl 2562 : * below, and the aggfilter expression, which should be applied only
2563 : * by the child not the parent. Rather than explicitly knowing about
2564 : * all the other fields here, we can momentarily modify child_agg to
2565 : * provide a suitable source for copyObject.
2566 : */
2478 tgl 2567 GIC 695 : child_agg->args = NIL;
2451 2568 695 : child_agg->aggfilter = NULL;
2222 peter_e 2569 695 : parent_agg = copyObject(child_agg);
2478 tgl 2570 695 : child_agg->args = orig_agg->args;
2451 2571 695 : child_agg->aggfilter = orig_agg->aggfilter;
2575 rhaas 2572 ECB :
2478 tgl 2573 : /*
2574 : * Now, set up child_agg to represent the first phase of partial
2575 : * aggregation. For now, assume serialization is required.
2576 : */
2478 tgl 2577 GIC 695 : mark_partial_aggref(child_agg, AGGSPLIT_INITIAL_SERIAL);
2578 :
2478 tgl 2579 ECB : /*
2580 : * And set up parent_agg to represent the second phase.
2581 : */
2478 tgl 2582 GIC 695 : parent_agg->args = list_make1(makeTargetEntry((Expr *) child_agg,
2478 tgl 2583 ECB : 1, NULL, false));
2478 tgl 2584 GIC 695 : mark_partial_aggref(parent_agg, AGGSPLIT_FINAL_DESERIAL);
2575 rhaas 2585 ECB :
2478 tgl 2586 CBC 695 : return (Node *) parent_agg;
2575 rhaas 2587 ECB : }
2478 tgl 2588 GIC 1956 : return expression_tree_mutator(node, convert_combining_aggrefs,
2589 : (void *) context);
2590 : }
2591 :
5889 tgl 2592 ECB : /*
2593 : * set_dummy_tlist_references
2594 : * Replace the targetlist of an upper-level plan node with a simple
4198 2595 : * list of OUTER_VAR references to its child.
2596 : *
2597 : * This is used for plan types like Sort and Append that don't evaluate
2598 : * their targetlists. Although the executor doesn't care at all what's in
2599 : * the tlist, EXPLAIN needs it to be realistic.
2600 : *
2601 : * Note: we could almost use set_upper_references() here, but it fails for
2602 : * Append for lack of a lefttree subplan. Single-purpose code is faster
2603 : * anyway.
2604 : */
5889 2605 : static void
5889 tgl 2606 GIC 56056 : set_dummy_tlist_references(Plan *plan, int rtoffset)
5889 tgl 2607 ECB : {
2608 : List *output_targetlist;
2609 : ListCell *l;
2610 :
5889 tgl 2611 GIC 56056 : output_targetlist = NIL;
5889 tgl 2612 CBC 237350 : foreach(l, plan->targetlist)
2613 : {
5889 tgl 2614 GIC 181294 : TargetEntry *tle = (TargetEntry *) lfirst(l);
5889 tgl 2615 CBC 181294 : Var *oldvar = (Var *) tle->expr;
2616 : Var *newvar;
5889 tgl 2617 ECB :
2618 : /*
2349 2619 : * As in search_indexed_tlist_for_non_var(), we prefer to keep Consts
2620 : * as Consts, not Vars referencing Consts. Here, there's no speed
2621 : * advantage to be had, but it makes EXPLAIN output look cleaner, and
2622 : * again it avoids confusing the executor.
2623 : */
2349 tgl 2624 CBC 181294 : if (IsA(oldvar, Const))
2625 : {
2626 : /* just reuse the existing TLE node */
2349 tgl 2627 GIC 7595 : output_targetlist = lappend(output_targetlist, tle);
2628 7595 : continue;
2629 : }
2630 :
4198 2631 173699 : newvar = makeVar(OUTER_VAR,
5889 2632 173699 : tle->resno,
5889 tgl 2633 ECB : exprType((Node *) oldvar),
2634 : exprTypmod((Node *) oldvar),
4443 peter_e 2635 : exprCollation((Node *) oldvar),
2636 : 0);
1186 tgl 2637 CBC 173699 : if (IsA(oldvar, Var) &&
2638 139501 : oldvar->varnosyn > 0)
2639 : {
2640 126729 : newvar->varnosyn = oldvar->varnosyn + rtoffset;
1186 tgl 2641 GIC 126729 : newvar->varattnosyn = oldvar->varattnosyn;
2642 : }
2643 : else
2644 : {
2645 46970 : newvar->varnosyn = 0; /* wasn't ever a plain Var */
2646 46970 : newvar->varattnosyn = 0;
2647 : }
2648 :
5889 2649 173699 : tle = flatCopyTargetEntry(tle);
2650 173699 : tle->expr = (Expr *) newvar;
2651 173699 : output_targetlist = lappend(output_targetlist, tle);
2652 : }
2653 56056 : plan->targetlist = output_targetlist;
2654 :
2655 : /* We don't touch plan->qual here */
2656 56056 : }
2657 :
2658 :
2659 : /*
6512 tgl 2660 ECB : * build_tlist_index --- build an index data structure for a child tlist
2661 : *
2662 : * In most cases, subplan tlists will be "flat" tlists with only Vars,
2663 : * so we try to optimize that case by extracting information about Vars
3260 bruce 2664 : * in advance. Matching a parent tlist to a child is still an O(N^2)
2665 : * operation, but at least with a much smaller constant factor than plain
6512 tgl 2666 : * tlist_member() searches.
2667 : *
2668 : * The result of this function is an indexed_tlist struct to pass to
2669 : * search_indexed_tlist_for_var() and siblings.
2670 : * When done, the indexed_tlist may be freed with a single pfree().
7384 2671 : */
6512 2672 : static indexed_tlist *
6512 tgl 2673 GIC 148282 : build_tlist_index(List *tlist)
2674 : {
2675 : indexed_tlist *itlist;
2676 : tlist_vinfo *vinfo;
2677 : ListCell *l;
2678 :
6512 tgl 2679 ECB : /* Create data structure with enough slots for all tlist entries */
2680 : itlist = (indexed_tlist *)
6512 tgl 2681 GIC 148282 : palloc(offsetof(indexed_tlist, vars) +
2682 148282 : list_length(tlist) * sizeof(tlist_vinfo));
2683 :
2684 148282 : itlist->tlist = tlist;
5283 2685 148282 : itlist->has_ph_vars = false;
6512 2686 148282 : itlist->has_non_vars = false;
2687 :
2688 : /* Find the Vars and fill in the index array */
2689 148282 : vinfo = itlist->vars;
7384 tgl 2690 CBC 1390906 : foreach(l, tlist)
7384 tgl 2691 ECB : {
7384 tgl 2692 CBC 1242624 : TargetEntry *tle = (TargetEntry *) lfirst(l);
7384 tgl 2693 ECB :
6512 tgl 2694 CBC 1242624 : if (tle->expr && IsA(tle->expr, Var))
6512 tgl 2695 GIC 1236227 : {
6385 bruce 2696 1236227 : Var *var = (Var *) tle->expr;
2697 :
6512 tgl 2698 1236227 : vinfo->varno = var->varno;
2699 1236227 : vinfo->varattno = var->varattno;
6512 tgl 2700 CBC 1236227 : vinfo->resno = tle->resno;
2701 : #ifdef USE_ASSERT_CHECKING
69 tgl 2702 GNC 1236227 : vinfo->varnullingrels = var->varnullingrels;
2703 : #endif
6512 tgl 2704 GIC 1236227 : vinfo++;
2705 : }
5283 2706 6397 : else if (tle->expr && IsA(tle->expr, PlaceHolderVar))
2707 926 : itlist->has_ph_vars = true;
6512 tgl 2708 ECB : else
6512 tgl 2709 GIC 5471 : itlist->has_non_vars = true;
6512 tgl 2710 ECB : }
2711 :
6512 tgl 2712 CBC 148282 : itlist->num_vars = (vinfo - itlist->vars);
2713 :
2714 148282 : return itlist;
2715 : }
2716 :
2717 : /*
2718 : * build_tlist_index_other_vars --- build a restricted tlist index
2719 : *
2720 : * This is like build_tlist_index, but we only index tlist entries that
2721 : * are Vars belonging to some rel other than the one specified. We will set
2722 : * has_ph_vars (allowing PlaceHolderVars to be matched), but not has_non_vars
2723 : * (so nothing other than Vars and PlaceHolderVars can be matched).
2724 : */
2725 : static indexed_tlist *
571 tgl 2726 GIC 1267 : build_tlist_index_other_vars(List *tlist, int ignore_rel)
2727 : {
2728 : indexed_tlist *itlist;
2729 : tlist_vinfo *vinfo;
2730 : ListCell *l;
2731 :
6084 tgl 2732 ECB : /* Create data structure with enough slots for all tlist entries */
2733 : itlist = (indexed_tlist *)
6084 tgl 2734 GIC 1267 : palloc(offsetof(indexed_tlist, vars) +
2735 1267 : list_length(tlist) * sizeof(tlist_vinfo));
2736 :
6084 tgl 2737 CBC 1267 : itlist->tlist = tlist;
5283 2738 1267 : itlist->has_ph_vars = false;
6084 tgl 2739 GIC 1267 : itlist->has_non_vars = false;
6084 tgl 2740 ECB :
2741 : /* Find the desired Vars and fill in the index array */
6084 tgl 2742 GIC 1267 : vinfo = itlist->vars;
2743 4656 : foreach(l, tlist)
2744 : {
2745 3389 : TargetEntry *tle = (TargetEntry *) lfirst(l);
2746 :
2747 3389 : if (tle->expr && IsA(tle->expr, Var))
2748 1724 : {
2749 1724 : Var *var = (Var *) tle->expr;
6084 tgl 2750 ECB :
6084 tgl 2751 GIC 1724 : if (var->varno != ignore_rel)
2752 : {
6084 tgl 2753 CBC 1251 : vinfo->varno = var->varno;
2754 1251 : vinfo->varattno = var->varattno;
6084 tgl 2755 GIC 1251 : vinfo->resno = tle->resno;
2756 : #ifdef USE_ASSERT_CHECKING
69 tgl 2757 GNC 1251 : vinfo->varnullingrels = var->varnullingrels;
2758 : #endif
6084 tgl 2759 GIC 1251 : vinfo++;
6084 tgl 2760 ECB : }
2761 : }
5283 tgl 2762 GIC 1665 : else if (tle->expr && IsA(tle->expr, PlaceHolderVar))
5283 tgl 2763 UIC 0 : itlist->has_ph_vars = true;
2764 : }
2765 :
6084 tgl 2766 CBC 1267 : itlist->num_vars = (vinfo - itlist->vars);
6084 tgl 2767 ECB :
6084 tgl 2768 GIC 1267 : return itlist;
6084 tgl 2769 ECB : }
2770 :
2771 : /*
2772 : * search_indexed_tlist_for_var --- find a Var in an indexed tlist
2773 : *
6512 2774 : * If a match is found, return a copy of the given Var with suitably
2775 : * modified varno/varattno (to wit, newvarno and the resno of the TLE entry).
2776 : * Also ensure that varnosyn is incremented by rtoffset.
2777 : * If no match, return NULL.
2778 : *
2779 : * In debugging builds, we cross-check the varnullingrels of the subplan
2780 : * output Var based on nrm_match. Most call sites should pass NRM_EQUAL
2781 : * indicating we expect an exact match. However, there are places where
2782 : * we haven't cleaned things up completely, and we have to settle for
2783 : * allowing subset or superset matches.
2784 : */
2785 : static Var *
5890 tgl 2786 CBC 512187 : search_indexed_tlist_for_var(Var *var, indexed_tlist *itlist,
2787 : int newvarno, int rtoffset,
2788 : NullingRelsMatch nrm_match)
6512 tgl 2789 ECB : {
571 tgl 2790 GIC 512187 : int varno = var->varno;
6512 2791 512187 : AttrNumber varattno = var->varattno;
6512 tgl 2792 ECB : tlist_vinfo *vinfo;
2793 : int i;
2794 :
6512 tgl 2795 GIC 512187 : vinfo = itlist->vars;
2796 512187 : i = itlist->num_vars;
2797 3379672 : while (i-- > 0)
2798 : {
2799 3262740 : if (vinfo->varno == varno && vinfo->varattno == varattno)
2800 : {
2801 : /* Found a match */
5823 2802 395255 : Var *newvar = copyVar(var);
2803 :
2804 : /*
2805 : * Assert that we kept all the nullingrels machinations straight.
2806 : *
2807 : * XXX we skip the check for system columns and whole-row Vars.
2808 : * That's because such Vars might be row identity Vars, which are
2809 : * generated without any varnullingrels. It'd be hard to do
2810 : * otherwise, since they're normally made very early in planning,
2811 : * when we haven't looked at the jointree yet and don't know which
2812 : * joins might null such Vars. Doesn't seem worth the expense to
2813 : * make them fully valid. (While it's slightly annoying that we
2814 : * thereby lose checking for user-written references to such
2815 : * columns, it seems unlikely that a bug in nullingrels logic
2816 : * would affect only system columns.)
2817 : */
69 tgl 2818 GNC 395255 : Assert(varattno <= 0 ||
2819 : (nrm_match == NRM_SUBSET ?
2820 : bms_is_subset(var->varnullingrels, vinfo->varnullingrels) :
2821 : nrm_match == NRM_SUPERSET ?
2822 : bms_is_subset(vinfo->varnullingrels, var->varnullingrels) :
2823 : bms_equal(vinfo->varnullingrels, var->varnullingrels)));
2824 :
6512 tgl 2825 GIC 395255 : newvar->varno = newvarno;
2826 395255 : newvar->varattno = vinfo->resno;
1186 2827 395255 : if (newvar->varnosyn > 0)
2828 392296 : newvar->varnosyn += rtoffset;
6512 2829 395255 : return newvar;
6512 tgl 2830 ECB : }
6512 tgl 2831 GIC 2867485 : vinfo++;
2832 : }
2833 116932 : return NULL; /* no match */
2834 : }
2835 :
2836 : /*
2837 : * search_indexed_tlist_for_phv --- find a PlaceHolderVar in an indexed tlist
6512 tgl 2838 ECB : *
2839 : * If a match is found, return a Var constructed to reference the tlist item.
2840 : * If no match, return NULL.
2841 : *
2842 : * Cross-check phnullingrels as in search_indexed_tlist_for_var.
2843 : *
2844 : * NOTE: it is a waste of time to call this unless itlist->has_ph_vars.
2845 : */
2846 : static Var *
69 tgl 2847 GNC 1115 : search_indexed_tlist_for_phv(PlaceHolderVar *phv,
2848 : indexed_tlist *itlist, int newvarno,
2849 : NullingRelsMatch nrm_match)
2850 : {
2851 : ListCell *lc;
2852 :
2853 3069 : foreach(lc, itlist->tlist)
2854 : {
2855 2896 : TargetEntry *tle = (TargetEntry *) lfirst(lc);
2856 :
2857 2896 : if (tle->expr && IsA(tle->expr, PlaceHolderVar))
2858 : {
2859 1284 : PlaceHolderVar *subphv = (PlaceHolderVar *) tle->expr;
2860 : Var *newvar;
2861 :
2862 : /*
2863 : * Analogously to search_indexed_tlist_for_var, we match on phid
2864 : * only. We don't use equal(), partially for speed but mostly
2865 : * because phnullingrels might not be exactly equal.
2866 : */
2867 1284 : if (phv->phid != subphv->phid)
2868 342 : continue;
2869 :
2870 : /* Assert that we kept all the nullingrels machinations straight */
2871 942 : Assert(nrm_match == NRM_SUBSET ?
2872 : bms_is_subset(phv->phnullingrels, subphv->phnullingrels) :
2873 : nrm_match == NRM_SUPERSET ?
2874 : bms_is_subset(subphv->phnullingrels, phv->phnullingrels) :
2875 : bms_equal(subphv->phnullingrels, phv->phnullingrels));
2876 :
2877 : /* Found a matching subplan output expression */
2878 942 : newvar = makeVarFromTargetEntry(newvarno, tle);
2879 942 : newvar->varnosyn = 0; /* wasn't ever a plain Var */
2880 942 : newvar->varattnosyn = 0;
2881 942 : return newvar;
2882 : }
2883 : }
2884 173 : return NULL; /* no match */
2885 : }
2886 :
2887 : /*
2888 : * search_indexed_tlist_for_non_var --- find a non-Var/PHV in an indexed tlist
2889 : *
2890 : * If a match is found, return a Var constructed to reference the tlist item.
2891 : * If no match, return NULL.
2892 : *
2893 : * NOTE: it is a waste of time to call this unless itlist->has_non_vars.
6512 tgl 2894 ECB : */
2895 : static Var *
2222 peter_e 2896 GIC 12643 : search_indexed_tlist_for_non_var(Expr *node,
571 tgl 2897 ECB : indexed_tlist *itlist, int newvarno)
2898 : {
6512 2899 : TargetEntry *tle;
2900 :
2349 2901 : /*
2902 : * If it's a simple Const, replacing it with a Var is silly, even if there
2903 : * happens to be an identical Const below; a Var is more expensive to
2904 : * execute than a Const. What's more, replacing it could confuse some
2905 : * places in the executor that expect to see simple Consts for, eg,
2906 : * dropped columns.
2907 : */
2349 tgl 2908 GIC 12643 : if (IsA(node, Const))
2349 tgl 2909 CBC 918 : return NULL;
2910 :
6512 2911 11725 : tle = tlist_member(node, itlist->tlist);
2912 11725 : if (tle)
2913 : {
6512 tgl 2914 ECB : /* Found a matching subplan output expression */
2915 : Var *newvar;
2916 :
4608 peter_e 2917 CBC 3175 : newvar = makeVarFromTargetEntry(newvarno, tle);
1186 tgl 2918 GIC 3175 : newvar->varnosyn = 0; /* wasn't ever a plain Var */
1186 tgl 2919 CBC 3175 : newvar->varattnosyn = 0;
6512 tgl 2920 GIC 3175 : return newvar;
2921 : }
2922 8550 : return NULL; /* no match */
2923 : }
2924 :
2925 : /*
2926 : * search_indexed_tlist_for_sortgroupref --- find a sort/group expression
2927 : *
2928 : * If a match is found, return a Var constructed to reference the tlist item.
2929 : * If no match, return NULL.
2930 : *
4892 tgl 2931 ECB : * This is needed to ensure that we select the right subplan TLE in cases
2932 : * where there are multiple textually-equal()-but-volatile sort expressions.
2933 : * And it's also faster than search_indexed_tlist_for_non_var.
2934 : */
2935 : static Var *
2222 peter_e 2936 GIC 8918 : search_indexed_tlist_for_sortgroupref(Expr *node,
2937 : Index sortgroupref,
2938 : indexed_tlist *itlist,
571 tgl 2939 ECB : int newvarno)
4892 2940 : {
2941 : ListCell *lc;
2942 :
4892 tgl 2943 CBC 18840 : foreach(lc, itlist->tlist)
4892 tgl 2944 ECB : {
4892 tgl 2945 GIC 17420 : TargetEntry *tle = (TargetEntry *) lfirst(lc);
2946 :
4892 tgl 2947 ECB : /* The equal() check should be redundant, but let's be paranoid */
4892 tgl 2948 CBC 24949 : if (tle->ressortgroupref == sortgroupref &&
4892 tgl 2949 GIC 7529 : equal(node, tle->expr))
4892 tgl 2950 ECB : {
2951 : /* Found a matching subplan output expression */
2952 : Var *newvar;
2953 :
4608 peter_e 2954 CBC 7498 : newvar = makeVarFromTargetEntry(newvarno, tle);
1186 tgl 2955 GIC 7498 : newvar->varnosyn = 0; /* wasn't ever a plain Var */
1186 tgl 2956 CBC 7498 : newvar->varattnosyn = 0;
4892 tgl 2957 GIC 7498 : return newvar;
4892 tgl 2958 ECB : }
2959 : }
4892 tgl 2960 CBC 1420 : return NULL; /* no match */
2961 : }
4892 tgl 2962 ECB :
2963 : /*
5890 2964 : * fix_join_expr
2965 : * Create a new set of targetlist entries or join qual clauses by
2966 : * changing the varno/varattno values of variables in the clauses
8631 2967 : * to reference target list values from the outer and inner join
5659 tgl 2968 EUB : * relation target lists. Also perform opcode lookup and add
2969 : * regclass OIDs to root->glob->relationOids.
2970 : *
362 alvherre 2971 ECB : * This is used in four different scenarios:
2972 : * 1) a normal join clause, where all the Vars in the clause *must* be
2745 andres 2973 : * replaced by OUTER_VAR or INNER_VAR references. In this case
2974 : * acceptable_rel should be zero so that any failure to match a Var will be
2975 : * reported as an error.
2976 : * 2) RETURNING clauses, which may contain both Vars of the target relation
2977 : * and Vars of other relations. In this case we want to replace the
2978 : * other-relation Vars by OUTER_VAR references, while leaving target Vars
2979 : * alone. Thus inner_itlist = NULL and acceptable_rel = the ID of the
2980 : * target relation should be passed.
2981 : * 3) ON CONFLICT UPDATE SET/WHERE clauses. Here references to EXCLUDED are
2982 : * to be replaced with INNER_VAR references, while leaving target Vars (the
2983 : * to-be-updated relation) alone. Correspondingly inner_itlist is to be
2984 : * EXCLUDED elements, outer_itlist = NULL and acceptable_rel the target
2985 : * relation.
2986 : * 4) MERGE. In this case, references to the source relation are to be
2987 : * replaced with INNER_VAR references, leaving Vars of the target
2988 : * relation (the to-be-modified relation) alone. So inner_itlist is to be
2989 : * the source relation elements, outer_itlist = NULL and acceptable_rel
2990 : * the target relation.
8631 tgl 2991 : *
2992 : * 'clauses' is the targetlist or list of join clauses
2993 : * 'outer_itlist' is the indexed target list of the outer join relation,
2994 : * or NULL
6512 2995 : * 'inner_itlist' is the indexed target list of the inner join relation,
2996 : * or NULL
2997 : * 'acceptable_rel' is either zero or the rangetable index of a relation
2998 : * whose Vars may appear in the clause without provoking an error
2999 : * 'rtoffset': how much to increment varnos by
3000 : * 'nrm_match': as for search_indexed_tlist_for_var()
924 3001 : * 'num_exec': estimated number of executions of expression
9345 bruce 3002 : *
8631 tgl 3003 : * Returns the new expression tree. The original clause structure is
3004 : * not modified.
9770 scrappy 3005 : */
3006 : static List *
4236 tgl 3007 GIC 166582 : fix_join_expr(PlannerInfo *root,
5659 tgl 3008 ECB : List *clauses,
3009 : indexed_tlist *outer_itlist,
3010 : indexed_tlist *inner_itlist,
3011 : Index acceptable_rel,
3012 : int rtoffset,
3013 : NullingRelsMatch nrm_match,
3014 : double num_exec)
3015 : {
3016 : fix_join_expr_context context;
3017 :
4236 tgl 3018 GIC 166582 : context.root = root;
6512 3019 166582 : context.outer_itlist = outer_itlist;
3020 166582 : context.inner_itlist = inner_itlist;
8631 3021 166582 : context.acceptable_rel = acceptable_rel;
5890 3022 166582 : context.rtoffset = rtoffset;
69 tgl 3023 GNC 166582 : context.nrm_match = nrm_match;
924 tgl 3024 GIC 166582 : context.num_exec = num_exec;
5890 3025 166582 : return (List *) fix_join_expr_mutator((Node *) clauses, &context);
9770 scrappy 3026 ECB : }
3027 :
3028 : static Node *
5624 bruce 3029 GIC 957113 : fix_join_expr_mutator(Node *node, fix_join_expr_context *context)
3030 : {
3031 : Var *newvar;
3032 :
8644 tgl 3033 CBC 957113 : if (node == NULL)
3034 101604 : return NULL;
3035 855509 : if (IsA(node, Var))
8644 tgl 3036 ECB : {
8644 tgl 3037 CBC 310749 : Var *var = (Var *) node;
3038 :
2745 andres 3039 ECB : /* Look for the var in the input tlists, first in the outer */
2893 andres 3040 GIC 310749 : if (context->outer_itlist)
2893 andres 3041 ECB : {
2893 andres 3042 GIC 308692 : newvar = search_indexed_tlist_for_var(var,
3043 : context->outer_itlist,
3044 : OUTER_VAR,
3045 : context->rtoffset,
3046 : context->nrm_match);
3047 308692 : if (newvar)
3048 192592 : return (Node *) newvar;
3049 : }
3050 :
3051 : /* then in the inner. */
6512 tgl 3052 118157 : if (context->inner_itlist)
3053 : {
3054 115014 : newvar = search_indexed_tlist_for_var(var,
3055 : context->inner_itlist,
4198 tgl 3056 ECB : INNER_VAR,
3057 : context->rtoffset,
3058 : context->nrm_match);
6512 tgl 3059 GIC 115014 : if (newvar)
3060 114182 : return (Node *) newvar;
3061 : }
3062 :
5890 tgl 3063 ECB : /* If it's for acceptable_rel, adjust and return it */
7446 tgl 3064 GIC 3975 : if (var->varno == context->acceptable_rel)
5890 tgl 3065 ECB : {
5823 tgl 3066 GIC 3975 : var = copyVar(var);
4001 tgl 3067 CBC 3975 : var->varno += context->rtoffset;
1186 tgl 3068 GIC 3975 : if (var->varnosyn > 0)
1186 tgl 3069 CBC 3854 : var->varnosyn += context->rtoffset;
5890 tgl 3070 GIC 3975 : return (Node *) var;
3071 : }
3072 :
3073 : /* No referent found for Var */
7198 tgl 3074 UIC 0 : elog(ERROR, "variable not found in subplan target lists");
3075 : }
5283 tgl 3076 GIC 544760 : if (IsA(node, PlaceHolderVar))
5283 tgl 3077 ECB : {
5283 tgl 3078 CBC 926 : PlaceHolderVar *phv = (PlaceHolderVar *) node;
3079 :
3080 : /* See if the PlaceHolderVar has bubbled up from a lower plan node */
2893 andres 3081 926 : if (context->outer_itlist && context->outer_itlist->has_ph_vars)
3082 : {
69 tgl 3083 GNC 441 : newvar = search_indexed_tlist_for_phv(phv,
3084 : context->outer_itlist,
3085 : OUTER_VAR,
3086 : context->nrm_match);
5283 tgl 3087 GIC 441 : if (newvar)
3088 295 : return (Node *) newvar;
5283 tgl 3089 ECB : }
5283 tgl 3090 CBC 631 : if (context->inner_itlist && context->inner_itlist->has_ph_vars)
5283 tgl 3091 ECB : {
69 tgl 3092 GNC 513 : newvar = search_indexed_tlist_for_phv(phv,
3093 : context->inner_itlist,
3094 : INNER_VAR,
3095 : context->nrm_match);
5283 tgl 3096 CBC 513 : if (newvar)
5283 tgl 3097 GIC 486 : return (Node *) newvar;
3098 : }
3099 :
3100 : /* If not supplied by input plans, evaluate the contained expr */
3101 : /* XXX can we assert something about phnullingrels? */
3102 145 : return fix_join_expr_mutator((Node *) phv->phexpr, context);
3103 : }
3104 : /* Try matching more complex expressions too, if tlists have any */
1682 efujita 3105 543834 : if (context->outer_itlist && context->outer_itlist->has_non_vars)
3106 : {
2222 peter_e 3107 617 : newvar = search_indexed_tlist_for_non_var((Expr *) node,
3108 : context->outer_itlist,
4198 tgl 3109 ECB : OUTER_VAR);
6512 tgl 3110 GIC 617 : if (newvar)
7384 3111 40 : return (Node *) newvar;
3112 : }
1682 efujita 3113 543794 : if (context->inner_itlist && context->inner_itlist->has_non_vars)
3114 : {
2222 peter_e 3115 545 : newvar = search_indexed_tlist_for_non_var((Expr *) node,
3116 : context->inner_itlist,
3117 : INNER_VAR);
6512 tgl 3118 545 : if (newvar)
7384 3119 42 : return (Node *) newvar;
3120 : }
1579 tgl 3121 ECB : /* Special cases (apply only AFTER failing to match to lower tlist) */
1579 tgl 3122 CBC 543752 : if (IsA(node, Param))
1579 tgl 3123 GIC 2492 : return fix_param_node(context->root, (Param *) node);
924 tgl 3124 CBC 541260 : if (IsA(node, AlternativeSubPlan))
3125 609 : return fix_join_expr_mutator(fix_alternative_subplan(context->root,
3126 : (AlternativeSubPlan *) node,
3127 : context->num_exec),
3128 : context);
4236 tgl 3129 GIC 540651 : fix_expr_common(context->root, node);
8631 tgl 3130 CBC 540651 : return expression_tree_mutator(node,
5890 tgl 3131 ECB : fix_join_expr_mutator,
8631 3132 : (void *) context);
9770 scrappy 3133 : }
3134 :
8631 tgl 3135 : /*
3136 : * fix_upper_expr
3137 : * Modifies an expression tree so that all Var nodes reference outputs
3138 : * of a subplan. Also looks for Aggref nodes that should be replaced
3139 : * by initplan output Params. Also performs opcode lookup, and adds
3140 : * regclass OIDs to root->glob->relationOids.
3141 : *
3142 : * This is used to fix up target and qual expressions of non-join upper-level
3143 : * plan nodes, as well as index-only scan nodes.
3144 : *
3145 : * An error is raised if no matching var can be found in the subplan tlist
3146 : * --- so this routine should only be applied to nodes whose subplans'
3147 : * targetlists were generated by flattening the expressions used in the
3148 : * parent node.
9770 scrappy 3149 : *
3150 : * If itlist->has_non_vars is true, then we try to match whole subexpressions
3151 : * against elements of the subplan tlist, so that we can avoid recomputing
3152 : * expressions that were already computed by the subplan. (This is relatively
3153 : * expensive, so we don't want to try it in the common case where the
3154 : * subplan tlist is just a flattened list of Vars.)
3155 : *
7831 tgl 3156 : * 'node': the tree to be fixed (a target item or qual)
3157 : * 'subplan_itlist': indexed target list for subplan (or index)
4198 3158 : * 'newvarno': varno to use for Vars referencing tlist elements
3159 : * 'rtoffset': how much to increment varnos by
3160 : * 'nrm_match': as for search_indexed_tlist_for_var()
3161 : * 'num_exec': estimated number of executions of expression
9345 bruce 3162 : *
8631 tgl 3163 : * The resulting tree is a copy of the original in which all Var nodes have
3164 : * varno = newvarno, varattno = resno of corresponding targetlist element.
3165 : * The original tree is not modified.
3166 : */
3167 : static Node *
4236 tgl 3168 CBC 135860 : fix_upper_expr(PlannerInfo *root,
5659 tgl 3169 ECB : Node *node,
5890 3170 : indexed_tlist *subplan_itlist,
571 3171 : int newvarno,
3172 : int rtoffset,
3173 : NullingRelsMatch nrm_match,
3174 : double num_exec)
9770 scrappy 3175 : {
3176 : fix_upper_expr_context context;
3177 :
4236 tgl 3178 GIC 135860 : context.root = root;
6512 3179 135860 : context.subplan_itlist = subplan_itlist;
4198 3180 135860 : context.newvarno = newvarno;
5890 3181 135860 : context.rtoffset = rtoffset;
69 tgl 3182 GNC 135860 : context.nrm_match = nrm_match;
924 tgl 3183 GIC 135860 : context.num_exec = num_exec;
5890 3184 135860 : return fix_upper_expr_mutator(node, &context);
3185 : }
3186 :
3187 : static Node *
5624 bruce 3188 388931 : fix_upper_expr_mutator(Node *node, fix_upper_expr_context *context)
3189 : {
3190 : Var *newvar;
3191 :
8644 tgl 3192 388931 : if (node == NULL)
8631 3193 124355 : return NULL;
8644 3194 264576 : if (IsA(node, Var))
3195 : {
3196 88481 : Var *var = (Var *) node;
3197 :
6512 3198 88481 : newvar = search_indexed_tlist_for_var(var,
3199 : context->subplan_itlist,
3200 : context->newvarno,
3201 : context->rtoffset,
3202 : context->nrm_match);
3203 88481 : if (!newvar)
7198 tgl 3204 UIC 0 : elog(ERROR, "variable not found in subplan target list");
8631 tgl 3205 GIC 88481 : return (Node *) newvar;
3206 : }
5283 3207 176095 : if (IsA(node, PlaceHolderVar))
3208 : {
3209 185 : PlaceHolderVar *phv = (PlaceHolderVar *) node;
3210 :
3211 : /* See if the PlaceHolderVar has bubbled up from a lower plan node */
3212 185 : if (context->subplan_itlist->has_ph_vars)
3213 : {
69 tgl 3214 GNC 161 : newvar = search_indexed_tlist_for_phv(phv,
3215 : context->subplan_itlist,
3216 : context->newvarno,
3217 : context->nrm_match);
5283 tgl 3218 GIC 161 : if (newvar)
3219 161 : return (Node *) newvar;
3220 : }
3221 : /* If not supplied by input plan, evaluate the contained expr */
3222 : /* XXX can we assert something about phnullingrels? */
3223 24 : return fix_upper_expr_mutator((Node *) phv->phexpr, context);
3224 : }
3225 : /* Try matching more complex expressions too, if tlist has any */
1579 tgl 3226 CBC 175910 : if (context->subplan_itlist->has_non_vars)
3227 : {
1579 tgl 3228 GIC 11400 : newvar = search_indexed_tlist_for_non_var((Expr *) node,
3229 : context->subplan_itlist,
3230 : context->newvarno);
3231 11400 : if (newvar)
3232 3012 : return (Node *) newvar;
3233 : }
3234 : /* Special cases (apply only AFTER failing to match to lower tlist) */
3217 3235 172898 : if (IsA(node, Param))
3236 2950 : return fix_param_node(context->root, (Param *) node);
2589 tgl 3237 CBC 169948 : if (IsA(node, Aggref))
2589 tgl 3238 ECB : {
2589 tgl 3239 CBC 19597 : Aggref *aggref = (Aggref *) node;
2589 tgl 3240 ECB :
3241 : /* See if the Aggref should be replaced by a Param */
2589 tgl 3242 CBC 19597 : if (context->root->minmax_aggs != NIL &&
2589 tgl 3243 LBC 0 : list_length(aggref->args) == 1)
2589 tgl 3244 ECB : {
2589 tgl 3245 UIC 0 : TargetEntry *curTarget = (TargetEntry *) linitial(aggref->args);
3246 : ListCell *lc;
3247 :
2589 tgl 3248 LBC 0 : foreach(lc, context->root->minmax_aggs)
3249 : {
2589 tgl 3250 UIC 0 : MinMaxAggInfo *mminfo = (MinMaxAggInfo *) lfirst(lc);
3251 :
2589 tgl 3252 LBC 0 : if (mminfo->aggfnoid == aggref->aggfnoid &&
3253 0 : equal(mminfo->target, curTarget->expr))
3254 0 : return (Node *) copyObject(mminfo->param);
3255 : }
2589 tgl 3256 ECB : }
3257 : /* If no match, just fall through to process it normally */
3258 : }
924 tgl 3259 CBC 169948 : if (IsA(node, AlternativeSubPlan))
924 tgl 3260 GIC 9 : return fix_upper_expr_mutator(fix_alternative_subplan(context->root,
924 tgl 3261 ECB : (AlternativeSubPlan *) node,
3262 : context->num_exec),
3263 : context);
4236 tgl 3264 GIC 169939 : fix_expr_common(context->root, node);
8631 3265 169939 : return expression_tree_mutator(node,
5890 tgl 3266 ECB : fix_upper_expr_mutator,
8631 3267 : (void *) context);
3268 : }
3269 :
3270 : /*
6084 3271 : * set_returning_clause_references
3272 : * Perform setrefs.c's work on a RETURNING targetlist
3273 : *
3274 : * If the query involves more than just the result table, we have to
3275 : * adjust any Vars that refer to other tables to reference junk tlist
3276 : * entries in the top subplan's targetlist. Vars referencing the result
3277 : * table should be left alone, however (the executor will evaluate them
3260 bruce 3278 : * using the actual heap tuple, after firing triggers if any). In the
4001 tgl 3279 : * adjusted RETURNING list, result-table Vars will have their original
3280 : * varno (plus rtoffset), but Vars for other rels will have varno OUTER_VAR.
3281 : *
3282 : * We also must perform opcode lookup and add regclass OIDs to
4236 3283 : * root->glob->relationOids.
3284 : *
6084 3285 : * 'rlist': the RETURNING targetlist to be fixed
4929 3286 : * 'topplan': the top subplan node that will be just below the ModifyTable
4001 3287 : * node (note it's not yet passed through set_plan_refs)
5890 3288 : * 'resultRelation': RT index of the associated result relation
4001 3289 : * 'rtoffset': how much to increment varnos by
3290 : *
3291 : * Note: the given 'root' is for the parent query level, not the 'topplan'.
3292 : * This does not matter currently since we only access the dependency-item
4001 tgl 3293 EUB : * lists in root->glob, but it would need some hacking if we wanted a root
3294 : * that actually matches the subplan.
4001 tgl 3295 ECB : *
3296 : * Note: resultRelation is not yet adjusted by rtoffset.
6084 3297 : */
3298 : static List *
4236 tgl 3299 GIC 1267 : set_returning_clause_references(PlannerInfo *root,
5659 tgl 3300 ECB : List *rlist,
3301 : Plan *topplan,
4001 3302 : Index resultRelation,
3303 : int rtoffset)
3304 : {
3305 : indexed_tlist *itlist;
6084 3306 :
3307 : /*
3308 : * We can perform the desired Var fixup by abusing the fix_join_expr
4654 3309 : * machinery that formerly handled inner indexscan fixup. We search the
3310 : * top plan's targetlist for Vars of non-result relations, and use
5624 bruce 3311 : * fix_join_expr to convert RETURNING Vars into references to those tlist
3312 : * entries, while leaving result-rel Vars as-is.
3313 : *
3314 : * PlaceHolderVars will also be sought in the targetlist, but no
5050 3315 : * more-complex expressions will be. Note that it is not possible for a
3316 : * PlaceHolderVar to refer to the result relation, since the result is
3317 : * never below an outer join. If that case could happen, we'd have to be
3318 : * prepared to pick apart the PlaceHolderVar and evaluate its contained
3319 : * expression instead.
3320 : */
6084 tgl 3321 CBC 1267 : itlist = build_tlist_index_other_vars(topplan->targetlist, resultRelation);
3322 :
4236 tgl 3323 GIC 1267 : rlist = fix_join_expr(root,
5659 tgl 3324 ECB : rlist,
3325 : itlist,
5890 3326 : NULL,
3327 : resultRelation,
3328 : rtoffset,
3329 : NRM_EQUAL,
924 3330 : NUM_EXEC_TLIST(topplan));
6084 3331 :
6084 tgl 3332 GIC 1267 : pfree(itlist);
6084 tgl 3333 ECB :
6084 tgl 3334 GIC 1267 : return rlist;
6084 tgl 3335 ECB : }
3336 :
3337 : /*
366 drowley 3338 : * fix_windowagg_condition_expr_mutator
3339 : * Mutator function for replacing WindowFuncs with the corresponding Var
3340 : * in the targetlist which references that WindowFunc.
3341 : */
3342 : static Node *
366 drowley 3343 CBC 1413 : fix_windowagg_condition_expr_mutator(Node *node,
366 drowley 3344 ECB : fix_windowagg_cond_context *context)
3345 : {
366 drowley 3346 GIC 1413 : if (node == NULL)
3347 1014 : return NULL;
3348 :
366 drowley 3349 CBC 399 : if (IsA(node, WindowFunc))
366 drowley 3350 ECB : {
3351 : Var *newvar;
3352 :
366 drowley 3353 GIC 81 : newvar = search_indexed_tlist_for_non_var((Expr *) node,
3354 : context->subplan_itlist,
3355 : context->newvarno);
3356 81 : if (newvar)
3357 81 : return (Node *) newvar;
366 drowley 3358 UIC 0 : elog(ERROR, "WindowFunc not found in subplan target lists");
3359 : }
3360 :
366 drowley 3361 GIC 318 : return expression_tree_mutator(node,
3362 : fix_windowagg_condition_expr_mutator,
3363 : (void *) context);
3364 : }
3365 :
3366 : /*
3367 : * fix_windowagg_condition_expr
3368 : * Converts references in 'runcondition' so that any WindowFunc
3369 : * references are swapped out for a Var which references the matching
3370 : * WindowFunc in 'subplan_itlist'.
3371 : */
3372 : static List *
3373 1089 : fix_windowagg_condition_expr(PlannerInfo *root,
3374 : List *runcondition,
3375 : indexed_tlist *subplan_itlist)
3376 : {
3377 : fix_windowagg_cond_context context;
3378 :
3379 1089 : context.root = root;
3380 1089 : context.subplan_itlist = subplan_itlist;
3381 1089 : context.newvarno = 0;
3382 :
3383 1089 : return (List *) fix_windowagg_condition_expr_mutator((Node *) runcondition,
3384 : &context);
3385 : }
3386 :
3387 : /*
366 drowley 3388 ECB : * set_windowagg_runcondition_references
3389 : * Converts references in 'runcondition' so that any WindowFunc
3390 : * references are swapped out for a Var which references the matching
3391 : * WindowFunc in 'plan' targetlist.
3392 : */
3393 : static List *
366 drowley 3394 GIC 1089 : set_windowagg_runcondition_references(PlannerInfo *root,
3395 : List *runcondition,
3396 : Plan *plan)
3397 : {
366 drowley 3398 ECB : List *newlist;
3399 : indexed_tlist *itlist;
3400 :
366 drowley 3401 CBC 1089 : itlist = build_tlist_index(plan->targetlist);
366 drowley 3402 ECB :
366 drowley 3403 CBC 1089 : newlist = fix_windowagg_condition_expr(root, runcondition, itlist);
366 drowley 3404 ECB :
366 drowley 3405 GIC 1089 : pfree(itlist);
3406 :
3407 1089 : return newlist;
366 drowley 3408 ECB : }
3409 :
3410 : /*****************************************************************************
3411 : * QUERY DEPENDENCY MANAGEMENT
5325 tgl 3412 : *****************************************************************************/
3413 :
3414 : /*
3415 : * record_plan_function_dependency
3416 : * Mark the current plan as depending on a particular function.
3417 : *
3418 : * This is exported so that the function-inlining code can record a
3419 : * dependency on a function that it's removed from the plan tree.
3420 : */
3421 : void
4236 tgl 3422 GIC 511051 : record_plan_function_dependency(PlannerInfo *root, Oid funcid)
5325 tgl 3423 ECB : {
5325 tgl 3424 EUB : /*
5325 tgl 3425 ECB : * For performance reasons, we don't bother to track built-in functions;
3426 : * we just assume they'll never change (or at least not in ways that'd
3427 : * invalidate plans using them). For this purpose we can consider a
3428 : * built-in function to be one with OID less than FirstUnpinnedObjectId.
5050 bruce 3429 : * Note that the OID generator guarantees never to generate such an OID
3430 : * after startup, even at OID wraparound.
3431 : */
633 tgl 3432 CBC 511051 : if (funcid >= (Oid) FirstUnpinnedObjectId)
3433 : {
4254 3434 26029 : PlanInvalItem *inval_item = makeNode(PlanInvalItem);
3435 :
3436 : /*
3437 : * It would work to use any syscache on pg_proc, but the easiest is
4254 tgl 3438 ECB : * PROCOID since we already have the function's OID at hand. Note
4050 3439 : * that plancache.c knows we use PROCOID.
3440 : */
5325 tgl 3441 GIC 26029 : inval_item->cacheId = PROCOID;
4050 3442 26029 : inval_item->hashValue = GetSysCacheHashValue1(PROCOID,
2118 tgl 3443 ECB : ObjectIdGetDatum(funcid));
3444 :
4236 tgl 3445 GIC 26029 : root->glob->invalItems = lappend(root->glob->invalItems, inval_item);
5325 tgl 3446 ECB : }
5325 tgl 3447 GIC 511051 : }
5325 tgl 3448 ECB :
3449 : /*
3450 : * record_plan_type_dependency
1578 3451 : * Mark the current plan as depending on a particular type.
3452 : *
3453 : * This is exported so that eval_const_expressions can record a
3454 : * dependency on a domain that it's removed a CoerceToDomain node for.
3455 : *
3456 : * We don't currently need to record dependencies on domains that the
3457 : * plan contains CoerceToDomain nodes for, though that might change in
3458 : * future. Hence, this isn't actually called in this module, though
3459 : * someday fix_expr_common might call it.
3460 : */
3461 : void
1550 tgl 3462 CBC 44826 : record_plan_type_dependency(PlannerInfo *root, Oid typid)
1578 tgl 3463 EUB : {
3464 : /*
3465 : * As in record_plan_function_dependency, ignore the possibility that
3466 : * someone would change a built-in domain.
3467 : */
633 tgl 3468 GBC 44826 : if (typid >= (Oid) FirstUnpinnedObjectId)
3469 : {
1578 3470 44826 : PlanInvalItem *inval_item = makeNode(PlanInvalItem);
3471 :
1578 tgl 3472 EUB : /*
3473 : * It would work to use any syscache on pg_type, but the easiest is
3474 : * TYPEOID since we already have the type's OID at hand. Note that
3475 : * plancache.c knows we use TYPEOID.
3476 : */
1578 tgl 3477 GIC 44826 : inval_item->cacheId = TYPEOID;
3478 44826 : inval_item->hashValue = GetSysCacheHashValue1(TYPEOID,
1550 tgl 3479 ECB : ObjectIdGetDatum(typid));
1578 3480 :
1578 tgl 3481 GIC 44826 : root->glob->invalItems = lappend(root->glob->invalItems, inval_item);
3482 : }
3483 44826 : }
1578 tgl 3484 ECB :
5325 3485 : /*
3486 : * extract_query_dependencies
3487 : * Given a rewritten, but not yet planned, query or queries
3488 : * (i.e. a Query node or list of Query nodes), extract dependencies
3489 : * just as set_plan_references would do. Also detect whether any
3490 : * rewrite steps were affected by RLS.
3491 : *
3492 : * This is needed by plancache.c to handle invalidation of cached unplanned
3493 : * queries.
3494 : *
3495 : * Note: this does not go through eval_const_expressions, and hence doesn't
3496 : * reflect its additions of inlined functions and elided CoerceToDomain nodes
3497 : * to the invalItems list. This is obviously OK for functions, since we'll
3498 : * see them in the original query tree anyway. For domains, it's OK because
3499 : * we don't care about domains unless they get elided. That is, a plan might
3500 : * have domain dependencies that the query tree doesn't.
3501 : */
3502 : void
4832 tgl 3503 GIC 25141 : extract_query_dependencies(Node *query,
3504 : List **relationOids,
3505 : List **invalItems,
3506 : bool *hasRowSecurity)
3507 : {
3508 : PlannerGlobal glob;
3509 : PlannerInfo root;
3510 :
3511 : /* Make up dummy planner state so we can use this module's machinery */
5325 3512 477679 : MemSet(&glob, 0, sizeof(glob));
3513 25141 : glob.type = T_PlannerGlobal;
3514 25141 : glob.relationOids = NIL;
3515 25141 : glob.invalItems = NIL;
3516 : /* Hack: we use glob.dependsOnRole to collect hasRowSecurity flags */
2459 3517 25141 : glob.dependsOnRole = false;
3518 :
4236 tgl 3519 CBC 2212408 : MemSet(&root, 0, sizeof(root));
4236 tgl 3520 GIC 25141 : root.type = T_PlannerInfo;
3521 25141 : root.glob = &glob;
3522 :
3523 25141 : (void) extract_query_dependencies_walker(query, &root);
3524 :
5325 3525 25141 : *relationOids = glob.relationOids;
3526 25141 : *invalItems = glob.invalItems;
2459 3527 25141 : *hasRowSecurity = glob.dependsOnRole;
5325 3528 25141 : }
3529 :
3530 : /*
3531 : * Tree walker for extract_query_dependencies.
3532 : *
3533 : * This is exported so that expression_planner_with_deps can call it on
3534 : * simple expressions (post-planning, not before planning, in that case).
3535 : * In that usage, glob.dependsOnRole isn't meaningful, but the relationOids
3536 : * and invalItems lists are added to as needed.
3537 : */
3538 : bool
4236 3539 747425 : extract_query_dependencies_walker(Node *node, PlannerInfo *context)
3540 : {
5325 tgl 3541 CBC 747425 : if (node == NULL)
5325 tgl 3542 GIC 287634 : return false;
5283 tgl 3543 CBC 459791 : Assert(!IsA(node, PlaceHolderVar));
5325 tgl 3544 GIC 459791 : if (IsA(node, Query))
3545 : {
3546 26506 : Query *query = (Query *) node;
3547 : ListCell *lc;
3548 :
3938 3549 26506 : if (query->commandType == CMD_UTILITY)
3550 : {
3551 : /*
4038 tgl 3552 ECB : * Ignore utility statements, except those (such as EXPLAIN) that
3553 : * contain a parsed-but-not-planned query.
3554 : */
4038 tgl 3555 GIC 4909 : query = UtilityContainsQuery(query->utilityStmt);
3556 4909 : if (query == NULL)
4832 3557 202 : return false;
3558 : }
3559 :
3560 : /* Remember if any Query has RLS quals applied by rewriter */
2459 3561 26304 : if (query->hasRowSecurity)
3562 82 : context->glob->dependsOnRole = true;
2459 tgl 3563 ECB :
3564 : /* Collect relation OIDs in this Query's rtable */
5325 tgl 3565 GIC 41621 : foreach(lc, query->rtable)
5325 tgl 3566 ECB : {
5325 tgl 3567 CBC 15317 : RangeTblEntry *rte = (RangeTblEntry *) lfirst(lc);
3568 :
81 tgl 3569 GNC 15317 : if (rte->rtekind == RTE_RELATION ||
3570 1904 : (rte->rtekind == RTE_SUBQUERY && OidIsValid(rte->relid)) ||
3571 1838 : (rte->rtekind == RTE_NAMEDTUPLESTORE && OidIsValid(rte->relid)))
4236 tgl 3572 GIC 13694 : context->glob->relationOids =
3573 13694 : lappend_oid(context->glob->relationOids, rte->relid);
5325 tgl 3574 ECB : }
5325 tgl 3575 EUB :
3576 : /* And recurse into the query's subexpressions */
5325 tgl 3577 GIC 26304 : return query_tree_walker(query, extract_query_dependencies_walker,
5325 tgl 3578 ECB : (void *) context, 0);
3579 : }
3580 : /* Extract function dependencies and check for regclass Consts */
1578 tgl 3581 GIC 433285 : fix_expr_common(context, node);
5325 3582 433285 : return expression_tree_walker(node, extract_query_dependencies_walker,
3583 : (void *) context);
3584 : }
|