00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024 #include "postgres.h"
00025
00026 #include "catalog/pg_type.h"
00027 #include "nodes/makefuncs.h"
00028 #include "nodes/nodeFuncs.h"
00029 #include "optimizer/clauses.h"
00030 #include "optimizer/placeholder.h"
00031 #include "optimizer/prep.h"
00032 #include "optimizer/subselect.h"
00033 #include "optimizer/tlist.h"
00034 #include "parser/parse_relation.h"
00035 #include "parser/parsetree.h"
00036 #include "rewrite/rewriteManip.h"
00037
00038
00039 typedef struct pullup_replace_vars_context
00040 {
00041 PlannerInfo *root;
00042 List *targetlist;
00043 RangeTblEntry *target_rte;
00044 bool *outer_hasSubLinks;
00045 int varno;
00046 bool need_phvs;
00047 bool wrap_non_vars;
00048 Node **rv_cache;
00049 } pullup_replace_vars_context;
00050
00051 typedef struct reduce_outer_joins_state
00052 {
00053 Relids relids;
00054 bool contains_outer;
00055 List *sub_states;
00056 } reduce_outer_joins_state;
00057
00058 static Node *pull_up_sublinks_jointree_recurse(PlannerInfo *root, Node *jtnode,
00059 Relids *relids);
00060 static Node *pull_up_sublinks_qual_recurse(PlannerInfo *root, Node *node,
00061 Node **jtlink1, Relids available_rels1,
00062 Node **jtlink2, Relids available_rels2);
00063 static Node *pull_up_subqueries_recurse(PlannerInfo *root, Node *jtnode,
00064 JoinExpr *lowest_outer_join,
00065 JoinExpr *lowest_nulling_outer_join,
00066 AppendRelInfo *containing_appendrel);
00067 static Node *pull_up_simple_subquery(PlannerInfo *root, Node *jtnode,
00068 RangeTblEntry *rte,
00069 JoinExpr *lowest_outer_join,
00070 JoinExpr *lowest_nulling_outer_join,
00071 AppendRelInfo *containing_appendrel);
00072 static Node *pull_up_simple_union_all(PlannerInfo *root, Node *jtnode,
00073 RangeTblEntry *rte);
00074 static void pull_up_union_leaf_queries(Node *setOp, PlannerInfo *root,
00075 int parentRTindex, Query *setOpQuery,
00076 int childRToffset);
00077 static void make_setop_translation_list(Query *query, Index newvarno,
00078 List **translated_vars);
00079 static bool is_simple_subquery(Query *subquery, RangeTblEntry *rte,
00080 JoinExpr *lowest_outer_join);
00081 static bool is_simple_union_all(Query *subquery);
00082 static bool is_simple_union_all_recurse(Node *setOp, Query *setOpQuery,
00083 List *colTypes);
00084 static bool is_safe_append_member(Query *subquery);
00085 static void replace_vars_in_jointree(Node *jtnode,
00086 pullup_replace_vars_context *context,
00087 JoinExpr *lowest_nulling_outer_join);
00088 static Node *pullup_replace_vars(Node *expr,
00089 pullup_replace_vars_context *context);
00090 static Node *pullup_replace_vars_callback(Var *var,
00091 replace_rte_variables_context *context);
00092 static Query *pullup_replace_vars_subquery(Query *query,
00093 pullup_replace_vars_context *context);
00094 static reduce_outer_joins_state *reduce_outer_joins_pass1(Node *jtnode);
00095 static void reduce_outer_joins_pass2(Node *jtnode,
00096 reduce_outer_joins_state *state,
00097 PlannerInfo *root,
00098 Relids nonnullable_rels,
00099 List *nonnullable_vars,
00100 List *forced_null_vars);
00101 static void substitute_multiple_relids(Node *node,
00102 int varno, Relids subrelids);
00103 static void fix_append_rel_relids(List *append_rel_list, int varno,
00104 Relids subrelids);
00105 static Node *find_jointree_node_for_rel(Node *jtnode, int relid);
00106
00107
00108
00109
00110
00111
00112
00113
00114
00115
00116
00117
00118
00119
00120
00121
00122
00123
00124
00125
00126
00127
00128
00129
00130
00131
00132
00133
00134
00135
00136 void
00137 pull_up_sublinks(PlannerInfo *root)
00138 {
00139 Node *jtnode;
00140 Relids relids;
00141
00142
00143 jtnode = pull_up_sublinks_jointree_recurse(root,
00144 (Node *) root->parse->jointree,
00145 &relids);
00146
00147
00148
00149
00150
00151 if (IsA(jtnode, FromExpr))
00152 root->parse->jointree = (FromExpr *) jtnode;
00153 else
00154 root->parse->jointree = makeFromExpr(list_make1(jtnode), NULL);
00155 }
00156
00157
00158
00159
00160
00161
00162
00163 static Node *
00164 pull_up_sublinks_jointree_recurse(PlannerInfo *root, Node *jtnode,
00165 Relids *relids)
00166 {
00167 if (jtnode == NULL)
00168 {
00169 *relids = NULL;
00170 }
00171 else if (IsA(jtnode, RangeTblRef))
00172 {
00173 int varno = ((RangeTblRef *) jtnode)->rtindex;
00174
00175 *relids = bms_make_singleton(varno);
00176
00177 }
00178 else if (IsA(jtnode, FromExpr))
00179 {
00180 FromExpr *f = (FromExpr *) jtnode;
00181 List *newfromlist = NIL;
00182 Relids frelids = NULL;
00183 FromExpr *newf;
00184 Node *jtlink;
00185 ListCell *l;
00186
00187
00188 foreach(l, f->fromlist)
00189 {
00190 Node *newchild;
00191 Relids childrelids;
00192
00193 newchild = pull_up_sublinks_jointree_recurse(root,
00194 lfirst(l),
00195 &childrelids);
00196 newfromlist = lappend(newfromlist, newchild);
00197 frelids = bms_join(frelids, childrelids);
00198 }
00199
00200 newf = makeFromExpr(newfromlist, NULL);
00201
00202 jtlink = (Node *) newf;
00203
00204 newf->quals = pull_up_sublinks_qual_recurse(root, f->quals,
00205 &jtlink, frelids,
00206 NULL, NULL);
00207
00208
00209
00210
00211
00212
00213
00214
00215
00216
00217 *relids = frelids;
00218 jtnode = jtlink;
00219 }
00220 else if (IsA(jtnode, JoinExpr))
00221 {
00222 JoinExpr *j;
00223 Relids leftrelids;
00224 Relids rightrelids;
00225 Node *jtlink;
00226
00227
00228
00229
00230
00231 j = (JoinExpr *) palloc(sizeof(JoinExpr));
00232 memcpy(j, jtnode, sizeof(JoinExpr));
00233 jtlink = (Node *) j;
00234
00235
00236 j->larg = pull_up_sublinks_jointree_recurse(root, j->larg,
00237 &leftrelids);
00238 j->rarg = pull_up_sublinks_jointree_recurse(root, j->rarg,
00239 &rightrelids);
00240
00241
00242
00243
00244
00245
00246
00247
00248
00249
00250
00251
00252
00253 switch (j->jointype)
00254 {
00255 case JOIN_INNER:
00256 j->quals = pull_up_sublinks_qual_recurse(root, j->quals,
00257 &jtlink,
00258 bms_union(leftrelids,
00259 rightrelids),
00260 NULL, NULL);
00261 break;
00262 case JOIN_LEFT:
00263 j->quals = pull_up_sublinks_qual_recurse(root, j->quals,
00264 &j->rarg,
00265 rightrelids,
00266 NULL, NULL);
00267 break;
00268 case JOIN_FULL:
00269
00270 break;
00271 case JOIN_RIGHT:
00272 j->quals = pull_up_sublinks_qual_recurse(root, j->quals,
00273 &j->larg,
00274 leftrelids,
00275 NULL, NULL);
00276 break;
00277 default:
00278 elog(ERROR, "unrecognized join type: %d",
00279 (int) j->jointype);
00280 break;
00281 }
00282
00283
00284
00285
00286
00287
00288
00289
00290
00291 *relids = bms_join(leftrelids, rightrelids);
00292 if (j->rtindex)
00293 *relids = bms_add_member(*relids, j->rtindex);
00294 jtnode = jtlink;
00295 }
00296 else
00297 elog(ERROR, "unrecognized node type: %d",
00298 (int) nodeTag(jtnode));
00299 return jtnode;
00300 }
00301
00302
00303
00304
00305
00306
00307
00308
00309
00310
00311
00312
00313
00314
00315
00316
00317 static Node *
00318 pull_up_sublinks_qual_recurse(PlannerInfo *root, Node *node,
00319 Node **jtlink1, Relids available_rels1,
00320 Node **jtlink2, Relids available_rels2)
00321 {
00322 if (node == NULL)
00323 return NULL;
00324 if (IsA(node, SubLink))
00325 {
00326 SubLink *sublink = (SubLink *) node;
00327 JoinExpr *j;
00328 Relids child_rels;
00329
00330
00331 if (sublink->subLinkType == ANY_SUBLINK)
00332 {
00333 if ((j = convert_ANY_sublink_to_join(root, sublink,
00334 available_rels1)) != NULL)
00335 {
00336
00337 j->larg = *jtlink1;
00338 *jtlink1 = (Node *) j;
00339
00340 j->rarg = pull_up_sublinks_jointree_recurse(root,
00341 j->rarg,
00342 &child_rels);
00343
00344
00345
00346
00347
00348
00349 j->quals = pull_up_sublinks_qual_recurse(root,
00350 j->quals,
00351 &j->larg,
00352 available_rels1,
00353 &j->rarg,
00354 child_rels);
00355
00356 return NULL;
00357 }
00358 if (available_rels2 != NULL &&
00359 (j = convert_ANY_sublink_to_join(root, sublink,
00360 available_rels2)) != NULL)
00361 {
00362
00363 j->larg = *jtlink2;
00364 *jtlink2 = (Node *) j;
00365
00366 j->rarg = pull_up_sublinks_jointree_recurse(root,
00367 j->rarg,
00368 &child_rels);
00369
00370
00371
00372
00373
00374
00375 j->quals = pull_up_sublinks_qual_recurse(root,
00376 j->quals,
00377 &j->larg,
00378 available_rels2,
00379 &j->rarg,
00380 child_rels);
00381
00382 return NULL;
00383 }
00384 }
00385 else if (sublink->subLinkType == EXISTS_SUBLINK)
00386 {
00387 if ((j = convert_EXISTS_sublink_to_join(root, sublink, false,
00388 available_rels1)) != NULL)
00389 {
00390
00391 j->larg = *jtlink1;
00392 *jtlink1 = (Node *) j;
00393
00394 j->rarg = pull_up_sublinks_jointree_recurse(root,
00395 j->rarg,
00396 &child_rels);
00397
00398
00399
00400
00401
00402
00403 j->quals = pull_up_sublinks_qual_recurse(root,
00404 j->quals,
00405 &j->larg,
00406 available_rels1,
00407 &j->rarg,
00408 child_rels);
00409
00410 return NULL;
00411 }
00412 if (available_rels2 != NULL &&
00413 (j = convert_EXISTS_sublink_to_join(root, sublink, false,
00414 available_rels2)) != NULL)
00415 {
00416
00417 j->larg = *jtlink2;
00418 *jtlink2 = (Node *) j;
00419
00420 j->rarg = pull_up_sublinks_jointree_recurse(root,
00421 j->rarg,
00422 &child_rels);
00423
00424
00425
00426
00427
00428
00429 j->quals = pull_up_sublinks_qual_recurse(root,
00430 j->quals,
00431 &j->larg,
00432 available_rels2,
00433 &j->rarg,
00434 child_rels);
00435
00436 return NULL;
00437 }
00438 }
00439
00440 return node;
00441 }
00442 if (not_clause(node))
00443 {
00444
00445 SubLink *sublink = (SubLink *) get_notclausearg((Expr *) node);
00446 JoinExpr *j;
00447 Relids child_rels;
00448
00449 if (sublink && IsA(sublink, SubLink))
00450 {
00451 if (sublink->subLinkType == EXISTS_SUBLINK)
00452 {
00453 if ((j = convert_EXISTS_sublink_to_join(root, sublink, true,
00454 available_rels1)) != NULL)
00455 {
00456
00457 j->larg = *jtlink1;
00458 *jtlink1 = (Node *) j;
00459
00460 j->rarg = pull_up_sublinks_jointree_recurse(root,
00461 j->rarg,
00462 &child_rels);
00463
00464
00465
00466
00467
00468
00469
00470 j->quals = pull_up_sublinks_qual_recurse(root,
00471 j->quals,
00472 &j->rarg,
00473 child_rels,
00474 NULL, NULL);
00475
00476 return NULL;
00477 }
00478 if (available_rels2 != NULL &&
00479 (j = convert_EXISTS_sublink_to_join(root, sublink, true,
00480 available_rels2)) != NULL)
00481 {
00482
00483 j->larg = *jtlink2;
00484 *jtlink2 = (Node *) j;
00485
00486 j->rarg = pull_up_sublinks_jointree_recurse(root,
00487 j->rarg,
00488 &child_rels);
00489
00490
00491
00492
00493
00494
00495
00496 j->quals = pull_up_sublinks_qual_recurse(root,
00497 j->quals,
00498 &j->rarg,
00499 child_rels,
00500 NULL, NULL);
00501
00502 return NULL;
00503 }
00504 }
00505 }
00506
00507 return node;
00508 }
00509 if (and_clause(node))
00510 {
00511
00512 List *newclauses = NIL;
00513 ListCell *l;
00514
00515 foreach(l, ((BoolExpr *) node)->args)
00516 {
00517 Node *oldclause = (Node *) lfirst(l);
00518 Node *newclause;
00519
00520 newclause = pull_up_sublinks_qual_recurse(root,
00521 oldclause,
00522 jtlink1,
00523 available_rels1,
00524 jtlink2,
00525 available_rels2);
00526 if (newclause)
00527 newclauses = lappend(newclauses, newclause);
00528 }
00529
00530 if (newclauses == NIL)
00531 return NULL;
00532 else if (list_length(newclauses) == 1)
00533 return (Node *) linitial(newclauses);
00534 else
00535 return (Node *) make_andclause(newclauses);
00536 }
00537
00538 return node;
00539 }
00540
00541
00542
00543
00544
00545
00546
00547
00548
00549
00550
00551
00552
00553
00554
00555
00556
00557
00558
00559 void
00560 inline_set_returning_functions(PlannerInfo *root)
00561 {
00562 ListCell *rt;
00563
00564 foreach(rt, root->parse->rtable)
00565 {
00566 RangeTblEntry *rte = (RangeTblEntry *) lfirst(rt);
00567
00568 if (rte->rtekind == RTE_FUNCTION)
00569 {
00570 Query *funcquery;
00571
00572
00573 funcquery = inline_set_returning_function(root, rte);
00574 if (funcquery)
00575 {
00576
00577 rte->rtekind = RTE_SUBQUERY;
00578 rte->subquery = funcquery;
00579 rte->funcexpr = NULL;
00580 rte->funccoltypes = NIL;
00581 rte->funccoltypmods = NIL;
00582 rte->funccolcollations = NIL;
00583 }
00584 }
00585 }
00586 }
00587
00588
00589
00590
00591
00592
00593
00594
00595
00596
00597
00598 Node *
00599 pull_up_subqueries(PlannerInfo *root, Node *jtnode)
00600 {
00601
00602 return pull_up_subqueries_recurse(root, jtnode, NULL, NULL, NULL);
00603 }
00604
00605
00606
00607
00608
00609
00610
00611
00612
00613
00614
00615
00616
00617
00618
00619
00620
00621
00622
00623
00624
00625
00626
00627
00628
00629
00630
00631
00632
00633
00634
00635
00636
00637
00638 static Node *
00639 pull_up_subqueries_recurse(PlannerInfo *root, Node *jtnode,
00640 JoinExpr *lowest_outer_join,
00641 JoinExpr *lowest_nulling_outer_join,
00642 AppendRelInfo *containing_appendrel)
00643 {
00644 if (jtnode == NULL)
00645 return NULL;
00646 if (IsA(jtnode, RangeTblRef))
00647 {
00648 int varno = ((RangeTblRef *) jtnode)->rtindex;
00649 RangeTblEntry *rte = rt_fetch(varno, root->parse->rtable);
00650
00651
00652
00653
00654
00655
00656
00657
00658 if (rte->rtekind == RTE_SUBQUERY &&
00659 is_simple_subquery(rte->subquery, rte, lowest_outer_join) &&
00660 (containing_appendrel == NULL ||
00661 is_safe_append_member(rte->subquery)))
00662 return pull_up_simple_subquery(root, jtnode, rte,
00663 lowest_outer_join,
00664 lowest_nulling_outer_join,
00665 containing_appendrel);
00666
00667
00668
00669
00670
00671
00672
00673
00674
00675
00676 if (rte->rtekind == RTE_SUBQUERY &&
00677 is_simple_union_all(rte->subquery))
00678 return pull_up_simple_union_all(root, jtnode, rte);
00679
00680
00681 }
00682 else if (IsA(jtnode, FromExpr))
00683 {
00684 FromExpr *f = (FromExpr *) jtnode;
00685 ListCell *l;
00686
00687 Assert(containing_appendrel == NULL);
00688 foreach(l, f->fromlist)
00689 lfirst(l) = pull_up_subqueries_recurse(root, lfirst(l),
00690 lowest_outer_join,
00691 lowest_nulling_outer_join,
00692 NULL);
00693 }
00694 else if (IsA(jtnode, JoinExpr))
00695 {
00696 JoinExpr *j = (JoinExpr *) jtnode;
00697
00698 Assert(containing_appendrel == NULL);
00699
00700 switch (j->jointype)
00701 {
00702 case JOIN_INNER:
00703 j->larg = pull_up_subqueries_recurse(root, j->larg,
00704 lowest_outer_join,
00705 lowest_nulling_outer_join,
00706 NULL);
00707 j->rarg = pull_up_subqueries_recurse(root, j->rarg,
00708 lowest_outer_join,
00709 lowest_nulling_outer_join,
00710 NULL);
00711 break;
00712 case JOIN_LEFT:
00713 case JOIN_SEMI:
00714 case JOIN_ANTI:
00715 j->larg = pull_up_subqueries_recurse(root, j->larg,
00716 j,
00717 lowest_nulling_outer_join,
00718 NULL);
00719 j->rarg = pull_up_subqueries_recurse(root, j->rarg,
00720 j,
00721 j,
00722 NULL);
00723 break;
00724 case JOIN_FULL:
00725 j->larg = pull_up_subqueries_recurse(root, j->larg,
00726 j,
00727 j,
00728 NULL);
00729 j->rarg = pull_up_subqueries_recurse(root, j->rarg,
00730 j,
00731 j,
00732 NULL);
00733 break;
00734 case JOIN_RIGHT:
00735 j->larg = pull_up_subqueries_recurse(root, j->larg,
00736 j,
00737 j,
00738 NULL);
00739 j->rarg = pull_up_subqueries_recurse(root, j->rarg,
00740 j,
00741 lowest_nulling_outer_join,
00742 NULL);
00743 break;
00744 default:
00745 elog(ERROR, "unrecognized join type: %d",
00746 (int) j->jointype);
00747 break;
00748 }
00749 }
00750 else
00751 elog(ERROR, "unrecognized node type: %d",
00752 (int) nodeTag(jtnode));
00753 return jtnode;
00754 }
00755
00756
00757
00758
00759
00760
00761
00762
00763
00764
00765
00766
00767
00768 static Node *
00769 pull_up_simple_subquery(PlannerInfo *root, Node *jtnode, RangeTblEntry *rte,
00770 JoinExpr *lowest_outer_join,
00771 JoinExpr *lowest_nulling_outer_join,
00772 AppendRelInfo *containing_appendrel)
00773 {
00774 Query *parse = root->parse;
00775 int varno = ((RangeTblRef *) jtnode)->rtindex;
00776 Query *subquery;
00777 PlannerInfo *subroot;
00778 int rtoffset;
00779 pullup_replace_vars_context rvcontext;
00780 ListCell *lc;
00781
00782
00783
00784
00785
00786
00787
00788 subquery = copyObject(rte->subquery);
00789
00790
00791
00792
00793
00794
00795
00796
00797 subroot = makeNode(PlannerInfo);
00798 subroot->parse = subquery;
00799 subroot->glob = root->glob;
00800 subroot->query_level = root->query_level;
00801 subroot->parent_root = root->parent_root;
00802 subroot->plan_params = NIL;
00803 subroot->planner_cxt = CurrentMemoryContext;
00804 subroot->init_plans = NIL;
00805 subroot->cte_plan_ids = NIL;
00806 subroot->eq_classes = NIL;
00807 subroot->append_rel_list = NIL;
00808 subroot->rowMarks = NIL;
00809 subroot->hasRecursion = false;
00810 subroot->wt_param_id = -1;
00811 subroot->non_recursive_plan = NULL;
00812
00813
00814 Assert(subquery->cteList == NIL);
00815
00816
00817
00818
00819
00820 if (subquery->hasSubLinks)
00821 pull_up_sublinks(subroot);
00822
00823
00824
00825
00826 inline_set_returning_functions(subroot);
00827
00828
00829
00830
00831
00832
00833
00834
00835
00836
00837
00838 subquery->jointree = (FromExpr *)
00839 pull_up_subqueries_recurse(subroot, (Node *) subquery->jointree,
00840 NULL, NULL, NULL);
00841
00842
00843
00844
00845
00846
00847
00848
00849
00850 if (is_simple_subquery(subquery, rte, lowest_outer_join) &&
00851 (containing_appendrel == NULL || is_safe_append_member(subquery)))
00852 {
00853
00854 }
00855 else
00856 {
00857
00858
00859
00860
00861
00862
00863
00864
00865 return jtnode;
00866 }
00867
00868
00869
00870
00871
00872
00873 rtoffset = list_length(parse->rtable);
00874 OffsetVarNodes((Node *) subquery, rtoffset, 0);
00875 OffsetVarNodes((Node *) subroot->append_rel_list, rtoffset, 0);
00876
00877
00878
00879
00880
00881 IncrementVarSublevelsUp((Node *) subquery, -1, 1);
00882 IncrementVarSublevelsUp((Node *) subroot->append_rel_list, -1, 1);
00883
00884
00885
00886
00887
00888
00889
00890
00891
00892 rvcontext.root = root;
00893 rvcontext.targetlist = subquery->targetList;
00894 rvcontext.target_rte = rte;
00895 rvcontext.outer_hasSubLinks = &parse->hasSubLinks;
00896 rvcontext.varno = varno;
00897 rvcontext.need_phvs = (lowest_nulling_outer_join != NULL ||
00898 containing_appendrel != NULL);
00899 rvcontext.wrap_non_vars = (containing_appendrel != NULL);
00900
00901 rvcontext.rv_cache = palloc0((list_length(subquery->targetList) + 1) *
00902 sizeof(Node *));
00903
00904
00905
00906
00907
00908
00909
00910
00911
00912
00913 parse->targetList = (List *)
00914 pullup_replace_vars((Node *) parse->targetList, &rvcontext);
00915 parse->returningList = (List *)
00916 pullup_replace_vars((Node *) parse->returningList, &rvcontext);
00917 replace_vars_in_jointree((Node *) parse->jointree, &rvcontext,
00918 lowest_nulling_outer_join);
00919 Assert(parse->setOperations == NULL);
00920 parse->havingQual = pullup_replace_vars(parse->havingQual, &rvcontext);
00921
00922
00923
00924
00925
00926
00927
00928
00929 foreach(lc, root->append_rel_list)
00930 {
00931 AppendRelInfo *appinfo = (AppendRelInfo *) lfirst(lc);
00932 bool save_need_phvs = rvcontext.need_phvs;
00933
00934 if (appinfo == containing_appendrel)
00935 rvcontext.need_phvs = false;
00936 appinfo->translated_vars = (List *)
00937 pullup_replace_vars((Node *) appinfo->translated_vars, &rvcontext);
00938 rvcontext.need_phvs = save_need_phvs;
00939 }
00940
00941
00942
00943
00944
00945
00946
00947
00948
00949
00950 foreach(lc, parse->rtable)
00951 {
00952 RangeTblEntry *otherrte = (RangeTblEntry *) lfirst(lc);
00953
00954 if (otherrte->rtekind == RTE_JOIN)
00955 otherrte->joinaliasvars = (List *)
00956 pullup_replace_vars((Node *) otherrte->joinaliasvars,
00957 &rvcontext);
00958 }
00959
00960
00961
00962
00963
00964
00965
00966
00967 if (rte->lateral)
00968 {
00969 foreach(lc, subquery->rtable)
00970 {
00971 RangeTblEntry *child_rte = (RangeTblEntry *) lfirst(lc);
00972
00973 switch (child_rte->rtekind)
00974 {
00975 case RTE_SUBQUERY:
00976 case RTE_FUNCTION:
00977 case RTE_VALUES:
00978 child_rte->lateral = true;
00979 break;
00980 case RTE_RELATION:
00981 case RTE_JOIN:
00982 case RTE_CTE:
00983
00984 break;
00985 }
00986 }
00987 }
00988
00989
00990
00991
00992
00993
00994 parse->rtable = list_concat(parse->rtable, subquery->rtable);
00995
00996
00997
00998
00999
01000 parse->rowMarks = list_concat(parse->rowMarks, subquery->rowMarks);
01001
01002
01003
01004
01005
01006
01007
01008
01009
01010
01011
01012
01013 if (parse->hasSubLinks || root->glob->lastPHId != 0 ||
01014 root->append_rel_list)
01015 {
01016 Relids subrelids;
01017
01018 subrelids = get_relids_in_jointree((Node *) subquery->jointree, false);
01019 substitute_multiple_relids((Node *) parse, varno, subrelids);
01020 fix_append_rel_relids(root->append_rel_list, varno, subrelids);
01021 }
01022
01023
01024
01025
01026 root->append_rel_list = list_concat(root->append_rel_list,
01027 subroot->append_rel_list);
01028
01029
01030
01031
01032
01033
01034 Assert(root->join_info_list == NIL);
01035 Assert(subroot->join_info_list == NIL);
01036 Assert(root->lateral_info_list == NIL);
01037 Assert(subroot->lateral_info_list == NIL);
01038 Assert(root->placeholder_list == NIL);
01039 Assert(subroot->placeholder_list == NIL);
01040
01041
01042
01043
01044
01045
01046
01047
01048
01049
01050 parse->hasSubLinks |= subquery->hasSubLinks;
01051
01052
01053
01054
01055
01056
01057
01058
01059
01060
01061 return (Node *) subquery->jointree;
01062 }
01063
01064
01065
01066
01067
01068
01069
01070
01071
01072
01073 static Node *
01074 pull_up_simple_union_all(PlannerInfo *root, Node *jtnode, RangeTblEntry *rte)
01075 {
01076 int varno = ((RangeTblRef *) jtnode)->rtindex;
01077 Query *subquery = rte->subquery;
01078 int rtoffset = list_length(root->parse->rtable);
01079 List *rtable;
01080
01081
01082
01083
01084
01085
01086 rtable = copyObject(subquery->rtable);
01087
01088
01089
01090
01091
01092
01093 IncrementVarSublevelsUp_rtable(rtable, -1, 1);
01094
01095
01096
01097
01098
01099
01100
01101 if (rte->lateral)
01102 {
01103 ListCell *rt;
01104
01105 foreach(rt, rtable)
01106 {
01107 RangeTblEntry *child_rte = (RangeTblEntry *) lfirst(rt);
01108
01109 Assert(child_rte->rtekind == RTE_SUBQUERY);
01110 child_rte->lateral = true;
01111 }
01112 }
01113
01114
01115
01116
01117 root->parse->rtable = list_concat(root->parse->rtable, rtable);
01118
01119
01120
01121
01122
01123
01124 Assert(subquery->setOperations);
01125 pull_up_union_leaf_queries(subquery->setOperations, root, varno, subquery,
01126 rtoffset);
01127
01128
01129
01130
01131 rte->inh = true;
01132
01133 return jtnode;
01134 }
01135
01136
01137
01138
01139
01140
01141
01142
01143
01144
01145
01146
01147
01148
01149
01150
01151
01152
01153
01154 static void
01155 pull_up_union_leaf_queries(Node *setOp, PlannerInfo *root, int parentRTindex,
01156 Query *setOpQuery, int childRToffset)
01157 {
01158 if (IsA(setOp, RangeTblRef))
01159 {
01160 RangeTblRef *rtr = (RangeTblRef *) setOp;
01161 int childRTindex;
01162 AppendRelInfo *appinfo;
01163
01164
01165
01166
01167 childRTindex = childRToffset + rtr->rtindex;
01168
01169
01170
01171
01172 appinfo = makeNode(AppendRelInfo);
01173 appinfo->parent_relid = parentRTindex;
01174 appinfo->child_relid = childRTindex;
01175 appinfo->parent_reltype = InvalidOid;
01176 appinfo->child_reltype = InvalidOid;
01177 make_setop_translation_list(setOpQuery, childRTindex,
01178 &appinfo->translated_vars);
01179 appinfo->parent_reloid = InvalidOid;
01180 root->append_rel_list = lappend(root->append_rel_list, appinfo);
01181
01182
01183
01184
01185
01186
01187
01188
01189 rtr = makeNode(RangeTblRef);
01190 rtr->rtindex = childRTindex;
01191 (void) pull_up_subqueries_recurse(root, (Node *) rtr,
01192 NULL, NULL, appinfo);
01193 }
01194 else if (IsA(setOp, SetOperationStmt))
01195 {
01196 SetOperationStmt *op = (SetOperationStmt *) setOp;
01197
01198
01199 pull_up_union_leaf_queries(op->larg, root, parentRTindex, setOpQuery,
01200 childRToffset);
01201 pull_up_union_leaf_queries(op->rarg, root, parentRTindex, setOpQuery,
01202 childRToffset);
01203 }
01204 else
01205 {
01206 elog(ERROR, "unrecognized node type: %d",
01207 (int) nodeTag(setOp));
01208 }
01209 }
01210
01211
01212
01213
01214
01215
01216
01217
01218 static void
01219 make_setop_translation_list(Query *query, Index newvarno,
01220 List **translated_vars)
01221 {
01222 List *vars = NIL;
01223 ListCell *l;
01224
01225 foreach(l, query->targetList)
01226 {
01227 TargetEntry *tle = (TargetEntry *) lfirst(l);
01228
01229 if (tle->resjunk)
01230 continue;
01231
01232 vars = lappend(vars, makeVarFromTargetEntry(newvarno, tle));
01233 }
01234
01235 *translated_vars = vars;
01236 }
01237
01238
01239
01240
01241
01242
01243
01244
01245
01246
01247
01248 static bool
01249 is_simple_subquery(Query *subquery, RangeTblEntry *rte,
01250 JoinExpr *lowest_outer_join)
01251 {
01252
01253
01254
01255 if (!IsA(subquery, Query) ||
01256 subquery->commandType != CMD_SELECT ||
01257 subquery->utilityStmt != NULL)
01258 elog(ERROR, "subquery is bogus");
01259
01260
01261
01262
01263
01264
01265 if (subquery->setOperations)
01266 return false;
01267
01268
01269
01270
01271
01272
01273
01274
01275
01276
01277
01278 if (subquery->hasAggs ||
01279 subquery->hasWindowFuncs ||
01280 subquery->groupClause ||
01281 subquery->havingQual ||
01282 subquery->sortClause ||
01283 subquery->distinctClause ||
01284 subquery->limitOffset ||
01285 subquery->limitCount ||
01286 subquery->hasForUpdate ||
01287 subquery->cteList)
01288 return false;
01289
01290
01291
01292
01293
01294
01295 if (rte->security_barrier)
01296 return false;
01297
01298
01299
01300
01301
01302
01303
01304
01305 if (rte->lateral && lowest_outer_join != NULL)
01306 {
01307 Relids lvarnos = pull_varnos_of_level((Node *) subquery, 1);
01308 Relids jvarnos = get_relids_in_jointree((Node *) lowest_outer_join,
01309 true);
01310
01311 if (!bms_is_subset(lvarnos, jvarnos))
01312 return false;
01313 }
01314
01315
01316
01317
01318
01319
01320
01321 if (expression_returns_set((Node *) subquery->targetList))
01322 return false;
01323
01324
01325
01326
01327
01328
01329
01330
01331
01332 if (contain_volatile_functions((Node *) subquery->targetList))
01333 return false;
01334
01335
01336
01337
01338
01339
01340
01341
01342
01343
01344
01345
01346 if (subquery->jointree->fromlist == NIL)
01347 return false;
01348
01349 return true;
01350 }
01351
01352
01353
01354
01355
01356
01357
01358
01359
01360 static bool
01361 is_simple_union_all(Query *subquery)
01362 {
01363 SetOperationStmt *topop;
01364
01365
01366 if (!IsA(subquery, Query) ||
01367 subquery->commandType != CMD_SELECT ||
01368 subquery->utilityStmt != NULL)
01369 elog(ERROR, "subquery is bogus");
01370
01371
01372 topop = (SetOperationStmt *) subquery->setOperations;
01373 if (!topop)
01374 return false;
01375 Assert(IsA(topop, SetOperationStmt));
01376
01377
01378 if (subquery->sortClause ||
01379 subquery->limitOffset ||
01380 subquery->limitCount ||
01381 subquery->rowMarks ||
01382 subquery->cteList)
01383 return false;
01384
01385
01386 return is_simple_union_all_recurse((Node *) topop, subquery,
01387 topop->colTypes);
01388 }
01389
01390 static bool
01391 is_simple_union_all_recurse(Node *setOp, Query *setOpQuery, List *colTypes)
01392 {
01393 if (IsA(setOp, RangeTblRef))
01394 {
01395 RangeTblRef *rtr = (RangeTblRef *) setOp;
01396 RangeTblEntry *rte = rt_fetch(rtr->rtindex, setOpQuery->rtable);
01397 Query *subquery = rte->subquery;
01398
01399 Assert(subquery != NULL);
01400
01401
01402
01403 return tlist_same_datatypes(subquery->targetList, colTypes, true);
01404 }
01405 else if (IsA(setOp, SetOperationStmt))
01406 {
01407 SetOperationStmt *op = (SetOperationStmt *) setOp;
01408
01409
01410 if (op->op != SETOP_UNION || !op->all)
01411 return false;
01412
01413
01414 return is_simple_union_all_recurse(op->larg, setOpQuery, colTypes) &&
01415 is_simple_union_all_recurse(op->rarg, setOpQuery, colTypes);
01416 }
01417 else
01418 {
01419 elog(ERROR, "unrecognized node type: %d",
01420 (int) nodeTag(setOp));
01421 return false;
01422 }
01423 }
01424
01425
01426
01427
01428
01429
01430 static bool
01431 is_safe_append_member(Query *subquery)
01432 {
01433 FromExpr *jtnode;
01434
01435
01436
01437
01438
01439
01440
01441
01442
01443
01444
01445
01446 jtnode = subquery->jointree;
01447 while (IsA(jtnode, FromExpr))
01448 {
01449 if (jtnode->quals != NULL)
01450 return false;
01451 if (list_length(jtnode->fromlist) != 1)
01452 return false;
01453 jtnode = linitial(jtnode->fromlist);
01454 }
01455 if (!IsA(jtnode, RangeTblRef))
01456 return false;
01457
01458 return true;
01459 }
01460
01461
01462
01463
01464
01465
01466
01467
01468
01469 static void
01470 replace_vars_in_jointree(Node *jtnode,
01471 pullup_replace_vars_context *context,
01472 JoinExpr *lowest_nulling_outer_join)
01473 {
01474 if (jtnode == NULL)
01475 return;
01476 if (IsA(jtnode, RangeTblRef))
01477 {
01478
01479
01480
01481
01482
01483
01484
01485
01486
01487 int varno = ((RangeTblRef *) jtnode)->rtindex;
01488
01489 if (varno != context->varno)
01490 {
01491 RangeTblEntry *rte = rt_fetch(varno, context->root->parse->rtable);
01492
01493 Assert(rte != context->target_rte);
01494 if (rte->lateral)
01495 {
01496 switch (rte->rtekind)
01497 {
01498 case RTE_SUBQUERY:
01499 rte->subquery =
01500 pullup_replace_vars_subquery(rte->subquery,
01501 context);
01502 break;
01503 case RTE_FUNCTION:
01504 rte->funcexpr =
01505 pullup_replace_vars(rte->funcexpr,
01506 context);
01507 break;
01508 case RTE_VALUES:
01509 rte->values_lists = (List *)
01510 pullup_replace_vars((Node *) rte->values_lists,
01511 context);
01512 break;
01513 case RTE_RELATION:
01514 case RTE_JOIN:
01515 case RTE_CTE:
01516
01517 Assert(false);
01518 break;
01519 }
01520 }
01521 }
01522 }
01523 else if (IsA(jtnode, FromExpr))
01524 {
01525 FromExpr *f = (FromExpr *) jtnode;
01526 ListCell *l;
01527
01528 foreach(l, f->fromlist)
01529 replace_vars_in_jointree(lfirst(l), context,
01530 lowest_nulling_outer_join);
01531 f->quals = pullup_replace_vars(f->quals, context);
01532 }
01533 else if (IsA(jtnode, JoinExpr))
01534 {
01535 JoinExpr *j = (JoinExpr *) jtnode;
01536 bool save_need_phvs = context->need_phvs;
01537
01538 if (j == lowest_nulling_outer_join)
01539 {
01540
01541 context->need_phvs = false;
01542 lowest_nulling_outer_join = NULL;
01543 }
01544 replace_vars_in_jointree(j->larg, context, lowest_nulling_outer_join);
01545 replace_vars_in_jointree(j->rarg, context, lowest_nulling_outer_join);
01546 j->quals = pullup_replace_vars(j->quals, context);
01547
01548
01549
01550
01551
01552 context->need_phvs = save_need_phvs;
01553 }
01554 else
01555 elog(ERROR, "unrecognized node type: %d",
01556 (int) nodeTag(jtnode));
01557 }
01558
01559
01560
01561
01562
01563
01564
01565 static Node *
01566 pullup_replace_vars(Node *expr, pullup_replace_vars_context *context)
01567 {
01568 return replace_rte_variables(expr,
01569 context->varno, 0,
01570 pullup_replace_vars_callback,
01571 (void *) context,
01572 context->outer_hasSubLinks);
01573 }
01574
01575 static Node *
01576 pullup_replace_vars_callback(Var *var,
01577 replace_rte_variables_context *context)
01578 {
01579 pullup_replace_vars_context *rcon = (pullup_replace_vars_context *) context->callback_arg;
01580 int varattno = var->varattno;
01581 Node *newnode;
01582
01583
01584
01585
01586
01587
01588
01589
01590
01591
01592 if (rcon->need_phvs &&
01593 varattno >= InvalidAttrNumber &&
01594 varattno <= list_length(rcon->targetlist) &&
01595 rcon->rv_cache[varattno] != NULL)
01596 {
01597
01598 newnode = copyObject(rcon->rv_cache[varattno]);
01599 }
01600 else if (varattno == InvalidAttrNumber)
01601 {
01602
01603 RowExpr *rowexpr;
01604 List *colnames;
01605 List *fields;
01606 bool save_need_phvs = rcon->need_phvs;
01607 int save_sublevelsup = context->sublevels_up;
01608
01609
01610
01611
01612
01613
01614
01615
01616
01617
01618
01619 expandRTE(rcon->target_rte,
01620 var->varno, 0 , var->location,
01621 (var->vartype != RECORDOID),
01622 &colnames, &fields);
01623
01624 rcon->need_phvs = false;
01625 context->sublevels_up = 0;
01626 fields = (List *) replace_rte_variables_mutator((Node *) fields,
01627 context);
01628 rcon->need_phvs = save_need_phvs;
01629 context->sublevels_up = save_sublevelsup;
01630
01631 rowexpr = makeNode(RowExpr);
01632 rowexpr->args = fields;
01633 rowexpr->row_typeid = var->vartype;
01634 rowexpr->row_format = COERCE_IMPLICIT_CAST;
01635 rowexpr->colnames = colnames;
01636 rowexpr->location = var->location;
01637 newnode = (Node *) rowexpr;
01638
01639
01640
01641
01642
01643
01644
01645
01646 if (rcon->need_phvs)
01647 {
01648
01649 newnode = (Node *)
01650 make_placeholder_expr(rcon->root,
01651 (Expr *) newnode,
01652 bms_make_singleton(rcon->varno));
01653
01654 rcon->rv_cache[InvalidAttrNumber] = copyObject(newnode);
01655 }
01656 }
01657 else
01658 {
01659
01660 TargetEntry *tle = get_tle_by_resno(rcon->targetlist, varattno);
01661
01662 if (tle == NULL)
01663 elog(ERROR, "could not find attribute %d in subquery targetlist",
01664 varattno);
01665
01666
01667 newnode = copyObject(tle->expr);
01668
01669
01670 if (rcon->need_phvs)
01671 {
01672 bool wrap;
01673
01674 if (newnode && IsA(newnode, Var) &&
01675 ((Var *) newnode)->varlevelsup == 0)
01676 {
01677
01678 wrap = false;
01679 }
01680 else if (newnode && IsA(newnode, PlaceHolderVar) &&
01681 ((PlaceHolderVar *) newnode)->phlevelsup == 0)
01682 {
01683
01684 wrap = false;
01685 }
01686 else if (rcon->wrap_non_vars)
01687 {
01688
01689 wrap = true;
01690 }
01691 else
01692 {
01693
01694
01695
01696
01697
01698
01699
01700
01701
01702
01703
01704
01705
01706 if (contain_vars_of_level((Node *) newnode, 0) &&
01707 !contain_nonstrict_functions((Node *) newnode))
01708 {
01709
01710 wrap = false;
01711 }
01712 else
01713 {
01714
01715 wrap = true;
01716 }
01717 }
01718
01719 if (wrap)
01720 newnode = (Node *)
01721 make_placeholder_expr(rcon->root,
01722 (Expr *) newnode,
01723 bms_make_singleton(rcon->varno));
01724
01725
01726
01727
01728
01729
01730
01731 if (varattno > InvalidAttrNumber &&
01732 varattno <= list_length(rcon->targetlist))
01733 rcon->rv_cache[varattno] = copyObject(newnode);
01734 }
01735 }
01736
01737
01738 if (var->varlevelsup > 0)
01739 IncrementVarSublevelsUp(newnode, var->varlevelsup, 0);
01740
01741 return newnode;
01742 }
01743
01744
01745
01746
01747
01748
01749
01750
01751 static Query *
01752 pullup_replace_vars_subquery(Query *query,
01753 pullup_replace_vars_context *context)
01754 {
01755 Assert(IsA(query, Query));
01756 return (Query *) replace_rte_variables((Node *) query,
01757 context->varno, 1,
01758 pullup_replace_vars_callback,
01759 (void *) context,
01760 NULL);
01761 }
01762
01763
01764
01765
01766
01767
01768
01769
01770
01771
01772
01773
01774
01775
01776
01777
01778 void
01779 flatten_simple_union_all(PlannerInfo *root)
01780 {
01781 Query *parse = root->parse;
01782 SetOperationStmt *topop;
01783 Node *leftmostjtnode;
01784 int leftmostRTI;
01785 RangeTblEntry *leftmostRTE;
01786 int childRTI;
01787 RangeTblEntry *childRTE;
01788 RangeTblRef *rtr;
01789
01790
01791 topop = (SetOperationStmt *) parse->setOperations;
01792 Assert(topop && IsA(topop, SetOperationStmt));
01793
01794
01795 if (root->hasRecursion)
01796 return;
01797
01798
01799
01800
01801
01802 if (!is_simple_union_all_recurse((Node *) topop, parse, topop->colTypes))
01803 return;
01804
01805
01806
01807
01808
01809 leftmostjtnode = topop->larg;
01810 while (leftmostjtnode && IsA(leftmostjtnode, SetOperationStmt))
01811 leftmostjtnode = ((SetOperationStmt *) leftmostjtnode)->larg;
01812 Assert(leftmostjtnode && IsA(leftmostjtnode, RangeTblRef));
01813 leftmostRTI = ((RangeTblRef *) leftmostjtnode)->rtindex;
01814 leftmostRTE = rt_fetch(leftmostRTI, parse->rtable);
01815 Assert(leftmostRTE->rtekind == RTE_SUBQUERY);
01816
01817
01818
01819
01820
01821
01822
01823
01824 childRTE = copyObject(leftmostRTE);
01825 parse->rtable = lappend(parse->rtable, childRTE);
01826 childRTI = list_length(parse->rtable);
01827
01828
01829 ((RangeTblRef *) leftmostjtnode)->rtindex = childRTI;
01830
01831
01832 leftmostRTE->inh = true;
01833
01834
01835
01836
01837
01838 rtr = makeNode(RangeTblRef);
01839 rtr->rtindex = leftmostRTI;
01840 Assert(parse->jointree->fromlist == NIL);
01841 parse->jointree->fromlist = list_make1(rtr);
01842
01843
01844
01845
01846
01847 parse->setOperations = NULL;
01848
01849
01850
01851
01852
01853
01854
01855 pull_up_union_leaf_queries((Node *) topop, root, leftmostRTI, parse, 0);
01856 }
01857
01858
01859
01860
01861
01862
01863
01864
01865
01866
01867
01868
01869
01870
01871
01872
01873
01874
01875
01876
01877
01878
01879
01880
01881
01882
01883
01884
01885
01886
01887
01888
01889
01890
01891
01892
01893
01894
01895
01896 void
01897 reduce_outer_joins(PlannerInfo *root)
01898 {
01899 reduce_outer_joins_state *state;
01900
01901
01902
01903
01904
01905
01906
01907
01908
01909
01910 state = reduce_outer_joins_pass1((Node *) root->parse->jointree);
01911
01912
01913 if (state == NULL || !state->contains_outer)
01914 elog(ERROR, "so where are the outer joins?");
01915
01916 reduce_outer_joins_pass2((Node *) root->parse->jointree,
01917 state, root, NULL, NIL, NIL);
01918 }
01919
01920
01921
01922
01923
01924
01925 static reduce_outer_joins_state *
01926 reduce_outer_joins_pass1(Node *jtnode)
01927 {
01928 reduce_outer_joins_state *result;
01929
01930 result = (reduce_outer_joins_state *)
01931 palloc(sizeof(reduce_outer_joins_state));
01932 result->relids = NULL;
01933 result->contains_outer = false;
01934 result->sub_states = NIL;
01935
01936 if (jtnode == NULL)
01937 return result;
01938 if (IsA(jtnode, RangeTblRef))
01939 {
01940 int varno = ((RangeTblRef *) jtnode)->rtindex;
01941
01942 result->relids = bms_make_singleton(varno);
01943 }
01944 else if (IsA(jtnode, FromExpr))
01945 {
01946 FromExpr *f = (FromExpr *) jtnode;
01947 ListCell *l;
01948
01949 foreach(l, f->fromlist)
01950 {
01951 reduce_outer_joins_state *sub_state;
01952
01953 sub_state = reduce_outer_joins_pass1(lfirst(l));
01954 result->relids = bms_add_members(result->relids,
01955 sub_state->relids);
01956 result->contains_outer |= sub_state->contains_outer;
01957 result->sub_states = lappend(result->sub_states, sub_state);
01958 }
01959 }
01960 else if (IsA(jtnode, JoinExpr))
01961 {
01962 JoinExpr *j = (JoinExpr *) jtnode;
01963 reduce_outer_joins_state *sub_state;
01964
01965
01966 if (IS_OUTER_JOIN(j->jointype))
01967 result->contains_outer = true;
01968
01969 sub_state = reduce_outer_joins_pass1(j->larg);
01970 result->relids = bms_add_members(result->relids,
01971 sub_state->relids);
01972 result->contains_outer |= sub_state->contains_outer;
01973 result->sub_states = lappend(result->sub_states, sub_state);
01974
01975 sub_state = reduce_outer_joins_pass1(j->rarg);
01976 result->relids = bms_add_members(result->relids,
01977 sub_state->relids);
01978 result->contains_outer |= sub_state->contains_outer;
01979 result->sub_states = lappend(result->sub_states, sub_state);
01980 }
01981 else
01982 elog(ERROR, "unrecognized node type: %d",
01983 (int) nodeTag(jtnode));
01984 return result;
01985 }
01986
01987
01988
01989
01990
01991
01992
01993
01994
01995
01996
01997 static void
01998 reduce_outer_joins_pass2(Node *jtnode,
01999 reduce_outer_joins_state *state,
02000 PlannerInfo *root,
02001 Relids nonnullable_rels,
02002 List *nonnullable_vars,
02003 List *forced_null_vars)
02004 {
02005
02006
02007
02008
02009 if (jtnode == NULL)
02010 elog(ERROR, "reached empty jointree");
02011 if (IsA(jtnode, RangeTblRef))
02012 elog(ERROR, "reached base rel");
02013 else if (IsA(jtnode, FromExpr))
02014 {
02015 FromExpr *f = (FromExpr *) jtnode;
02016 ListCell *l;
02017 ListCell *s;
02018 Relids pass_nonnullable_rels;
02019 List *pass_nonnullable_vars;
02020 List *pass_forced_null_vars;
02021
02022
02023 pass_nonnullable_rels = find_nonnullable_rels(f->quals);
02024 pass_nonnullable_rels = bms_add_members(pass_nonnullable_rels,
02025 nonnullable_rels);
02026
02027 pass_nonnullable_vars = find_nonnullable_vars(f->quals);
02028 pass_nonnullable_vars = list_concat(pass_nonnullable_vars,
02029 nonnullable_vars);
02030 pass_forced_null_vars = find_forced_null_vars(f->quals);
02031 pass_forced_null_vars = list_concat(pass_forced_null_vars,
02032 forced_null_vars);
02033
02034 Assert(list_length(f->fromlist) == list_length(state->sub_states));
02035 forboth(l, f->fromlist, s, state->sub_states)
02036 {
02037 reduce_outer_joins_state *sub_state = lfirst(s);
02038
02039 if (sub_state->contains_outer)
02040 reduce_outer_joins_pass2(lfirst(l), sub_state, root,
02041 pass_nonnullable_rels,
02042 pass_nonnullable_vars,
02043 pass_forced_null_vars);
02044 }
02045 bms_free(pass_nonnullable_rels);
02046
02047 }
02048 else if (IsA(jtnode, JoinExpr))
02049 {
02050 JoinExpr *j = (JoinExpr *) jtnode;
02051 int rtindex = j->rtindex;
02052 JoinType jointype = j->jointype;
02053 reduce_outer_joins_state *left_state = linitial(state->sub_states);
02054 reduce_outer_joins_state *right_state = lsecond(state->sub_states);
02055 List *local_nonnullable_vars = NIL;
02056 bool computed_local_nonnullable_vars = false;
02057
02058
02059 switch (jointype)
02060 {
02061 case JOIN_INNER:
02062 break;
02063 case JOIN_LEFT:
02064 if (bms_overlap(nonnullable_rels, right_state->relids))
02065 jointype = JOIN_INNER;
02066 break;
02067 case JOIN_RIGHT:
02068 if (bms_overlap(nonnullable_rels, left_state->relids))
02069 jointype = JOIN_INNER;
02070 break;
02071 case JOIN_FULL:
02072 if (bms_overlap(nonnullable_rels, left_state->relids))
02073 {
02074 if (bms_overlap(nonnullable_rels, right_state->relids))
02075 jointype = JOIN_INNER;
02076 else
02077 jointype = JOIN_LEFT;
02078 }
02079 else
02080 {
02081 if (bms_overlap(nonnullable_rels, right_state->relids))
02082 jointype = JOIN_RIGHT;
02083 }
02084 break;
02085 case JOIN_SEMI:
02086 case JOIN_ANTI:
02087
02088
02089
02090
02091
02092
02093 break;
02094 default:
02095 elog(ERROR, "unrecognized join type: %d",
02096 (int) jointype);
02097 break;
02098 }
02099
02100
02101
02102
02103
02104
02105
02106
02107 if (jointype == JOIN_RIGHT)
02108 {
02109 Node *tmparg;
02110
02111 tmparg = j->larg;
02112 j->larg = j->rarg;
02113 j->rarg = tmparg;
02114 jointype = JOIN_LEFT;
02115 right_state = linitial(state->sub_states);
02116 left_state = lsecond(state->sub_states);
02117 }
02118
02119
02120
02121
02122
02123
02124
02125
02126
02127
02128
02129 if (jointype == JOIN_LEFT)
02130 {
02131 List *overlap;
02132
02133 local_nonnullable_vars = find_nonnullable_vars(j->quals);
02134 computed_local_nonnullable_vars = true;
02135
02136
02137
02138
02139
02140
02141 overlap = list_intersection(local_nonnullable_vars,
02142 forced_null_vars);
02143 if (overlap != NIL &&
02144 bms_overlap(pull_varnos((Node *) overlap),
02145 right_state->relids))
02146 jointype = JOIN_ANTI;
02147 }
02148
02149
02150 if (rtindex && jointype != j->jointype)
02151 {
02152 RangeTblEntry *rte = rt_fetch(rtindex, root->parse->rtable);
02153
02154 Assert(rte->rtekind == RTE_JOIN);
02155 Assert(rte->jointype == j->jointype);
02156 rte->jointype = jointype;
02157 }
02158 j->jointype = jointype;
02159
02160
02161 if (left_state->contains_outer || right_state->contains_outer)
02162 {
02163 Relids local_nonnullable_rels;
02164 List *local_forced_null_vars;
02165 Relids pass_nonnullable_rels;
02166 List *pass_nonnullable_vars;
02167 List *pass_forced_null_vars;
02168
02169
02170
02171
02172
02173
02174
02175
02176
02177
02178
02179
02180
02181
02182
02183
02184
02185
02186
02187
02188
02189
02190 if (jointype != JOIN_FULL)
02191 {
02192 local_nonnullable_rels = find_nonnullable_rels(j->quals);
02193 if (!computed_local_nonnullable_vars)
02194 local_nonnullable_vars = find_nonnullable_vars(j->quals);
02195 local_forced_null_vars = find_forced_null_vars(j->quals);
02196 if (jointype == JOIN_INNER || jointype == JOIN_SEMI)
02197 {
02198
02199 local_nonnullable_rels = bms_add_members(local_nonnullable_rels,
02200 nonnullable_rels);
02201 local_nonnullable_vars = list_concat(local_nonnullable_vars,
02202 nonnullable_vars);
02203 local_forced_null_vars = list_concat(local_forced_null_vars,
02204 forced_null_vars);
02205 }
02206 }
02207 else
02208 {
02209
02210 local_nonnullable_rels = NULL;
02211 local_forced_null_vars = NIL;
02212 }
02213
02214 if (left_state->contains_outer)
02215 {
02216 if (jointype == JOIN_INNER || jointype == JOIN_SEMI)
02217 {
02218
02219 pass_nonnullable_rels = local_nonnullable_rels;
02220 pass_nonnullable_vars = local_nonnullable_vars;
02221 pass_forced_null_vars = local_forced_null_vars;
02222 }
02223 else if (jointype != JOIN_FULL)
02224 {
02225
02226 pass_nonnullable_rels = nonnullable_rels;
02227 pass_nonnullable_vars = nonnullable_vars;
02228 pass_forced_null_vars = forced_null_vars;
02229 }
02230 else
02231 {
02232
02233 pass_nonnullable_rels = NULL;
02234 pass_nonnullable_vars = NIL;
02235 pass_forced_null_vars = NIL;
02236 }
02237 reduce_outer_joins_pass2(j->larg, left_state, root,
02238 pass_nonnullable_rels,
02239 pass_nonnullable_vars,
02240 pass_forced_null_vars);
02241 }
02242
02243 if (right_state->contains_outer)
02244 {
02245 if (jointype != JOIN_FULL)
02246 {
02247
02248 pass_nonnullable_rels = local_nonnullable_rels;
02249 pass_nonnullable_vars = local_nonnullable_vars;
02250 pass_forced_null_vars = local_forced_null_vars;
02251 }
02252 else
02253 {
02254
02255 pass_nonnullable_rels = NULL;
02256 pass_nonnullable_vars = NIL;
02257 pass_forced_null_vars = NIL;
02258 }
02259 reduce_outer_joins_pass2(j->rarg, right_state, root,
02260 pass_nonnullable_rels,
02261 pass_nonnullable_vars,
02262 pass_forced_null_vars);
02263 }
02264 bms_free(local_nonnullable_rels);
02265 }
02266 }
02267 else
02268 elog(ERROR, "unrecognized node type: %d",
02269 (int) nodeTag(jtnode));
02270 }
02271
02272
02273
02274
02275
02276
02277
02278
02279
02280
02281
02282
02283
02284
02285 typedef struct
02286 {
02287 int varno;
02288 int sublevels_up;
02289 Relids subrelids;
02290 } substitute_multiple_relids_context;
02291
02292 static bool
02293 substitute_multiple_relids_walker(Node *node,
02294 substitute_multiple_relids_context *context)
02295 {
02296 if (node == NULL)
02297 return false;
02298 if (IsA(node, PlaceHolderVar))
02299 {
02300 PlaceHolderVar *phv = (PlaceHolderVar *) node;
02301
02302 if (phv->phlevelsup == context->sublevels_up &&
02303 bms_is_member(context->varno, phv->phrels))
02304 {
02305 phv->phrels = bms_union(phv->phrels,
02306 context->subrelids);
02307 phv->phrels = bms_del_member(phv->phrels,
02308 context->varno);
02309 }
02310
02311 }
02312 if (IsA(node, Query))
02313 {
02314
02315 bool result;
02316
02317 context->sublevels_up++;
02318 result = query_tree_walker((Query *) node,
02319 substitute_multiple_relids_walker,
02320 (void *) context, 0);
02321 context->sublevels_up--;
02322 return result;
02323 }
02324
02325 Assert(!IsA(node, SpecialJoinInfo));
02326 Assert(!IsA(node, LateralJoinInfo));
02327 Assert(!IsA(node, AppendRelInfo));
02328 Assert(!IsA(node, PlaceHolderInfo));
02329 Assert(!IsA(node, MinMaxAggInfo));
02330
02331 return expression_tree_walker(node, substitute_multiple_relids_walker,
02332 (void *) context);
02333 }
02334
02335 static void
02336 substitute_multiple_relids(Node *node, int varno, Relids subrelids)
02337 {
02338 substitute_multiple_relids_context context;
02339
02340 context.varno = varno;
02341 context.sublevels_up = 0;
02342 context.subrelids = subrelids;
02343
02344
02345
02346
02347 query_or_expression_tree_walker(node,
02348 substitute_multiple_relids_walker,
02349 (void *) &context,
02350 0);
02351 }
02352
02353
02354
02355
02356
02357
02358
02359
02360
02361
02362
02363 static void
02364 fix_append_rel_relids(List *append_rel_list, int varno, Relids subrelids)
02365 {
02366 ListCell *l;
02367 int subvarno = -1;
02368
02369
02370
02371
02372
02373
02374
02375 foreach(l, append_rel_list)
02376 {
02377 AppendRelInfo *appinfo = (AppendRelInfo *) lfirst(l);
02378
02379
02380 Assert(appinfo->parent_relid != varno);
02381
02382 if (appinfo->child_relid == varno)
02383 {
02384 if (subvarno < 0)
02385 subvarno = bms_singleton_member(subrelids);
02386 appinfo->child_relid = subvarno;
02387 }
02388
02389
02390 substitute_multiple_relids((Node *) appinfo->translated_vars,
02391 varno, subrelids);
02392 }
02393 }
02394
02395
02396
02397
02398
02399
02400
02401 Relids
02402 get_relids_in_jointree(Node *jtnode, bool include_joins)
02403 {
02404 Relids result = NULL;
02405
02406 if (jtnode == NULL)
02407 return result;
02408 if (IsA(jtnode, RangeTblRef))
02409 {
02410 int varno = ((RangeTblRef *) jtnode)->rtindex;
02411
02412 result = bms_make_singleton(varno);
02413 }
02414 else if (IsA(jtnode, FromExpr))
02415 {
02416 FromExpr *f = (FromExpr *) jtnode;
02417 ListCell *l;
02418
02419 foreach(l, f->fromlist)
02420 {
02421 result = bms_join(result,
02422 get_relids_in_jointree(lfirst(l),
02423 include_joins));
02424 }
02425 }
02426 else if (IsA(jtnode, JoinExpr))
02427 {
02428 JoinExpr *j = (JoinExpr *) jtnode;
02429
02430 result = get_relids_in_jointree(j->larg, include_joins);
02431 result = bms_join(result,
02432 get_relids_in_jointree(j->rarg, include_joins));
02433 if (include_joins && j->rtindex)
02434 result = bms_add_member(result, j->rtindex);
02435 }
02436 else
02437 elog(ERROR, "unrecognized node type: %d",
02438 (int) nodeTag(jtnode));
02439 return result;
02440 }
02441
02442
02443
02444
02445 Relids
02446 get_relids_for_join(PlannerInfo *root, int joinrelid)
02447 {
02448 Node *jtnode;
02449
02450 jtnode = find_jointree_node_for_rel((Node *) root->parse->jointree,
02451 joinrelid);
02452 if (!jtnode)
02453 elog(ERROR, "could not find join node %d", joinrelid);
02454 return get_relids_in_jointree(jtnode, false);
02455 }
02456
02457
02458
02459
02460
02461
02462 static Node *
02463 find_jointree_node_for_rel(Node *jtnode, int relid)
02464 {
02465 if (jtnode == NULL)
02466 return NULL;
02467 if (IsA(jtnode, RangeTblRef))
02468 {
02469 int varno = ((RangeTblRef *) jtnode)->rtindex;
02470
02471 if (relid == varno)
02472 return jtnode;
02473 }
02474 else if (IsA(jtnode, FromExpr))
02475 {
02476 FromExpr *f = (FromExpr *) jtnode;
02477 ListCell *l;
02478
02479 foreach(l, f->fromlist)
02480 {
02481 jtnode = find_jointree_node_for_rel(lfirst(l), relid);
02482 if (jtnode)
02483 return jtnode;
02484 }
02485 }
02486 else if (IsA(jtnode, JoinExpr))
02487 {
02488 JoinExpr *j = (JoinExpr *) jtnode;
02489
02490 if (relid == j->rtindex)
02491 return jtnode;
02492 jtnode = find_jointree_node_for_rel(j->larg, relid);
02493 if (jtnode)
02494 return jtnode;
02495 jtnode = find_jointree_node_for_rel(j->rarg, relid);
02496 if (jtnode)
02497 return jtnode;
02498 }
02499 else
02500 elog(ERROR, "unrecognized node type: %d",
02501 (int) nodeTag(jtnode));
02502 return NULL;
02503 }