Age Owner TLA Line data Source code
1 : /*-------------------------------------------------------------------------
2 : *
3 : * prepjointree.c
4 : * Planner preprocessing for subqueries and join tree manipulation.
5 : *
6 : * NOTE: the intended sequence for invoking these operations is
7 : * replace_empty_jointree
8 : * pull_up_sublinks
9 : * preprocess_function_rtes
10 : * pull_up_subqueries
11 : * flatten_simple_union_all
12 : * do expression preprocessing (including flattening JOIN alias vars)
13 : * reduce_outer_joins
14 : * remove_useless_result_rtes
15 : *
16 : *
17 : * Portions Copyright (c) 1996-2023, PostgreSQL Global Development Group
18 : * Portions Copyright (c) 1994, Regents of the University of California
19 : *
20 : *
21 : * IDENTIFICATION
22 : * src/backend/optimizer/prep/prepjointree.c
23 : *
24 : *-------------------------------------------------------------------------
25 : */
26 : #include "postgres.h"
27 :
28 : #include "catalog/pg_type.h"
29 : #include "funcapi.h"
30 : #include "miscadmin.h"
31 : #include "nodes/makefuncs.h"
32 : #include "nodes/multibitmapset.h"
33 : #include "nodes/nodeFuncs.h"
34 : #include "optimizer/clauses.h"
35 : #include "optimizer/optimizer.h"
36 : #include "optimizer/placeholder.h"
37 : #include "optimizer/prep.h"
38 : #include "optimizer/subselect.h"
39 : #include "optimizer/tlist.h"
40 : #include "parser/parse_relation.h"
41 : #include "parser/parsetree.h"
42 : #include "rewrite/rewriteManip.h"
43 :
44 :
45 : typedef struct pullup_replace_vars_context
46 : {
47 : PlannerInfo *root;
48 : List *targetlist; /* tlist of subquery being pulled up */
49 : RangeTblEntry *target_rte; /* RTE of subquery */
50 : Relids relids; /* relids within subquery, as numbered after
51 : * pullup (set only if target_rte->lateral) */
52 : bool *outer_hasSubLinks; /* -> outer query's hasSubLinks */
53 : int varno; /* varno of subquery */
54 : bool wrap_non_vars; /* do we need all non-Var outputs to be PHVs? */
55 : Node **rv_cache; /* cache for results with PHVs */
56 : } pullup_replace_vars_context;
57 :
58 : typedef struct reduce_outer_joins_pass1_state
59 : {
60 : Relids relids; /* base relids within this subtree */
61 : bool contains_outer; /* does subtree contain outer join(s)? */
62 : List *sub_states; /* List of states for subtree components */
63 : } reduce_outer_joins_pass1_state;
64 :
65 : typedef struct reduce_outer_joins_pass2_state
66 : {
67 : Relids inner_reduced; /* OJ relids reduced to plain inner joins */
68 : List *partial_reduced; /* List of partially reduced FULL joins */
69 : } reduce_outer_joins_pass2_state;
70 :
71 : typedef struct reduce_outer_joins_partial_state
72 : {
73 : int full_join_rti; /* RT index of a formerly-FULL join */
74 : Relids unreduced_side; /* relids in its still-nullable side */
75 : } reduce_outer_joins_partial_state;
76 :
77 : static Node *pull_up_sublinks_jointree_recurse(PlannerInfo *root, Node *jtnode,
78 : Relids *relids);
79 : static Node *pull_up_sublinks_qual_recurse(PlannerInfo *root, Node *node,
80 : Node **jtlink1, Relids available_rels1,
81 : Node **jtlink2, Relids available_rels2);
82 : static Node *pull_up_subqueries_recurse(PlannerInfo *root, Node *jtnode,
83 : JoinExpr *lowest_outer_join,
84 : AppendRelInfo *containing_appendrel);
85 : static Node *pull_up_simple_subquery(PlannerInfo *root, Node *jtnode,
86 : RangeTblEntry *rte,
87 : JoinExpr *lowest_outer_join,
88 : AppendRelInfo *containing_appendrel);
89 : static Node *pull_up_simple_union_all(PlannerInfo *root, Node *jtnode,
90 : RangeTblEntry *rte);
91 : static void pull_up_union_leaf_queries(Node *setOp, PlannerInfo *root,
92 : int parentRTindex, Query *setOpQuery,
93 : int childRToffset);
94 : static void make_setop_translation_list(Query *query, int newvarno,
95 : AppendRelInfo *appinfo);
96 : static bool is_simple_subquery(PlannerInfo *root, Query *subquery,
97 : RangeTblEntry *rte,
98 : JoinExpr *lowest_outer_join);
99 : static Node *pull_up_simple_values(PlannerInfo *root, Node *jtnode,
100 : RangeTblEntry *rte);
101 : static bool is_simple_values(PlannerInfo *root, RangeTblEntry *rte);
102 : static Node *pull_up_constant_function(PlannerInfo *root, Node *jtnode,
103 : RangeTblEntry *rte,
104 : AppendRelInfo *containing_appendrel);
105 : static bool is_simple_union_all(Query *subquery);
106 : static bool is_simple_union_all_recurse(Node *setOp, Query *setOpQuery,
107 : List *colTypes);
108 : static bool is_safe_append_member(Query *subquery);
109 : static bool jointree_contains_lateral_outer_refs(PlannerInfo *root,
110 : Node *jtnode, bool restricted,
111 : Relids safe_upper_varnos);
112 : static void perform_pullup_replace_vars(PlannerInfo *root,
113 : pullup_replace_vars_context *rvcontext,
114 : AppendRelInfo *containing_appendrel);
115 : static void replace_vars_in_jointree(Node *jtnode,
116 : pullup_replace_vars_context *context);
117 : static Node *pullup_replace_vars(Node *expr,
118 : pullup_replace_vars_context *context);
119 : static Node *pullup_replace_vars_callback(Var *var,
120 : replace_rte_variables_context *context);
121 : static Query *pullup_replace_vars_subquery(Query *query,
122 : pullup_replace_vars_context *context);
123 : static reduce_outer_joins_pass1_state *reduce_outer_joins_pass1(Node *jtnode);
124 : static void reduce_outer_joins_pass2(Node *jtnode,
125 : reduce_outer_joins_pass1_state *state1,
126 : reduce_outer_joins_pass2_state *state2,
127 : PlannerInfo *root,
128 : Relids nonnullable_rels,
129 : List *forced_null_vars);
130 : static void report_reduced_full_join(reduce_outer_joins_pass2_state *state2,
131 : int rtindex, Relids relids);
132 : static Node *remove_useless_results_recurse(PlannerInfo *root, Node *jtnode,
133 : Node **parent_quals,
134 : Relids *dropped_outer_joins);
135 : static int get_result_relid(PlannerInfo *root, Node *jtnode);
136 : static void remove_result_refs(PlannerInfo *root, int varno, Node *newjtloc);
137 : static bool find_dependent_phvs(PlannerInfo *root, int varno);
138 : static bool find_dependent_phvs_in_jointree(PlannerInfo *root,
139 : Node *node, int varno);
140 : static void substitute_phv_relids(Node *node,
141 : int varno, Relids subrelids);
142 : static void fix_append_rel_relids(PlannerInfo *root, int varno,
143 : Relids subrelids);
144 : static Node *find_jointree_node_for_rel(Node *jtnode, int relid);
145 :
146 :
147 : /*
148 : * transform_MERGE_to_join
149 : * Replace a MERGE's jointree to also include the target relation.
150 : */
151 : void
377 alvherre 152 GIC 227033 : transform_MERGE_to_join(Query *parse)
153 : {
154 : RangeTblEntry *joinrte;
155 : JoinExpr *joinexpr;
156 : JoinType jointype;
157 : int joinrti;
158 : List *vars;
159 :
160 227033 : if (parse->commandType != CMD_MERGE)
161 226568 : return;
162 :
377 alvherre 163 ECB : /* XXX probably bogus */
377 alvherre 164 GIC 465 : vars = NIL;
165 :
166 : /*
167 : * When any WHEN NOT MATCHED THEN INSERT clauses exist, we need to use an
168 : * outer join so that we process all unmatched tuples from the source
169 : * relation. If none exist, we can use an inner join.
170 : */
377 alvherre 171 CBC 465 : if (parse->mergeUseOuterJoin)
172 277 : jointype = JOIN_RIGHT;
173 : else
377 alvherre 174 GIC 188 : jointype = JOIN_INNER;
377 alvherre 175 ECB :
176 : /* Manufacture a join RTE to use. */
377 alvherre 177 GIC 465 : joinrte = makeNode(RangeTblEntry);
178 465 : joinrte->rtekind = RTE_JOIN;
179 465 : joinrte->jointype = jointype;
180 465 : joinrte->joinmergedcols = 0;
181 465 : joinrte->joinaliasvars = vars;
377 alvherre 182 CBC 465 : joinrte->joinleftcols = NIL; /* MERGE does not allow JOIN USING */
183 465 : joinrte->joinrightcols = NIL; /* ditto */
377 alvherre 184 GIC 465 : joinrte->join_using_alias = NULL;
377 alvherre 185 ECB :
377 alvherre 186 GIC 465 : joinrte->alias = NULL;
187 465 : joinrte->eref = makeAlias("*MERGE*", NIL);
377 alvherre 188 CBC 465 : joinrte->lateral = false;
189 465 : joinrte->inh = false;
190 465 : joinrte->inFromCl = true;
377 alvherre 191 ECB :
192 : /*
193 : * Add completed RTE to pstate's range table list, so that we know its
194 : * index.
195 : */
377 alvherre 196 GIC 465 : parse->rtable = lappend(parse->rtable, joinrte);
197 465 : joinrti = list_length(parse->rtable);
198 :
199 : /*
377 alvherre 200 ECB : * Create a JOIN between the target and the source relation.
201 : */
377 alvherre 202 GIC 465 : joinexpr = makeNode(JoinExpr);
203 465 : joinexpr->jointype = jointype;
204 465 : joinexpr->isNatural = false;
205 465 : joinexpr->larg = (Node *) makeNode(RangeTblRef);
377 alvherre 206 CBC 465 : ((RangeTblRef *) joinexpr->larg)->rtindex = parse->resultRelation;
207 465 : joinexpr->rarg = linitial(parse->jointree->fromlist); /* original join */
208 465 : joinexpr->usingClause = NIL;
209 465 : joinexpr->join_using_alias = NULL;
377 alvherre 210 ECB : /* The quals are removed from the jointree and into this specific join */
377 alvherre 211 CBC 465 : joinexpr->quals = parse->jointree->quals;
212 465 : joinexpr->alias = NULL;
213 465 : joinexpr->rtindex = joinrti;
214 :
377 alvherre 215 ECB : /* Make the new join be the sole entry in the query's jointree */
377 alvherre 216 CBC 465 : parse->jointree->fromlist = list_make1(joinexpr);
217 465 : parse->jointree->quals = NULL;
218 : }
219 :
1532 tgl 220 ECB : /*
221 : * replace_empty_jointree
222 : * If the Query's jointree is empty, replace it with a dummy RTE_RESULT
223 : * relation.
224 : *
225 : * By doing this, we can avoid a bunch of corner cases that formerly existed
226 : * for SELECTs with omitted FROM clauses. An example is that a subquery
227 : * with empty jointree previously could not be pulled up, because that would
228 : * have resulted in an empty relid set, making the subquery not uniquely
229 : * identifiable for join or PlaceHolderVar processing.
230 : *
231 : * Unlike most other functions in this file, this function doesn't recurse;
232 : * we rely on other processing to invoke it on sub-queries at suitable times.
233 : */
234 : void
1532 tgl 235 GIC 244584 : replace_empty_jointree(Query *parse)
236 : {
237 : RangeTblEntry *rte;
238 : Index rti;
1532 tgl 239 ECB : RangeTblRef *rtr;
240 :
241 : /* Nothing to do if jointree is already nonempty */
1532 tgl 242 GIC 244584 : if (parse->jointree->fromlist != NIL)
243 147578 : return;
244 :
245 : /* We mustn't change it in the top level of a setop tree, either */
1532 tgl 246 CBC 99749 : if (parse->setOperations)
247 2743 : return;
248 :
249 : /* Create suitable RTE */
250 97006 : rte = makeNode(RangeTblEntry);
251 97006 : rte->rtekind = RTE_RESULT;
1532 tgl 252 GIC 97006 : rte->eref = makeAlias("*RESULT*", NIL);
253 :
1532 tgl 254 ECB : /* Add it to rangetable */
1532 tgl 255 CBC 97006 : parse->rtable = lappend(parse->rtable, rte);
256 97006 : rti = list_length(parse->rtable);
257 :
258 : /* And jam a reference into the jointree */
259 97006 : rtr = makeNode(RangeTblRef);
260 97006 : rtr->rtindex = rti;
1532 tgl 261 GIC 97006 : parse->jointree->fromlist = list_make1(rtr);
262 : }
1532 tgl 263 ECB :
7384 264 : /*
5351 265 : * pull_up_sublinks
266 : * Attempt to pull up ANY and EXISTS SubLinks to be treated as
267 : * semijoins or anti-semijoins.
268 : *
269 : * A clause "foo op ANY (sub-SELECT)" can be processed by pulling the
270 : * sub-SELECT up to become a rangetable entry and treating the implied
271 : * comparisons as quals of a semijoin. However, this optimization *only*
272 : * works at the top level of WHERE or a JOIN/ON clause, because we cannot
273 : * distinguish whether the ANY ought to return FALSE or NULL in cases
274 : * involving NULL inputs. Also, in an outer join's ON clause we can only
275 : * do this if the sublink is degenerate (ie, references only the nullable
276 : * side of the join). In that case it is legal to push the semijoin
277 : * down into the nullable side of the join. If the sublink references any
278 : * nonnullable-side variables then it would have to be evaluated as part
279 : * of the outer join, which makes things way too complicated.
280 : *
281 : * Under similar conditions, EXISTS and NOT EXISTS clauses can be handled
282 : * by pulling up the sub-SELECT and creating a semijoin or anti-semijoin.
283 : *
284 : * This routine searches for such clauses and does the necessary parsetree
285 : * transformations if any are found.
286 : *
287 : * This routine has to run before preprocess_expression(), so the quals
288 : * clauses are not yet reduced to implicit-AND format, and are not guaranteed
289 : * to be AND/OR-flat either. That means we need to recursively search through
290 : * explicit AND clauses. We stop as soon as we hit a non-AND item.
291 : */
292 : void
5348 tgl 293 GIC 16500 : pull_up_sublinks(PlannerInfo *root)
294 : {
295 : Node *jtnode;
296 : Relids relids;
5348 tgl 297 ECB :
298 : /* Begin recursion through the jointree */
5156 tgl 299 GIC 16500 : jtnode = pull_up_sublinks_jointree_recurse(root,
300 16500 : (Node *) root->parse->jointree,
301 : &relids);
302 :
5156 tgl 303 ECB : /*
304 : * root->parse->jointree must always be a FromExpr, so insert a dummy one
305 : * if we got a bare RangeTblRef or JoinExpr out of the recursion.
306 : */
5156 tgl 307 GIC 16500 : if (IsA(jtnode, FromExpr))
308 14469 : root->parse->jointree = (FromExpr *) jtnode;
309 : else
310 2031 : root->parse->jointree = makeFromExpr(list_make1(jtnode), NULL);
5348 tgl 311 CBC 16500 : }
5348 tgl 312 ECB :
313 : /*
314 : * Recurse through jointree nodes for pull_up_sublinks()
7384 315 : *
316 : * In addition to returning the possibly-modified jointree node, we return
317 : * a relids set of the contained rels into *relids.
318 : */
319 : static Node *
5348 tgl 320 GIC 49779 : pull_up_sublinks_jointree_recurse(PlannerInfo *root, Node *jtnode,
321 : Relids *relids)
322 : {
323 : /* Since this function recurses, it could be driven to stack overflow. */
108 tgl 324 CBC 49779 : check_stack_depth();
325 :
5348 tgl 326 GIC 49779 : if (jtnode == NULL)
327 : {
5348 tgl 328 LBC 0 : *relids = NULL;
329 : }
5348 tgl 330 CBC 49779 : else if (IsA(jtnode, RangeTblRef))
331 : {
5348 tgl 332 GBC 26801 : int varno = ((RangeTblRef *) jtnode)->rtindex;
333 :
5348 tgl 334 CBC 26801 : *relids = bms_make_singleton(varno);
335 : /* jtnode is returned unmodified */
5348 tgl 336 ECB : }
5348 tgl 337 GIC 22978 : else if (IsA(jtnode, FromExpr))
5348 tgl 338 ECB : {
5348 tgl 339 GIC 16503 : FromExpr *f = (FromExpr *) jtnode;
340 16503 : List *newfromlist = NIL;
5348 tgl 341 CBC 16503 : Relids frelids = NULL;
342 : FromExpr *newf;
5156 tgl 343 ECB : Node *jtlink;
5348 344 : ListCell *l;
345 :
346 : /* First, recurse to process children and collect their relids */
5348 tgl 347 GIC 34474 : foreach(l, f->fromlist)
348 : {
349 : Node *newchild;
350 : Relids childrelids;
5348 tgl 351 ECB :
5348 tgl 352 GIC 17971 : newchild = pull_up_sublinks_jointree_recurse(root,
353 17971 : lfirst(l),
354 : &childrelids);
355 17971 : newfromlist = lappend(newfromlist, newchild);
5348 tgl 356 CBC 17971 : frelids = bms_join(frelids, childrelids);
5348 tgl 357 ECB : }
358 : /* Build the replacement FromExpr; no quals yet */
5156 tgl 359 CBC 16503 : newf = makeFromExpr(newfromlist, NULL);
5156 tgl 360 ECB : /* Set up a link representing the rebuilt jointree */
5156 tgl 361 GIC 16503 : jtlink = (Node *) newf;
362 : /* Now process qual --- all children are available for use */
4090 tgl 363 CBC 16503 : newf->quals = pull_up_sublinks_qual_recurse(root, f->quals,
364 : &jtlink, frelids,
4090 tgl 365 ECB : NULL, NULL);
366 :
5348 367 : /*
368 : * Note that the result will be either newf, or a stack of JoinExprs
369 : * with newf at the base. We rely on subsequent optimization steps to
370 : * flatten this and rearrange the joins as needed.
371 : *
372 : * Although we could include the pulled-up subqueries in the returned
373 : * relids, there's no need since upper quals couldn't refer to their
374 : * outputs anyway.
375 : */
5348 tgl 376 GIC 16503 : *relids = frelids;
5156 377 16503 : jtnode = jtlink;
378 : }
5348 379 6475 : else if (IsA(jtnode, JoinExpr))
5348 tgl 380 ECB : {
381 : JoinExpr *j;
382 : Relids leftrelids;
383 : Relids rightrelids;
384 : Node *jtlink;
385 :
386 : /*
387 : * Make a modifiable copy of join node, but don't bother copying its
388 : * subnodes (yet).
389 : */
5348 tgl 390 GIC 6475 : j = (JoinExpr *) palloc(sizeof(JoinExpr));
391 6475 : memcpy(j, jtnode, sizeof(JoinExpr));
5156 392 6475 : jtlink = (Node *) j;
393 :
5348 tgl 394 ECB : /* Recurse to process children and collect their relids */
5348 tgl 395 CBC 6475 : j->larg = pull_up_sublinks_jointree_recurse(root, j->larg,
5348 tgl 396 ECB : &leftrelids);
5348 tgl 397 GIC 6475 : j->rarg = pull_up_sublinks_jointree_recurse(root, j->rarg,
398 : &rightrelids);
5348 tgl 399 ECB :
400 : /*
401 : * Now process qual, showing appropriate child relids as available,
402 : * and attach any pulled-up jointree items at the right place. In the
403 : * inner-join case we put new JoinExprs above the existing one (much
404 : * as for a FromExpr-style join). In outer-join cases the new
405 : * JoinExprs must go into the nullable side of the outer join. The
406 : * point of the available_rels machinations is to ensure that we only
407 : * pull up quals for which that's okay.
408 : *
409 : * We don't expect to see any pre-existing JOIN_SEMI, JOIN_ANTI, or
410 : * JOIN_RIGHT_ANTI jointypes here.
411 : */
5348 tgl 412 GIC 6475 : switch (j->jointype)
413 : {
414 3500 : case JOIN_INNER:
415 3500 : j->quals = pull_up_sublinks_qual_recurse(root, j->quals,
4090 tgl 416 ECB : &jtlink,
417 : bms_union(leftrelids,
2118 418 : rightrelids),
4090 419 : NULL, NULL);
5348 tgl 420 GIC 3500 : break;
421 2945 : case JOIN_LEFT:
422 2945 : j->quals = pull_up_sublinks_qual_recurse(root, j->quals,
423 : &j->rarg,
5348 tgl 424 ECB : rightrelids,
4090 425 : NULL, NULL);
5348 tgl 426 CBC 2945 : break;
5348 tgl 427 UIC 0 : case JOIN_FULL:
428 : /* can't do anything with full-join quals */
429 0 : break;
5348 tgl 430 CBC 30 : case JOIN_RIGHT:
5348 tgl 431 GBC 30 : j->quals = pull_up_sublinks_qual_recurse(root, j->quals,
432 : &j->larg,
5348 tgl 433 EUB : leftrelids,
4090 tgl 434 ECB : NULL, NULL);
5348 tgl 435 CBC 30 : break;
5348 tgl 436 UIC 0 : default:
437 0 : elog(ERROR, "unrecognized join type: %d",
438 : (int) j->jointype);
5348 tgl 439 ECB : break;
5348 tgl 440 EUB : }
441 :
442 : /*
443 : * Although we could include the pulled-up subqueries in the returned
444 : * relids, there's no need since upper quals couldn't refer to their
445 : * outputs anyway. But we *do* need to include the join's own rtindex
446 : * because we haven't yet collapsed join alias variables, so upper
447 : * levels would mistakenly think they couldn't use references to this
448 : * join.
449 : */
5156 tgl 450 GIC 6475 : *relids = bms_join(leftrelids, rightrelids);
451 6475 : if (j->rtindex)
452 6475 : *relids = bms_add_member(*relids, j->rtindex);
453 6475 : jtnode = jtlink;
5348 tgl 454 ECB : }
455 : else
5348 tgl 456 LBC 0 : elog(ERROR, "unrecognized node type: %d",
5348 tgl 457 ECB : (int) nodeTag(jtnode));
5348 tgl 458 GIC 49779 : return jtnode;
459 : }
5348 tgl 460 EUB :
461 : /*
5348 tgl 462 ECB : * Recurse through top-level qual nodes for pull_up_sublinks()
463 : *
464 : * jtlink1 points to the link in the jointree where any new JoinExprs should
465 : * be inserted if they reference available_rels1 (i.e., available_rels1
466 : * denotes the relations present underneath jtlink1). Optionally, jtlink2 can
467 : * point to a second link where new JoinExprs should be inserted if they
468 : * reference available_rels2 (pass NULL for both those arguments if not used).
469 : * Note that SubLinks referencing both sets of variables cannot be optimized.
470 : * If we find multiple pull-up-able SubLinks, they'll get stacked onto jtlink1
471 : * and/or jtlink2 in the order we encounter them. We rely on subsequent
472 : * optimization to rearrange the stack if appropriate.
473 : *
474 : * Returns the replacement qual node, or NULL if the qual should be removed.
475 : */
476 : static Node *
5348 tgl 477 GIC 44814 : pull_up_sublinks_qual_recurse(PlannerInfo *root, Node *node,
478 : Node **jtlink1, Relids available_rels1,
479 : Node **jtlink2, Relids available_rels2)
480 : {
7384 tgl 481 CBC 44814 : if (node == NULL)
7384 tgl 482 GIC 3386 : return NULL;
483 41428 : if (IsA(node, SubLink))
484 : {
7188 bruce 485 CBC 808 : SubLink *sublink = (SubLink *) node;
5156 tgl 486 ECB : JoinExpr *j;
4360 487 : Relids child_rels;
488 :
5351 489 : /* Is it a convertible ANY or EXISTS clause? */
5351 tgl 490 GIC 808 : if (sublink->subLinkType == ANY_SUBLINK)
491 : {
4090 492 607 : if ((j = convert_ANY_sublink_to_join(root, sublink,
493 : available_rels1)) != NULL)
4090 tgl 494 ECB : {
495 : /* Yes; insert the new join node into the join tree */
4090 tgl 496 CBC 545 : j->larg = *jtlink1;
4090 tgl 497 GIC 545 : *jtlink1 = (Node *) j;
498 : /* Recursively process pulled-up jointree nodes */
499 545 : j->rarg = pull_up_sublinks_jointree_recurse(root,
4090 tgl 500 ECB : j->rarg,
501 : &child_rels);
502 :
503 : /*
504 : * Now recursively process the pulled-up quals. Any inserted
505 : * joins can get stacked onto either j->larg or j->rarg,
506 : * depending on which rels they reference.
507 : */
4090 tgl 508 GIC 545 : j->quals = pull_up_sublinks_qual_recurse(root,
509 : j->quals,
510 : &j->larg,
511 : available_rels1,
4090 tgl 512 ECB : &j->rarg,
513 : child_rels);
514 : /* Return NULL representing constant TRUE */
4090 tgl 515 GIC 545 : return NULL;
516 : }
517 62 : if (available_rels2 != NULL &&
4090 tgl 518 UIC 0 : (j = convert_ANY_sublink_to_join(root, sublink,
4090 tgl 519 ECB : available_rels2)) != NULL)
520 : {
521 : /* Yes; insert the new join node into the join tree */
4090 tgl 522 UBC 0 : j->larg = *jtlink2;
4090 tgl 523 UIC 0 : *jtlink2 = (Node *) j;
524 : /* Recursively process pulled-up jointree nodes */
4360 525 0 : j->rarg = pull_up_sublinks_jointree_recurse(root,
4360 tgl 526 EUB : j->rarg,
527 : &child_rels);
528 :
4090 529 : /*
530 : * Now recursively process the pulled-up quals. Any inserted
531 : * joins can get stacked onto either j->larg or j->rarg,
532 : * depending on which rels they reference.
533 : */
4360 tgl 534 UIC 0 : j->quals = pull_up_sublinks_qual_recurse(root,
535 : j->quals,
536 : &j->larg,
537 : available_rels2,
4090 tgl 538 EUB : &j->rarg,
539 : child_rels);
540 : /* Return NULL representing constant TRUE */
5156 tgl 541 UIC 0 : return NULL;
542 : }
543 : }
5351 tgl 544 GIC 201 : else if (sublink->subLinkType == EXISTS_SUBLINK)
5351 tgl 545 EUB : {
4090 tgl 546 GIC 177 : if ((j = convert_EXISTS_sublink_to_join(root, sublink, false,
547 : available_rels1)) != NULL)
5348 tgl 548 ECB : {
549 : /* Yes; insert the new join node into the join tree */
4090 tgl 550 CBC 140 : j->larg = *jtlink1;
4090 tgl 551 GIC 140 : *jtlink1 = (Node *) j;
552 : /* Recursively process pulled-up jointree nodes */
4360 553 140 : j->rarg = pull_up_sublinks_jointree_recurse(root,
4360 tgl 554 ECB : j->rarg,
555 : &child_rels);
556 :
4090 557 : /*
558 : * Now recursively process the pulled-up quals. Any inserted
559 : * joins can get stacked onto either j->larg or j->rarg,
560 : * depending on which rels they reference.
561 : */
4360 tgl 562 GIC 140 : j->quals = pull_up_sublinks_qual_recurse(root,
563 : j->quals,
564 : &j->larg,
565 : available_rels1,
4090 tgl 566 ECB : &j->rarg,
567 : child_rels);
568 : /* Return NULL representing constant TRUE */
4090 tgl 569 GIC 140 : return NULL;
570 : }
571 37 : if (available_rels2 != NULL &&
4090 tgl 572 UIC 0 : (j = convert_EXISTS_sublink_to_join(root, sublink, false,
4090 tgl 573 ECB : available_rels2)) != NULL)
574 : {
575 : /* Yes; insert the new join node into the join tree */
4090 tgl 576 UBC 0 : j->larg = *jtlink2;
4090 tgl 577 UIC 0 : *jtlink2 = (Node *) j;
578 : /* Recursively process pulled-up jointree nodes */
579 0 : j->rarg = pull_up_sublinks_jointree_recurse(root,
4090 tgl 580 EUB : j->rarg,
581 : &child_rels);
582 :
583 : /*
584 : * Now recursively process the pulled-up quals. Any inserted
585 : * joins can get stacked onto either j->larg or j->rarg,
586 : * depending on which rels they reference.
587 : */
4090 tgl 588 UIC 0 : j->quals = pull_up_sublinks_qual_recurse(root,
589 : j->quals,
590 : &j->larg,
591 : available_rels2,
4090 tgl 592 EUB : &j->rarg,
593 : child_rels);
594 : /* Return NULL representing constant TRUE */
5156 tgl 595 UIC 0 : return NULL;
596 : }
597 : }
598 : /* Else return it unmodified */
5351 tgl 599 GBC 123 : return node;
600 : }
1531 tgl 601 GIC 40620 : if (is_notclause(node))
602 : {
5351 tgl 603 ECB : /* If the immediate argument of NOT is EXISTS, try to convert */
5351 tgl 604 GIC 3384 : SubLink *sublink = (SubLink *) get_notclausearg((Expr *) node);
5156 tgl 605 ECB : JoinExpr *j;
606 : Relids child_rels;
607 :
5351 tgl 608 CBC 3384 : if (sublink && IsA(sublink, SubLink))
609 : {
5351 tgl 610 GIC 1734 : if (sublink->subLinkType == EXISTS_SUBLINK)
611 : {
4090 tgl 612 CBC 1686 : if ((j = convert_EXISTS_sublink_to_join(root, sublink, true,
613 : available_rels1)) != NULL)
5348 tgl 614 ECB : {
615 : /* Yes; insert the new join node into the join tree */
4090 tgl 616 CBC 1673 : j->larg = *jtlink1;
4090 tgl 617 GIC 1673 : *jtlink1 = (Node *) j;
618 : /* Recursively process pulled-up jointree nodes */
619 1673 : j->rarg = pull_up_sublinks_jointree_recurse(root,
4090 tgl 620 ECB : j->rarg,
621 : &child_rels);
622 :
4311 623 : /*
624 : * Now recursively process the pulled-up quals. Because
625 : * we are underneath a NOT, we can't pull up sublinks that
626 : * reference the left-hand stuff, but it's still okay to
627 : * pull up sublinks referencing j->rarg.
628 : */
4090 tgl 629 GIC 1673 : j->quals = pull_up_sublinks_qual_recurse(root,
630 : j->quals,
631 : &j->rarg,
632 : child_rels,
4090 tgl 633 ECB : NULL, NULL);
634 : /* Return NULL representing constant TRUE */
4090 tgl 635 GIC 1673 : return NULL;
636 : }
637 13 : if (available_rels2 != NULL &&
4090 tgl 638 UIC 0 : (j = convert_EXISTS_sublink_to_join(root, sublink, true,
2118 tgl 639 ECB : available_rels2)) != NULL)
640 : {
4090 641 : /* Yes; insert the new join node into the join tree */
4090 tgl 642 UBC 0 : j->larg = *jtlink2;
4090 tgl 643 UIC 0 : *jtlink2 = (Node *) j;
644 : /* Recursively process pulled-up jointree nodes */
4360 645 0 : j->rarg = pull_up_sublinks_jointree_recurse(root,
4360 tgl 646 EUB : j->rarg,
647 : &child_rels);
648 :
4090 649 : /*
650 : * Now recursively process the pulled-up quals. Because
651 : * we are underneath a NOT, we can't pull up sublinks that
652 : * reference the left-hand stuff, but it's still okay to
653 : * pull up sublinks referencing j->rarg.
654 : */
4360 tgl 655 UIC 0 : j->quals = pull_up_sublinks_qual_recurse(root,
656 : j->quals,
657 : &j->rarg,
658 : child_rels,
4090 tgl 659 EUB : NULL, NULL);
660 : /* Return NULL representing constant TRUE */
5156 tgl 661 UIC 0 : return NULL;
662 : }
663 : }
664 : }
5351 tgl 665 EUB : /* Else return it unmodified */
5351 tgl 666 GIC 1711 : return node;
667 : }
1531 668 37236 : if (is_andclause(node))
669 : {
5348 tgl 670 ECB : /* Recurse into AND clause */
7188 bruce 671 GIC 7212 : List *newclauses = NIL;
6892 neilc 672 ECB : ListCell *l;
673 :
6892 neilc 674 GIC 26690 : foreach(l, ((BoolExpr *) node)->args)
7384 tgl 675 ECB : {
6892 neilc 676 GIC 19478 : Node *oldclause = (Node *) lfirst(l);
677 : Node *newclause;
5156 tgl 678 ECB :
5156 tgl 679 GIC 19478 : newclause = pull_up_sublinks_qual_recurse(root,
5156 tgl 680 ECB : oldclause,
681 : jtlink1,
682 : available_rels1,
4090 683 : jtlink2,
684 : available_rels2);
5156 tgl 685 GIC 19478 : if (newclause)
686 17932 : newclauses = lappend(newclauses, newclause);
687 : }
688 : /* We might have got back fewer clauses than we started with */
5156 tgl 689 CBC 7212 : if (newclauses == NIL)
690 303 : return NULL;
5156 tgl 691 GIC 6909 : else if (list_length(newclauses) == 1)
692 468 : return (Node *) linitial(newclauses);
5156 tgl 693 ECB : else
5156 tgl 694 CBC 6441 : return (Node *) make_andclause(newclauses);
7384 tgl 695 ECB : }
696 : /* Stop if not an AND */
7384 tgl 697 GIC 30024 : return node;
7384 tgl 698 ECB : }
699 :
700 : /*
1347 701 : * preprocess_function_rtes
702 : * Constant-simplify any FUNCTION RTEs in the FROM clause, and then
703 : * attempt to "inline" any that are set-returning functions.
704 : *
705 : * If an RTE_FUNCTION rtable entry invokes a set-returning function that
706 : * contains just a simple SELECT, we can convert the rtable entry to an
707 : * RTE_SUBQUERY entry exposing the SELECT directly. This is especially
708 : * useful if the subquery can then be "pulled up" for further optimization,
709 : * but we do it even if not, to reduce executor overhead.
710 : *
711 : * This has to be done before we have started to do any optimization of
712 : * subqueries, else any such steps wouldn't get applied to subqueries
713 : * obtained via inlining. However, we do it after pull_up_sublinks
714 : * so that we can inline any functions used in SubLink subselects.
715 : *
716 : * The reason for applying const-simplification at this stage is that
717 : * (a) we'd need to do it anyway to inline a SRF, and (b) by doing it now,
718 : * we can be sure that pull_up_constant_function() will see constants
719 : * if there are constants to be seen. This approach also guarantees
720 : * that every FUNCTION RTE has been const-simplified, allowing planner.c's
721 : * preprocess_expression() to skip doing it again.
722 : *
723 : * Like most of the planner, this feels free to scribble on its input data
724 : * structure.
725 : */
726 : void
1347 tgl 727 GIC 242771 : preprocess_function_rtes(PlannerInfo *root)
728 : {
729 : ListCell *rt;
730 :
5500 tgl 731 CBC 620063 : foreach(rt, root->parse->rtable)
732 : {
5500 tgl 733 GIC 377295 : RangeTblEntry *rte = (RangeTblEntry *) lfirst(rt);
734 :
5500 tgl 735 CBC 377295 : if (rte->rtekind == RTE_FUNCTION)
736 : {
5050 bruce 737 ECB : Query *funcquery;
738 :
1347 tgl 739 : /* Apply const-simplification */
1347 tgl 740 GIC 17937 : rte->functions = (List *)
741 17937 : eval_const_expressions(root, (Node *) rte->functions);
742 :
743 : /* Check safety of expansion, and expand if possible */
5295 tgl 744 CBC 17937 : funcquery = inline_set_returning_function(root, rte);
5500 745 17934 : if (funcquery)
746 : {
747 : /* Successful expansion, convert the RTE to a subquery */
748 69 : rte->rtekind = RTE_SUBQUERY;
749 69 : rte->subquery = funcquery;
1664 tgl 750 GIC 69 : rte->security_barrier = false;
751 : /* Clear fields that should not be set in a subquery RTE */
3426 tgl 752 CBC 69 : rte->functions = NIL;
1664 753 69 : rte->funcordinality = false;
5500 tgl 754 ECB : }
755 : }
756 : }
5500 tgl 757 CBC 242768 : }
758 :
759 : /*
760 : * pull_up_subqueries
7384 tgl 761 ECB : * Look for subqueries in the rangetable that can be pulled up into
762 : * the parent query. If the subquery has no special features like
763 : * grouping/aggregation then we can merge it into the parent's jointree.
764 : * Also, subqueries that are simple UNION ALL structures can be
765 : * converted into "append relations".
766 : */
767 : void
2951 tgl 768 GIC 242768 : pull_up_subqueries(PlannerInfo *root)
769 : {
770 : /* Top level of jointree must always be a FromExpr */
771 242768 : Assert(IsA(root->parse->jointree, FromExpr));
2951 tgl 772 ECB : /* Recursion starts with no containing join nor appendrel */
2951 tgl 773 GIC 485533 : root->parse->jointree = (FromExpr *)
774 242768 : pull_up_subqueries_recurse(root, (Node *) root->parse->jointree,
775 : NULL, NULL);
776 : /* We should still have a FromExpr */
2951 tgl 777 CBC 242765 : Assert(IsA(root->parse->jointree, FromExpr));
3892 778 242765 : }
779 :
780 : /*
3892 tgl 781 ECB : * pull_up_subqueries_recurse
782 : * Recursive guts of pull_up_subqueries.
783 : *
784 : * This recursively processes the jointree and returns a modified jointree.
785 : *
786 : * If this jointree node is within either side of an outer join, then
787 : * lowest_outer_join references the lowest such JoinExpr node; otherwise
788 : * it is NULL. We use this to constrain the effects of LATERAL subqueries.
789 : *
790 : * If we are looking at a member subquery of an append relation,
791 : * containing_appendrel describes that relation; else it is NULL.
792 : * This forces use of the PlaceHolderVar mechanism for all non-Var targetlist
793 : * items, and puts some additional restrictions on what can be pulled up.
794 : *
795 : * A tricky aspect of this code is that if we pull up a subquery we have
796 : * to replace Vars that reference the subquery's outputs throughout the
797 : * parent query, including quals attached to jointree nodes above the one
798 : * we are currently processing! We handle this by being careful to maintain
799 : * validity of the jointree structure while recursing, in the following sense:
800 : * whenever we recurse, all qual expressions in the tree must be reachable
801 : * from the top level, in case the recursive call needs to modify them.
802 : *
803 : * Notice also that we can't turn pullup_replace_vars loose on the whole
804 : * jointree, because it'd return a mutated copy of the tree; we have to
805 : * invoke it just on the quals, instead. This behavior is what makes it
806 : * reasonable to pass lowest_outer_join as a pointer rather than some
807 : * more-indirect way of identifying the lowest OJ. Likewise, we don't
808 : * replace append_rel_list members but only their substructure, so the
809 : * containing_appendrel reference is safe to use.
7384 810 : */
811 : static Node *
3892 tgl 812 GIC 573199 : pull_up_subqueries_recurse(PlannerInfo *root, Node *jtnode,
813 : JoinExpr *lowest_outer_join,
1532 tgl 814 ECB : AppendRelInfo *containing_appendrel)
815 : {
108 816 : /* Since this function recurses, it could be driven to stack overflow. */
108 tgl 817 GIC 573199 : check_stack_depth();
108 tgl 818 ECB : /* Also, since it's a bit expensive, let's check for query cancel. */
108 tgl 819 CBC 573199 : CHECK_FOR_INTERRUPTS();
820 :
2951 821 573199 : Assert(jtnode != NULL);
7384 822 573199 : if (IsA(jtnode, RangeTblRef))
823 : {
7384 tgl 824 GIC 294109 : int varno = ((RangeTblRef *) jtnode)->rtindex;
6274 825 294109 : RangeTblEntry *rte = rt_fetch(varno, root->parse->rtable);
826 :
827 : /*
828 : * Is this a subquery RTE, and if so, is the subquery simple enough to
829 : * pull up?
830 : *
6031 bruce 831 ECB : * If we are looking at an append-relation member, we can't pull it up
832 : * unless is_safe_append_member says so.
7384 tgl 833 : */
6908 tgl 834 CBC 314172 : if (rte->rtekind == RTE_SUBQUERY &&
808 835 36069 : is_simple_subquery(root, rte->subquery, rte, lowest_outer_join) &&
5094 tgl 836 GIC 1534 : (containing_appendrel == NULL ||
837 1534 : is_safe_append_member(rte->subquery)))
6274 838 15738 : return pull_up_simple_subquery(root, jtnode, rte,
839 : lowest_outer_join,
840 : containing_appendrel);
841 :
842 : /*
843 : * Alternatively, is it a simple UNION ALL subquery? If so, flatten
844 : * into an "append relation".
845 : *
846 : * It's safe to do this regardless of whether this query is itself an
5050 bruce 847 ECB : * appendrel member. (If you're thinking we should try to flatten the
848 : * two levels of appendrel together, you're right; but we handle that
849 : * in set_append_rel_pathlist, not here.)
850 : */
6274 tgl 851 GIC 282696 : if (rte->rtekind == RTE_SUBQUERY &&
852 4325 : is_simple_union_all(rte->subquery))
853 625 : return pull_up_simple_union_all(root, jtnode, rte);
854 :
855 : /*
856 : * Or perhaps it's a simple VALUES RTE?
2951 tgl 857 ECB : *
858 : * We don't allow VALUES pullup below an outer join nor into an
859 : * appendrel (such cases are impossible anyway at the moment).
860 : */
2951 tgl 861 CBC 277746 : if (rte->rtekind == RTE_VALUES &&
2951 tgl 862 GIC 4129 : lowest_outer_join == NULL &&
863 4129 : containing_appendrel == NULL &&
1532 864 4129 : is_simple_values(root, rte))
2951 865 570 : return pull_up_simple_values(root, jtnode, rte);
2951 tgl 866 ECB :
1347 867 : /*
868 : * Or perhaps it's a FUNCTION RTE that we could inline?
869 : */
1347 tgl 870 GIC 277176 : if (rte->rtekind == RTE_FUNCTION)
871 17865 : return pull_up_constant_function(root, jtnode, rte,
872 : containing_appendrel);
1347 tgl 873 ECB :
874 : /* Otherwise, do nothing at this node. */
875 : }
7384 tgl 876 CBC 279090 : else if (IsA(jtnode, FromExpr))
877 : {
878 244802 : FromExpr *f = (FromExpr *) jtnode;
879 : ListCell *l;
7384 tgl 880 ECB :
5094 tgl 881 GIC 244802 : Assert(containing_appendrel == NULL);
882 : /* Recursively transform all the child nodes */
7384 883 504854 : foreach(l, f->fromlist)
884 : {
3892 tgl 885 CBC 260055 : lfirst(l) = pull_up_subqueries_recurse(root, lfirst(l),
886 : lowest_outer_join,
887 : NULL);
2951 tgl 888 ECB : }
889 : }
7384 tgl 890 CBC 34288 : else if (IsA(jtnode, JoinExpr))
891 : {
892 34288 : JoinExpr *j = (JoinExpr *) jtnode;
7384 tgl 893 ECB :
5094 tgl 894 GIC 34288 : Assert(containing_appendrel == NULL);
895 : /* Recurse, being careful to tell myself when inside outer join */
7384 tgl 896 CBC 34288 : switch (j->jointype)
897 : {
7384 tgl 898 GIC 13321 : case JOIN_INNER:
3892 tgl 899 CBC 13321 : j->larg = pull_up_subqueries_recurse(root, j->larg,
3892 tgl 900 ECB : lowest_outer_join,
901 : NULL);
3892 tgl 902 CBC 13321 : j->rarg = pull_up_subqueries_recurse(root, j->rarg,
903 : lowest_outer_join,
1532 tgl 904 ECB : NULL);
7384 tgl 905 GIC 13321 : break;
906 20060 : case JOIN_LEFT:
5156 tgl 907 ECB : case JOIN_SEMI:
908 : case JOIN_ANTI:
3892 tgl 909 CBC 20060 : j->larg = pull_up_subqueries_recurse(root, j->larg,
910 : j,
1532 tgl 911 ECB : NULL);
3892 tgl 912 GIC 20060 : j->rarg = pull_up_subqueries_recurse(root, j->rarg,
3892 tgl 913 ECB : j,
1532 914 : NULL);
7384 tgl 915 CBC 20060 : break;
7384 tgl 916 GIC 470 : case JOIN_FULL:
3892 917 470 : j->larg = pull_up_subqueries_recurse(root, j->larg,
918 : j,
919 : NULL);
3892 tgl 920 CBC 470 : j->rarg = pull_up_subqueries_recurse(root, j->rarg,
3892 tgl 921 EUB : j,
922 : NULL);
7384 tgl 923 GIC 470 : break;
924 437 : case JOIN_RIGHT:
3892 925 437 : j->larg = pull_up_subqueries_recurse(root, j->larg,
3892 tgl 926 EUB : j,
927 : NULL);
3892 tgl 928 CBC 437 : j->rarg = pull_up_subqueries_recurse(root, j->rarg,
929 : j,
930 : NULL);
7384 tgl 931 GIC 437 : break;
7384 tgl 932 UIC 0 : default:
7198 933 0 : elog(ERROR, "unrecognized join type: %d",
934 : (int) j->jointype);
935 : break;
936 : }
937 : }
938 : else
939 0 : elog(ERROR, "unrecognized node type: %d",
940 : (int) nodeTag(jtnode));
7384 tgl 941 GIC 538398 : return jtnode;
942 : }
7384 tgl 943 ECB :
944 : /*
945 : * pull_up_simple_subquery
946 : * Attempt to pull up a single simple subquery.
6274 947 : *
948 : * jtnode is a RangeTblRef that has been tentatively identified as a simple
949 : * subquery by pull_up_subqueries. We return the replacement jointree node,
950 : * or jtnode itself if we determine that the subquery can't be pulled up
951 : * after all.
952 : *
953 : * rte is the RangeTblEntry referenced by jtnode. Remaining parameters are
954 : * as for pull_up_subqueries_recurse.
955 : */
956 : static Node *
6274 tgl 957 GIC 15738 : pull_up_simple_subquery(PlannerInfo *root, Node *jtnode, RangeTblEntry *rte,
958 : JoinExpr *lowest_outer_join,
1532 tgl 959 ECB : AppendRelInfo *containing_appendrel)
960 : {
6274 tgl 961 GIC 15738 : Query *parse = root->parse;
962 15738 : int varno = ((RangeTblRef *) jtnode)->rtindex;
963 : Query *subquery;
964 : PlannerInfo *subroot;
965 : int rtoffset;
966 : pullup_replace_vars_context rvcontext;
967 : ListCell *lc;
6274 tgl 968 ECB :
969 : /*
642 970 : * Make a modifiable copy of the subquery to hack on, so that the RTE will
971 : * be left unchanged in case we decide below that we can't pull it up
972 : * after all.
6274 973 : */
6274 tgl 974 CBC 15738 : subquery = copyObject(rte->subquery);
6274 tgl 975 ECB :
976 : /*
977 : * Create a PlannerInfo data structure for this subquery.
978 : *
979 : * NOTE: the next few steps should match the first processing in
3260 bruce 980 : * subquery_planner(). Can we refactor to avoid code duplication, or
6031 981 : * would that just make things uglier?
6274 tgl 982 : */
6274 tgl 983 CBC 15738 : subroot = makeNode(PlannerInfo);
984 15738 : subroot->parse = subquery;
5893 985 15738 : subroot->glob = root->glob;
986 15738 : subroot->query_level = root->query_level;
5300 987 15738 : subroot->parent_root = root->parent_root;
3868 988 15738 : subroot->plan_params = NIL;
2798 989 15738 : subroot->outer_params = NULL;
5923 990 15738 : subroot->planner_cxt = CurrentMemoryContext;
5893 991 15738 : subroot->init_plans = NIL;
5300 992 15738 : subroot->cte_plan_ids = NIL;
3217 993 15738 : subroot->multiexpr_params = NIL;
69 tgl 994 GNC 15738 : subroot->join_domains = NIL;
5500 tgl 995 CBC 15738 : subroot->eq_classes = NIL;
1358 drowley 996 15738 : subroot->ec_merging_done = false;
69 tgl 997 GNC 15738 : subroot->last_rinfo_serial = 0;
739 tgl 998 CBC 15738 : subroot->all_result_relids = NULL;
999 15738 : subroot->leaf_result_relids = NULL;
6274 1000 15738 : subroot->append_rel_list = NIL;
739 1001 15738 : subroot->row_identity_vars = NIL;
4913 1002 15738 : subroot->rowMarks = NIL;
2589 tgl 1003 GIC 15738 : memset(subroot->upper_rels, 0, sizeof(subroot->upper_rels));
2582 1004 15738 : memset(subroot->upper_targets, 0, sizeof(subroot->upper_targets));
81 tgl 1005 GNC 15738 : subroot->processed_groupClause = NIL;
1006 15738 : subroot->processed_distinctClause = NIL;
2589 tgl 1007 GIC 15738 : subroot->processed_tlist = NIL;
739 tgl 1008 CBC 15738 : subroot->update_colnos = NIL;
2589 tgl 1009 GIC 15738 : subroot->grouping_map = NULL;
1010 15738 : subroot->minmax_aggs = NIL;
2272 1011 15738 : subroot->qual_security_level = 0;
235 tgl 1012 GNC 15738 : subroot->placeholdersFrozen = false;
5300 tgl 1013 GIC 15738 : subroot->hasRecursion = false;
1014 15738 : subroot->wt_param_id = -1;
2589 tgl 1015 CBC 15738 : subroot->non_recursive_path = NULL;
1016 : /* We don't currently need a top JoinDomain for the subroot */
1017 :
1018 : /* No CTEs to worry about */
5300 tgl 1019 GIC 15738 : Assert(subquery->cteList == NIL);
1020 :
1021 : /*
1532 tgl 1022 ECB : * If the FROM clause is empty, replace it with a dummy RTE_RESULT RTE, so
1023 : * that we don't need so many special cases to deal with that situation.
1024 : */
1532 tgl 1025 GIC 15738 : replace_empty_jointree(subquery);
1026 :
1027 : /*
1028 : * Pull up any SubLinks within the subquery's quals, so that we don't
5351 tgl 1029 ECB : * leave unoptimized SubLinks behind.
1030 : */
6274 tgl 1031 GIC 15738 : if (subquery->hasSubLinks)
5348 1032 3494 : pull_up_sublinks(subroot);
1033 :
1034 : /*
1035 : * Similarly, preprocess its function RTEs to inline any set-returning
1036 : * functions in its rangetable.
1037 : */
1347 1038 15738 : preprocess_function_rtes(subroot);
1039 :
1040 : /*
6274 tgl 1041 ECB : * Recursively pull up the subquery's subqueries, so that
1042 : * pull_up_subqueries' processing is complete for its jointree and
1043 : * rangetable.
1044 : *
1045 : * Note: it's okay that the subquery's recursion starts with NULL for
1046 : * containing-join info, even if we are within an outer join in the upper
1047 : * query; the lower query starts with a clean slate for outer-join
1048 : * semantics. Likewise, we needn't pass down appendrel state.
1049 : */
2951 tgl 1050 GIC 15738 : pull_up_subqueries(subroot);
6274 tgl 1051 ECB :
1052 : /*
1053 : * Now we must recheck whether the subquery is still simple enough to pull
1054 : * up. If not, abandon processing it.
1055 : *
1056 : * We don't really need to recheck all the conditions involved, but it's
1057 : * easier just to keep this "if" looking the same as the one in
1058 : * pull_up_subqueries_recurse.
1059 : */
808 tgl 1060 GIC 15738 : if (is_simple_subquery(root, subquery, rte, lowest_outer_join) &&
5094 1061 1266 : (containing_appendrel == NULL || is_safe_append_member(subquery)))
1062 : {
1063 : /* good to go */
1064 : }
1065 : else
6274 tgl 1066 ECB : {
1067 : /*
1068 : * Give up, return unmodified RangeTblRef.
1069 : *
1070 : * Note: The work we just did will be redone when the subquery gets
1071 : * planned on its own. Perhaps we could avoid that by storing the
1072 : * modified subquery back into the rangetable, but I'm not gonna risk
1073 : * it now.
1074 : */
6274 tgl 1075 GIC 28 : return jtnode;
1076 : }
1077 :
3425 tgl 1078 ECB : /*
1079 : * We must flatten any join alias Vars in the subquery's targetlist,
1080 : * because pulling up the subquery's subqueries might have changed their
1081 : * expansions into arbitrary expressions, which could affect
1082 : * pullup_replace_vars' decisions about whether PlaceHolderVar wrappers
1083 : * are needed for tlist entries. (Likely it'd be better to do
1084 : * flatten_join_alias_vars on the whole query tree at some earlier stage,
1085 : * maybe even in the rewriter; but for now let's just fix this case here.)
1086 : */
3425 tgl 1087 CBC 15710 : subquery->targetList = (List *)
69 tgl 1088 GNC 15710 : flatten_join_alias_vars(subroot, subroot->parse,
1089 15710 : (Node *) subquery->targetList);
3425 tgl 1090 ECB :
1091 : /*
1092 : * Adjust level-0 varnos in subquery so that we can append its rangetable
1093 : * to upper query's. We have to fix the subquery's append_rel_list as
1094 : * well.
1095 : */
6274 tgl 1096 CBC 15710 : rtoffset = list_length(parse->rtable);
1097 15710 : OffsetVarNodes((Node *) subquery, rtoffset, 0);
6274 tgl 1098 GIC 15710 : OffsetVarNodes((Node *) subroot->append_rel_list, rtoffset, 0);
1099 :
1100 : /*
1101 : * Upper-level vars in subquery are now one level closer to their parent
1102 : * than before.
1103 : */
1104 15710 : IncrementVarSublevelsUp((Node *) subquery, -1, 1);
1105 15710 : IncrementVarSublevelsUp((Node *) subroot->append_rel_list, -1, 1);
5283 tgl 1106 ECB :
1107 : /*
1108 : * The subquery's targetlist items are now in the appropriate form to
1913 1109 : * insert into the top query, except that we may need to wrap them in
1110 : * PlaceHolderVars. Set up required context data for pullup_replace_vars.
1111 : * (Note that we should include the subquery's inner joins in relids,
1112 : * since it may include join alias vars referencing them.)
1113 : */
4967 tgl 1114 GIC 15710 : rvcontext.root = root;
4967 tgl 1115 CBC 15710 : rvcontext.targetlist = subquery->targetList;
1116 15710 : rvcontext.target_rte = rte;
3522 1117 15710 : if (rte->lateral)
3522 tgl 1118 GIC 307 : rvcontext.relids = get_relids_in_jointree((Node *) subquery->jointree,
1119 : true, true);
1120 : else /* won't need relids */
3522 tgl 1121 CBC 15403 : rvcontext.relids = NULL;
4967 tgl 1122 GIC 15710 : rvcontext.outer_hasSubLinks = &parse->hasSubLinks;
1123 15710 : rvcontext.varno = varno;
1124 : /* this flag will be set below, if needed */
1913 1125 15710 : rvcontext.wrap_non_vars = false;
1126 : /* initialize cache array with indexes 0 .. length(tlist) */
4967 1127 15710 : rvcontext.rv_cache = palloc0((list_length(subquery->targetList) + 1) *
1128 : sizeof(Node *));
1129 :
1130 : /*
1131 : * If we are dealing with an appendrel member then anything that's not a
1132 : * simple Var has to be turned into a PlaceHolderVar. We force this to
1133 : * ensure that what we pull up doesn't get merged into a surrounding
1134 : * expression during later processing and then fail to match the
1913 tgl 1135 ECB : * expression actually available from the appendrel.
1136 : */
1913 tgl 1137 GIC 15710 : if (containing_appendrel != NULL)
1138 1238 : rvcontext.wrap_non_vars = true;
1139 :
1913 tgl 1140 ECB : /*
1141 : * If the parent query uses grouping sets, we need a PlaceHolderVar for
1142 : * anything that's not a simple Var. Again, this ensures that expressions
1143 : * retain their separate identity so that they will match grouping set
1144 : * columns when appropriate. (It'd be sufficient to wrap values used in
1145 : * grouping set columns, and do so only in non-aggregated portions of the
1146 : * tlist and havingQual, but that would require a lot of infrastructure
1147 : * that pullup_replace_vars hasn't currently got.)
1148 : */
1913 tgl 1149 GIC 15710 : if (parse->groupingSets)
1913 tgl 1150 CBC 124 : rvcontext.wrap_non_vars = true;
1913 tgl 1151 ECB :
1152 : /*
6031 bruce 1153 : * Replace all of the top query's references to the subquery's outputs
1154 : * with copies of the adjusted subtlist items, being careful not to
1347 tgl 1155 : * replace any of the jointree structure.
6274 1156 : */
1347 tgl 1157 CBC 15710 : perform_pullup_replace_vars(root, &rvcontext,
1347 tgl 1158 ECB : containing_appendrel);
1159 :
1160 : /*
1161 : * If the subquery had a LATERAL marker, propagate that to any of its
3892 1162 : * child RTEs that could possibly now contain lateral cross-references.
1163 : * The children might or might not contain any actual lateral
1164 : * cross-references, but we have to mark the pulled-up child RTEs so that
1165 : * later planner stages will check for such.
1166 : */
3892 tgl 1167 GIC 15707 : if (rte->lateral)
1168 : {
3892 tgl 1169 CBC 782 : foreach(lc, subquery->rtable)
1170 : {
3892 tgl 1171 GIC 475 : RangeTblEntry *child_rte = (RangeTblEntry *) lfirst(lc);
1172 :
1173 475 : switch (child_rte->rtekind)
1174 : {
2815 1175 207 : case RTE_RELATION:
1176 207 : if (child_rte->tablesample)
1177 9 : child_rte->lateral = true;
1178 207 : break;
3892 tgl 1179 CBC 101 : case RTE_SUBQUERY:
1180 : case RTE_FUNCTION:
1181 : case RTE_VALUES:
1182 : case RTE_TABLEFUNC:
3892 tgl 1183 GIC 101 : child_rte->lateral = true;
1184 101 : break;
1185 167 : case RTE_JOIN:
3892 tgl 1186 ECB : case RTE_CTE:
1187 : case RTE_NAMEDTUPLESTORE:
1188 : case RTE_RESULT:
1189 : /* these can't contain any lateral references */
3892 tgl 1190 GIC 167 : break;
1191 : }
1192 : }
1193 : }
1194 :
1195 : /*
1196 : * Now append the adjusted rtable entries and their perminfos to upper
1197 : * query. (We hold off until after fixing the upper rtable entries; no
1198 : * point in running that code on the subquery ones too.)
6274 tgl 1199 ECB : */
124 alvherre 1200 GNC 15707 : CombineRangeTables(&parse->rtable, &parse->rteperminfos,
1201 : subquery->rtable, subquery->rteperminfos);
1202 :
1203 : /*
6031 bruce 1204 ECB : * Pull up any FOR UPDATE/SHARE markers, too. (OffsetVarNodes already
1205 : * adjusted the marker rtindexes, so just concat the lists.)
6274 tgl 1206 : */
6274 tgl 1207 CBC 15707 : parse->rowMarks = list_concat(parse->rowMarks, subquery->rowMarks);
6274 tgl 1208 ECB :
1209 : /*
1210 : * We also have to fix the relid sets of any PlaceHolderVar nodes in the
1211 : * parent query. (This could perhaps be done by pullup_replace_vars(),
1212 : * but it seems cleaner to use two passes.) Note in particular that any
1213 : * PlaceHolderVar nodes just created by pullup_replace_vars() will be
4790 bruce 1214 : * adjusted, so having created them with the subquery's varno is correct.
6274 tgl 1215 : *
1216 : * Likewise, relids appearing in AppendRelInfo nodes have to be fixed. We
1217 : * already checked that this won't require introducing multiple subrelids
1218 : * into the single-slot AppendRelInfo structs.
1219 : */
108 tgl 1220 GNC 15707 : if (root->glob->lastPHId != 0 || root->append_rel_list)
6274 tgl 1221 ECB : {
1222 : Relids subrelids;
1223 :
69 tgl 1224 GNC 1852 : subrelids = get_relids_in_jointree((Node *) subquery->jointree,
1225 : true, false);
108 1226 1852 : if (root->glob->lastPHId != 0)
1227 644 : substitute_phv_relids((Node *) parse, varno, subrelids);
1228 1852 : fix_append_rel_relids(root, varno, subrelids);
1229 : }
1230 :
1231 : /*
1232 : * And now add subquery's AppendRelInfos to our list.
6274 tgl 1233 ECB : */
6274 tgl 1234 GIC 31414 : root->append_rel_list = list_concat(root->append_rel_list,
1235 15707 : subroot->append_rel_list);
1236 :
1237 : /*
1238 : * We don't have to do the equivalent bookkeeping for outer-join info,
1239 : * because that hasn't been set up yet. placeholder_list likewise.
1240 : */
5351 1241 15707 : Assert(root->join_info_list == NIL);
1242 15707 : Assert(subroot->join_info_list == NIL);
5282 1243 15707 : Assert(root->placeholder_list == NIL);
5282 tgl 1244 CBC 15707 : Assert(subroot->placeholder_list == NIL);
1245 :
1246 : /*
642 tgl 1247 ECB : * We no longer need the RTE's copy of the subquery's query tree. Getting
1248 : * rid of it saves nothing in particular so far as this level of query is
1249 : * concerned; but if this query level is in turn pulled up into a parent,
1250 : * we'd waste cycles copying the now-unused query tree.
1251 : */
642 tgl 1252 GIC 15707 : rte->subquery = NULL;
1253 :
1254 : /*
1255 : * Miscellaneous housekeeping.
1256 : *
1257 : * Although replace_rte_variables() faithfully updated parse->hasSubLinks
1258 : * if it copied any SubLinks out of the subquery's targetlist, we still
4967 tgl 1259 ECB : * could have SubLinks added to the query in the expressions of FUNCTION
1260 : * and VALUES RTEs copied up from the subquery. So it's necessary to copy
1261 : * subquery->hasSubLinks anyway. Perhaps this can be improved someday.
6274 1262 : */
6274 tgl 1263 CBC 15707 : parse->hasSubLinks |= subquery->hasSubLinks;
1264 :
2341 tgl 1265 ECB : /* If subquery had any RLS conditions, now main query does too */
2341 tgl 1266 GIC 15707 : parse->hasRowSecurity |= subquery->hasRowSecurity;
1267 :
1268 : /*
1269 : * subquery won't be pulled up if it hasAggs, hasWindowFuncs, or
1270 : * hasTargetSRFs, so no work needed on those flags
1271 : */
1272 :
1273 : /*
1274 : * Return the adjusted subquery jointree to replace the RangeTblRef entry
1275 : * in parent's jointree; or, if the FromExpr is degenerate, just return
1276 : * its single member.
1277 : */
1532 tgl 1278 CBC 15707 : Assert(IsA(subquery->jointree, FromExpr));
1532 tgl 1279 GIC 15707 : Assert(subquery->jointree->fromlist != NIL);
1532 tgl 1280 CBC 26831 : if (subquery->jointree->quals == NULL &&
1281 11124 : list_length(subquery->jointree->fromlist) == 1)
1282 10986 : return (Node *) linitial(subquery->jointree->fromlist);
1283 :
6274 tgl 1284 GIC 4721 : return (Node *) subquery->jointree;
1285 : }
1286 :
1287 : /*
1288 : * pull_up_simple_union_all
1289 : * Pull up a single simple UNION ALL subquery.
6274 tgl 1290 ECB : *
1291 : * jtnode is a RangeTblRef that has been identified as a simple UNION ALL
1292 : * subquery by pull_up_subqueries. We pull up the leaf subqueries and
1293 : * build an "append relation" for the union set. The result value is just
1294 : * jtnode, since we don't actually need to change the query jointree.
1295 : */
1296 : static Node *
6274 tgl 1297 CBC 625 : pull_up_simple_union_all(PlannerInfo *root, Node *jtnode, RangeTblEntry *rte)
1298 : {
6274 tgl 1299 GIC 625 : int varno = ((RangeTblRef *) jtnode)->rtindex;
1300 625 : Query *subquery = rte->subquery;
3893 1301 625 : int rtoffset = list_length(root->parse->rtable);
1302 : List *rtable;
1303 :
1304 : /*
3893 tgl 1305 ECB : * Make a modifiable copy of the subquery's rtable, so we can adjust
1306 : * upper-level Vars in it. There are no such Vars in the setOperations
1307 : * tree proper, so fixing the rtable should be sufficient.
1308 : */
3893 tgl 1309 CBC 625 : rtable = copyObject(subquery->rtable);
1310 :
3893 tgl 1311 ECB : /*
1312 : * Upper-level vars in subquery are now one level closer to their parent
5050 bruce 1313 : * than before. We don't have to worry about offsetting varnos, though,
3893 tgl 1314 : * because the UNION leaf queries can't cross-reference each other.
1315 : */
5351 heikki.linnakangas 1316 GIC 625 : IncrementVarSublevelsUp_rtable(rtable, -1, 1);
1317 :
1318 : /*
1319 : * If the UNION ALL subquery had a LATERAL marker, propagate that to all
1320 : * its children. The individual children might or might not contain any
3893 tgl 1321 ECB : * actual lateral cross-references, but we have to mark the pulled-up
1322 : * child RTEs so that later planner stages will check for such.
1323 : */
3893 tgl 1324 GIC 625 : if (rte->lateral)
1325 : {
1326 : ListCell *rt;
1327 :
1328 90 : foreach(rt, rtable)
3893 tgl 1329 ECB : {
3893 tgl 1330 CBC 60 : RangeTblEntry *child_rte = (RangeTblEntry *) lfirst(rt);
1331 :
3893 tgl 1332 GIC 60 : Assert(child_rte->rtekind == RTE_SUBQUERY);
1333 60 : child_rte->lateral = true;
1334 : }
1335 : }
3893 tgl 1336 ECB :
1337 : /*
1338 : * Append child RTEs (and their perminfos) to parent rtable.
1339 : */
124 alvherre 1340 GNC 625 : CombineRangeTables(&root->parse->rtable, &root->parse->rteperminfos,
1341 : rtable, subquery->rteperminfos);
1342 :
1343 : /*
1344 : * Recursively scan the subquery's setOperations tree and add
1345 : * AppendRelInfo nodes for leaf subqueries to the parent's
1346 : * append_rel_list. Also apply pull_up_subqueries to the leaf subqueries.
1347 : */
6274 tgl 1348 GIC 625 : Assert(subquery->setOperations);
5351 heikki.linnakangas 1349 625 : pull_up_union_leaf_queries(subquery->setOperations, root, varno, subquery,
1350 : rtoffset);
1351 :
1352 : /*
1353 : * Mark the parent as an append relation.
1354 : */
6274 tgl 1355 625 : rte->inh = true;
1356 :
1357 625 : return jtnode;
1358 : }
1359 :
1360 : /*
6274 tgl 1361 ECB : * pull_up_union_leaf_queries -- recursive guts of pull_up_simple_union_all
1362 : *
1363 : * Build an AppendRelInfo for each leaf query in the setop tree, and then
4535 1364 : * apply pull_up_subqueries to the leaf query.
1365 : *
1366 : * Note that setOpQuery is the Query containing the setOp node, whose tlist
1367 : * contains references to all the setop output columns. When called from
1368 : * pull_up_simple_union_all, this is *not* the same as root->parse, which is
1369 : * the parent Query we are pulling up into.
1370 : *
1371 : * parentRTindex is the appendrel parent's index in root->parse->rtable.
1372 : *
1373 : * The child RTEs have already been copied to the parent. childRToffset
1374 : * tells us where in the parent's range table they were copied. When called
1375 : * from flatten_simple_union_all, childRToffset is 0 since the child RTEs
1376 : * were already in root->parse->rtable and no RT index adjustment is needed.
1377 : */
6274 1378 : static void
6274 tgl 1379 CBC 2823 : pull_up_union_leaf_queries(Node *setOp, PlannerInfo *root, int parentRTindex,
5351 heikki.linnakangas 1380 ECB : Query *setOpQuery, int childRToffset)
6274 tgl 1381 : {
6274 tgl 1382 CBC 2823 : if (IsA(setOp, RangeTblRef))
6274 tgl 1383 ECB : {
6274 tgl 1384 CBC 1800 : RangeTblRef *rtr = (RangeTblRef *) setOp;
6274 tgl 1385 ECB : int childRTindex;
1386 : AppendRelInfo *appinfo;
1387 :
1388 : /*
1389 : * Calculate the index in the parent's range table
1390 : */
5351 heikki.linnakangas 1391 GIC 1800 : childRTindex = childRToffset + rtr->rtindex;
1392 :
1393 : /*
1394 : * Build a suitable AppendRelInfo, and attach to parent's list.
1395 : */
6274 tgl 1396 1800 : appinfo = makeNode(AppendRelInfo);
1397 1800 : appinfo->parent_relid = parentRTindex;
1398 1800 : appinfo->child_relid = childRTindex;
1399 1800 : appinfo->parent_reltype = InvalidOid;
6274 tgl 1400 CBC 1800 : appinfo->child_reltype = InvalidOid;
1224 1401 1800 : make_setop_translation_list(setOpQuery, childRTindex, appinfo);
6274 1402 1800 : appinfo->parent_reloid = InvalidOid;
6274 tgl 1403 GIC 1800 : root->append_rel_list = lappend(root->append_rel_list, appinfo);
1404 :
6274 tgl 1405 ECB : /*
1406 : * Recursively apply pull_up_subqueries to the new child RTE. (We
1407 : * must build the AppendRelInfo first, because this will modify it;
1408 : * indeed, that's the only part of the upper query where Vars
1409 : * referencing childRTindex can exist at this point.)
1410 : *
1411 : * Note that we can pass NULL for containing-join info even if we're
1412 : * actually under an outer join, because the child's expressions
2951 1413 : * aren't going to propagate up to the join. Also, we ignore the
1414 : * possibility that pull_up_subqueries_recurse() returns a different
1415 : * jointree node than what we pass it; if it does, the important thing
1416 : * is that it replaced the child relid in the AppendRelInfo node.
1417 : */
6274 tgl 1418 GIC 1800 : rtr = makeNode(RangeTblRef);
1419 1800 : rtr->rtindex = childRTindex;
3892 tgl 1420 GBC 1800 : (void) pull_up_subqueries_recurse(root, (Node *) rtr,
1421 : NULL, appinfo);
1422 : }
6274 tgl 1423 CBC 1023 : else if (IsA(setOp, SetOperationStmt))
1424 : {
6274 tgl 1425 GIC 1023 : SetOperationStmt *op = (SetOperationStmt *) setOp;
1426 :
1427 : /* Recurse to reach leaf queries */
5351 heikki.linnakangas 1428 1023 : pull_up_union_leaf_queries(op->larg, root, parentRTindex, setOpQuery,
1429 : childRToffset);
1430 1023 : pull_up_union_leaf_queries(op->rarg, root, parentRTindex, setOpQuery,
1431 : childRToffset);
1432 : }
1433 : else
6274 tgl 1434 ECB : {
6274 tgl 1435 UIC 0 : elog(ERROR, "unrecognized node type: %d",
1436 : (int) nodeTag(setOp));
6274 tgl 1437 ECB : }
6274 tgl 1438 GIC 2823 : }
1439 :
1440 : /*
1441 : * make_setop_translation_list
1442 : * Build the list of translations from parent Vars to child Vars for
5262 tgl 1443 ECB : * a UNION ALL member. (At this point it's just a simple list of
1444 : * referencing Vars, but if we succeed in pulling up the member
1445 : * subquery, the Vars will get replaced by pulled-up expressions.)
1446 : * Also create the rather trivial reverse-translation array.
6274 1447 : */
1448 : static void
571 tgl 1449 CBC 1800 : make_setop_translation_list(Query *query, int newvarno,
1450 : AppendRelInfo *appinfo)
6274 tgl 1451 ECB : {
6274 tgl 1452 GBC 1800 : List *vars = NIL;
1453 : AttrNumber *pcolnos;
6274 tgl 1454 ECB : ListCell *l;
1455 :
1456 : /* Initialize reverse-translation array with all entries zero */
1457 : /* (entries for resjunk columns will stay that way) */
1224 tgl 1458 CBC 1800 : appinfo->num_child_cols = list_length(query->targetList);
1459 1800 : appinfo->parent_colnos = pcolnos =
1224 tgl 1460 GIC 1800 : (AttrNumber *) palloc0(appinfo->num_child_cols * sizeof(AttrNumber));
1461 :
6274 1462 5955 : foreach(l, query->targetList)
1463 : {
1464 4155 : TargetEntry *tle = (TargetEntry *) lfirst(l);
1465 :
1466 4155 : if (tle->resjunk)
6274 tgl 1467 UIC 0 : continue;
1468 :
4608 peter_e 1469 GIC 4155 : vars = lappend(vars, makeVarFromTargetEntry(newvarno, tle));
1224 tgl 1470 4155 : pcolnos[tle->resno - 1] = tle->resno;
1471 : }
6274 tgl 1472 ECB :
1224 tgl 1473 GIC 1800 : appinfo->translated_vars = vars;
6274 1474 1800 : }
1475 :
1476 : /*
1477 : * is_simple_subquery
7384 tgl 1478 ECB : * Check a subquery in the range table to see if it's simple enough
1479 : * to pull up into the parent query.
3892 tgl 1480 EUB : *
1481 : * rte is the RTE_SUBQUERY RangeTblEntry that contained the subquery.
1482 : * (Note subquery is not necessarily equal to rte->subquery; it could be a
1483 : * processed copy of that.)
1484 : * lowest_outer_join is the lowest outer join above the subquery, or NULL.
1485 : */
1486 : static bool
808 tgl 1487 CBC 35801 : is_simple_subquery(PlannerInfo *root, Query *subquery, RangeTblEntry *rte,
1532 tgl 1488 ECB : JoinExpr *lowest_outer_join)
1489 : {
1490 : /*
1491 : * Let's just make sure it's a valid subselect ...
1492 : */
7384 tgl 1493 GIC 35801 : if (!IsA(subquery, Query) ||
2276 1494 35801 : subquery->commandType != CMD_SELECT)
7198 tgl 1495 UIC 0 : elog(ERROR, "subquery is bogus");
1496 :
1497 : /*
1498 : * Can't currently pull up a query with setops (unless it's simple UNION
1499 : * ALL, which is handled by a different code path). Maybe after querytree
7384 tgl 1500 ECB : * redesign...
1501 : */
7384 tgl 1502 CBC 35801 : if (subquery->setOperations)
1503 1132 : return false;
7384 tgl 1504 ECB :
1505 : /*
2399 1506 : * Can't pull up a subquery involving grouping, aggregation, SRFs,
1507 : * sorting, limiting, or WITH. (XXX WITH could possibly be allowed later)
4911 1508 : *
1509 : * We also don't pull up a subquery that has explicit FOR UPDATE/SHARE
1510 : * clauses, because pullup would cause the locking to occur semantically
4790 bruce 1511 : * higher than it should. Implicit FOR UPDATE/SHARE is okay because in
1512 : * that case the locking was originally declared in the upper query
1513 : * anyway.
1514 : */
7384 tgl 1515 GIC 34669 : if (subquery->hasAggs ||
5215 1516 34003 : subquery->hasWindowFuncs ||
2399 1517 33838 : subquery->hasTargetSRFs ||
7384 1518 33114 : subquery->groupClause ||
2885 andres 1519 CBC 33088 : subquery->groupingSets ||
7384 tgl 1520 33088 : subquery->havingQual ||
7384 tgl 1521 GIC 33088 : subquery->sortClause ||
1522 32476 : subquery->distinctClause ||
1523 32363 : subquery->limitOffset ||
5300 1524 32204 : subquery->limitCount ||
4911 tgl 1525 CBC 32070 : subquery->hasForUpdate ||
5300 tgl 1526 GIC 32063 : subquery->cteList)
7384 1527 2681 : return false;
1528 :
1529 : /*
1530 : * Don't pull up if the RTE represents a security-barrier view; we
1531 : * couldn't prevent information leakage once the RTE's Vars are scattered
1532 : * about in the upper query.
1533 : */
3892 1534 31988 : if (rte->security_barrier)
3897 1535 144 : return false;
1536 :
1537 : /*
1538 : * If the subquery is LATERAL, check for pullup restrictions from that.
3892 tgl 1539 ECB : */
3520 tgl 1540 GIC 31844 : if (rte->lateral)
3892 tgl 1541 ECB : {
3520 1542 : bool restricted;
1543 : Relids safe_upper_varnos;
1544 :
1545 : /*
1546 : * The subquery's WHERE and JOIN/ON quals mustn't contain any lateral
1547 : * references to rels outside a higher outer join (including the case
1548 : * where the outer join is within the subquery itself). In such a
1549 : * case, pulling up would result in a situation where we need to
1550 : * postpone quals from below an outer join to above it, which is
1551 : * probably completely wrong and in any case is a complication that
1552 : * doesn't seem worth addressing at the moment.
1553 : */
3520 tgl 1554 CBC 647 : if (lowest_outer_join != NULL)
1555 : {
3520 tgl 1556 GIC 192 : restricted = true;
1557 192 : safe_upper_varnos = get_relids_in_jointree((Node *) lowest_outer_join,
1558 : true, true);
1559 : }
1560 : else
1561 : {
1562 455 : restricted = false;
1563 455 : safe_upper_varnos = NULL; /* doesn't matter */
1564 : }
1565 :
808 1566 647 : if (jointree_contains_lateral_outer_refs(root,
1567 647 : (Node *) subquery->jointree,
1568 : restricted, safe_upper_varnos))
3892 tgl 1569 CBC 6 : return false;
1570 :
3520 tgl 1571 ECB : /*
1572 : * If there's an outer join above the LATERAL subquery, also disallow
1573 : * pullup if the subquery's targetlist has any references to rels
1574 : * outside the outer join, since these might get pulled into quals
1575 : * above the subquery (but in or below the outer join) and then lead
1576 : * to qual-postponement issues similar to the case checked for above.
1577 : * (We wouldn't need to prevent pullup if no such references appear in
1578 : * outer-query quals, but we don't have enough info here to check
1579 : * that. Also, maybe this restriction could be removed if we forced
1580 : * such refs to be wrapped in PlaceHolderVars, even when they're below
1581 : * the nearest outer join? But it's a pretty hokey usage, so not
1582 : * clear this is worth sweating over.)
1583 : */
3520 tgl 1584 GIC 641 : if (lowest_outer_join != NULL)
1585 : {
808 1586 192 : Relids lvarnos = pull_varnos_of_level(root,
1587 192 : (Node *) subquery->targetList,
808 tgl 1588 ECB : 1);
3520 1589 :
3520 tgl 1590 GIC 192 : if (!bms_is_subset(lvarnos, safe_upper_varnos))
3520 tgl 1591 CBC 6 : return false;
1592 : }
1593 : }
1594 :
1595 : /*
1596 : * Don't pull up a subquery that has any volatile functions in its
1597 : * targetlist. Otherwise we might introduce multiple evaluations of these
1598 : * functions, if they get copied to multiple places in the upper query,
1599 : * leading to surprising results. (Note: the PlaceHolderVar mechanism
1600 : * doesn't quite guarantee single evaluation; else we could pull up anyway
1601 : * and just wrap such items in PlaceHolderVars ...)
1602 : */
6077 tgl 1603 GIC 31832 : if (contain_volatile_functions((Node *) subquery->targetList))
7384 1604 88 : return false;
1605 :
2951 1606 31744 : return true;
1607 : }
1608 :
2951 tgl 1609 ECB : /*
1610 : * pull_up_simple_values
1611 : * Pull up a single simple VALUES RTE.
1612 : *
1613 : * jtnode is a RangeTblRef that has been identified as a simple VALUES RTE
1614 : * by pull_up_subqueries. We always return a RangeTblRef representing a
1615 : * RESULT RTE to replace it (all failure cases should have been detected by
1616 : * is_simple_values()). Actually, what we return is just jtnode, because
1617 : * we replace the VALUES RTE in the rangetable with the RESULT RTE.
1618 : *
1619 : * rte is the RangeTblEntry referenced by jtnode. Because of the limited
1620 : * possible usage of VALUES RTEs, we do not need the remaining parameters
1621 : * of pull_up_subqueries_recurse.
1622 : */
1623 : static Node *
2951 tgl 1624 GIC 570 : pull_up_simple_values(PlannerInfo *root, Node *jtnode, RangeTblEntry *rte)
1625 : {
2951 tgl 1626 CBC 570 : Query *parse = root->parse;
2951 tgl 1627 GIC 570 : int varno = ((RangeTblRef *) jtnode)->rtindex;
1628 : List *values_list;
1629 : List *tlist;
1630 : AttrNumber attrno;
1631 : pullup_replace_vars_context rvcontext;
2951 tgl 1632 ECB : ListCell *lc;
1633 :
2951 tgl 1634 GIC 570 : Assert(rte->rtekind == RTE_VALUES);
1635 570 : Assert(list_length(rte->values_lists) == 1);
1636 :
1637 : /*
2951 tgl 1638 ECB : * Need a modifiable copy of the VALUES list to hack on, just in case it's
1639 : * multiply referenced.
7384 1640 : */
2222 peter_e 1641 GIC 570 : values_list = copyObject(linitial(rte->values_lists));
2951 tgl 1642 ECB :
1643 : /*
1644 : * The VALUES RTE can't contain any Vars of level zero, let alone any that
1645 : * are join aliases, so no need to flatten join alias Vars.
1646 : */
2951 tgl 1647 CBC 570 : Assert(!contain_vars_of_level((Node *) values_list, 0));
1648 :
2951 tgl 1649 ECB : /*
1650 : * Set up required context data for pullup_replace_vars. In particular,
1651 : * we have to make the VALUES list look like a subquery targetlist.
1652 : */
2951 tgl 1653 CBC 570 : tlist = NIL;
1654 570 : attrno = 1;
1655 1333 : foreach(lc, values_list)
1656 : {
1657 763 : tlist = lappend(tlist,
2951 tgl 1658 GIC 763 : makeTargetEntry((Expr *) lfirst(lc),
1659 : attrno,
1660 : NULL,
1661 : false));
1662 763 : attrno++;
1663 : }
1664 570 : rvcontext.root = root;
1665 570 : rvcontext.targetlist = tlist;
2951 tgl 1666 CBC 570 : rvcontext.target_rte = rte;
2951 tgl 1667 GIC 570 : rvcontext.relids = NULL;
1668 570 : rvcontext.outer_hasSubLinks = &parse->hasSubLinks;
1669 570 : rvcontext.varno = varno;
1670 570 : rvcontext.wrap_non_vars = false;
2951 tgl 1671 ECB : /* initialize cache array with indexes 0 .. length(tlist) */
2951 tgl 1672 CBC 570 : rvcontext.rv_cache = palloc0((list_length(tlist) + 1) *
2951 tgl 1673 ECB : sizeof(Node *));
1674 :
1675 : /*
1676 : * Replace all of the top query's references to the RTE's outputs with
1677 : * copies of the adjusted VALUES expressions, being careful not to replace
1678 : * any of the jointree structure. We can assume there's no outer joins or
1347 1679 : * appendrels in the dummy Query that surrounds a VALUES RTE.
1680 : */
69 tgl 1681 GNC 570 : perform_pullup_replace_vars(root, &rvcontext, NULL);
2951 tgl 1682 ECB :
1683 : /*
1347 1684 : * There should be no appendrels to fix, nor any outer joins and hence no
1685 : * PlaceHolderVars.
1686 : */
2951 tgl 1687 CBC 570 : Assert(root->append_rel_list == NIL);
2951 tgl 1688 GIC 570 : Assert(root->join_info_list == NIL);
1689 570 : Assert(root->placeholder_list == NIL);
2951 tgl 1690 ECB :
1691 : /*
1532 1692 : * Replace the VALUES RTE with a RESULT RTE. The VALUES RTE is the only
1693 : * rtable entry in the current query level, so this is easy.
1694 : */
1532 tgl 1695 GIC 570 : Assert(list_length(parse->rtable) == 1);
1696 :
1697 : /* Create suitable RTE */
1698 570 : rte = makeNode(RangeTblEntry);
1699 570 : rte->rtekind = RTE_RESULT;
1700 570 : rte->eref = makeAlias("*RESULT*", NIL);
1701 :
1702 : /* Replace rangetable */
1532 tgl 1703 CBC 570 : parse->rtable = list_make1(rte);
1704 :
1532 tgl 1705 ECB : /* We could manufacture a new RangeTblRef, but the one we have is fine */
1532 tgl 1706 GIC 570 : Assert(varno == 1);
1707 :
1708 570 : return jtnode;
1709 : }
1710 :
1711 : /*
2951 tgl 1712 ECB : * is_simple_values
1713 : * Check a VALUES RTE in the range table to see if it's simple enough
1714 : * to pull up into the parent query.
1715 : *
1716 : * rte is the RTE_VALUES RangeTblEntry to check.
1717 : */
1718 : static bool
1532 tgl 1719 GIC 4129 : is_simple_values(PlannerInfo *root, RangeTblEntry *rte)
1720 : {
2951 1721 4129 : Assert(rte->rtekind == RTE_VALUES);
1722 :
1723 : /*
1724 : * There must be exactly one VALUES list, else it's not semantically
1725 : * correct to replace the VALUES RTE with a RESULT RTE, nor would we have
1532 tgl 1726 ECB : * a unique set of expressions to substitute into the parent query.
2951 1727 : */
2951 tgl 1728 GBC 4129 : if (list_length(rte->values_lists) != 1)
2951 tgl 1729 GIC 3559 : return false;
1730 :
1731 : /*
1732 : * Because VALUES can't appear under an outer join (or at least, we won't
1733 : * try to pull it up if it does), we need not worry about LATERAL, nor
1734 : * about validity of PHVs for the VALUES' outputs.
1735 : */
2951 tgl 1736 ECB :
1737 : /*
2951 tgl 1738 EUB : * Don't pull up a VALUES that contains any set-returning or volatile
1739 : * functions. The considerations here are basically identical to the
1532 tgl 1740 ECB : * restrictions on a pull-able subquery's targetlist.
1741 : */
2951 tgl 1742 GIC 1140 : if (expression_returns_set((Node *) rte->values_lists) ||
1743 570 : contain_volatile_functions((Node *) rte->values_lists))
2951 tgl 1744 UIC 0 : return false;
1745 :
1746 : /*
1747 : * Do not pull up a VALUES that's not the only RTE in its parent query.
1748 : * This is actually the only case that the parser will generate at the
1749 : * moment, and assuming this is true greatly simplifies
1750 : * pull_up_simple_values().
1751 : */
2951 tgl 1752 GIC 570 : if (list_length(root->parse->rtable) != 1 ||
1753 570 : rte != (RangeTblEntry *) linitial(root->parse->rtable))
7384 tgl 1754 UIC 0 : return false;
1755 :
7384 tgl 1756 GIC 570 : return true;
1757 : }
1758 :
1759 : /*
1760 : * pull_up_constant_function
1761 : * Pull up an RTE_FUNCTION expression that was simplified to a constant.
1347 tgl 1762 ECB : *
1763 : * jtnode is a RangeTblRef that has been identified as a FUNCTION RTE by
1764 : * pull_up_subqueries. If its expression is just a Const, hoist that value
1765 : * up into the parent query, and replace the RTE_FUNCTION with RTE_RESULT.
1766 : *
1767 : * In principle we could pull up any immutable expression, but we don't.
1768 : * That might result in multiple evaluations of the expression, which could
1769 : * be costly if it's not just a Const. Also, the main value of this is
1770 : * to let the constant participate in further const-folding, and of course
1771 : * that won't happen for a non-Const.
1772 : *
1773 : * The pulled-up value might need to be wrapped in a PlaceHolderVar if the
1774 : * RTE is below an outer join or is part of an appendrel; the extra
1775 : * parameters show whether that's needed.
1776 : */
1777 : static Node *
1347 tgl 1778 CBC 17865 : pull_up_constant_function(PlannerInfo *root, Node *jtnode,
1347 tgl 1779 ECB : RangeTblEntry *rte,
1780 : AppendRelInfo *containing_appendrel)
1781 : {
1347 tgl 1782 GIC 17865 : Query *parse = root->parse;
1783 : RangeTblFunction *rtf;
1784 : TypeFuncClass functypclass;
1785 : Oid funcrettype;
1786 : TupleDesc tupdesc;
1787 : pullup_replace_vars_context rvcontext;
1347 tgl 1788 ECB :
1789 : /* Fail if the RTE has ORDINALITY - we don't implement that here. */
1347 tgl 1790 GIC 17865 : if (rte->funcordinality)
1347 tgl 1791 CBC 308 : return jtnode;
1792 :
1793 : /* Fail if RTE isn't a single, simple Const expr */
1794 17557 : if (list_length(rte->functions) != 1)
1795 36 : return jtnode;
1347 tgl 1796 GIC 17521 : rtf = linitial_node(RangeTblFunction, rte->functions);
1797 17521 : if (!IsA(rtf->funcexpr, Const))
1347 tgl 1798 CBC 17338 : return jtnode;
1347 tgl 1799 ECB :
1800 : /*
1801 : * If the function's result is not a scalar, we punt. In principle we
1802 : * could break the composite constant value apart into per-column
1293 1803 : * constants, but for now it seems not worth the work.
1804 : */
1293 tgl 1805 GIC 183 : if (rtf->funccolcount != 1)
1806 12 : return jtnode; /* definitely composite */
1807 :
1808 171 : functypclass = get_expr_result_type(rtf->funcexpr,
1809 : &funcrettype,
1293 tgl 1810 ECB : &tupdesc);
1293 tgl 1811 GIC 171 : if (functypclass != TYPEFUNC_SCALAR)
1293 tgl 1812 CBC 6 : return jtnode; /* must be a one-column composite type */
1293 tgl 1813 ECB :
1814 : /* Create context for applying pullup_replace_vars */
1347 tgl 1815 CBC 165 : rvcontext.root = root;
1347 tgl 1816 GIC 165 : rvcontext.targetlist = list_make1(makeTargetEntry((Expr *) rtf->funcexpr,
1347 tgl 1817 ECB : 1, /* resno */
1818 : NULL, /* resname */
1819 : false)); /* resjunk */
1347 tgl 1820 GIC 165 : rvcontext.target_rte = rte;
1821 :
1822 : /*
1823 : * Since this function was reduced to a Const, it doesn't contain any
1824 : * lateral references, even if it's marked as LATERAL. This means we
1347 tgl 1825 ECB : * don't need to fill relids.
1347 tgl 1826 EUB : */
1347 tgl 1827 GIC 165 : rvcontext.relids = NULL;
1828 :
1829 165 : rvcontext.outer_hasSubLinks = &parse->hasSubLinks;
1830 165 : rvcontext.varno = ((RangeTblRef *) jtnode)->rtindex;
1831 : /* this flag will be set below, if needed */
1347 tgl 1832 GBC 165 : rvcontext.wrap_non_vars = false;
1833 : /* initialize cache array with indexes 0 .. length(tlist) */
1347 tgl 1834 GIC 165 : rvcontext.rv_cache = palloc0((list_length(rvcontext.targetlist) + 1) *
1835 : sizeof(Node *));
1836 :
1837 : /*
1838 : * If we are dealing with an appendrel member then anything that's not a
1839 : * simple Var has to be turned into a PlaceHolderVar. (See comments in
1840 : * pull_up_simple_subquery().)
1841 : */
1842 165 : if (containing_appendrel != NULL)
1347 tgl 1843 UIC 0 : rvcontext.wrap_non_vars = true;
1347 tgl 1844 ECB :
1845 : /*
1846 : * If the parent query uses grouping sets, we need a PlaceHolderVar for
1847 : * anything that's not a simple Var.
1848 : */
1347 tgl 1849 GIC 165 : if (parse->groupingSets)
1347 tgl 1850 UIC 0 : rvcontext.wrap_non_vars = true;
1851 :
1852 : /*
1853 : * Replace all of the top query's references to the RTE's output with
1854 : * copies of the funcexpr, being careful not to replace any of the
1855 : * jointree structure.
1856 : */
1347 tgl 1857 GIC 165 : perform_pullup_replace_vars(root, &rvcontext,
1858 : containing_appendrel);
1347 tgl 1859 ECB :
1860 : /*
1861 : * We don't need to bother with changing PlaceHolderVars in the parent
1862 : * query. Their references to the RT index are still good for now, and
1863 : * will get removed later if we're able to drop the RTE_RESULT.
1864 : */
1865 :
1347 tgl 1866 EUB : /*
1867 : * Convert the RTE to be RTE_RESULT type, signifying that we don't need to
1868 : * scan it anymore, and zero out RTE_FUNCTION-specific fields. Also make
639 tgl 1869 ECB : * sure the RTE is not marked LATERAL, since elsewhere we don't expect
1870 : * RTE_RESULTs to be LATERAL.
1347 1871 : */
1347 tgl 1872 GIC 165 : rte->rtekind = RTE_RESULT;
1873 165 : rte->functions = NIL;
639 tgl 1874 CBC 165 : rte->lateral = false;
1347 tgl 1875 ECB :
1876 : /*
1877 : * We can reuse the RangeTblRef node.
1878 : */
1347 tgl 1879 CBC 165 : return jtnode;
1880 : }
1881 :
6274 tgl 1882 ECB : /*
1883 : * is_simple_union_all
1884 : * Check a subquery to see if it's a simple UNION ALL.
1885 : *
1886 : * We require all the setops to be UNION ALL (no mixing) and there can't be
1887 : * any datatype coercions involved, ie, all the leaf queries must emit the
1888 : * same datatypes.
1889 : */
1890 : static bool
6274 tgl 1891 GIC 4325 : is_simple_union_all(Query *subquery)
6274 tgl 1892 ECB : {
1893 : SetOperationStmt *topop;
1894 :
1895 : /* Let's just make sure it's a valid subselect ... */
6274 tgl 1896 CBC 4325 : if (!IsA(subquery, Query) ||
2276 tgl 1897 GIC 4325 : subquery->commandType != CMD_SELECT)
6274 tgl 1898 LBC 0 : elog(ERROR, "subquery is bogus");
1899 :
1900 : /* Is it a set-operation query at all? */
2238 peter_e 1901 GIC 4325 : topop = castNode(SetOperationStmt, subquery->setOperations);
6274 tgl 1902 CBC 4325 : if (!topop)
6274 tgl 1903 GIC 3193 : return false;
6274 tgl 1904 ECB :
1905 : /* Can't handle ORDER BY, LIMIT/OFFSET, locking, or WITH */
6274 tgl 1906 CBC 1132 : if (subquery->sortClause ||
6274 tgl 1907 GIC 1112 : subquery->limitOffset ||
1908 1112 : subquery->limitCount ||
5300 tgl 1909 CBC 1112 : subquery->rowMarks ||
1910 1112 : subquery->cteList)
6274 tgl 1911 GIC 47 : return false;
1912 :
6274 tgl 1913 ECB : /* Recursively check the tree of set operations */
6274 tgl 1914 CBC 1085 : return is_simple_union_all_recurse((Node *) topop, subquery,
1915 : topop->colTypes);
1916 : }
1917 :
6274 tgl 1918 EUB : static bool
6274 tgl 1919 GIC 6103 : is_simple_union_all_recurse(Node *setOp, Query *setOpQuery, List *colTypes)
1920 : {
1921 : /* Since this function recurses, it could be driven to stack overflow. */
108 1922 6103 : check_stack_depth();
1923 :
6274 1924 6103 : if (IsA(setOp, RangeTblRef))
1925 : {
1926 2223 : RangeTblRef *rtr = (RangeTblRef *) setOp;
1927 2223 : RangeTblEntry *rte = rt_fetch(rtr->rtindex, setOpQuery->rtable);
1928 2223 : Query *subquery = rte->subquery;
1929 :
6274 tgl 1930 CBC 2223 : Assert(subquery != NULL);
1931 :
1932 : /* Leaf nodes are OK if they match the toplevel column types */
1933 : /* We don't have to compare typmods or collations here */
6274 tgl 1934 GIC 2223 : return tlist_same_datatypes(subquery->targetList, colTypes, true);
1935 : }
1936 3880 : else if (IsA(setOp, SetOperationStmt))
1937 : {
1938 3880 : SetOperationStmt *op = (SetOperationStmt *) setOp;
1939 :
1940 : /* Must be UNION ALL */
1941 3880 : if (op->op != SETOP_UNION || !op->all)
1942 2464 : return false;
1943 :
1944 : /* Recurse to check inputs */
1945 2632 : return is_simple_union_all_recurse(op->larg, setOpQuery, colTypes) &&
1946 1216 : is_simple_union_all_recurse(op->rarg, setOpQuery, colTypes);
6274 tgl 1947 ECB : }
1948 : else
1949 : {
6274 tgl 1950 LBC 0 : elog(ERROR, "unrecognized node type: %d",
6274 tgl 1951 ECB : (int) nodeTag(setOp));
1952 : return false; /* keep compiler quiet */
1953 : }
1954 : }
1955 :
1956 : /*
1957 : * is_safe_append_member
6274 tgl 1958 EUB : * Check a subquery that is a leaf of a UNION ALL appendrel to see if it's
6274 tgl 1959 ECB : * safe to pull up.
1960 : */
1961 : static bool
6274 tgl 1962 CBC 2800 : is_safe_append_member(Query *subquery)
1963 : {
6274 tgl 1964 ECB : FromExpr *jtnode;
1965 :
1966 : /*
1967 : * It's only safe to pull up the child if its jointree contains exactly
1968 : * one RTE, else the AppendRelInfo data structure breaks. The one base RTE
1969 : * could be buried in several levels of FromExpr, however. Also, if the
1970 : * child's jointree is completely empty, we can pull up because
1971 : * pull_up_simple_subquery will insert a single RTE_RESULT RTE instead.
1972 : *
1973 : * Also, the child can't have any WHERE quals because there's no place to
1974 : * put them in an appendrel. (This is a bit annoying...) If we didn't
1975 : * need to check this, we'd just test whether get_relids_in_jointree()
1976 : * yields a singleton set, to be more consistent with the coding of
1977 : * fix_append_rel_relids().
1978 : */
6274 tgl 1979 GIC 2800 : jtnode = subquery->jointree;
1532 1980 2800 : Assert(IsA(jtnode, FromExpr));
1981 : /* Check the completely-empty case */
1532 tgl 1982 CBC 2800 : if (jtnode->fromlist == NIL && jtnode->quals == NULL)
1532 tgl 1983 GBC 259 : return true;
1532 tgl 1984 ECB : /* Check the more general case */
6274 tgl 1985 CBC 4836 : while (IsA(jtnode, FromExpr))
6274 tgl 1986 ECB : {
6274 tgl 1987 GIC 2547 : if (jtnode->quals != NULL)
6274 tgl 1988 CBC 252 : return false;
6274 tgl 1989 GIC 2295 : if (list_length(jtnode->fromlist) != 1)
6274 tgl 1990 UIC 0 : return false;
6274 tgl 1991 GIC 2295 : jtnode = linitial(jtnode->fromlist);
6274 tgl 1992 ECB : }
6274 tgl 1993 GIC 2289 : if (!IsA(jtnode, RangeTblRef))
6274 tgl 1994 CBC 44 : return false;
6274 tgl 1995 ECB :
6274 tgl 1996 GIC 2245 : return true;
1997 : }
6274 tgl 1998 ECB :
1999 : /*
2000 : * jointree_contains_lateral_outer_refs
2001 : * Check for disallowed lateral references in a jointree's quals
3520 2002 : *
2003 : * If restricted is false, all level-1 Vars are allowed (but we still must
2004 : * search the jointree, since it might contain outer joins below which there
2062 peter_e 2005 EUB : * will be restrictions). If restricted is true, return true when any qual
2006 : * in the jointree contains level-1 Vars coming from outside the rels listed
3520 tgl 2007 ECB : * in safe_upper_varnos.
2008 : */
2009 : static bool
808 tgl 2010 GIC 1503 : jointree_contains_lateral_outer_refs(PlannerInfo *root, Node *jtnode,
2011 : bool restricted,
2012 : Relids safe_upper_varnos)
2013 : {
3520 2014 1503 : if (jtnode == NULL)
3520 tgl 2015 LBC 0 : return false;
3520 tgl 2016 GIC 1503 : if (IsA(jtnode, RangeTblRef))
3520 tgl 2017 CBC 717 : return false;
2018 786 : else if (IsA(jtnode, FromExpr))
2019 : {
3520 tgl 2020 GIC 659 : FromExpr *f = (FromExpr *) jtnode;
2021 : ListCell *l;
3520 tgl 2022 ECB :
2023 : /* First, recurse to check child joins */
3520 tgl 2024 GIC 1255 : foreach(l, f->fromlist)
2025 : {
808 tgl 2026 GBC 602 : if (jointree_contains_lateral_outer_refs(root,
808 tgl 2027 CBC 602 : lfirst(l),
2028 : restricted,
2029 : safe_upper_varnos))
3520 tgl 2030 GIC 6 : return true;
3520 tgl 2031 EUB : }
2032 :
2033 : /* Then check the top-level quals */
3520 tgl 2034 CBC 653 : if (restricted &&
808 2035 204 : !bms_is_subset(pull_varnos_of_level(root, f->quals, 1),
2036 : safe_upper_varnos))
3520 tgl 2037 LBC 0 : return true;
2038 : }
3520 tgl 2039 GIC 127 : else if (IsA(jtnode, JoinExpr))
3520 tgl 2040 EUB : {
3520 tgl 2041 GIC 127 : JoinExpr *j = (JoinExpr *) jtnode;
3520 tgl 2042 ECB :
2043 : /*
2044 : * If this is an outer join, we mustn't allow any upper lateral
2045 : * references in or below it.
2046 : */
3520 tgl 2047 GIC 127 : if (j->jointype != JOIN_INNER)
2048 : {
2049 55 : restricted = true;
2050 55 : safe_upper_varnos = NULL;
2051 : }
2052 :
3520 tgl 2053 ECB : /* Check the child joins */
808 tgl 2054 GIC 127 : if (jointree_contains_lateral_outer_refs(root,
2055 : j->larg,
2056 : restricted,
3520 tgl 2057 ECB : safe_upper_varnos))
3520 tgl 2058 UIC 0 : return true;
808 tgl 2059 GIC 127 : if (jointree_contains_lateral_outer_refs(root,
2060 : j->rarg,
2061 : restricted,
2062 : safe_upper_varnos))
3520 tgl 2063 UIC 0 : return true;
2064 :
2065 : /* Check the JOIN's qual clauses */
3520 tgl 2066 GIC 127 : if (restricted &&
808 tgl 2067 CBC 115 : !bms_is_subset(pull_varnos_of_level(root, j->quals, 1),
2068 : safe_upper_varnos))
3520 2069 6 : return true;
2070 : }
3520 tgl 2071 ECB : else
3520 tgl 2072 LBC 0 : elog(ERROR, "unrecognized node type: %d",
3520 tgl 2073 ECB : (int) nodeTag(jtnode));
3520 tgl 2074 GIC 774 : return false;
3520 tgl 2075 ECB : }
2076 :
2077 : /*
2078 : * Perform pullup_replace_vars everyplace it's needed in the query tree.
2079 : *
2080 : * Caller has already filled *rvcontext with data describing what to
2081 : * substitute for Vars referencing the target subquery. In addition
2082 : * we need the identity of the containing appendrel if any.
2083 : */
2084 : static void
1347 tgl 2085 GIC 16445 : perform_pullup_replace_vars(PlannerInfo *root,
2086 : pullup_replace_vars_context *rvcontext,
1347 tgl 2087 ECB : AppendRelInfo *containing_appendrel)
2088 : {
1347 tgl 2089 CBC 16445 : Query *parse = root->parse;
2090 : ListCell *lc;
1347 tgl 2091 ECB :
2092 : /*
2093 : * If we are considering an appendrel child subquery (that is, a UNION ALL
2094 : * member query that we're pulling up), then the only part of the upper
2095 : * query that could reference the child yet is the translated_vars list of
2096 : * the associated AppendRelInfo. Furthermore, we do not want to force use
2097 : * of PHVs in the AppendRelInfo --- there isn't any outer join between.
2098 : */
108 tgl 2099 GNC 16445 : if (containing_appendrel)
2100 : {
69 2101 1238 : bool save_wrap_non_vars = rvcontext->wrap_non_vars;
2102 :
2103 1238 : rvcontext->wrap_non_vars = false;
108 2104 1238 : containing_appendrel->translated_vars = (List *)
2105 1238 : pullup_replace_vars((Node *) containing_appendrel->translated_vars,
2106 : rvcontext);
69 2107 1238 : rvcontext->wrap_non_vars = save_wrap_non_vars;
108 2108 1238 : return;
2109 : }
2110 :
2111 : /*
1347 tgl 2112 ECB : * Replace all of the top query's references to the subquery's outputs
2113 : * with copies of the adjusted subtlist items, being careful not to
2114 : * replace any of the jointree structure. (This'd be a lot cleaner if we
1347 tgl 2115 EUB : * could use query_tree_mutator.) We have to use PHVs in the targetList,
2116 : * returningList, and havingQual, since those are certainly above any
2117 : * outer join. replace_vars_in_jointree tracks its location in the
1347 tgl 2118 ECB : * jointree and uses PHVs or not appropriately.
2119 : */
1347 tgl 2120 CBC 15207 : parse->targetList = (List *)
2121 15207 : pullup_replace_vars((Node *) parse->targetList, rvcontext);
1347 tgl 2122 GIC 15207 : parse->returningList = (List *)
1347 tgl 2123 CBC 15207 : pullup_replace_vars((Node *) parse->returningList, rvcontext);
120 drowley 2124 ECB :
120 drowley 2125 GIC 15387 : foreach(lc, parse->windowClause)
2126 : {
2127 180 : WindowClause *wc = lfirst_node(WindowClause, lc);
2128 :
2129 180 : if (wc->runCondition != NIL)
120 drowley 2130 UIC 0 : wc->runCondition = (List *)
2131 0 : pullup_replace_vars((Node *) wc->runCondition, rvcontext);
120 drowley 2132 ECB : }
1347 tgl 2133 GIC 15207 : if (parse->onConflict)
1347 tgl 2134 ECB : {
1347 tgl 2135 GIC 22 : parse->onConflict->onConflictSet = (List *)
1347 tgl 2136 CBC 11 : pullup_replace_vars((Node *) parse->onConflict->onConflictSet,
2137 : rvcontext);
2138 11 : parse->onConflict->onConflictWhere =
2139 11 : pullup_replace_vars(parse->onConflict->onConflictWhere,
1347 tgl 2140 ECB : rvcontext);
2141 :
2142 : /*
2143 : * We assume ON CONFLICT's arbiterElems, arbiterWhere, exclRelTlist
2144 : * can't contain any references to a subquery.
2145 : */
2146 : }
377 alvherre 2147 GIC 15207 : if (parse->mergeActionList)
2148 : {
2149 460 : foreach(lc, parse->mergeActionList)
377 alvherre 2150 ECB : {
377 alvherre 2151 GIC 290 : MergeAction *action = lfirst(lc);
377 alvherre 2152 EUB :
377 alvherre 2153 GIC 290 : action->qual = pullup_replace_vars(action->qual, rvcontext);
377 alvherre 2154 GBC 290 : action->targetList = (List *)
2155 290 : pullup_replace_vars((Node *) action->targetList, rvcontext);
2156 : }
2157 : }
69 tgl 2158 GNC 15207 : replace_vars_in_jointree((Node *) parse->jointree, rvcontext);
1347 tgl 2159 GIC 15204 : Assert(parse->setOperations == NULL);
1347 tgl 2160 CBC 15204 : parse->havingQual = pullup_replace_vars(parse->havingQual, rvcontext);
2161 :
1347 tgl 2162 ECB : /*
2163 : * Replace references in the translated_vars lists of appendrels.
2164 : */
1347 tgl 2165 GIC 15204 : foreach(lc, root->append_rel_list)
2166 : {
1347 tgl 2167 UIC 0 : AppendRelInfo *appinfo = (AppendRelInfo *) lfirst(lc);
2168 :
2169 0 : appinfo->translated_vars = (List *)
1347 tgl 2170 LBC 0 : pullup_replace_vars((Node *) appinfo->translated_vars, rvcontext);
2171 : }
1347 tgl 2172 ECB :
1347 tgl 2173 EUB : /*
1347 tgl 2174 ECB : * Replace references in the joinaliasvars lists of join RTEs.
2175 : */
1347 tgl 2176 GIC 43145 : foreach(lc, parse->rtable)
1347 tgl 2177 ECB : {
1347 tgl 2178 GIC 27941 : RangeTblEntry *otherrte = (RangeTblEntry *) lfirst(lc);
1347 tgl 2179 ECB :
1347 tgl 2180 GIC 27941 : if (otherrte->rtekind == RTE_JOIN)
1347 tgl 2181 CBC 2070 : otherrte->joinaliasvars = (List *)
1347 tgl 2182 GIC 2070 : pullup_replace_vars((Node *) otherrte->joinaliasvars,
1347 tgl 2183 ECB : rvcontext);
2184 : }
2185 : }
2186 :
2187 : /*
1347 tgl 2188 EUB : * Helper routine for perform_pullup_replace_vars: do pullup_replace_vars on
2189 : * every expression in the jointree, without changing the jointree structure
2190 : * itself. Ugly, but there's no other way...
7384 2191 : */
7384 tgl 2192 ECB : static void
4967 tgl 2193 CBC 38364 : replace_vars_in_jointree(Node *jtnode,
2194 : pullup_replace_vars_context *context)
7384 tgl 2195 ECB : {
7384 tgl 2196 CBC 38364 : if (jtnode == NULL)
7384 tgl 2197 LBC 0 : return;
7384 tgl 2198 CBC 38364 : if (IsA(jtnode, RangeTblRef))
2199 : {
3886 tgl 2200 ECB : /*
2201 : * If the RangeTblRef refers to a LATERAL subquery (that isn't the
2202 : * same subquery we're pulling up), it might contain references to the
3260 bruce 2203 : * target subquery, which we must replace. We drive this from the
2204 : * jointree scan, rather than a scan of the rtable, so that we can
2205 : * avoid processing no-longer-referenced RTEs.
3886 tgl 2206 EUB : */
3886 tgl 2207 GIC 19365 : int varno = ((RangeTblRef *) jtnode)->rtindex;
3886 tgl 2208 EUB :
3886 tgl 2209 GBC 19365 : if (varno != context->varno) /* ignore target subquery itself */
2210 : {
3886 tgl 2211 GIC 4158 : RangeTblEntry *rte = rt_fetch(varno, context->root->parse->rtable);
2212 :
2213 4158 : Assert(rte != context->target_rte);
3886 tgl 2214 GBC 4158 : if (rte->lateral)
2215 : {
3886 tgl 2216 GIC 361 : switch (rte->rtekind)
2217 : {
2815 tgl 2218 UIC 0 : case RTE_RELATION:
2219 : /* shouldn't be marked LATERAL unless tablesample */
2815 tgl 2220 LBC 0 : Assert(rte->tablesample);
2815 tgl 2221 UIC 0 : rte->tablesample = (TableSampleClause *)
2815 tgl 2222 LBC 0 : pullup_replace_vars((Node *) rte->tablesample,
2223 : context);
2815 tgl 2224 UIC 0 : break;
3886 tgl 2225 CBC 171 : case RTE_SUBQUERY:
2226 171 : rte->subquery =
2227 171 : pullup_replace_vars_subquery(rte->subquery,
2228 : context);
2229 171 : break;
3886 tgl 2230 GIC 157 : case RTE_FUNCTION:
3426 tgl 2231 CBC 157 : rte->functions = (List *)
2232 157 : pullup_replace_vars((Node *) rte->functions,
2233 : context);
3886 2234 157 : break;
2223 alvherre 2235 33 : case RTE_TABLEFUNC:
2223 alvherre 2236 GIC 33 : rte->tablefunc = (TableFunc *)
2237 33 : pullup_replace_vars((Node *) rte->tablefunc,
2238 : context);
2239 33 : break;
3886 tgl 2240 UIC 0 : case RTE_VALUES:
2241 0 : rte->values_lists = (List *)
2242 0 : pullup_replace_vars((Node *) rte->values_lists,
2243 : context);
3886 tgl 2244 LBC 0 : break;
2245 0 : case RTE_JOIN:
2246 : case RTE_CTE:
2200 kgrittn 2247 ECB : case RTE_NAMEDTUPLESTORE:
2248 : case RTE_RESULT:
3886 tgl 2249 : /* these shouldn't be marked LATERAL */
3886 tgl 2250 UIC 0 : Assert(false);
2251 : break;
3886 tgl 2252 EUB : }
2253 : }
2254 : }
2255 : }
7384 tgl 2256 GIC 18999 : else if (IsA(jtnode, FromExpr))
2257 : {
2258 15999 : FromExpr *f = (FromExpr *) jtnode;
2259 : ListCell *l;
2260 :
2261 33156 : foreach(l, f->fromlist)
69 tgl 2262 GNC 17157 : replace_vars_in_jointree(lfirst(l), context);
4967 tgl 2263 GIC 15999 : f->quals = pullup_replace_vars(f->quals, context);
7384 tgl 2264 ECB : }
7384 tgl 2265 GIC 3000 : else if (IsA(jtnode, JoinExpr))
2266 : {
2267 3000 : JoinExpr *j = (JoinExpr *) jtnode;
69 tgl 2268 GNC 3000 : bool save_wrap_non_vars = context->wrap_non_vars;
2269 :
2270 3000 : replace_vars_in_jointree(j->larg, context);
2271 3000 : replace_vars_in_jointree(j->rarg, context);
2272 :
2273 : /*
2274 : * Use PHVs within the join quals of a full join. Otherwise, we
2275 : * cannot identify which side of the join a pulled-up var-free
2276 : * expression came from, which can lead to failure to make a plan at
2277 : * all because none of the quals appear to be mergeable or hashable
2278 : * conditions.
2279 : */
1638 tgl 2280 CBC 3000 : if (j->jointype == JOIN_FULL)
69 tgl 2281 GNC 290 : context->wrap_non_vars = true;
2282 :
4967 tgl 2283 GIC 3000 : j->quals = pullup_replace_vars(j->quals, context);
2284 :
69 tgl 2285 GNC 3000 : context->wrap_non_vars = save_wrap_non_vars;
2286 : }
2287 : else
7198 tgl 2288 UIC 0 : elog(ERROR, "unrecognized node type: %d",
2289 : (int) nodeTag(jtnode));
7384 tgl 2290 ECB : }
2291 :
4967 2292 : /*
2293 : * Apply pullup variable replacement throughout an expression tree
2294 : *
2295 : * Returns a modified copy of the tree, so this can't be used where we
2296 : * need to do in-place replacement.
2297 : */
2298 : static Node *
4967 tgl 2299 GIC 68717 : pullup_replace_vars(Node *expr, pullup_replace_vars_context *context)
2300 : {
2301 68717 : return replace_rte_variables(expr,
2302 : context->varno, 0,
2303 : pullup_replace_vars_callback,
4967 tgl 2304 ECB : (void *) context,
2305 : context->outer_hasSubLinks);
2306 : }
2307 :
2308 : static Node *
4967 tgl 2309 GIC 53598 : pullup_replace_vars_callback(Var *var,
2310 : replace_rte_variables_context *context)
2311 : {
2312 53598 : pullup_replace_vars_context *rcon = (pullup_replace_vars_context *) context->callback_arg;
2313 53598 : int varattno = var->varattno;
2314 : bool need_phv;
2315 : Node *newnode;
2316 :
2317 : /*
2318 : * We need a PlaceHolderVar if the Var-to-be-replaced has nonempty
2319 : * varnullingrels (unless we find below that the replacement expression is
2320 : * a Var or PlaceHolderVar that we can just add the nullingrels to). We
2321 : * also need one if the caller has instructed us that all non-Var/PHV
2322 : * replacements need to be wrapped for identification purposes.
2323 : */
69 tgl 2324 GNC 53598 : need_phv = (var->varnullingrels != NULL) || rcon->wrap_non_vars;
2325 :
2326 : /*
4967 tgl 2327 ECB : * If PlaceHolderVars are needed, we cache the modified expressions in
2328 : * rcon->rv_cache[]. This is not in hopes of any material speed gain
2329 : * within this function, but to avoid generating identical PHVs with
2330 : * different IDs. That would result in duplicate evaluations at runtime,
2331 : * and possibly prevent optimizations that rely on recognizing different
2332 : * references to the same subquery output as being equal(). So it's worth
2333 : * a bit of extra effort to avoid it.
2334 : *
2335 : * The cached items have phlevelsup = 0 and phnullingrels = NULL; we'll
2336 : * copy them and adjust those values for this reference site below.
2337 : */
69 tgl 2338 GNC 53598 : if (need_phv &&
4967 tgl 2339 CBC 5355 : varattno >= InvalidAttrNumber &&
2340 5355 : varattno <= list_length(rcon->targetlist) &&
4967 tgl 2341 GIC 5355 : rcon->rv_cache[varattno] != NULL)
4967 tgl 2342 ECB : {
2343 : /* Just copy the entry and fall through to adjust phlevelsup etc */
4967 tgl 2344 CBC 830 : newnode = copyObject(rcon->rv_cache[varattno]);
4967 tgl 2345 ECB : }
4967 tgl 2346 CBC 52768 : else if (varattno == InvalidAttrNumber)
4967 tgl 2347 ECB : {
2348 : /* Must expand whole-tuple reference into RowExpr */
2349 : RowExpr *rowexpr;
2350 : List *colnames;
2351 : List *fields;
69 tgl 2352 GNC 212 : bool save_wrap_non_vars = rcon->wrap_non_vars;
4675 tgl 2353 GIC 212 : int save_sublevelsup = context->sublevels_up;
2354 :
2355 : /*
2356 : * If generating an expansion for a var of a named rowtype (ie, this
4967 tgl 2357 ECB : * is a plain relation RTE), then we must include dummy items for
2358 : * dropped columns. If the var is RECORD (ie, this is a JOIN), then
2359 : * omit dropped columns. In the latter case, attach column names to
388 2360 : * the RowExpr for use of the executor and ruleutils.c.
2361 : *
2362 : * In order to be able to cache the results, we always generate the
2363 : * expansion with varlevelsup = 0, and then adjust below if needed.
4967 2364 : */
4967 tgl 2365 GIC 212 : expandRTE(rcon->target_rte,
2366 : var->varno, 0 /* not varlevelsup */ , var->location,
2367 212 : (var->vartype != RECORDOID),
2368 : &colnames, &fields);
2369 : /* Expand the generated per-field Vars, but don't insert PHVs there */
69 tgl 2370 GNC 212 : rcon->wrap_non_vars = false;
2118 tgl 2371 GIC 212 : context->sublevels_up = 0; /* to match the expandRTE output */
4967 tgl 2372 CBC 212 : fields = (List *) replace_rte_variables_mutator((Node *) fields,
4967 tgl 2373 EUB : context);
69 tgl 2374 GNC 212 : rcon->wrap_non_vars = save_wrap_non_vars;
4675 tgl 2375 GIC 212 : context->sublevels_up = save_sublevelsup;
2376 :
4967 tgl 2377 CBC 212 : rowexpr = makeNode(RowExpr);
4967 tgl 2378 GIC 212 : rowexpr->args = fields;
2379 212 : rowexpr->row_typeid = var->vartype;
4967 tgl 2380 CBC 212 : rowexpr->row_format = COERCE_IMPLICIT_CAST;
388 tgl 2381 GIC 212 : rowexpr->colnames = (var->vartype == RECORDOID) ? colnames : NIL;
4967 2382 212 : rowexpr->location = var->location;
2383 212 : newnode = (Node *) rowexpr;
4967 tgl 2384 ECB :
2385 : /*
2386 : * Insert PlaceHolderVar if needed. Notice that we are wrapping one
2387 : * PlaceHolderVar around the whole RowExpr, rather than putting one
2388 : * around each element of the row. This is because we need the
2389 : * expression to yield NULL, not ROW(NULL,NULL,...) when it is forced
2390 : * to null by an outer join.
2391 : */
69 tgl 2392 GNC 212 : if (need_phv)
2393 : {
4967 tgl 2394 ECB : newnode = (Node *)
4967 tgl 2395 CBC 6 : make_placeholder_expr(rcon->root,
2396 : (Expr *) newnode,
4967 tgl 2397 ECB : bms_make_singleton(rcon->varno));
2398 : /* cache it with the PHV, and with phlevelsup etc not set yet */
4967 tgl 2399 CBC 6 : rcon->rv_cache[InvalidAttrNumber] = copyObject(newnode);
4967 tgl 2400 ECB : }
2401 : }
2402 : else
2403 : {
2404 : /* Normal case referencing one targetlist element */
4967 tgl 2405 GIC 52556 : TargetEntry *tle = get_tle_by_resno(rcon->targetlist, varattno);
2406 :
2407 52556 : if (tle == NULL) /* shouldn't happen */
4967 tgl 2408 UIC 0 : elog(ERROR, "could not find attribute %d in subquery targetlist",
2409 : varattno);
2410 :
2411 : /* Make a copy of the tlist item to return */
2222 peter_e 2412 CBC 52556 : newnode = (Node *) copyObject(tle->expr);
2413 :
2414 : /* Insert PlaceHolderVar if needed */
69 tgl 2415 GNC 52556 : if (need_phv)
2416 : {
2417 : bool wrap;
4967 tgl 2418 ECB :
4967 tgl 2419 GIC 4519 : if (newnode && IsA(newnode, Var) &&
2420 3809 : ((Var *) newnode)->varlevelsup == 0)
2421 : {
2422 : /*
2423 : * Simple Vars always escape being wrapped, unless they are
2424 : * lateral references to something outside the subquery being
2425 : * pulled up. (Even then, we could omit the PlaceHolderVar if
3522 tgl 2426 ECB : * the referenced rel is under the same lowest outer join, but
2427 : * it doesn't seem worth the trouble to check that.)
2428 : */
3522 tgl 2429 GIC 3801 : if (rcon->target_rte->lateral &&
2430 318 : !bms_is_member(((Var *) newnode)->varno, rcon->relids))
2431 12 : wrap = true;
2432 : else
2433 3789 : wrap = false;
4967 tgl 2434 ECB : }
4261 tgl 2435 CBC 718 : else if (newnode && IsA(newnode, PlaceHolderVar) &&
4261 tgl 2436 GIC 66 : ((PlaceHolderVar *) newnode)->phlevelsup == 0)
2437 : {
4041 tgl 2438 ECB : /* No need to wrap a PlaceHolderVar with another one, either */
4041 tgl 2439 GIC 66 : wrap = false;
4261 tgl 2440 ECB : }
4967 2441 : else
2442 : {
2443 : /*
2444 : * Must wrap, either because we need a place to insert
2445 : * varnullingrels or because caller told us to wrap
2446 : * everything.
2447 : */
69 tgl 2448 GNC 652 : wrap = true;
2449 : }
2450 :
4967 tgl 2451 GIC 4519 : if (wrap)
2452 : {
2453 : newnode = (Node *)
2454 664 : make_placeholder_expr(rcon->root,
2455 : (Expr *) newnode,
2456 : bms_make_singleton(rcon->varno));
2457 :
2458 : /*
2459 : * Cache it if possible (ie, if the attno is in range, which
2460 : * it probably always should be).
2461 : */
69 tgl 2462 GNC 1328 : if (varattno > InvalidAttrNumber &&
2463 664 : varattno <= list_length(rcon->targetlist))
2464 664 : rcon->rv_cache[varattno] = copyObject(newnode);
2465 : }
2466 : }
4967 tgl 2467 ECB : }
2468 :
2469 : /* Must adjust varlevelsup if replaced Var is within a subquery */
4967 tgl 2470 GIC 53598 : if (var->varlevelsup > 0)
2471 423 : IncrementVarSublevelsUp(newnode, var->varlevelsup, 0);
2472 :
2473 : /* Propagate any varnullingrels into the replacement Var or PHV */
69 tgl 2474 GNC 53598 : if (var->varnullingrels != NULL)
2475 : {
2476 4525 : if (IsA(newnode, Var))
2477 : {
2478 3079 : Var *newvar = (Var *) newnode;
2479 :
2480 3079 : Assert(newvar->varlevelsup == var->varlevelsup);
2481 3079 : newvar->varnullingrels = bms_add_members(newvar->varnullingrels,
2482 3079 : var->varnullingrels);
2483 : }
2484 1446 : else if (IsA(newnode, PlaceHolderVar))
2485 : {
2486 1446 : PlaceHolderVar *newphv = (PlaceHolderVar *) newnode;
2487 :
2488 1446 : Assert(newphv->phlevelsup == var->varlevelsup);
2489 1446 : newphv->phnullingrels = bms_add_members(newphv->phnullingrels,
2490 1446 : var->varnullingrels);
2491 : }
2492 : else
69 tgl 2493 UNC 0 : elog(ERROR, "failed to wrap a non-Var");
2494 : }
2495 :
4967 tgl 2496 GIC 53598 : return newnode;
2497 : }
2498 :
2499 : /*
2500 : * Apply pullup variable replacement to a subquery
2501 : *
3886 tgl 2502 ECB : * This needs to be different from pullup_replace_vars() because
2503 : * replace_rte_variables will think that it shouldn't increment sublevels_up
2504 : * before entering the Query; so we need to call it with sublevels_up == 1.
2505 : */
2506 : static Query *
3886 tgl 2507 CBC 171 : pullup_replace_vars_subquery(Query *query,
2508 : pullup_replace_vars_context *context)
2509 : {
3886 tgl 2510 GIC 171 : Assert(IsA(query, Query));
2511 171 : return (Query *) replace_rte_variables((Node *) query,
2512 : context->varno, 1,
3886 tgl 2513 ECB : pullup_replace_vars_callback,
2514 : (void *) context,
2515 : NULL);
2516 : }
2517 :
2518 :
2519 : /*
4535 2520 : * flatten_simple_union_all
2521 : * Try to optimize top-level UNION ALL structure into an appendrel
2522 : *
2523 : * If a query's setOperations tree consists entirely of simple UNION ALL
2524 : * operations, flatten it into an append relation, which we can process more
3260 bruce 2525 : * intelligently than the general setops case. Otherwise, do nothing.
4535 tgl 2526 : *
2527 : * In most cases, this can succeed only for a top-level query, because for a
2528 : * subquery in FROM, the parent query's invocation of pull_up_subqueries would
2529 : * already have flattened the UNION via pull_up_simple_union_all. But there
2530 : * are a few cases we can support here but not in that code path, for example
2531 : * when the subquery also contains ORDER BY.
2532 : */
2533 : void
4535 tgl 2534 GIC 2743 : flatten_simple_union_all(PlannerInfo *root)
4535 tgl 2535 ECB : {
4535 tgl 2536 CBC 2743 : Query *parse = root->parse;
4535 tgl 2537 ECB : SetOperationStmt *topop;
2538 : Node *leftmostjtnode;
2539 : int leftmostRTI;
2540 : RangeTblEntry *leftmostRTE;
2541 : int childRTI;
2542 : RangeTblEntry *childRTE;
2543 : RangeTblRef *rtr;
2544 :
2545 : /* Shouldn't be called unless query has setops */
2238 peter_e 2546 GIC 2743 : topop = castNode(SetOperationStmt, parse->setOperations);
2547 2743 : Assert(topop);
2548 :
4535 tgl 2549 ECB : /* Can't optimize away a recursive UNION */
4535 tgl 2550 CBC 2743 : if (root->hasRecursion)
2551 2591 : return;
4535 tgl 2552 ECB :
2553 : /*
2554 : * Recursively check the tree of set operations. If not all UNION ALL
2555 : * with identical column types, punt.
2556 : */
4535 tgl 2557 GIC 2386 : if (!is_simple_union_all_recurse((Node *) topop, parse, topop->colTypes))
4535 tgl 2558 CBC 2234 : return;
2559 :
2560 : /*
2561 : * Locate the leftmost leaf query in the setops tree. The upper query's
2562 : * Vars all refer to this RTE (see transformSetOperationStmt).
2563 : */
4535 tgl 2564 GIC 152 : leftmostjtnode = topop->larg;
2565 224 : while (leftmostjtnode && IsA(leftmostjtnode, SetOperationStmt))
4535 tgl 2566 CBC 72 : leftmostjtnode = ((SetOperationStmt *) leftmostjtnode)->larg;
4535 tgl 2567 GIC 152 : Assert(leftmostjtnode && IsA(leftmostjtnode, RangeTblRef));
2568 152 : leftmostRTI = ((RangeTblRef *) leftmostjtnode)->rtindex;
2569 152 : leftmostRTE = rt_fetch(leftmostRTI, parse->rtable);
2570 152 : Assert(leftmostRTE->rtekind == RTE_SUBQUERY);
2571 :
2572 : /*
2573 : * Make a copy of the leftmost RTE and add it to the rtable. This copy
2574 : * will represent the leftmost leaf query in its capacity as a member of
2575 : * the appendrel. The original will represent the appendrel as a whole.
2576 : * (We must do things this way because the upper query's Vars have to be
2577 : * seen as referring to the whole appendrel.)
2578 : */
2579 152 : childRTE = copyObject(leftmostRTE);
2580 152 : parse->rtable = lappend(parse->rtable, childRTE);
2581 152 : childRTI = list_length(parse->rtable);
2582 :
2583 : /* Modify the setops tree to reference the child copy */
2584 152 : ((RangeTblRef *) leftmostjtnode)->rtindex = childRTI;
2585 :
2586 : /* Modify the formerly-leftmost RTE to mark it as an appendrel parent */
2587 152 : leftmostRTE->inh = true;
2588 :
2589 : /*
2590 : * Form a RangeTblRef for the appendrel, and insert it into FROM. The top
2591 : * Query of a setops tree should have had an empty FromClause initially.
2592 : */
2593 152 : rtr = makeNode(RangeTblRef);
2594 152 : rtr->rtindex = leftmostRTI;
2595 152 : Assert(parse->jointree->fromlist == NIL);
2596 152 : parse->jointree->fromlist = list_make1(rtr);
2597 :
2598 : /*
2599 : * Now pretend the query has no setops. We must do this before trying to
2600 : * do subquery pullup, because of Assert in pull_up_simple_subquery.
2601 : */
2602 152 : parse->setOperations = NULL;
2603 :
2604 : /*
2605 : * Build AppendRelInfo information, and apply pull_up_subqueries to the
2606 : * leaf queries of the UNION ALL. (We must do that now because they
2607 : * weren't previously referenced by the jointree, and so were missed by
2608 : * the main invocation of pull_up_subqueries.)
4535 tgl 2609 ECB : */
4535 tgl 2610 GIC 152 : pull_up_union_leaf_queries((Node *) topop, root, leftmostRTI, parse, 0);
2611 : }
2612 :
2613 :
2614 : /*
2615 : * reduce_outer_joins
2616 : * Attempt to reduce outer joins to plain inner joins.
2617 : *
2618 : * The idea here is that given a query like
2619 : * SELECT ... FROM a LEFT JOIN b ON (...) WHERE b.y = 42;
2620 : * we can reduce the LEFT JOIN to a plain JOIN if the "=" operator in WHERE
2621 : * is strict. The strict operator will always return NULL, causing the outer
2622 : * WHERE to fail, on any row where the LEFT JOIN filled in NULLs for b's
2623 : * columns. Therefore, there's no need for the join to produce null-extended
7364 tgl 2624 ECB : * rows in the first place --- which makes it a plain join not an outer join.
2625 : * (This scenario may not be very likely in a query written out by hand, but
2626 : * it's reasonably likely when pushing quals down into complex views.)
2627 : *
7364 tgl 2628 EUB : * More generally, an outer join can be reduced in strength if there is a
2629 : * strict qual above it in the qual tree that constrains a Var from the
7364 tgl 2630 ECB : * nullable side of the join to be non-null. (For FULL joins this applies
2631 : * to each side separately.)
2632 : *
5351 2633 : * Another transformation we apply here is to recognize cases like
2634 : * SELECT ... FROM a LEFT JOIN b ON (a.x = b.y) WHERE b.y IS NULL;
2635 : * If the join clause is strict for b.y, then only null-extended rows could
2636 : * pass the upper WHERE, and we can conclude that what the query is really
2637 : * specifying is an anti-semijoin. We change the join type from JOIN_LEFT
2638 : * to JOIN_ANTI. The IS NULL clause then becomes redundant, and must be
2639 : * removed to prevent bogus selectivity calculations, but we leave it to
2640 : * distribute_qual_to_rels to get rid of such clauses.
2641 : *
2642 : * Also, we get rid of JOIN_RIGHT cases by flipping them around to become
2643 : * JOIN_LEFT. This saves some code here and in some later planner routines;
2644 : * the main benefit is to reduce the number of jointypes that can appear in
2645 : * SpecialJoinInfo nodes. Note that we can still generate Paths and Plans
2646 : * that use JOIN_RIGHT (or JOIN_RIGHT_ANTI) by switching the inputs again.
2647 : *
7364 2648 : * To ease recognition of strict qual clauses, we require this routine to be
2649 : * run after expression preprocessing (i.e., qual canonicalization and JOIN
2650 : * alias-var expansion).
2651 : */
2652 : void
6517 tgl 2653 CBC 12570 : reduce_outer_joins(PlannerInfo *root)
2654 : {
2655 : reduce_outer_joins_pass1_state *state1;
2656 : reduce_outer_joins_pass2_state state2;
2657 : ListCell *lc;
2658 :
2659 : /*
2660 : * To avoid doing strictness checks on more quals than necessary, we want
2661 : * to stop descending the jointree as soon as there are no outer joins
2662 : * below our current point. This consideration forces a two-pass process.
6385 bruce 2663 ECB : * The first pass gathers information about which base rels appear below
2664 : * each side of each join clause, and about whether there are outer
2665 : * join(s) below each side of each join clause. The second pass examines
2666 : * qual clauses and changes join types as it descends the tree.
2667 : */
69 tgl 2668 GNC 12570 : state1 = reduce_outer_joins_pass1((Node *) root->parse->jointree);
7364 tgl 2669 ECB :
2670 : /* planner.c shouldn't have called me if no outer joins */
69 tgl 2671 GNC 12570 : if (state1 == NULL || !state1->contains_outer)
7198 tgl 2672 LBC 0 : elog(ERROR, "so where are the outer joins?");
7364 tgl 2673 ECB :
69 tgl 2674 GNC 12570 : state2.inner_reduced = NULL;
2675 12570 : state2.partial_reduced = NIL;
2676 :
6517 tgl 2677 GIC 12570 : reduce_outer_joins_pass2((Node *) root->parse->jointree,
2678 : state1, &state2,
2679 : root, NULL, NIL);
2680 :
2681 : /*
2682 : * If we successfully reduced the strength of any outer joins, we must
2683 : * remove references to those joins as nulling rels. This is handled as
2684 : * an additional pass, for simplicity and because we can handle all
2685 : * fully-reduced joins in a single pass over the parse tree.
2686 : */
69 tgl 2687 GNC 12570 : if (!bms_is_empty(state2.inner_reduced))
2688 : {
2689 651 : root->parse = (Query *)
2690 651 : remove_nulling_relids((Node *) root->parse,
2691 651 : state2.inner_reduced,
2692 : NULL);
2693 : /* There could be references in the append_rel_list, too */
2694 651 : root->append_rel_list = (List *)
2695 651 : remove_nulling_relids((Node *) root->append_rel_list,
2696 651 : state2.inner_reduced,
2697 : NULL);
2698 : }
2699 :
2700 : /*
2701 : * Partially-reduced full joins have to be done one at a time, since
2702 : * they'll each need a different setting of except_relids.
2703 : */
2704 12595 : foreach(lc, state2.partial_reduced)
2705 : {
2706 25 : reduce_outer_joins_partial_state *statep = lfirst(lc);
2707 25 : Relids full_join_relids = bms_make_singleton(statep->full_join_rti);
2708 :
2709 25 : root->parse = (Query *)
2710 25 : remove_nulling_relids((Node *) root->parse,
2711 : full_join_relids,
2712 25 : statep->unreduced_side);
2713 25 : root->append_rel_list = (List *)
2714 25 : remove_nulling_relids((Node *) root->append_rel_list,
2715 : full_join_relids,
2716 25 : statep->unreduced_side);
2717 : }
7364 tgl 2718 GIC 12570 : }
7364 tgl 2719 ECB :
2720 : /*
2721 : * reduce_outer_joins_pass1 - phase 1 data collection
2722 : *
2723 : * Returns a state node describing the given jointree node.
2724 : */
2725 : static reduce_outer_joins_pass1_state *
7364 tgl 2726 GIC 70991 : reduce_outer_joins_pass1(Node *jtnode)
7364 tgl 2727 ECB : {
2728 : reduce_outer_joins_pass1_state *result;
2729 :
2730 : result = (reduce_outer_joins_pass1_state *)
69 tgl 2731 GNC 70991 : palloc(sizeof(reduce_outer_joins_pass1_state));
7364 tgl 2732 CBC 70991 : result->relids = NULL;
2733 70991 : result->contains_outer = false;
2734 70991 : result->sub_states = NIL;
7364 tgl 2735 ECB :
7364 tgl 2736 GIC 70991 : if (jtnode == NULL)
7364 tgl 2737 LBC 0 : return result;
7364 tgl 2738 GBC 70991 : if (IsA(jtnode, RangeTblRef))
7364 tgl 2739 ECB : {
7364 tgl 2740 GIC 35568 : int varno = ((RangeTblRef *) jtnode)->rtindex;
7364 tgl 2741 ECB :
7364 tgl 2742 GIC 35568 : result->relids = bms_make_singleton(varno);
7364 tgl 2743 ECB : }
7364 tgl 2744 GIC 35423 : else if (IsA(jtnode, FromExpr))
7364 tgl 2745 ECB : {
7364 tgl 2746 GIC 13504 : FromExpr *f = (FromExpr *) jtnode;
6892 neilc 2747 ECB : ListCell *l;
2748 :
7364 tgl 2749 GIC 28087 : foreach(l, f->fromlist)
7364 tgl 2750 ECB : {
2751 : reduce_outer_joins_pass1_state *sub_state;
2752 :
7364 tgl 2753 GIC 14583 : sub_state = reduce_outer_joins_pass1(lfirst(l));
7364 tgl 2754 CBC 29166 : result->relids = bms_add_members(result->relids,
2755 14583 : sub_state->relids);
2756 14583 : result->contains_outer |= sub_state->contains_outer;
2757 14583 : result->sub_states = lappend(result->sub_states, sub_state);
7364 tgl 2758 ECB : }
2759 : }
7364 tgl 2760 GIC 21919 : else if (IsA(jtnode, JoinExpr))
7364 tgl 2761 ECB : {
7364 tgl 2762 GIC 21919 : JoinExpr *j = (JoinExpr *) jtnode;
2763 : reduce_outer_joins_pass1_state *sub_state;
2764 :
2765 : /* join's own RT index is not wanted in result->relids */
2766 21919 : if (IS_OUTER_JOIN(j->jointype))
7364 tgl 2767 CBC 18749 : result->contains_outer = true;
7364 tgl 2768 ECB :
7364 tgl 2769 GIC 21919 : sub_state = reduce_outer_joins_pass1(j->larg);
7364 tgl 2770 CBC 43838 : result->relids = bms_add_members(result->relids,
2771 21919 : sub_state->relids);
2772 21919 : result->contains_outer |= sub_state->contains_outer;
2773 21919 : result->sub_states = lappend(result->sub_states, sub_state);
7364 tgl 2774 ECB :
7364 tgl 2775 GIC 21919 : sub_state = reduce_outer_joins_pass1(j->rarg);
7364 tgl 2776 CBC 43838 : result->relids = bms_add_members(result->relids,
2777 21919 : sub_state->relids);
2778 21919 : result->contains_outer |= sub_state->contains_outer;
2779 21919 : result->sub_states = lappend(result->sub_states, sub_state);
7364 tgl 2780 ECB : }
2781 : else
7198 tgl 2782 UIC 0 : elog(ERROR, "unrecognized node type: %d",
7198 tgl 2783 EUB : (int) nodeTag(jtnode));
7364 tgl 2784 GIC 70991 : return result;
7364 tgl 2785 ECB : }
2786 :
2787 : /*
2788 : * reduce_outer_joins_pass2 - phase 2 processing
2789 : *
2790 : * jtnode: current jointree node
2791 : * state1: state data collected by phase 1 for this node
2792 : * state2: where to accumulate info about successfully-reduced joins
2793 : * root: toplevel planner state
2794 : * nonnullable_rels: set of base relids forced non-null by upper quals
2795 : * forced_null_vars: multibitmapset of Vars forced null by upper quals
2796 : *
2797 : * Returns info in state2 about outer joins that were successfully simplified.
2798 : * Joins that were fully reduced to inner joins are all added to
2799 : * state2->inner_reduced. If a full join is reduced to a left join,
2800 : * it needs its own entry in state2->partial_reduced, since that will
2801 : * require custom processing to remove only the correct nullingrel markers.
2802 : */
2803 : static void
7364 tgl 2804 GIC 32157 : reduce_outer_joins_pass2(Node *jtnode,
2805 : reduce_outer_joins_pass1_state *state1,
2806 : reduce_outer_joins_pass2_state *state2,
2807 : PlannerInfo *root,
2808 : Relids nonnullable_rels,
2809 : List *forced_null_vars)
2810 : {
7364 tgl 2811 ECB : /*
2812 : * pass 2 should never descend as far as an empty subnode or base rel,
2813 : * because it's only called on subtrees marked as contains_outer.
2814 : */
7364 tgl 2815 GIC 32157 : if (jtnode == NULL)
7198 tgl 2816 UIC 0 : elog(ERROR, "reached empty jointree");
7364 tgl 2817 GIC 32157 : if (IsA(jtnode, RangeTblRef))
7198 tgl 2818 UIC 0 : elog(ERROR, "reached base rel");
7364 tgl 2819 GIC 32157 : else if (IsA(jtnode, FromExpr))
2820 : {
2821 13131 : FromExpr *f = (FromExpr *) jtnode;
6892 neilc 2822 ECB : ListCell *l;
6892 neilc 2823 EUB : ListCell *s;
5351 tgl 2824 ECB : Relids pass_nonnullable_rels;
2825 : List *pass_forced_null_vars;
2826 :
2827 : /* Scan quals to see if we can add any constraints */
5351 tgl 2828 GIC 13131 : pass_nonnullable_rels = find_nonnullable_rels(f->quals);
2829 13131 : pass_nonnullable_rels = bms_add_members(pass_nonnullable_rels,
2830 : nonnullable_rels);
5351 tgl 2831 CBC 13131 : pass_forced_null_vars = find_forced_null_vars(f->quals);
144 tgl 2832 GNC 13131 : pass_forced_null_vars = mbms_add_members(pass_forced_null_vars,
2833 : forced_null_vars);
7364 tgl 2834 ECB : /* And recurse --- but only into interesting subtrees */
69 tgl 2835 GNC 13131 : Assert(list_length(f->fromlist) == list_length(state1->sub_states));
2836 27278 : forboth(l, f->fromlist, s, state1->sub_states)
2837 : {
2838 14147 : reduce_outer_joins_pass1_state *sub_state = lfirst(s);
7364 tgl 2839 ECB :
7364 tgl 2840 GIC 14147 : if (sub_state->contains_outer)
69 tgl 2841 GNC 13146 : reduce_outer_joins_pass2(lfirst(l), sub_state,
2842 : state2, root,
2843 : pass_nonnullable_rels,
5351 tgl 2844 ECB : pass_forced_null_vars);
2845 : }
5351 tgl 2846 GIC 13131 : bms_free(pass_nonnullable_rels);
2847 : /* can't so easily clean up var lists, unfortunately */
2848 : }
7364 tgl 2849 CBC 19026 : else if (IsA(jtnode, JoinExpr))
2850 : {
7364 tgl 2851 GIC 19026 : JoinExpr *j = (JoinExpr *) jtnode;
7364 tgl 2852 CBC 19026 : int rtindex = j->rtindex;
7364 tgl 2853 GIC 19026 : JoinType jointype = j->jointype;
69 tgl 2854 GNC 19026 : reduce_outer_joins_pass1_state *left_state = linitial(state1->sub_states);
2855 19026 : reduce_outer_joins_pass1_state *right_state = lsecond(state1->sub_states);
7364 tgl 2856 ECB :
2857 : /* Can we simplify this join? */
7364 tgl 2858 GIC 19026 : switch (jointype)
7364 tgl 2859 ECB : {
5351 tgl 2860 GIC 259 : case JOIN_INNER:
5351 tgl 2861 CBC 259 : break;
7364 2862 17702 : case JOIN_LEFT:
2863 17702 : if (bms_overlap(nonnullable_rels, right_state->relids))
2864 692 : jointype = JOIN_INNER;
2865 17702 : break;
2866 437 : case JOIN_RIGHT:
2867 437 : if (bms_overlap(nonnullable_rels, left_state->relids))
2868 25 : jointype = JOIN_INNER;
2869 437 : break;
2870 470 : case JOIN_FULL:
2871 470 : if (bms_overlap(nonnullable_rels, left_state->relids))
7364 tgl 2872 ECB : {
7364 tgl 2873 GIC 12 : if (bms_overlap(nonnullable_rels, right_state->relids))
7364 tgl 2874 CBC 6 : jointype = JOIN_INNER;
7364 tgl 2875 ECB : else
2876 : {
7364 tgl 2877 GIC 6 : jointype = JOIN_LEFT;
2878 : /* Also report partial reduction in state2 */
69 tgl 2879 GNC 6 : report_reduced_full_join(state2, rtindex,
2880 : right_state->relids);
2881 : }
2882 : }
7364 tgl 2883 ECB : else
2884 : {
7364 tgl 2885 CBC 458 : if (bms_overlap(nonnullable_rels, right_state->relids))
2886 : {
7364 tgl 2887 GIC 19 : jointype = JOIN_RIGHT;
2888 : /* Also report partial reduction in state2 */
69 tgl 2889 GNC 19 : report_reduced_full_join(state2, rtindex,
2890 : left_state->relids);
2891 : }
2892 : }
7364 tgl 2893 GIC 470 : break;
5156 2894 158 : case JOIN_SEMI:
2895 : case JOIN_ANTI:
5050 bruce 2896 ECB :
2897 : /*
5156 tgl 2898 : * These could only have been introduced by pull_up_sublinks,
2899 : * so there's no way that upper quals could refer to their
2900 : * righthand sides, and no point in checking. We don't expect
2901 : * to see JOIN_RIGHT_ANTI yet.
2902 : */
5156 tgl 2903 GIC 158 : break;
7364 tgl 2904 UIC 0 : default:
5351 tgl 2905 LBC 0 : elog(ERROR, "unrecognized join type: %d",
5351 tgl 2906 ECB : (int) jointype);
2907 : break;
2908 : }
2909 :
2910 : /*
2911 : * Convert JOIN_RIGHT to JOIN_LEFT. Note that in the case where we
2912 : * reduced JOIN_FULL to JOIN_RIGHT, this will mean the JoinExpr no
2913 : * longer matches the internal ordering of any CoalesceExpr's built to
2914 : * represent merged join variables. We don't care about that at
2915 : * present, but be wary of it ...
5351 tgl 2916 EUB : */
5351 tgl 2917 GBC 19026 : if (jointype == JOIN_RIGHT)
2918 : {
2919 : Node *tmparg;
2920 :
5351 tgl 2921 GIC 431 : tmparg = j->larg;
2922 431 : j->larg = j->rarg;
2923 431 : j->rarg = tmparg;
2924 431 : jointype = JOIN_LEFT;
69 tgl 2925 GNC 431 : right_state = linitial(state1->sub_states);
2926 431 : left_state = lsecond(state1->sub_states);
2927 : }
2928 :
5351 tgl 2929 ECB : /*
2930 : * See if we can reduce JOIN_LEFT to JOIN_ANTI. This is the case if
2931 : * the join's own quals are strict for any var that was forced null by
2932 : * higher qual levels. NOTE: there are other ways that we could
5050 bruce 2933 : * detect an anti-join, in particular if we were to check whether Vars
2934 : * coming from the RHS must be non-null because of table constraints.
2935 : * That seems complicated and expensive though (in particular, one
2936 : * would have to be wary of lower outer joins). For the moment this
2937 : * seems sufficient.
5351 tgl 2938 : */
5351 tgl 2939 GIC 19026 : if (jointype == JOIN_LEFT)
2940 : {
2941 : List *nonnullable_vars;
2942 : Bitmapset *overlap;
2943 :
2944 : /* Find Vars in j->quals that must be non-null in joined rows */
155 tgl 2945 GNC 17447 : nonnullable_vars = find_nonnullable_vars(j->quals);
2946 :
2947 : /*
2948 : * It's not sufficient to check whether nonnullable_vars and
2949 : * forced_null_vars overlap: we need to know if the overlap
2950 : * includes any RHS variables.
2951 : */
144 2952 17447 : overlap = mbms_overlap_sets(nonnullable_vars, forced_null_vars);
2953 17447 : if (bms_overlap(overlap, right_state->relids))
5351 tgl 2954 GIC 481 : jointype = JOIN_ANTI;
5351 tgl 2955 ECB : }
2956 :
2957 : /*
2958 : * Apply the jointype change, if any, to both jointree node and RTE.
2959 : * Also, if we changed an RTE to INNER, add its RTI to inner_reduced.
2960 : */
5156 tgl 2961 GIC 19026 : if (rtindex && jointype != j->jointype)
2962 : {
6517 2963 1641 : RangeTblEntry *rte = rt_fetch(rtindex, root->parse->rtable);
2964 :
7364 tgl 2965 CBC 1641 : Assert(rte->rtekind == RTE_JOIN);
2966 1641 : Assert(rte->jointype == j->jointype);
5156 2967 1641 : rte->jointype = jointype;
69 tgl 2968 GNC 1641 : if (jointype == JOIN_INNER)
2969 723 : state2->inner_reduced = bms_add_member(state2->inner_reduced,
2970 : rtindex);
2971 : }
5156 tgl 2972 GIC 19026 : j->jointype = jointype;
2973 :
2974 : /* Only recurse if there's more to do below here */
7364 2975 19026 : if (left_state->contains_outer || right_state->contains_outer)
2976 : {
5351 tgl 2977 ECB : Relids local_nonnullable_rels;
2978 : List *local_forced_null_vars;
2979 : Relids pass_nonnullable_rels;
2980 : List *pass_forced_null_vars;
7364 2981 :
2982 : /*
5351 2983 : * If this join is (now) inner, we can add any constraints its
2984 : * quals provide to those we got from above. But if it is outer,
2985 : * we can pass down the local constraints only into the nullable
2986 : * side, because an outer join never eliminates any rows from its
2987 : * non-nullable side. Also, there is no point in passing upper
2988 : * constraints into the nullable side, since if there were any
2989 : * we'd have been able to reduce the join. (In the case of upper
5050 bruce 2990 : * forced-null constraints, we *must not* pass them into the
2991 : * nullable side --- they either applied here, or not.) The upshot
2992 : * is that we pass either the local or the upper constraints,
2993 : * never both, to the children of an outer join.
2994 : *
2995 : * Note that a SEMI join works like an inner join here: it's okay
2996 : * to pass down both local and upper constraints. (There can't be
2997 : * any upper constraints affecting its inner side, but it's not
2998 : * worth having a separate code path to avoid passing them.)
2999 : *
3000 : * At a FULL join we just punt and pass nothing down --- is it
3001 : * possible to be smarter?
3002 : */
7363 tgl 3003 GIC 6411 : if (jointype != JOIN_FULL)
3004 : {
5351 3005 6343 : local_nonnullable_rels = find_nonnullable_rels(j->quals);
3006 6343 : local_forced_null_vars = find_forced_null_vars(j->quals);
4452 3007 6343 : if (jointype == JOIN_INNER || jointype == JOIN_SEMI)
3008 : {
3009 : /* OK to merge upper and local constraints */
5351 3010 423 : local_nonnullable_rels = bms_add_members(local_nonnullable_rels,
3011 : nonnullable_rels);
144 tgl 3012 GNC 423 : local_forced_null_vars = mbms_add_members(local_forced_null_vars,
3013 : forced_null_vars);
5351 tgl 3014 ECB : }
3015 : }
7363 3016 : else
5351 3017 : {
3018 : /* no use in calculating these */
5351 tgl 3019 GIC 68 : local_nonnullable_rels = NULL;
3020 68 : local_forced_null_vars = NIL;
5351 tgl 3021 ECB : }
3022 :
7364 tgl 3023 CBC 6411 : if (left_state->contains_outer)
3024 : {
4452 tgl 3025 GIC 6114 : if (jointype == JOIN_INNER || jointype == JOIN_SEMI)
3026 : {
3027 : /* pass union of local and upper constraints */
5351 3028 328 : pass_nonnullable_rels = local_nonnullable_rels;
5351 tgl 3029 CBC 328 : pass_forced_null_vars = local_forced_null_vars;
5351 tgl 3030 ECB : }
4382 bruce 3031 GIC 5786 : else if (jointype != JOIN_FULL) /* ie, LEFT or ANTI */
3032 : {
5351 tgl 3033 ECB : /* can't pass local constraints to non-nullable side */
5351 tgl 3034 GIC 5732 : pass_nonnullable_rels = nonnullable_rels;
3035 5732 : pass_forced_null_vars = forced_null_vars;
3036 : }
7363 tgl 3037 ECB : else
5351 3038 : {
3039 : /* no constraints pass through JOIN_FULL */
5351 tgl 3040 CBC 54 : pass_nonnullable_rels = NULL;
5351 tgl 3041 GIC 54 : pass_forced_null_vars = NIL;
5351 tgl 3042 ECB : }
69 tgl 3043 GNC 6114 : reduce_outer_joins_pass2(j->larg, left_state,
3044 : state2, root,
3045 : pass_nonnullable_rels,
3046 : pass_forced_null_vars);
3047 : }
5351 tgl 3048 ECB :
7364 tgl 3049 CBC 6411 : if (right_state->contains_outer)
3050 : {
2118 3051 327 : if (jointype != JOIN_FULL) /* ie, INNER/LEFT/SEMI/ANTI */
3052 : {
3053 : /* pass appropriate constraints, per comment above */
5351 tgl 3054 GIC 313 : pass_nonnullable_rels = local_nonnullable_rels;
3055 313 : pass_forced_null_vars = local_forced_null_vars;
5351 tgl 3056 ECB : }
3057 : else
3058 : {
3059 : /* no constraints pass through JOIN_FULL */
5351 tgl 3060 GIC 14 : pass_nonnullable_rels = NULL;
5351 tgl 3061 CBC 14 : pass_forced_null_vars = NIL;
3062 : }
69 tgl 3063 GNC 327 : reduce_outer_joins_pass2(j->rarg, right_state,
3064 : state2, root,
3065 : pass_nonnullable_rels,
5351 tgl 3066 ECB : pass_forced_null_vars);
7363 3067 : }
5351 tgl 3068 GIC 6411 : bms_free(local_nonnullable_rels);
7364 tgl 3069 ECB : }
3070 : }
3071 : else
7198 tgl 3072 UIC 0 : elog(ERROR, "unrecognized node type: %d",
3073 : (int) nodeTag(jtnode));
7364 tgl 3074 CBC 32157 : }
3075 :
3076 : /* Helper for reduce_outer_joins_pass2 */
3077 : static void
69 tgl 3078 GNC 25 : report_reduced_full_join(reduce_outer_joins_pass2_state *state2,
3079 : int rtindex, Relids relids)
3080 : {
3081 : reduce_outer_joins_partial_state *statep;
3082 :
3083 25 : statep = palloc(sizeof(reduce_outer_joins_partial_state));
3084 25 : statep->full_join_rti = rtindex;
3085 25 : statep->unreduced_side = relids;
3086 25 : state2->partial_reduced = lappend(state2->partial_reduced, statep);
3087 25 : }
3088 :
3089 :
3090 : /*
1532 tgl 3091 EUB : * remove_useless_result_rtes
3092 : * Attempt to remove RTE_RESULT RTEs from the join tree.
3093 : * Also, elide single-child FromExprs where possible.
1532 tgl 3094 ECB : *
3095 : * We can remove RTE_RESULT entries from the join tree using the knowledge
3096 : * that RTE_RESULT returns exactly one row and has no output columns. Hence,
3097 : * if one is inner-joined to anything else, we can delete it. Optimizations
3098 : * are also possible for some outer-join cases, as detailed below.
3099 : *
3100 : * This pass also replaces single-child FromExprs with their child node
3101 : * where possible. It's appropriate to do that here and not earlier because
3102 : * RTE_RESULT removal might reduce a multiple-child FromExpr to have only one
3103 : * child. We can remove such a FromExpr if its quals are empty, or if it's
3104 : * semantically valid to merge the quals into those of the parent node.
3105 : * While removing unnecessary join tree nodes has some micro-efficiency value,
3106 : * the real reason to do this is to eliminate cases where the nullable side of
3107 : * an outer join node is a FromExpr whose single child is another outer join.
3108 : * To correctly determine whether the two outer joins can commute,
3109 : * deconstruct_jointree() must treat any quals of such a FromExpr as being
3110 : * degenerate quals of the upper outer join. The best way to do that is to
3111 : * make them actually *be* quals of the upper join, by dropping the FromExpr
3112 : * and hoisting the quals up into the upper join's quals. (Note that there is
3113 : * no hazard when the intermediate FromExpr has multiple children, since then
3114 : * it represents an inner join that cannot commute with the upper outer join.)
3115 : * As long as we have to do that, we might as well elide such FromExprs
3116 : * everywhere.
3117 : *
3118 : * Some of these optimizations depend on recognizing empty (constant-true)
3119 : * quals for FromExprs and JoinExprs. That makes it useful to apply this
3120 : * optimization pass after expression preprocessing, since that will have
3121 : * eliminated constant-true quals, allowing more cases to be recognized as
3122 : * optimizable. What's more, the usual reason for an RTE_RESULT to be present
3123 : * is that we pulled up a subquery or VALUES clause, thus very possibly
3124 : * replacing Vars with constants, making it more likely that a qual can be
3125 : * reduced to constant true. Also, because some optimizations depend on
3126 : * the outer-join type, it's best to have done reduce_outer_joins() first.
3127 : *
3128 : * A PlaceHolderVar referencing an RTE_RESULT RTE poses an obstacle to this
3129 : * process: we must remove the RTE_RESULT's relid from the PHV's phrels, but
3130 : * we must not reduce the phrels set to empty. If that would happen, and
3131 : * the RTE_RESULT is an immediate child of an outer join, we have to give up
3132 : * and not remove the RTE_RESULT: there is noplace else to evaluate the
3133 : * PlaceHolderVar. (That is, in such cases the RTE_RESULT *does* have output
3134 : * columns.) But if the RTE_RESULT is an immediate child of an inner join,
3135 : * we can usually change the PlaceHolderVar's phrels so as to evaluate it at
3136 : * the inner join instead. This is OK because we really only care that PHVs
3137 : * are evaluated above or below the correct outer joins. We can't, however,
3138 : * postpone the evaluation of a PHV to above where it is used; so there are
3139 : * some checks below on whether output PHVs are laterally referenced in the
3140 : * other join input rel(s).
3141 : *
3142 : * We used to try to do this work as part of pull_up_subqueries() where the
3143 : * potentially-optimizable cases get introduced; but it's way simpler, and
3144 : * more effective, to do it separately.
3145 : */
3146 : void
1532 tgl 3147 GIC 108355 : remove_useless_result_rtes(PlannerInfo *root)
3148 : {
69 tgl 3149 GNC 108355 : Relids dropped_outer_joins = NULL;
3150 : ListCell *cell;
3151 :
3152 : /* Top level of jointree must always be a FromExpr */
1532 tgl 3153 GIC 108355 : Assert(IsA(root->parse->jointree, FromExpr));
3154 : /* Recurse ... */
3155 216710 : root->parse->jointree = (FromExpr *)
69 tgl 3156 GNC 108355 : remove_useless_results_recurse(root,
3157 108355 : (Node *) root->parse->jointree,
3158 : NULL,
3159 : &dropped_outer_joins);
3160 : /* We should still have a FromExpr */
1532 tgl 3161 GIC 108355 : Assert(IsA(root->parse->jointree, FromExpr));
3162 :
3163 : /*
3164 : * If we removed any outer-join nodes from the jointree, run around and
3165 : * remove references to those joins as nulling rels. (There could be such
3166 : * references in PHVs that we pulled up out of the original subquery that
3167 : * the RESULT rel replaced. This is kosher on the grounds that we now
3168 : * know that such an outer join wouldn't really have nulled anything.) We
3169 : * don't do this during the main recursion, for simplicity and because we
3170 : * can handle all such joins in a single pass over the parse tree.
3171 : */
69 tgl 3172 GNC 108355 : if (!bms_is_empty(dropped_outer_joins))
3173 : {
3174 24 : root->parse = (Query *)
3175 24 : remove_nulling_relids((Node *) root->parse,
3176 : dropped_outer_joins,
3177 : NULL);
3178 : /* There could be references in the append_rel_list, too */
3179 24 : root->append_rel_list = (List *)
3180 24 : remove_nulling_relids((Node *) root->append_rel_list,
3181 : dropped_outer_joins,
3182 : NULL);
3183 : }
3184 :
3185 : /*
3186 : * Remove any PlanRowMark referencing an RTE_RESULT RTE. We obviously
3187 : * must do that for any RTE_RESULT that we just removed. But one for a
3188 : * RTE that we did not remove can be dropped anyway: since the RTE has
3189 : * only one possible output row, there is no need for EPQ to mark and
3190 : * restore that row.
3191 : *
3192 : * It's necessary, not optional, to remove the PlanRowMark for a surviving
3193 : * RTE_RESULT RTE; otherwise we'll generate a whole-row Var for the
3194 : * RTE_RESULT, which the executor has no support for.
3195 : */
1364 tgl 3196 GIC 108549 : foreach(cell, root->rowMarks)
3197 : {
1532 3198 194 : PlanRowMark *rc = (PlanRowMark *) lfirst(cell);
3199 :
3200 194 : if (rt_fetch(rc->rti, root->parse->rtable)->rtekind == RTE_RESULT)
1364 3201 10 : root->rowMarks = foreach_delete_current(root->rowMarks, cell);
3202 : }
1532 3203 108355 : }
3204 :
3205 : /*
3206 : * remove_useless_results_recurse
3207 : * Recursive guts of remove_useless_result_rtes.
3208 : *
3209 : * This recursively processes the jointree and returns a modified jointree.
3210 : * In addition, the RT indexes of any removed outer-join nodes are added to
3211 : * *dropped_outer_joins.
3212 : *
3213 : * jtnode is the current jointree node. If it could be valid to merge
3214 : * its quals into those of the parent node, parent_quals should point to
3215 : * the parent's quals list; otherwise, pass NULL for parent_quals.
3216 : */
1532 tgl 3217 ECB : static Node *
69 tgl 3218 GNC 263678 : remove_useless_results_recurse(PlannerInfo *root, Node *jtnode,
3219 : Node **parent_quals,
3220 : Relids *dropped_outer_joins)
1532 tgl 3221 ECB : {
1532 tgl 3222 GIC 263678 : Assert(jtnode != NULL);
3223 263678 : if (IsA(jtnode, RangeTblRef))
3224 : {
1532 tgl 3225 ECB : /* Can't immediately do anything with a RangeTblRef */
3226 : }
1532 tgl 3227 CBC 131757 : else if (IsA(jtnode, FromExpr))
1532 tgl 3228 ECB : {
1532 tgl 3229 CBC 109519 : FromExpr *f = (FromExpr *) jtnode;
1532 tgl 3230 GIC 109519 : Relids result_relids = NULL;
3231 : ListCell *cell;
3232 :
1532 tgl 3233 ECB : /*
3234 : * We can drop RTE_RESULT rels from the fromlist so long as at least
3235 : * one child remains, since joining to a one-row table changes
3236 : * nothing. (But we can't drop a RTE_RESULT that computes PHV(s) that
3237 : * are needed by some sibling. The cleanup transformation below would
3238 : * reassign the PHVs to be computed at the join, which is too late for
3239 : * the sibling's use.) The easiest way to mechanize this rule is to
3240 : * modify the list in-place.
3241 : */
1364 tgl 3242 GIC 220366 : foreach(cell, f->fromlist)
3243 : {
1532 tgl 3244 CBC 110847 : Node *child = (Node *) lfirst(cell);
3245 : int varno;
1532 tgl 3246 ECB :
3247 : /* Recursively transform child, allowing it to push up quals ... */
69 tgl 3248 GNC 110847 : child = remove_useless_results_recurse(root, child,
3249 : &f->quals,
3250 : dropped_outer_joins);
3251 : /* ... and stick it back into the tree */
1532 tgl 3252 GIC 110847 : lfirst(cell) = child;
1532 tgl 3253 ECB :
3254 : /*
3255 : * If it's an RTE_RESULT with at least one sibling, and no sibling
3256 : * references dependent PHVs, we can drop it. We don't yet know
3257 : * what the inner join's final relid set will be, so postpone
3258 : * cleanup of PHVs etc till after this loop.
3259 : */
1532 tgl 3260 GIC 112992 : if (list_length(f->fromlist) > 1 &&
1212 3261 2145 : (varno = get_result_relid(root, child)) != 0 &&
3262 132 : !find_dependent_phvs_in_jointree(root, (Node *) f, varno))
3263 : {
1364 3264 120 : f->fromlist = foreach_delete_current(f->fromlist, cell);
1532 3265 120 : result_relids = bms_add_member(result_relids, varno);
3266 : }
3267 : }
3268 :
3269 : /*
1532 tgl 3270 ECB : * Clean up if we dropped any RTE_RESULT RTEs. This is a bit
3271 : * inefficient if there's more than one, but it seems better to
3272 : * optimize the support code for the single-relid case.
3273 : */
1532 tgl 3274 CBC 109519 : if (result_relids)
1532 tgl 3275 ECB : {
1532 tgl 3276 GIC 114 : int varno = -1;
1532 tgl 3277 ECB :
1532 tgl 3278 GIC 234 : while ((varno = bms_next_member(result_relids, varno)) >= 0)
3279 120 : remove_result_refs(root, varno, (Node *) f);
3280 : }
3281 :
3282 : /*
3283 : * If the FromExpr now has only one child, see if we can elide it.
3284 : * This is always valid if there are no quals, except at the top of
3285 : * the jointree (since Query.jointree is required to point to a
3286 : * FromExpr). Otherwise, we can do it if we can push the quals up to
3287 : * the parent node.
3288 : *
3289 : * Note: while it would not be terribly hard to generalize this
3290 : * transformation to merge multi-child FromExprs into their parent
3291 : * FromExpr, that risks making the parent join too expensive to plan.
3292 : * We leave it to later processing to decide heuristically whether
3293 : * that's a good idea. Pulling up a single child is always OK,
3294 : * however.
3295 : */
69 tgl 3296 GNC 109519 : if (list_length(f->fromlist) == 1 &&
3297 108786 : f != root->parse->jointree &&
3298 1076 : (f->quals == NULL || parent_quals != NULL))
3299 : {
3300 : /*
3301 : * Merge any quals up to parent. They should be in implicit-AND
3302 : * format by now, so we just need to concatenate lists. Put the
3303 : * child quals at the front, on the grounds that they should
3304 : * nominally be evaluated earlier.
3305 : */
3306 528 : if (f->quals != NULL)
3307 492 : *parent_quals = (Node *)
3308 492 : list_concat(castNode(List, f->quals),
3309 492 : castNode(List, *parent_quals));
1532 tgl 3310 GIC 528 : return (Node *) linitial(f->fromlist);
3311 : }
1532 tgl 3312 ECB : }
1532 tgl 3313 GIC 22238 : else if (IsA(jtnode, JoinExpr))
3314 : {
3315 22238 : JoinExpr *j = (JoinExpr *) jtnode;
1532 tgl 3316 ECB : int varno;
3317 :
3318 : /*
3319 : * First, recurse. We can accept pushed-up FromExpr quals from either
3320 : * child if the jointype is INNER, and we can accept them from the RHS
3321 : * child if the jointype is LEFT.
3322 : */
69 tgl 3323 GNC 22238 : j->larg = remove_useless_results_recurse(root, j->larg,
3324 22238 : (j->jointype == JOIN_INNER) ?
3325 : &j->quals : NULL,
3326 : dropped_outer_joins);
3327 22238 : j->rarg = remove_useless_results_recurse(root, j->rarg,
3328 22238 : (j->jointype == JOIN_INNER ||
3329 18263 : j->jointype == JOIN_LEFT) ?
3330 : &j->quals : NULL,
3331 : dropped_outer_joins);
1532 tgl 3332 ECB :
3333 : /* Apply join-type-specific optimization rules */
1532 tgl 3334 CBC 22238 : switch (j->jointype)
1532 tgl 3335 ECB : {
1532 tgl 3336 GIC 3975 : case JOIN_INNER:
3337 :
3338 : /*
3339 : * An inner join is equivalent to a FromExpr, so if either
3340 : * side was simplified to an RTE_RESULT rel, we can replace
3341 : * the join with a FromExpr with just the other side.
3342 : * Furthermore, we can elide that FromExpr according to the
3343 : * same rules as above.
3344 : *
3345 : * Just as in the FromExpr case, we can't simplify if the
3346 : * other input rel references any PHVs that are marked as to
1212 tgl 3347 ECB : * be evaluated at the RTE_RESULT rel, because we can't
3348 : * postpone their evaluation in that case. But we only have
3349 : * to check this in cases where it's syntactically legal for
3350 : * the other input to have a LATERAL reference to the
3351 : * RTE_RESULT rel. Only RHSes of inner and left joins are
3352 : * allowed to have such refs.
1532 3353 : */
1212 tgl 3354 GIC 3975 : if ((varno = get_result_relid(root, j->larg)) != 0 &&
3355 21 : !find_dependent_phvs_in_jointree(root, j->rarg, varno))
3356 : {
1532 tgl 3357 CBC 21 : remove_result_refs(root, varno, j->rarg);
69 tgl 3358 GNC 21 : if (j->quals != NULL && parent_quals == NULL)
1532 tgl 3359 GIC 6 : jtnode = (Node *)
3360 6 : makeFromExpr(list_make1(j->rarg), j->quals);
3361 : else
3362 : {
3363 : /* Merge any quals up to parent */
69 tgl 3364 GNC 15 : if (j->quals != NULL)
3365 6 : *parent_quals = (Node *)
3366 6 : list_concat(castNode(List, j->quals),
3367 6 : castNode(List, *parent_quals));
1532 tgl 3368 GIC 15 : jtnode = j->rarg;
3369 : }
3370 : }
3371 3954 : else if ((varno = get_result_relid(root, j->rarg)) != 0)
1532 tgl 3372 ECB : {
1532 tgl 3373 CBC 115 : remove_result_refs(root, varno, j->larg);
69 tgl 3374 GNC 115 : if (j->quals != NULL && parent_quals == NULL)
1532 tgl 3375 GIC 8 : jtnode = (Node *)
1532 tgl 3376 CBC 8 : makeFromExpr(list_make1(j->larg), j->quals);
1532 tgl 3377 ECB : else
3378 : {
3379 : /* Merge any quals up to parent */
69 tgl 3380 GNC 107 : if (j->quals != NULL)
3381 88 : *parent_quals = (Node *)
3382 88 : list_concat(castNode(List, j->quals),
3383 88 : castNode(List, *parent_quals));
1532 tgl 3384 GIC 107 : jtnode = j->larg;
3385 : }
3386 : }
3387 3975 : break;
3388 16966 : case JOIN_LEFT:
3389 :
3390 : /*
3391 : * We can simplify this case if the RHS is an RTE_RESULT, with
3392 : * two different possibilities:
1532 tgl 3393 ECB : *
3394 : * If the qual is empty (JOIN ON TRUE), then the join can be
3395 : * strength-reduced to a plain inner join, since each LHS row
3396 : * necessarily has exactly one join partner. So we can always
3397 : * discard the RHS, much as in the JOIN_INNER case above.
1212 3398 : * (Again, the LHS could not contain a lateral reference to
3399 : * the RHS.)
3400 : *
3401 : * Otherwise, it's still true that each LHS row should be
3402 : * returned exactly once, and since the RHS returns no columns
3403 : * (unless there are PHVs that have to be evaluated there), we
3404 : * don't much care if it's null-extended or not. So in this
3405 : * case also, we can just ignore the qual and discard the left
3406 : * join.
3407 : */
1532 tgl 3408 GIC 16966 : if ((varno = get_result_relid(root, j->rarg)) != 0 &&
3409 57 : (j->quals == NULL ||
1212 3410 33 : !find_dependent_phvs(root, varno)))
3411 : {
1532 3412 24 : remove_result_refs(root, varno, j->larg);
69 tgl 3413 GNC 24 : *dropped_outer_joins = bms_add_member(*dropped_outer_joins,
3414 : j->rtindex);
1532 tgl 3415 GIC 24 : jtnode = j->larg;
3416 : }
1532 tgl 3417 CBC 16966 : break;
3418 237 : case JOIN_SEMI:
1532 tgl 3419 ECB :
3420 : /*
3421 : * We may simplify this case if the RHS is an RTE_RESULT; the
3422 : * join qual becomes effectively just a filter qual for the
3423 : * LHS, since we should either return the LHS row or not. The
3424 : * filter clause must go into a new FromExpr if we can't push
3425 : * it up to the parent.
3426 : *
3427 : * There is a fine point about PHVs that are supposed to be
131 3428 : * evaluated at the RHS. Such PHVs could only appear in the
3429 : * semijoin's qual, since the rest of the query cannot
3430 : * reference any outputs of the semijoin's RHS. Therefore,
3431 : * they can't actually go to null before being examined, and
3432 : * it'd be OK to just remove the PHV wrapping. We don't have
3433 : * infrastructure for that, but remove_result_refs() will
3434 : * relabel them as to be evaluated at the LHS, which is fine.
3435 : *
3436 : * Also, we don't need to worry about removing traces of the
3437 : * join's rtindex, since it hasn't got one.
1532 3438 : */
1532 tgl 3439 GIC 237 : if ((varno = get_result_relid(root, j->rarg)) != 0)
1532 tgl 3440 ECB : {
69 tgl 3441 GNC 12 : Assert(j->rtindex == 0);
1532 tgl 3442 GIC 12 : remove_result_refs(root, varno, j->larg);
69 tgl 3443 GNC 12 : if (j->quals != NULL && parent_quals == NULL)
1532 tgl 3444 UIC 0 : jtnode = (Node *)
3445 0 : makeFromExpr(list_make1(j->larg), j->quals);
3446 : else
3447 : {
3448 : /* Merge any quals up to parent */
69 tgl 3449 GNC 12 : if (j->quals != NULL)
3450 12 : *parent_quals = (Node *)
3451 12 : list_concat(castNode(List, j->quals),
3452 12 : castNode(List, *parent_quals));
1532 tgl 3453 GIC 12 : jtnode = j->larg;
3454 : }
3455 : }
1532 tgl 3456 CBC 237 : break;
3457 1060 : case JOIN_FULL:
3458 : case JOIN_ANTI:
3459 : /* We have no special smarts for these cases */
3460 1060 : break;
1532 tgl 3461 LBC 0 : default:
131 tgl 3462 ECB : /* Note: JOIN_RIGHT should be gone at this point */
1532 tgl 3463 UIC 0 : elog(ERROR, "unrecognized join type: %d",
3464 : (int) j->jointype);
3465 : break;
3466 : }
1532 tgl 3467 ECB : }
3468 : else
1532 tgl 3469 LBC 0 : elog(ERROR, "unrecognized node type: %d",
3470 : (int) nodeTag(jtnode));
1532 tgl 3471 GIC 263150 : return jtnode;
3472 : }
3473 :
3474 : /*
3475 : * get_result_relid
3476 : * If jtnode is a RangeTblRef for an RTE_RESULT RTE, return its relid;
3477 : * otherwise return 0.
3478 : */
3479 : static int
3480 27277 : get_result_relid(PlannerInfo *root, Node *jtnode)
3481 : {
3482 : int varno;
3483 :
3484 27277 : if (!IsA(jtnode, RangeTblRef))
3485 2508 : return 0;
3486 24769 : varno = ((RangeTblRef *) jtnode)->rtindex;
1532 tgl 3487 CBC 24769 : if (rt_fetch(varno, root->parse->rtable)->rtekind != RTE_RESULT)
3488 24432 : return 0;
1532 tgl 3489 GIC 337 : return varno;
1532 tgl 3490 ECB : }
3491 :
3492 : /*
3493 : * remove_result_refs
3494 : * Helper routine for dropping an unneeded RTE_RESULT RTE.
3495 : *
3496 : * This doesn't physically remove the RTE from the jointree, because that's
3497 : * more easily handled in remove_useless_results_recurse. What it does do
3498 : * is the necessary cleanup in the rest of the tree: we must adjust any PHVs
3499 : * that may reference the RTE. Be sure to call this at a point where the
3500 : * jointree is valid (no disconnected nodes).
3501 : *
3502 : * Note that we don't need to process the append_rel_list, since RTEs
3503 : * referenced directly in the jointree won't be appendrel members.
3504 : *
3505 : * varno is the RTE_RESULT's relid.
3506 : * newjtloc is the jointree location at which any PHVs referencing the
3507 : * RTE_RESULT should be evaluated instead.
3508 : */
3509 : static void
1532 tgl 3510 GIC 292 : remove_result_refs(PlannerInfo *root, int varno, Node *newjtloc)
3511 : {
3512 : /* Fix up PlaceHolderVars as needed */
1532 tgl 3513 ECB : /* If there are no PHVs anywhere, we can skip this bit */
1532 tgl 3514 CBC 292 : if (root->glob->lastPHId != 0)
1532 tgl 3515 ECB : {
3516 : Relids subrelids;
3517 :
69 tgl 3518 GNC 69 : subrelids = get_relids_in_jointree(newjtloc, true, false);
1532 tgl 3519 GIC 69 : Assert(!bms_is_empty(subrelids));
1532 tgl 3520 CBC 69 : substitute_phv_relids((Node *) root->parse, varno, subrelids);
108 tgl 3521 GNC 69 : fix_append_rel_relids(root, varno, subrelids);
3522 : }
3523 :
3524 : /*
3525 : * We also need to remove any PlanRowMark referencing the RTE, but we
3526 : * postpone that work until we return to remove_useless_result_rtes.
3527 : */
1532 tgl 3528 GIC 292 : }
3529 :
3530 :
3531 : /*
3532 : * find_dependent_phvs - are there any PlaceHolderVars whose relids are
3533 : * exactly the given varno?
3534 : *
3535 : * find_dependent_phvs should be used when we want to see if there are
3536 : * any such PHVs anywhere in the Query. Another use-case is to see if
3537 : * a subtree of the join tree contains such PHVs; but for that, we have
3538 : * to look not only at the join tree nodes themselves but at the
3539 : * referenced RTEs. For that, use find_dependent_phvs_in_jointree.
3540 : */
1532 tgl 3541 ECB :
3542 : typedef struct
3543 : {
3544 : Relids relids;
3545 : int sublevels_up;
3546 : } find_dependent_phvs_context;
3547 :
3548 : static bool
1532 tgl 3549 GIC 975 : find_dependent_phvs_walker(Node *node,
1532 tgl 3550 ECB : find_dependent_phvs_context *context)
3551 : {
1532 tgl 3552 GIC 975 : if (node == NULL)
3553 231 : return false;
3554 744 : if (IsA(node, PlaceHolderVar))
3555 : {
3556 60 : PlaceHolderVar *phv = (PlaceHolderVar *) node;
3557 :
3558 120 : if (phv->phlevelsup == context->sublevels_up &&
3559 60 : bms_equal(context->relids, phv->phrels))
3560 45 : return true;
3561 : /* fall through to examine children */
3562 : }
3563 699 : if (IsA(node, Query))
3564 : {
3565 : /* Recurse into subselects */
3566 : bool result;
3567 :
3568 24 : context->sublevels_up++;
3569 24 : result = query_tree_walker((Query *) node,
3570 : find_dependent_phvs_walker,
3571 : (void *) context, 0);
1532 tgl 3572 CBC 24 : context->sublevels_up--;
1532 tgl 3573 GIC 24 : return result;
1532 tgl 3574 ECB : }
3575 : /* Shouldn't need to handle most planner auxiliary nodes here */
1532 tgl 3576 CBC 675 : Assert(!IsA(node, SpecialJoinInfo));
1532 tgl 3577 GBC 675 : Assert(!IsA(node, PlaceHolderInfo));
1532 tgl 3578 GIC 675 : Assert(!IsA(node, MinMaxAggInfo));
3579 :
3580 675 : return expression_tree_walker(node, find_dependent_phvs_walker,
1532 tgl 3581 ECB : (void *) context);
3582 : }
3583 :
3584 : static bool
1212 tgl 3585 CBC 33 : find_dependent_phvs(PlannerInfo *root, int varno)
3586 : {
3587 : find_dependent_phvs_context context;
1532 tgl 3588 ECB :
1212 3589 : /* If there are no PHVs anywhere, we needn't work hard */
1212 tgl 3590 GIC 33 : if (root->glob->lastPHId == 0)
1212 tgl 3591 UIC 0 : return false;
1212 tgl 3592 ECB :
1532 tgl 3593 GBC 33 : context.relids = bms_make_singleton(varno);
1532 tgl 3594 GIC 33 : context.sublevels_up = 0;
1532 tgl 3595 EUB :
69 tgl 3596 GNC 33 : if (query_tree_walker(root->parse,
3597 : find_dependent_phvs_walker,
3598 : (void *) &context,
3599 : 0))
3600 33 : return true;
3601 : /* The append_rel_list could be populated already, so check it too */
69 tgl 3602 UNC 0 : if (expression_tree_walker((Node *) root->append_rel_list,
3603 : find_dependent_phvs_walker,
3604 : (void *) &context))
3605 0 : return true;
3606 0 : return false;
3607 : }
1212 tgl 3608 EUB :
3609 : static bool
1212 tgl 3610 CBC 153 : find_dependent_phvs_in_jointree(PlannerInfo *root, Node *node, int varno)
3611 : {
3612 : find_dependent_phvs_context context;
3613 : Relids subrelids;
3614 : int relid;
3615 :
3616 : /* If there are no PHVs anywhere, we needn't work hard */
1212 tgl 3617 GIC 153 : if (root->glob->lastPHId == 0)
3618 120 : return false;
1212 tgl 3619 ECB :
1212 tgl 3620 GIC 33 : context.relids = bms_make_singleton(varno);
3621 33 : context.sublevels_up = 0;
3622 :
1212 tgl 3623 ECB : /*
3624 : * See if the jointree fragment itself contains references (in join quals)
3625 : */
1212 tgl 3626 CBC 33 : if (find_dependent_phvs_walker(node, &context))
1212 tgl 3627 LBC 0 : return true;
1212 tgl 3628 ECB :
3629 : /*
3630 : * Otherwise, identify the set of referenced RTEs (we can ignore joins,
3631 : * since they should be flattened already, so their join alias lists no
3632 : * longer matter), and tediously check each RTE. We can ignore RTEs that
3633 : * are not marked LATERAL, though, since they couldn't possibly contain
3634 : * any cross-references to other RTEs.
3635 : */
69 tgl 3636 GNC 33 : subrelids = get_relids_in_jointree(node, false, false);
1212 tgl 3637 GIC 33 : relid = -1;
3638 72 : while ((relid = bms_next_member(subrelids, relid)) >= 0)
3639 : {
3640 51 : RangeTblEntry *rte = rt_fetch(relid, root->parse->rtable);
3641 :
3642 63 : if (rte->lateral &&
3643 12 : range_table_entry_walker(rte,
3644 : find_dependent_phvs_walker,
3645 : (void *) &context,
3646 : 0))
3647 12 : return true;
3648 : }
1212 tgl 3649 ECB :
1212 tgl 3650 GIC 21 : return false;
3651 : }
3652 :
7384 tgl 3653 ECB : /*
3654 : * substitute_phv_relids - adjust PlaceHolderVar relid sets after pulling up
3655 : * a subquery or removing an RTE_RESULT jointree item
3656 : *
5156 3657 : * Find any PlaceHolderVar nodes in the given tree that reference the
3658 : * pulled-up relid, and change them to reference the replacement relid(s).
7384 3659 : *
5351 3660 : * NOTE: although this has the form of a walker, we cheat and modify the
3661 : * nodes in-place. This should be OK since the tree was copied by
3662 : * pullup_replace_vars earlier. Avoid scribbling on the original values of
3663 : * the bitmapsets, though, because expression_tree_mutator doesn't copy those.
3664 : */
3665 :
3666 : typedef struct
7384 3667 : {
3668 : int varno;
3669 : int sublevels_up;
3670 : Relids subrelids;
3671 : } substitute_phv_relids_context;
3672 :
3673 : static bool
1532 tgl 3674 GIC 77788 : substitute_phv_relids_walker(Node *node,
3675 : substitute_phv_relids_context *context)
3676 : {
5351 3677 77788 : if (node == NULL)
3678 29745 : return false;
5283 3679 48043 : if (IsA(node, PlaceHolderVar))
3680 : {
3681 2406 : PlaceHolderVar *phv = (PlaceHolderVar *) node;
3682 :
4033 3683 4796 : if (phv->phlevelsup == context->sublevels_up &&
3684 2390 : bms_is_member(context->varno, phv->phrels))
3685 : {
5283 3686 3150 : phv->phrels = bms_union(phv->phrels,
3687 1575 : context->subrelids);
5283 tgl 3688 CBC 1575 : phv->phrels = bms_del_member(phv->phrels,
3689 : context->varno);
3690 : /* Assert we haven't broken the PHV */
1532 3691 1575 : Assert(!bms_is_empty(phv->phrels));
5283 tgl 3692 ECB : }
3693 : /* fall through to examine children */
3694 : }
4033 tgl 3695 CBC 48043 : if (IsA(node, Query))
3696 : {
4033 tgl 3697 ECB : /* Recurse into subselects */
3698 : bool result;
3699 :
4033 tgl 3700 GIC 1360 : context->sublevels_up++;
3701 1360 : result = query_tree_walker((Query *) node,
1532 tgl 3702 ECB : substitute_phv_relids_walker,
3703 : (void *) context, 0);
4033 tgl 3704 GIC 1360 : context->sublevels_up--;
3705 1360 : return result;
3706 : }
5282 tgl 3707 ECB : /* Shouldn't need to handle planner auxiliary nodes here */
5282 tgl 3708 CBC 46683 : Assert(!IsA(node, SpecialJoinInfo));
5282 tgl 3709 GIC 46683 : Assert(!IsA(node, AppendRelInfo));
3710 46683 : Assert(!IsA(node, PlaceHolderInfo));
4539 tgl 3711 CBC 46683 : Assert(!IsA(node, MinMaxAggInfo));
5283 tgl 3712 ECB :
1532 tgl 3713 GIC 46683 : return expression_tree_walker(node, substitute_phv_relids_walker,
3714 : (void *) context);
5351 tgl 3715 ECB : }
3716 :
3717 : static void
1532 tgl 3718 GIC 770 : substitute_phv_relids(Node *node, int varno, Relids subrelids)
5351 tgl 3719 ECB : {
3720 : substitute_phv_relids_context context;
3721 :
5351 tgl 3722 GIC 770 : context.varno = varno;
4033 3723 770 : context.sublevels_up = 0;
5351 tgl 3724 CBC 770 : context.subrelids = subrelids;
3725 :
3726 : /*
3727 : * Must be prepared to start with a Query or a bare expression tree.
3728 : */
3729 770 : query_or_expression_tree_walker(node,
1532 tgl 3730 EUB : substitute_phv_relids_walker,
3731 : (void *) &context,
5351 tgl 3732 ECB : 0);
7384 tgl 3733 CBC 770 : }
3734 :
6274 tgl 3735 ECB : /*
3736 : * fix_append_rel_relids: update RT-index fields of AppendRelInfo nodes
3737 : *
3738 : * When we pull up a subquery, any AppendRelInfo references to the subquery's
3739 : * RT index have to be replaced by the substituted relid (and there had better
3740 : * be only one). We also need to apply substitute_phv_relids to their
5262 tgl 3741 EUB : * translated_vars lists, since those might contain PlaceHolderVars.
3742 : *
3743 : * We assume we may modify the AppendRelInfo nodes in-place.
6274 3744 : */
3745 : static void
108 tgl 3746 GNC 1921 : fix_append_rel_relids(PlannerInfo *root, int varno, Relids subrelids)
3747 : {
3748 : ListCell *l;
6274 tgl 3749 CBC 1921 : int subvarno = -1;
3750 :
3751 : /*
3752 : * We only want to extract the member relid once, but we mustn't fail
3753 : * immediately if there are multiple members; it could be that none of the
3754 : * AppendRelInfo nodes refer to it. So compute it on first use. Note that
3755 : * bms_singleton_member will complain if set is not singleton.
6274 tgl 3756 ECB : */
108 tgl 3757 GNC 4178 : foreach(l, root->append_rel_list)
3758 : {
6274 tgl 3759 CBC 2257 : AppendRelInfo *appinfo = (AppendRelInfo *) lfirst(l);
6274 tgl 3760 ECB :
3761 : /* The parent_relid shouldn't ever be a pullup target */
6274 tgl 3762 GIC 2257 : Assert(appinfo->parent_relid != varno);
3763 :
3764 2257 : if (appinfo->child_relid == varno)
6274 tgl 3765 ECB : {
6274 tgl 3766 GBC 1238 : if (subvarno < 0)
6274 tgl 3767 GIC 1238 : subvarno = bms_singleton_member(subrelids);
3768 1238 : appinfo->child_relid = subvarno;
3769 : }
3770 :
3771 : /* Also fix up any PHVs in its translated vars */
108 tgl 3772 GNC 2257 : if (root->glob->lastPHId != 0)
3773 57 : substitute_phv_relids((Node *) appinfo->translated_vars,
3774 : varno, subrelids);
3775 : }
6274 tgl 3776 CBC 1921 : }
6274 tgl 3777 ECB :
7384 3778 : /*
3779 : * get_relids_in_jointree: get set of RT indexes present in a jointree
5348 3780 : *
3781 : * Base-relation relids are always included in the result.
3782 : * If include_outer_joins is true, outer-join RT indexes are included.
3783 : * If include_inner_joins is true, inner-join RT indexes are included.
3784 : *
3785 : * Note that for most purposes in the planner, outer joins are included
3786 : * in standard relid sets. Setting include_inner_joins true is only
3787 : * appropriate for special purposes during subquery flattening.
7384 3788 : */
3789 : Relids
69 tgl 3790 GNC 33306 : get_relids_in_jointree(Node *jtnode, bool include_outer_joins,
3791 : bool include_inner_joins)
3792 : {
7365 tgl 3793 CBC 33306 : Relids result = NULL;
3794 :
7384 tgl 3795 GIC 33306 : if (jtnode == NULL)
7384 tgl 3796 LBC 0 : return result;
7384 tgl 3797 GIC 33306 : if (IsA(jtnode, RangeTblRef))
3798 : {
3799 17012 : int varno = ((RangeTblRef *) jtnode)->rtindex;
3800 :
7365 3801 17012 : result = bms_make_singleton(varno);
3802 : }
7384 3803 16294 : else if (IsA(jtnode, FromExpr))
3804 : {
3805 15292 : FromExpr *f = (FromExpr *) jtnode;
3806 : ListCell *l;
3807 :
3808 31081 : foreach(l, f->fromlist)
3809 : {
7365 3810 15789 : result = bms_join(result,
5348 3811 15789 : get_relids_in_jointree(lfirst(l),
3812 : include_outer_joins,
3813 : include_inner_joins));
3814 : }
3815 : }
7384 3816 1002 : else if (IsA(jtnode, JoinExpr))
3817 : {
3818 1002 : JoinExpr *j = (JoinExpr *) jtnode;
3819 :
69 tgl 3820 GNC 1002 : result = get_relids_in_jointree(j->larg,
3821 : include_outer_joins,
3822 : include_inner_joins);
5348 tgl 3823 CBC 1002 : result = bms_join(result,
3824 : get_relids_in_jointree(j->rarg,
3825 : include_outer_joins,
3826 : include_inner_joins));
69 tgl 3827 GNC 1002 : if (j->rtindex)
3828 : {
3829 929 : if (j->jointype == JOIN_INNER)
3830 : {
3831 304 : if (include_inner_joins)
3832 78 : result = bms_add_member(result, j->rtindex);
3833 : }
3834 : else
3835 : {
3836 625 : if (include_outer_joins)
3837 530 : result = bms_add_member(result, j->rtindex);
3838 : }
3839 : }
7384 tgl 3840 ECB : }
3841 : else
7198 tgl 3842 UIC 0 : elog(ERROR, "unrecognized node type: %d",
7198 tgl 3843 ECB : (int) nodeTag(jtnode));
7384 tgl 3844 GIC 33306 : return result;
7384 tgl 3845 ECB : }
3846 :
3847 : /*
3848 : * get_relids_for_join: get set of base+OJ RT indexes making up a join
3849 : */
7365 3850 : Relids
1531 tgl 3851 GIC 140 : get_relids_for_join(Query *query, int joinrelid)
3852 : {
7384 tgl 3853 ECB : Node *jtnode;
3854 :
1531 tgl 3855 GIC 140 : jtnode = find_jointree_node_for_rel((Node *) query->jointree,
3856 : joinrelid);
7384 tgl 3857 CBC 140 : if (!jtnode)
7198 tgl 3858 UIC 0 : elog(ERROR, "could not find join node %d", joinrelid);
69 tgl 3859 GNC 140 : return get_relids_in_jointree(jtnode, true, false);
3860 : }
3861 :
7384 tgl 3862 ECB : /*
3863 : * find_jointree_node_for_rel: locate jointree node for a base or join RT index
3864 : *
3865 : * Returns NULL if not found
3866 : */
3867 : static Node *
7384 tgl 3868 GIC 688 : find_jointree_node_for_rel(Node *jtnode, int relid)
3869 : {
7384 tgl 3870 CBC 688 : if (jtnode == NULL)
7384 tgl 3871 LBC 0 : return NULL;
7384 tgl 3872 CBC 688 : if (IsA(jtnode, RangeTblRef))
7384 tgl 3873 ECB : {
7384 tgl 3874 GIC 191 : int varno = ((RangeTblRef *) jtnode)->rtindex;
7384 tgl 3875 ECB :
7384 tgl 3876 GIC 191 : if (relid == varno)
7384 tgl 3877 UIC 0 : return jtnode;
3878 : }
7384 tgl 3879 GIC 497 : else if (IsA(jtnode, FromExpr))
7384 tgl 3880 ECB : {
7384 tgl 3881 GIC 148 : FromExpr *f = (FromExpr *) jtnode;
3882 : ListCell *l;
3883 :
7384 tgl 3884 CBC 166 : foreach(l, f->fromlist)
7384 tgl 3885 ECB : {
7384 tgl 3886 CBC 166 : jtnode = find_jointree_node_for_rel(lfirst(l), relid);
7384 tgl 3887 GIC 166 : if (jtnode)
3888 148 : return jtnode;
3889 : }
3890 : }
7384 tgl 3891 CBC 349 : else if (IsA(jtnode, JoinExpr))
3892 : {
7384 tgl 3893 GIC 349 : JoinExpr *j = (JoinExpr *) jtnode;
3894 :
7384 tgl 3895 CBC 349 : if (relid == j->rtindex)
7384 tgl 3896 GIC 140 : return jtnode;
3897 209 : jtnode = find_jointree_node_for_rel(j->larg, relid);
3898 209 : if (jtnode)
3899 36 : return jtnode;
3900 173 : jtnode = find_jointree_node_for_rel(j->rarg, relid);
3901 173 : if (jtnode)
3902 173 : return jtnode;
3903 : }
3904 : else
7198 tgl 3905 UIC 0 : elog(ERROR, "unrecognized node type: %d",
3906 : (int) nodeTag(jtnode));
7384 tgl 3907 GIC 191 : return NULL;
7384 tgl 3908 ECB : }
|