63
63
static List *insert_targetlist_placeholders(PlannerInfo *root, List *tlist,
64
64
int varno, bool wrap_non_vars);
65
65
static bool is_safe_append_member(Query *subquery);
66
static void resolvenew_in_jointree(Node *jtnode, int varno,
67
RangeTblEntry *rte, List *subtlist);
66
static void resolvenew_in_jointree(Node *jtnode, int varno, RangeTblEntry *rte,
67
List *subtlist, List *subtlist_with_phvs,
68
JoinExpr *lowest_outer_join);
68
69
static reduce_outer_joins_state *reduce_outer_joins_pass1(Node *jtnode);
69
70
static void reduce_outer_joins_pass2(Node *jtnode,
70
71
reduce_outer_joins_state *state,
440
441
* Also, subqueries that are simple UNION ALL structures can be
441
442
* converted into "append relations".
443
* below_outer_join is true if this jointree node is within the nullable
444
* side of an outer join. This forces use of the PlaceHolderVar mechanism
445
* for non-nullable targetlist items.
444
* If this jointree node is within the nullable side of an outer join, then
445
* lowest_outer_join references the lowest such JoinExpr node; otherwise it
446
* is NULL. This forces use of the PlaceHolderVar mechanism for references
447
* to non-nullable targetlist items, but only for references above that join.
447
* append_rel_member is true if we are looking at a member subquery of
448
* an append relation. This forces use of the PlaceHolderVar mechanism
449
* for all non-Var targetlist items, and puts some additional restrictions
450
* on what can be pulled up.
449
* If we are looking at a member subquery of an append relation,
450
* containing_appendrel describes that relation; else it is NULL.
451
* This forces use of the PlaceHolderVar mechanism for all non-Var targetlist
452
* items, and puts some additional restrictions on what can be pulled up.
452
454
* A tricky aspect of this code is that if we pull up a subquery we have
453
455
* to replace Vars that reference the subquery's outputs throughout the
457
459
* subquery RangeTblRef entries will be replaced. Also, we can't turn
458
460
* ResolveNew loose on the whole jointree, because it'll return a mutated
459
461
* copy of the tree; we have to invoke it just on the quals, instead.
462
* This behavior is what makes it reasonable to pass lowest_outer_join as a
463
* pointer rather than some more-indirect way of identifying the lowest OJ.
464
* Likewise, we don't replace append_rel_list members but only their
465
* substructure, so the containing_appendrel reference is safe to use.
462
468
pull_up_subqueries(PlannerInfo *root, Node *jtnode,
463
bool below_outer_join, bool append_rel_member)
469
JoinExpr *lowest_outer_join,
470
AppendRelInfo *containing_appendrel)
465
472
if (jtnode == NULL)
503
511
FromExpr *f = (FromExpr *) jtnode;
506
Assert(!append_rel_member);
514
Assert(containing_appendrel == NULL);
507
515
foreach(l, f->fromlist)
508
516
lfirst(l) = pull_up_subqueries(root, lfirst(l),
509
below_outer_join, false);
517
lowest_outer_join, NULL);
511
519
else if (IsA(jtnode, JoinExpr))
513
521
JoinExpr *j = (JoinExpr *) jtnode;
515
Assert(!append_rel_member);
523
Assert(containing_appendrel == NULL);
516
524
/* Recurse, being careful to tell myself when inside outer join */
517
525
switch (j->jointype)
520
528
j->larg = pull_up_subqueries(root, j->larg,
521
below_outer_join, false);
529
lowest_outer_join, NULL);
522
530
j->rarg = pull_up_subqueries(root, j->rarg,
523
below_outer_join, false);
531
lowest_outer_join, NULL);
528
536
j->larg = pull_up_subqueries(root, j->larg,
529
below_outer_join, false);
537
lowest_outer_join, NULL);
530
538
j->rarg = pull_up_subqueries(root, j->rarg,
534
542
j->larg = pull_up_subqueries(root, j->larg,
536
544
j->rarg = pull_up_subqueries(root, j->rarg,
540
548
j->larg = pull_up_subqueries(root, j->larg,
542
550
j->rarg = pull_up_subqueries(root, j->rarg,
543
below_outer_join, false);
551
lowest_outer_join, NULL);
546
554
elog(ERROR, "unrecognized join type: %d",
624
637
* pull_up_subqueries' processing is complete for its jointree and
627
* Note: below_outer_join = false is correct here even if we are within an
628
* outer join in the upper query; the lower query starts with a clean
629
* slate for outer-join semantics. Likewise, we say we aren't handling an
640
* Note: we should pass NULL for containing-join info even if we are within
641
* an outer join in the upper query; the lower query starts with a clean
642
* slate for outer-join semantics. Likewise, we say we aren't handling an
630
643
* appendrel member.
632
645
subquery->jointree = (FromExpr *)
633
pull_up_subqueries(subroot, (Node *) subquery->jointree, false, false);
646
pull_up_subqueries(subroot, (Node *) subquery->jointree, NULL, NULL);
636
649
* Now we must recheck whether the subquery is still simple enough to pull
678
691
* The subquery's targetlist items are now in the appropriate form to
679
692
* insert into the top query, but if we are under an outer join then
680
* non-nullable items have to be turned into PlaceHolderVars. If we
693
* non-nullable items may have to be turned into PlaceHolderVars. If we
681
694
* are dealing with an appendrel member then anything that's not a
682
695
* simple Var has to be turned into a PlaceHolderVar.
684
if (below_outer_join || append_rel_member)
685
subtlist = insert_targetlist_placeholders(root, subquery->targetList,
686
varno, append_rel_member);
697
subtlist = subquery->targetList;
698
if (lowest_outer_join != NULL || containing_appendrel != NULL)
699
subtlist_with_phvs = insert_targetlist_placeholders(root,
702
containing_appendrel != NULL);
688
subtlist = subquery->targetList;
704
subtlist_with_phvs = subtlist;
691
707
* Replace all of the top query's references to the subquery's outputs
692
708
* with copies of the adjusted subtlist items, being careful not to
693
709
* replace any of the jointree structure. (This'd be a lot cleaner if we
694
* could use query_tree_mutator.)
710
* could use query_tree_mutator.) We have to use PHVs in the targetList,
711
* returningList, and havingQual, since those are certainly above any
712
* outer join. resolvenew_in_jointree tracks its location in the jointree
713
* and uses PHVs or not appropriately.
696
715
parse->targetList = (List *)
697
716
ResolveNew((Node *) parse->targetList,
699
subtlist, CMD_SELECT, 0);
718
subtlist_with_phvs, CMD_SELECT, 0);
700
719
parse->returningList = (List *)
701
720
ResolveNew((Node *) parse->returningList,
703
subtlist, CMD_SELECT, 0);
704
resolvenew_in_jointree((Node *) parse->jointree, varno,
722
subtlist_with_phvs, CMD_SELECT, 0);
723
resolvenew_in_jointree((Node *) parse->jointree, varno, rte,
724
subtlist, subtlist_with_phvs,
706
726
Assert(parse->setOperations == NULL);
707
727
parse->havingQual =
708
728
ResolveNew(parse->havingQual,
710
subtlist, CMD_SELECT, 0);
711
root->append_rel_list = (List *)
712
ResolveNew((Node *) root->append_rel_list,
714
subtlist, CMD_SELECT, 0);
716
foreach(rt, parse->rtable)
718
RangeTblEntry *otherrte = (RangeTblEntry *) lfirst(rt);
730
subtlist_with_phvs, CMD_SELECT, 0);
733
* Replace references in the translated_vars lists of appendrels.
734
* When pulling up an appendrel member, we do not need PHVs in the list
735
* of the parent appendrel --- there isn't any outer join between.
736
* Elsewhere, use PHVs for safety. (This analysis could be made tighter
737
* but it seems unlikely to be worth much trouble.)
739
foreach(lc, root->append_rel_list)
741
AppendRelInfo *appinfo = (AppendRelInfo *) lfirst(lc);
743
appinfo->translated_vars = (List *)
744
ResolveNew((Node *) appinfo->translated_vars,
746
(appinfo == containing_appendrel) ?
747
subtlist : subtlist_with_phvs,
752
* Replace references in the joinaliasvars lists of join RTEs.
754
* You might think that we could avoid using PHVs for alias vars of joins
755
* below lowest_outer_join, but that doesn't work because the alias vars
756
* could be referenced above that join; we need the PHVs to be present
757
* in such references after the alias vars get flattened. (It might be
758
* worth trying to be smarter here, someday.)
760
foreach(lc, parse->rtable)
762
RangeTblEntry *otherrte = (RangeTblEntry *) lfirst(lc);
720
764
if (otherrte->rtekind == RTE_JOIN)
721
765
otherrte->joinaliasvars = (List *)
722
766
ResolveNew((Node *) otherrte->joinaliasvars,
724
subtlist, CMD_SELECT, 0);
768
subtlist_with_phvs, CMD_SELECT, 0);
885
929
* Recursively apply pull_up_subqueries to the new child RTE. (We
886
930
* must build the AppendRelInfo first, because this will modify it.)
887
* Note that we can pass below_outer_join = false even if we're
931
* Note that we can pass NULL for containing-join info even if we're
888
932
* actually under an outer join, because the child's expressions
889
933
* aren't going to propagate up above the join.
891
935
rtr = makeNode(RangeTblRef);
892
936
rtr->rtindex = childRTindex;
893
(void) pull_up_subqueries(root, (Node *) rtr, false, true);
937
(void) pull_up_subqueries(root, (Node *) rtr, NULL, appinfo);
895
939
else if (IsA(setOp, SetOperationStmt))
1187
1246
* Helper routine for pull_up_subqueries: do ResolveNew on every expression
1188
1247
* in the jointree, without changing the jointree structure itself. Ugly,
1189
1248
* but there's no other way...
1250
* If we are above lowest_outer_join then use subtlist_with_phvs; at or
1251
* below it, use subtlist. (When no outer joins are in the picture,
1252
* these will be the same list.)
1192
resolvenew_in_jointree(Node *jtnode, int varno,
1193
RangeTblEntry *rte, List *subtlist)
1255
resolvenew_in_jointree(Node *jtnode, int varno, RangeTblEntry *rte,
1256
List *subtlist, List *subtlist_with_phvs,
1257
JoinExpr *lowest_outer_join)
1195
1259
if (jtnode == NULL)
1206
1270
foreach(l, f->fromlist)
1207
resolvenew_in_jointree(lfirst(l), varno, rte, subtlist);
1271
resolvenew_in_jointree(lfirst(l), varno, rte,
1272
subtlist, subtlist_with_phvs,
1208
1274
f->quals = ResolveNew(f->quals,
1210
subtlist, CMD_SELECT, 0);
1276
subtlist_with_phvs, CMD_SELECT, 0);
1212
1278
else if (IsA(jtnode, JoinExpr))
1214
1280
JoinExpr *j = (JoinExpr *) jtnode;
1216
resolvenew_in_jointree(j->larg, varno, rte, subtlist);
1217
resolvenew_in_jointree(j->rarg, varno, rte, subtlist);
1282
if (j == lowest_outer_join)
1284
/* no more PHVs in or below this join */
1285
subtlist_with_phvs = subtlist;
1286
lowest_outer_join = NULL;
1288
resolvenew_in_jointree(j->larg, varno, rte,
1289
subtlist, subtlist_with_phvs,
1291
resolvenew_in_jointree(j->rarg, varno, rte,
1292
subtlist, subtlist_with_phvs,
1218
1294
j->quals = ResolveNew(j->quals,
1220
subtlist, CMD_SELECT, 0);
1296
subtlist_with_phvs, CMD_SELECT, 0);
1223
1299
* We don't bother to update the colvars list, since it won't be used