00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016 #include "postgres.h"
00017
00018 #include <math.h>
00019
00020 #include "catalog/pg_class.h"
00021 #include "foreign/fdwapi.h"
00022 #include "nodes/nodeFuncs.h"
00023 #ifdef OPTIMIZER_DEBUG
00024 #include "nodes/print.h"
00025 #endif
00026 #include "optimizer/clauses.h"
00027 #include "optimizer/cost.h"
00028 #include "optimizer/geqo.h"
00029 #include "optimizer/pathnode.h"
00030 #include "optimizer/paths.h"
00031 #include "optimizer/plancat.h"
00032 #include "optimizer/planner.h"
00033 #include "optimizer/prep.h"
00034 #include "optimizer/restrictinfo.h"
00035 #include "optimizer/var.h"
00036 #include "parser/parse_clause.h"
00037 #include "parser/parsetree.h"
00038 #include "rewrite/rewriteManip.h"
00039 #include "utils/lsyscache.h"
00040
00041
00042
00043 bool enable_geqo = false;
00044 int geqo_threshold;
00045
00046
00047 join_search_hook_type join_search_hook = NULL;
00048
00049
00050 static void set_base_rel_sizes(PlannerInfo *root);
00051 static void set_base_rel_pathlists(PlannerInfo *root);
00052 static void set_rel_size(PlannerInfo *root, RelOptInfo *rel,
00053 Index rti, RangeTblEntry *rte);
00054 static void set_rel_pathlist(PlannerInfo *root, RelOptInfo *rel,
00055 Index rti, RangeTblEntry *rte);
00056 static void set_plain_rel_size(PlannerInfo *root, RelOptInfo *rel,
00057 RangeTblEntry *rte);
00058 static void set_plain_rel_pathlist(PlannerInfo *root, RelOptInfo *rel,
00059 RangeTblEntry *rte);
00060 static void set_foreign_size(PlannerInfo *root, RelOptInfo *rel,
00061 RangeTblEntry *rte);
00062 static void set_foreign_pathlist(PlannerInfo *root, RelOptInfo *rel,
00063 RangeTblEntry *rte);
00064 static void set_append_rel_size(PlannerInfo *root, RelOptInfo *rel,
00065 Index rti, RangeTblEntry *rte);
00066 static void set_append_rel_pathlist(PlannerInfo *root, RelOptInfo *rel,
00067 Index rti, RangeTblEntry *rte);
00068 static void generate_mergeappend_paths(PlannerInfo *root, RelOptInfo *rel,
00069 List *live_childrels,
00070 List *all_child_pathkeys);
00071 static List *accumulate_append_subpath(List *subpaths, Path *path);
00072 static void set_dummy_rel_pathlist(RelOptInfo *rel);
00073 static void set_subquery_pathlist(PlannerInfo *root, RelOptInfo *rel,
00074 Index rti, RangeTblEntry *rte);
00075 static void set_function_pathlist(PlannerInfo *root, RelOptInfo *rel,
00076 RangeTblEntry *rte);
00077 static void set_values_pathlist(PlannerInfo *root, RelOptInfo *rel,
00078 RangeTblEntry *rte);
00079 static void set_cte_pathlist(PlannerInfo *root, RelOptInfo *rel,
00080 RangeTblEntry *rte);
00081 static void set_worktable_pathlist(PlannerInfo *root, RelOptInfo *rel,
00082 RangeTblEntry *rte);
00083 static RelOptInfo *make_rel_from_joinlist(PlannerInfo *root, List *joinlist);
00084 static bool subquery_is_pushdown_safe(Query *subquery, Query *topquery,
00085 bool *differentTypes);
00086 static bool recurse_pushdown_safe(Node *setOp, Query *topquery,
00087 bool *differentTypes);
00088 static void compare_tlist_datatypes(List *tlist, List *colTypes,
00089 bool *differentTypes);
00090 static bool qual_is_pushdown_safe(Query *subquery, Index rti, Node *qual,
00091 bool *differentTypes);
00092 static void subquery_push_qual(Query *subquery,
00093 RangeTblEntry *rte, Index rti, Node *qual);
00094 static void recurse_push_qual(Node *setOp, Query *topquery,
00095 RangeTblEntry *rte, Index rti, Node *qual);
00096
00097
00098
00099
00100
00101
00102
00103 RelOptInfo *
00104 make_one_rel(PlannerInfo *root, List *joinlist)
00105 {
00106 RelOptInfo *rel;
00107 Index rti;
00108
00109
00110
00111
00112 root->all_baserels = NULL;
00113 for (rti = 1; rti < root->simple_rel_array_size; rti++)
00114 {
00115 RelOptInfo *brel = root->simple_rel_array[rti];
00116
00117
00118 if (brel == NULL)
00119 continue;
00120
00121 Assert(brel->relid == rti);
00122
00123
00124 if (brel->reloptkind != RELOPT_BASEREL)
00125 continue;
00126
00127 root->all_baserels = bms_add_member(root->all_baserels, brel->relid);
00128 }
00129
00130
00131
00132
00133 set_base_rel_sizes(root);
00134 set_base_rel_pathlists(root);
00135
00136
00137
00138
00139 rel = make_rel_from_joinlist(root, joinlist);
00140
00141
00142
00143
00144 Assert(bms_equal(rel->relids, root->all_baserels));
00145
00146 return rel;
00147 }
00148
00149
00150
00151
00152
00153
00154
00155
00156 static void
00157 set_base_rel_sizes(PlannerInfo *root)
00158 {
00159 Index rti;
00160
00161 for (rti = 1; rti < root->simple_rel_array_size; rti++)
00162 {
00163 RelOptInfo *rel = root->simple_rel_array[rti];
00164
00165
00166 if (rel == NULL)
00167 continue;
00168
00169 Assert(rel->relid == rti);
00170
00171
00172 if (rel->reloptkind != RELOPT_BASEREL)
00173 continue;
00174
00175 set_rel_size(root, rel, rti, root->simple_rte_array[rti]);
00176 }
00177 }
00178
00179
00180
00181
00182
00183
00184
00185 static void
00186 set_base_rel_pathlists(PlannerInfo *root)
00187 {
00188 Index rti;
00189
00190 for (rti = 1; rti < root->simple_rel_array_size; rti++)
00191 {
00192 RelOptInfo *rel = root->simple_rel_array[rti];
00193
00194
00195 if (rel == NULL)
00196 continue;
00197
00198 Assert(rel->relid == rti);
00199
00200
00201 if (rel->reloptkind != RELOPT_BASEREL)
00202 continue;
00203
00204 set_rel_pathlist(root, rel, rti, root->simple_rte_array[rti]);
00205 }
00206 }
00207
00208
00209
00210
00211
00212 static void
00213 set_rel_size(PlannerInfo *root, RelOptInfo *rel,
00214 Index rti, RangeTblEntry *rte)
00215 {
00216 if (rel->reloptkind == RELOPT_BASEREL &&
00217 relation_excluded_by_constraints(root, rel, rte))
00218 {
00219
00220
00221
00222
00223
00224
00225
00226
00227
00228
00229
00230 set_dummy_rel_pathlist(rel);
00231 }
00232 else if (rte->inh)
00233 {
00234
00235 set_append_rel_size(root, rel, rti, rte);
00236 }
00237 else
00238 {
00239 switch (rel->rtekind)
00240 {
00241 case RTE_RELATION:
00242 if (rte->relkind == RELKIND_FOREIGN_TABLE)
00243 {
00244
00245 set_foreign_size(root, rel, rte);
00246 }
00247 else
00248 {
00249
00250 set_plain_rel_size(root, rel, rte);
00251 }
00252 break;
00253 case RTE_SUBQUERY:
00254
00255
00256
00257
00258
00259
00260 set_subquery_pathlist(root, rel, rti, rte);
00261 break;
00262 case RTE_FUNCTION:
00263 set_function_size_estimates(root, rel);
00264 break;
00265 case RTE_VALUES:
00266 set_values_size_estimates(root, rel);
00267 break;
00268 case RTE_CTE:
00269
00270
00271
00272
00273
00274
00275 if (rte->self_reference)
00276 set_worktable_pathlist(root, rel, rte);
00277 else
00278 set_cte_pathlist(root, rel, rte);
00279 break;
00280 default:
00281 elog(ERROR, "unexpected rtekind: %d", (int) rel->rtekind);
00282 break;
00283 }
00284 }
00285 }
00286
00287
00288
00289
00290
00291 static void
00292 set_rel_pathlist(PlannerInfo *root, RelOptInfo *rel,
00293 Index rti, RangeTblEntry *rte)
00294 {
00295 if (IS_DUMMY_REL(rel))
00296 {
00297
00298 }
00299 else if (rte->inh)
00300 {
00301
00302 set_append_rel_pathlist(root, rel, rti, rte);
00303 }
00304 else
00305 {
00306 switch (rel->rtekind)
00307 {
00308 case RTE_RELATION:
00309 if (rte->relkind == RELKIND_FOREIGN_TABLE)
00310 {
00311
00312 set_foreign_pathlist(root, rel, rte);
00313 }
00314 else
00315 {
00316
00317 set_plain_rel_pathlist(root, rel, rte);
00318 }
00319 break;
00320 case RTE_SUBQUERY:
00321
00322 break;
00323 case RTE_FUNCTION:
00324
00325 set_function_pathlist(root, rel, rte);
00326 break;
00327 case RTE_VALUES:
00328
00329 set_values_pathlist(root, rel, rte);
00330 break;
00331 case RTE_CTE:
00332
00333 break;
00334 default:
00335 elog(ERROR, "unexpected rtekind: %d", (int) rel->rtekind);
00336 break;
00337 }
00338 }
00339
00340 #ifdef OPTIMIZER_DEBUG
00341 debug_print_rel(root, rel);
00342 #endif
00343 }
00344
00345
00346
00347
00348
00349 static void
00350 set_plain_rel_size(PlannerInfo *root, RelOptInfo *rel, RangeTblEntry *rte)
00351 {
00352
00353
00354
00355
00356 check_partial_indexes(root, rel);
00357
00358
00359 set_baserel_size_estimates(root, rel);
00360
00361
00362
00363
00364
00365
00366 if (create_or_index_quals(root, rel))
00367 {
00368 check_partial_indexes(root, rel);
00369 set_baserel_size_estimates(root, rel);
00370 }
00371 }
00372
00373
00374
00375
00376
00377 static void
00378 set_plain_rel_pathlist(PlannerInfo *root, RelOptInfo *rel, RangeTblEntry *rte)
00379 {
00380 Relids required_outer;
00381
00382
00383
00384
00385
00386
00387
00388 required_outer = rel->lateral_relids;
00389
00390
00391 add_path(rel, create_seqscan_path(root, rel, required_outer));
00392
00393
00394 create_index_paths(root, rel);
00395
00396
00397 create_tidscan_paths(root, rel);
00398
00399
00400 set_cheapest(rel);
00401 }
00402
00403
00404
00405
00406
00407 static void
00408 set_foreign_size(PlannerInfo *root, RelOptInfo *rel, RangeTblEntry *rte)
00409 {
00410
00411 set_foreign_size_estimates(root, rel);
00412
00413
00414 rel->fdwroutine->GetForeignRelSize(root, rel, rte->relid);
00415 }
00416
00417
00418
00419
00420
00421 static void
00422 set_foreign_pathlist(PlannerInfo *root, RelOptInfo *rel, RangeTblEntry *rte)
00423 {
00424
00425 rel->fdwroutine->GetForeignPaths(root, rel, rte->relid);
00426
00427
00428 set_cheapest(rel);
00429 }
00430
00431
00432
00433
00434
00435
00436
00437
00438
00439
00440
00441
00442 static void
00443 set_append_rel_size(PlannerInfo *root, RelOptInfo *rel,
00444 Index rti, RangeTblEntry *rte)
00445 {
00446 int parentRTindex = rti;
00447 double parent_rows;
00448 double parent_size;
00449 double *parent_attrsizes;
00450 int nattrs;
00451 ListCell *l;
00452
00453
00454
00455
00456
00457
00458
00459
00460
00461
00462
00463
00464
00465
00466
00467 parent_rows = 0;
00468 parent_size = 0;
00469 nattrs = rel->max_attr - rel->min_attr + 1;
00470 parent_attrsizes = (double *) palloc0(nattrs * sizeof(double));
00471
00472 foreach(l, root->append_rel_list)
00473 {
00474 AppendRelInfo *appinfo = (AppendRelInfo *) lfirst(l);
00475 int childRTindex;
00476 RangeTblEntry *childRTE;
00477 RelOptInfo *childrel;
00478 List *childquals;
00479 Node *childqual;
00480 ListCell *parentvars;
00481 ListCell *childvars;
00482
00483
00484 if (appinfo->parent_relid != parentRTindex)
00485 continue;
00486
00487 childRTindex = appinfo->child_relid;
00488 childRTE = root->simple_rte_array[childRTindex];
00489
00490
00491
00492
00493
00494 childrel = find_base_rel(root, childRTindex);
00495 Assert(childrel->reloptkind == RELOPT_OTHER_MEMBER_REL);
00496
00497
00498
00499
00500
00501
00502
00503
00504
00505
00506
00507
00508
00509
00510
00511 childquals = get_all_actual_clauses(rel->baserestrictinfo);
00512 childquals = (List *) adjust_appendrel_attrs(root,
00513 (Node *) childquals,
00514 appinfo);
00515 childqual = eval_const_expressions(root, (Node *)
00516 make_ands_explicit(childquals));
00517 if (childqual && IsA(childqual, Const) &&
00518 (((Const *) childqual)->constisnull ||
00519 !DatumGetBool(((Const *) childqual)->constvalue)))
00520 {
00521
00522
00523
00524
00525 set_dummy_rel_pathlist(childrel);
00526 continue;
00527 }
00528 childquals = make_ands_implicit((Expr *) childqual);
00529 childquals = make_restrictinfos_from_actual_clauses(root,
00530 childquals);
00531 childrel->baserestrictinfo = childquals;
00532
00533 if (relation_excluded_by_constraints(root, childrel, childRTE))
00534 {
00535
00536
00537
00538
00539 set_dummy_rel_pathlist(childrel);
00540 continue;
00541 }
00542
00543
00544
00545
00546
00547
00548
00549
00550
00551
00552 childrel->joininfo = (List *)
00553 adjust_appendrel_attrs(root,
00554 (Node *) rel->joininfo,
00555 appinfo);
00556 childrel->reltargetlist = (List *)
00557 adjust_appendrel_attrs(root,
00558 (Node *) rel->reltargetlist,
00559 appinfo);
00560
00561
00562
00563
00564
00565
00566
00567
00568
00569 if (rel->has_eclass_joins || has_useful_pathkeys(root, rel))
00570 add_child_rel_equivalences(root, appinfo, rel, childrel);
00571 childrel->has_eclass_joins = rel->has_eclass_joins;
00572
00573
00574
00575
00576
00577
00578
00579
00580
00581
00582
00583
00584 set_rel_size(root, childrel, childRTindex, childRTE);
00585
00586
00587
00588
00589
00590
00591 if (IS_DUMMY_REL(childrel))
00592 continue;
00593
00594
00595
00596
00597 if (childrel->rows > 0)
00598 {
00599 parent_rows += childrel->rows;
00600 parent_size += childrel->width * childrel->rows;
00601
00602
00603
00604
00605
00606
00607
00608
00609
00610 forboth(parentvars, rel->reltargetlist,
00611 childvars, childrel->reltargetlist)
00612 {
00613 Var *parentvar = (Var *) lfirst(parentvars);
00614 Node *childvar = (Node *) lfirst(childvars);
00615
00616 if (IsA(parentvar, Var))
00617 {
00618 int pndx = parentvar->varattno - rel->min_attr;
00619 int32 child_width = 0;
00620
00621 if (IsA(childvar, Var) &&
00622 ((Var *) childvar)->varno == childrel->relid)
00623 {
00624 int cndx = ((Var *) childvar)->varattno - childrel->min_attr;
00625
00626 child_width = childrel->attr_widths[cndx];
00627 }
00628 if (child_width <= 0)
00629 child_width = get_typavgwidth(exprType(childvar),
00630 exprTypmod(childvar));
00631 Assert(child_width > 0);
00632 parent_attrsizes[pndx] += child_width * childrel->rows;
00633 }
00634 }
00635 }
00636 }
00637
00638
00639
00640
00641 rel->rows = parent_rows;
00642 if (parent_rows > 0)
00643 {
00644 int i;
00645
00646 rel->width = rint(parent_size / parent_rows);
00647 for (i = 0; i < nattrs; i++)
00648 rel->attr_widths[i] = rint(parent_attrsizes[i] / parent_rows);
00649 }
00650 else
00651 rel->width = 0;
00652
00653
00654
00655
00656
00657 rel->tuples = parent_rows;
00658
00659 pfree(parent_attrsizes);
00660 }
00661
00662
00663
00664
00665
00666 static void
00667 set_append_rel_pathlist(PlannerInfo *root, RelOptInfo *rel,
00668 Index rti, RangeTblEntry *rte)
00669 {
00670 int parentRTindex = rti;
00671 List *live_childrels = NIL;
00672 List *subpaths = NIL;
00673 bool subpaths_valid = true;
00674 List *all_child_pathkeys = NIL;
00675 List *all_child_outers = NIL;
00676 ListCell *l;
00677
00678
00679
00680
00681
00682
00683
00684 foreach(l, root->append_rel_list)
00685 {
00686 AppendRelInfo *appinfo = (AppendRelInfo *) lfirst(l);
00687 int childRTindex;
00688 RangeTblEntry *childRTE;
00689 RelOptInfo *childrel;
00690 ListCell *lcp;
00691
00692
00693 if (appinfo->parent_relid != parentRTindex)
00694 continue;
00695
00696
00697 childRTindex = appinfo->child_relid;
00698 childRTE = root->simple_rte_array[childRTindex];
00699 childrel = root->simple_rel_array[childRTindex];
00700
00701
00702
00703
00704 set_rel_pathlist(root, childrel, childRTindex, childRTE);
00705
00706
00707
00708
00709 if (IS_DUMMY_REL(childrel))
00710 continue;
00711
00712
00713
00714
00715 live_childrels = lappend(live_childrels, childrel);
00716
00717
00718
00719
00720
00721
00722 if (childrel->cheapest_total_path->param_info == NULL)
00723 subpaths = accumulate_append_subpath(subpaths,
00724 childrel->cheapest_total_path);
00725 else
00726 subpaths_valid = false;
00727
00728
00729
00730
00731
00732
00733
00734 foreach(lcp, childrel->pathlist)
00735 {
00736 Path *childpath = (Path *) lfirst(lcp);
00737 List *childkeys = childpath->pathkeys;
00738 Relids childouter = PATH_REQ_OUTER(childpath);
00739
00740
00741 if (childkeys != NIL)
00742 {
00743 ListCell *lpk;
00744 bool found = false;
00745
00746
00747 foreach(lpk, all_child_pathkeys)
00748 {
00749 List *existing_pathkeys = (List *) lfirst(lpk);
00750
00751 if (compare_pathkeys(existing_pathkeys,
00752 childkeys) == PATHKEYS_EQUAL)
00753 {
00754 found = true;
00755 break;
00756 }
00757 }
00758 if (!found)
00759 {
00760
00761 all_child_pathkeys = lappend(all_child_pathkeys,
00762 childkeys);
00763 }
00764 }
00765
00766
00767 if (childouter)
00768 {
00769 ListCell *lco;
00770 bool found = false;
00771
00772
00773 foreach(lco, all_child_outers)
00774 {
00775 Relids existing_outers = (Relids) lfirst(lco);
00776
00777 if (bms_equal(existing_outers, childouter))
00778 {
00779 found = true;
00780 break;
00781 }
00782 }
00783 if (!found)
00784 {
00785
00786 all_child_outers = lappend(all_child_outers,
00787 childouter);
00788 }
00789 }
00790 }
00791 }
00792
00793
00794
00795
00796
00797
00798 if (subpaths_valid)
00799 add_path(rel, (Path *) create_append_path(rel, subpaths, NULL));
00800
00801
00802
00803
00804
00805 if (subpaths_valid)
00806 generate_mergeappend_paths(root, rel, live_childrels,
00807 all_child_pathkeys);
00808
00809
00810
00811
00812
00813
00814
00815
00816
00817
00818
00819
00820
00821
00822 foreach(l, all_child_outers)
00823 {
00824 Relids required_outer = (Relids) lfirst(l);
00825 ListCell *lcr;
00826
00827
00828 subpaths = NIL;
00829 subpaths_valid = true;
00830 foreach(lcr, live_childrels)
00831 {
00832 RelOptInfo *childrel = (RelOptInfo *) lfirst(lcr);
00833 Path *cheapest_total;
00834
00835 cheapest_total =
00836 get_cheapest_path_for_pathkeys(childrel->pathlist,
00837 NIL,
00838 required_outer,
00839 TOTAL_COST);
00840 Assert(cheapest_total != NULL);
00841
00842
00843 if (!bms_equal(PATH_REQ_OUTER(cheapest_total), required_outer))
00844 {
00845 cheapest_total = reparameterize_path(root, cheapest_total,
00846 required_outer, 1.0);
00847 if (cheapest_total == NULL)
00848 {
00849 subpaths_valid = false;
00850 break;
00851 }
00852 }
00853
00854 subpaths = accumulate_append_subpath(subpaths, cheapest_total);
00855 }
00856
00857 if (subpaths_valid)
00858 add_path(rel, (Path *)
00859 create_append_path(rel, subpaths, required_outer));
00860 }
00861
00862
00863 set_cheapest(rel);
00864 }
00865
00866
00867
00868
00869
00870
00871
00872
00873
00874
00875
00876
00877
00878
00879
00880
00881
00882
00883
00884
00885
00886
00887
00888
00889 static void
00890 generate_mergeappend_paths(PlannerInfo *root, RelOptInfo *rel,
00891 List *live_childrels,
00892 List *all_child_pathkeys)
00893 {
00894 ListCell *lcp;
00895
00896 foreach(lcp, all_child_pathkeys)
00897 {
00898 List *pathkeys = (List *) lfirst(lcp);
00899 List *startup_subpaths = NIL;
00900 List *total_subpaths = NIL;
00901 bool startup_neq_total = false;
00902 ListCell *lcr;
00903
00904
00905 foreach(lcr, live_childrels)
00906 {
00907 RelOptInfo *childrel = (RelOptInfo *) lfirst(lcr);
00908 Path *cheapest_startup,
00909 *cheapest_total;
00910
00911
00912 cheapest_startup =
00913 get_cheapest_path_for_pathkeys(childrel->pathlist,
00914 pathkeys,
00915 NULL,
00916 STARTUP_COST);
00917 cheapest_total =
00918 get_cheapest_path_for_pathkeys(childrel->pathlist,
00919 pathkeys,
00920 NULL,
00921 TOTAL_COST);
00922
00923
00924
00925
00926
00927 if (cheapest_startup == NULL || cheapest_total == NULL)
00928 {
00929 cheapest_startup = cheapest_total =
00930 childrel->cheapest_total_path;
00931
00932 Assert(cheapest_total->param_info == NULL);
00933 }
00934
00935
00936
00937
00938
00939
00940 if (cheapest_startup != cheapest_total)
00941 startup_neq_total = true;
00942
00943 startup_subpaths =
00944 accumulate_append_subpath(startup_subpaths, cheapest_startup);
00945 total_subpaths =
00946 accumulate_append_subpath(total_subpaths, cheapest_total);
00947 }
00948
00949
00950 add_path(rel, (Path *) create_merge_append_path(root,
00951 rel,
00952 startup_subpaths,
00953 pathkeys,
00954 NULL));
00955 if (startup_neq_total)
00956 add_path(rel, (Path *) create_merge_append_path(root,
00957 rel,
00958 total_subpaths,
00959 pathkeys,
00960 NULL));
00961 }
00962 }
00963
00964
00965
00966
00967
00968
00969
00970
00971
00972
00973 static List *
00974 accumulate_append_subpath(List *subpaths, Path *path)
00975 {
00976 if (IsA(path, AppendPath))
00977 {
00978 AppendPath *apath = (AppendPath *) path;
00979
00980
00981 return list_concat(subpaths, list_copy(apath->subpaths));
00982 }
00983 else
00984 return lappend(subpaths, path);
00985 }
00986
00987
00988
00989
00990
00991
00992
00993
00994 static void
00995 set_dummy_rel_pathlist(RelOptInfo *rel)
00996 {
00997
00998 rel->rows = 0;
00999 rel->width = 0;
01000
01001
01002 rel->pathlist = NIL;
01003
01004 add_path(rel, (Path *) create_append_path(rel, NIL, NULL));
01005
01006
01007 set_cheapest(rel);
01008 }
01009
01010
01011 static bool
01012 has_multiple_baserels(PlannerInfo *root)
01013 {
01014 int num_base_rels = 0;
01015 Index rti;
01016
01017 for (rti = 1; rti < root->simple_rel_array_size; rti++)
01018 {
01019 RelOptInfo *brel = root->simple_rel_array[rti];
01020
01021 if (brel == NULL)
01022 continue;
01023
01024
01025 if (brel->reloptkind == RELOPT_BASEREL)
01026 if (++num_base_rels > 1)
01027 return true;
01028 }
01029 return false;
01030 }
01031
01032
01033
01034
01035
01036
01037
01038
01039
01040
01041
01042
01043
01044 static void
01045 set_subquery_pathlist(PlannerInfo *root, RelOptInfo *rel,
01046 Index rti, RangeTblEntry *rte)
01047 {
01048 Query *parse = root->parse;
01049 Query *subquery = rte->subquery;
01050 Relids required_outer;
01051 bool *differentTypes;
01052 double tuple_fraction;
01053 PlannerInfo *subroot;
01054 List *pathkeys;
01055
01056
01057
01058
01059
01060
01061 subquery = copyObject(subquery);
01062
01063
01064
01065
01066
01067
01068 required_outer = rel->lateral_relids;
01069
01070
01071 differentTypes = (bool *)
01072 palloc0((list_length(subquery->targetList) + 1) * sizeof(bool));
01073
01074
01075
01076
01077
01078
01079
01080
01081
01082
01083
01084
01085
01086
01087
01088
01089
01090
01091
01092
01093
01094
01095
01096
01097
01098 if (rel->baserestrictinfo != NIL &&
01099 subquery_is_pushdown_safe(subquery, subquery, differentTypes))
01100 {
01101
01102 List *upperrestrictlist = NIL;
01103 ListCell *l;
01104
01105 foreach(l, rel->baserestrictinfo)
01106 {
01107 RestrictInfo *rinfo = (RestrictInfo *) lfirst(l);
01108 Node *clause = (Node *) rinfo->clause;
01109
01110 if (!rinfo->pseudoconstant &&
01111 (!rte->security_barrier ||
01112 !contain_leaky_functions(clause)) &&
01113 qual_is_pushdown_safe(subquery, rti, clause, differentTypes))
01114 {
01115
01116 subquery_push_qual(subquery, rte, rti, clause);
01117 }
01118 else
01119 {
01120
01121 upperrestrictlist = lappend(upperrestrictlist, rinfo);
01122 }
01123 }
01124 rel->baserestrictinfo = upperrestrictlist;
01125 }
01126
01127 pfree(differentTypes);
01128
01129
01130
01131
01132
01133
01134
01135 if (parse->hasAggs ||
01136 parse->groupClause ||
01137 parse->havingQual ||
01138 parse->distinctClause ||
01139 parse->sortClause ||
01140 has_multiple_baserels(root))
01141 tuple_fraction = 0.0;
01142 else
01143 tuple_fraction = root->tuple_fraction;
01144
01145
01146 Assert(root->plan_params == NIL);
01147
01148
01149 rel->subplan = subquery_planner(root->glob, subquery,
01150 root,
01151 false, tuple_fraction,
01152 &subroot);
01153 rel->subroot = subroot;
01154
01155
01156 rel->subplan_params = root->plan_params;
01157 root->plan_params = NIL;
01158
01159
01160
01161
01162
01163
01164
01165
01166 if (is_dummy_plan(rel->subplan))
01167 {
01168 set_dummy_rel_pathlist(rel);
01169 return;
01170 }
01171
01172
01173 set_subquery_size_estimates(root, rel);
01174
01175
01176 pathkeys = convert_subquery_pathkeys(root, rel, subroot->query_pathkeys);
01177
01178
01179 add_path(rel, create_subqueryscan_path(root, rel, pathkeys, required_outer));
01180
01181
01182 set_cheapest(rel);
01183 }
01184
01185
01186
01187
01188
01189 static void
01190 set_function_pathlist(PlannerInfo *root, RelOptInfo *rel, RangeTblEntry *rte)
01191 {
01192 Relids required_outer;
01193
01194
01195
01196
01197
01198
01199 required_outer = rel->lateral_relids;
01200
01201
01202 add_path(rel, create_functionscan_path(root, rel, required_outer));
01203
01204
01205 set_cheapest(rel);
01206 }
01207
01208
01209
01210
01211
01212 static void
01213 set_values_pathlist(PlannerInfo *root, RelOptInfo *rel, RangeTblEntry *rte)
01214 {
01215 Relids required_outer;
01216
01217
01218
01219
01220
01221
01222 required_outer = rel->lateral_relids;
01223
01224
01225 add_path(rel, create_valuesscan_path(root, rel, required_outer));
01226
01227
01228 set_cheapest(rel);
01229 }
01230
01231
01232
01233
01234
01235
01236
01237
01238 static void
01239 set_cte_pathlist(PlannerInfo *root, RelOptInfo *rel, RangeTblEntry *rte)
01240 {
01241 Plan *cteplan;
01242 PlannerInfo *cteroot;
01243 Index levelsup;
01244 int ndx;
01245 ListCell *lc;
01246 int plan_id;
01247 Relids required_outer;
01248
01249
01250
01251
01252 levelsup = rte->ctelevelsup;
01253 cteroot = root;
01254 while (levelsup-- > 0)
01255 {
01256 cteroot = cteroot->parent_root;
01257 if (!cteroot)
01258 elog(ERROR, "bad levelsup for CTE \"%s\"", rte->ctename);
01259 }
01260
01261
01262
01263
01264
01265
01266 ndx = 0;
01267 foreach(lc, cteroot->parse->cteList)
01268 {
01269 CommonTableExpr *cte = (CommonTableExpr *) lfirst(lc);
01270
01271 if (strcmp(cte->ctename, rte->ctename) == 0)
01272 break;
01273 ndx++;
01274 }
01275 if (lc == NULL)
01276 elog(ERROR, "could not find CTE \"%s\"", rte->ctename);
01277 if (ndx >= list_length(cteroot->cte_plan_ids))
01278 elog(ERROR, "could not find plan for CTE \"%s\"", rte->ctename);
01279 plan_id = list_nth_int(cteroot->cte_plan_ids, ndx);
01280 Assert(plan_id > 0);
01281 cteplan = (Plan *) list_nth(root->glob->subplans, plan_id - 1);
01282
01283
01284 set_cte_size_estimates(root, rel, cteplan);
01285
01286
01287
01288
01289
01290
01291
01292 required_outer = rel->lateral_relids;
01293
01294
01295 add_path(rel, create_ctescan_path(root, rel, required_outer));
01296
01297
01298 set_cheapest(rel);
01299 }
01300
01301
01302
01303
01304
01305
01306
01307
01308 static void
01309 set_worktable_pathlist(PlannerInfo *root, RelOptInfo *rel, RangeTblEntry *rte)
01310 {
01311 Plan *cteplan;
01312 PlannerInfo *cteroot;
01313 Index levelsup;
01314 Relids required_outer;
01315
01316
01317
01318
01319
01320
01321 levelsup = rte->ctelevelsup;
01322 if (levelsup == 0)
01323 elog(ERROR, "bad levelsup for CTE \"%s\"", rte->ctename);
01324 levelsup--;
01325 cteroot = root;
01326 while (levelsup-- > 0)
01327 {
01328 cteroot = cteroot->parent_root;
01329 if (!cteroot)
01330 elog(ERROR, "bad levelsup for CTE \"%s\"", rte->ctename);
01331 }
01332 cteplan = cteroot->non_recursive_plan;
01333 if (!cteplan)
01334 elog(ERROR, "could not find plan for CTE \"%s\"", rte->ctename);
01335
01336
01337 set_cte_size_estimates(root, rel, cteplan);
01338
01339
01340
01341
01342
01343
01344
01345
01346
01347 required_outer = rel->lateral_relids;
01348
01349
01350 add_path(rel, create_worktablescan_path(root, rel, required_outer));
01351
01352
01353 set_cheapest(rel);
01354 }
01355
01356
01357
01358
01359
01360
01361
01362
01363 static RelOptInfo *
01364 make_rel_from_joinlist(PlannerInfo *root, List *joinlist)
01365 {
01366 int levels_needed;
01367 List *initial_rels;
01368 ListCell *jl;
01369
01370
01371
01372
01373
01374
01375 levels_needed = list_length(joinlist);
01376
01377 if (levels_needed <= 0)
01378 return NULL;
01379
01380
01381
01382
01383
01384
01385 initial_rels = NIL;
01386 foreach(jl, joinlist)
01387 {
01388 Node *jlnode = (Node *) lfirst(jl);
01389 RelOptInfo *thisrel;
01390
01391 if (IsA(jlnode, RangeTblRef))
01392 {
01393 int varno = ((RangeTblRef *) jlnode)->rtindex;
01394
01395 thisrel = find_base_rel(root, varno);
01396 }
01397 else if (IsA(jlnode, List))
01398 {
01399
01400 thisrel = make_rel_from_joinlist(root, (List *) jlnode);
01401 }
01402 else
01403 {
01404 elog(ERROR, "unrecognized joinlist node type: %d",
01405 (int) nodeTag(jlnode));
01406 thisrel = NULL;
01407 }
01408
01409 initial_rels = lappend(initial_rels, thisrel);
01410 }
01411
01412 if (levels_needed == 1)
01413 {
01414
01415
01416
01417 return (RelOptInfo *) linitial(initial_rels);
01418 }
01419 else
01420 {
01421
01422
01423
01424
01425
01426
01427
01428 root->initial_rels = initial_rels;
01429
01430 if (join_search_hook)
01431 return (*join_search_hook) (root, levels_needed, initial_rels);
01432 else if (enable_geqo && levels_needed >= geqo_threshold)
01433 return geqo(root, levels_needed, initial_rels);
01434 else
01435 return standard_join_search(root, levels_needed, initial_rels);
01436 }
01437 }
01438
01439
01440
01441
01442
01443
01444
01445
01446
01447
01448
01449
01450
01451
01452
01453
01454
01455
01456
01457
01458
01459
01460
01461
01462
01463
01464
01465
01466
01467
01468 RelOptInfo *
01469 standard_join_search(PlannerInfo *root, int levels_needed, List *initial_rels)
01470 {
01471 int lev;
01472 RelOptInfo *rel;
01473
01474
01475
01476
01477
01478 Assert(root->join_rel_level == NULL);
01479
01480
01481
01482
01483
01484
01485
01486
01487
01488
01489
01490
01491 root->join_rel_level = (List **) palloc0((levels_needed + 1) * sizeof(List *));
01492
01493 root->join_rel_level[1] = initial_rels;
01494
01495 for (lev = 2; lev <= levels_needed; lev++)
01496 {
01497 ListCell *lc;
01498
01499
01500
01501
01502
01503
01504 join_search_one_level(root, lev);
01505
01506
01507
01508
01509 foreach(lc, root->join_rel_level[lev])
01510 {
01511 rel = (RelOptInfo *) lfirst(lc);
01512
01513
01514 set_cheapest(rel);
01515
01516 #ifdef OPTIMIZER_DEBUG
01517 debug_print_rel(root, rel);
01518 #endif
01519 }
01520 }
01521
01522
01523
01524
01525 if (root->join_rel_level[levels_needed] == NIL)
01526 elog(ERROR, "failed to build any %d-way joins", levels_needed);
01527 Assert(list_length(root->join_rel_level[levels_needed]) == 1);
01528
01529 rel = (RelOptInfo *) linitial(root->join_rel_level[levels_needed]);
01530
01531 root->join_rel_level = NULL;
01532
01533 return rel;
01534 }
01535
01536
01537
01538
01539
01540
01541
01542
01543
01544
01545
01546
01547
01548
01549
01550
01551
01552
01553
01554
01555
01556
01557
01558
01559
01560
01561
01562
01563
01564
01565
01566 static bool
01567 subquery_is_pushdown_safe(Query *subquery, Query *topquery,
01568 bool *differentTypes)
01569 {
01570 SetOperationStmt *topop;
01571
01572
01573 if (subquery->limitOffset != NULL || subquery->limitCount != NULL)
01574 return false;
01575
01576
01577 if (subquery->hasWindowFuncs)
01578 return false;
01579
01580
01581 if (subquery == topquery)
01582 {
01583
01584 if (subquery->setOperations != NULL)
01585 if (!recurse_pushdown_safe(subquery->setOperations, topquery,
01586 differentTypes))
01587 return false;
01588 }
01589 else
01590 {
01591
01592 if (subquery->setOperations != NULL)
01593 return false;
01594
01595 topop = (SetOperationStmt *) topquery->setOperations;
01596 Assert(topop && IsA(topop, SetOperationStmt));
01597 compare_tlist_datatypes(subquery->targetList,
01598 topop->colTypes,
01599 differentTypes);
01600 }
01601 return true;
01602 }
01603
01604
01605
01606
01607 static bool
01608 recurse_pushdown_safe(Node *setOp, Query *topquery,
01609 bool *differentTypes)
01610 {
01611 if (IsA(setOp, RangeTblRef))
01612 {
01613 RangeTblRef *rtr = (RangeTblRef *) setOp;
01614 RangeTblEntry *rte = rt_fetch(rtr->rtindex, topquery->rtable);
01615 Query *subquery = rte->subquery;
01616
01617 Assert(subquery != NULL);
01618 return subquery_is_pushdown_safe(subquery, topquery, differentTypes);
01619 }
01620 else if (IsA(setOp, SetOperationStmt))
01621 {
01622 SetOperationStmt *op = (SetOperationStmt *) setOp;
01623
01624
01625 if (op->op == SETOP_EXCEPT)
01626 return false;
01627
01628 if (!recurse_pushdown_safe(op->larg, topquery, differentTypes))
01629 return false;
01630 if (!recurse_pushdown_safe(op->rarg, topquery, differentTypes))
01631 return false;
01632 }
01633 else
01634 {
01635 elog(ERROR, "unrecognized node type: %d",
01636 (int) nodeTag(setOp));
01637 }
01638 return true;
01639 }
01640
01641
01642
01643
01644
01645
01646
01647
01648
01649
01650 static void
01651 compare_tlist_datatypes(List *tlist, List *colTypes,
01652 bool *differentTypes)
01653 {
01654 ListCell *l;
01655 ListCell *colType = list_head(colTypes);
01656
01657 foreach(l, tlist)
01658 {
01659 TargetEntry *tle = (TargetEntry *) lfirst(l);
01660
01661 if (tle->resjunk)
01662 continue;
01663 if (colType == NULL)
01664 elog(ERROR, "wrong number of tlist entries");
01665 if (exprType((Node *) tle->expr) != lfirst_oid(colType))
01666 differentTypes[tle->resno] = true;
01667 colType = lnext(colType);
01668 }
01669 if (colType != NULL)
01670 elog(ERROR, "wrong number of tlist entries");
01671 }
01672
01673
01674
01675
01676
01677
01678
01679
01680
01681
01682
01683
01684
01685
01686
01687
01688
01689
01690
01691
01692
01693
01694
01695
01696
01697
01698
01699
01700
01701
01702
01703
01704
01705
01706
01707
01708
01709 static bool
01710 qual_is_pushdown_safe(Query *subquery, Index rti, Node *qual,
01711 bool *differentTypes)
01712 {
01713 bool safe = true;
01714 List *vars;
01715 ListCell *vl;
01716 Bitmapset *tested = NULL;
01717
01718
01719 if (contain_subplans(qual))
01720 return false;
01721
01722
01723
01724
01725
01726
01727 Assert(!contain_window_function(qual));
01728
01729
01730
01731
01732
01733 vars = pull_var_clause(qual,
01734 PVC_REJECT_AGGREGATES,
01735 PVC_INCLUDE_PLACEHOLDERS);
01736 foreach(vl, vars)
01737 {
01738 Var *var = (Var *) lfirst(vl);
01739 TargetEntry *tle;
01740
01741
01742
01743
01744
01745
01746
01747
01748 if (!IsA(var, Var))
01749 {
01750 safe = false;
01751 break;
01752 }
01753
01754 Assert(var->varno == rti);
01755
01756
01757 if (var->varattno == 0)
01758 {
01759 safe = false;
01760 break;
01761 }
01762
01763
01764
01765
01766
01767
01768 if (bms_is_member(var->varattno, tested))
01769 continue;
01770 tested = bms_add_member(tested, var->varattno);
01771
01772
01773 if (differentTypes[var->varattno])
01774 {
01775 safe = false;
01776 break;
01777 }
01778
01779
01780 tle = get_tle_by_resno(subquery->targetList, var->varattno);
01781 Assert(tle != NULL);
01782 Assert(!tle->resjunk);
01783
01784
01785 if (subquery->hasDistinctOn &&
01786 !targetIsInSortList(tle, InvalidOid, subquery->distinctClause))
01787 {
01788
01789 safe = false;
01790 break;
01791 }
01792
01793
01794 if (expression_returns_set((Node *) tle->expr))
01795 {
01796 safe = false;
01797 break;
01798 }
01799
01800
01801 if (contain_volatile_functions((Node *) tle->expr))
01802 {
01803 safe = false;
01804 break;
01805 }
01806 }
01807
01808 list_free(vars);
01809 bms_free(tested);
01810
01811 return safe;
01812 }
01813
01814
01815
01816
01817 static void
01818 subquery_push_qual(Query *subquery, RangeTblEntry *rte, Index rti, Node *qual)
01819 {
01820 if (subquery->setOperations != NULL)
01821 {
01822
01823 recurse_push_qual(subquery->setOperations, subquery,
01824 rte, rti, qual);
01825 }
01826 else
01827 {
01828
01829
01830
01831
01832
01833
01834
01835
01836
01837 qual = ReplaceVarsFromTargetList(qual, rti, 0, rte,
01838 subquery->targetList,
01839 REPLACEVARS_REPORT_ERROR, 0,
01840 &subquery->hasSubLinks);
01841
01842
01843
01844
01845
01846
01847 if (subquery->hasAggs || subquery->groupClause || subquery->havingQual)
01848 subquery->havingQual = make_and_qual(subquery->havingQual, qual);
01849 else
01850 subquery->jointree->quals =
01851 make_and_qual(subquery->jointree->quals, qual);
01852
01853
01854
01855
01856
01857
01858 }
01859 }
01860
01861
01862
01863
01864 static void
01865 recurse_push_qual(Node *setOp, Query *topquery,
01866 RangeTblEntry *rte, Index rti, Node *qual)
01867 {
01868 if (IsA(setOp, RangeTblRef))
01869 {
01870 RangeTblRef *rtr = (RangeTblRef *) setOp;
01871 RangeTblEntry *subrte = rt_fetch(rtr->rtindex, topquery->rtable);
01872 Query *subquery = subrte->subquery;
01873
01874 Assert(subquery != NULL);
01875 subquery_push_qual(subquery, rte, rti, qual);
01876 }
01877 else if (IsA(setOp, SetOperationStmt))
01878 {
01879 SetOperationStmt *op = (SetOperationStmt *) setOp;
01880
01881 recurse_push_qual(op->larg, topquery, rte, rti, qual);
01882 recurse_push_qual(op->rarg, topquery, rte, rti, qual);
01883 }
01884 else
01885 {
01886 elog(ERROR, "unrecognized node type: %d",
01887 (int) nodeTag(setOp));
01888 }
01889 }
01890
01891
01892
01893
01894
01895 #ifdef OPTIMIZER_DEBUG
01896
01897 static void
01898 print_relids(Relids relids)
01899 {
01900 Relids tmprelids;
01901 int x;
01902 bool first = true;
01903
01904 tmprelids = bms_copy(relids);
01905 while ((x = bms_first_member(tmprelids)) >= 0)
01906 {
01907 if (!first)
01908 printf(" ");
01909 printf("%d", x);
01910 first = false;
01911 }
01912 bms_free(tmprelids);
01913 }
01914
01915 static void
01916 print_restrictclauses(PlannerInfo *root, List *clauses)
01917 {
01918 ListCell *l;
01919
01920 foreach(l, clauses)
01921 {
01922 RestrictInfo *c = lfirst(l);
01923
01924 print_expr((Node *) c->clause, root->parse->rtable);
01925 if (lnext(l))
01926 printf(", ");
01927 }
01928 }
01929
01930 static void
01931 print_path(PlannerInfo *root, Path *path, int indent)
01932 {
01933 const char *ptype;
01934 bool join = false;
01935 Path *subpath = NULL;
01936 int i;
01937
01938 switch (nodeTag(path))
01939 {
01940 case T_Path:
01941 ptype = "SeqScan";
01942 break;
01943 case T_IndexPath:
01944 ptype = "IdxScan";
01945 break;
01946 case T_BitmapHeapPath:
01947 ptype = "BitmapHeapScan";
01948 break;
01949 case T_BitmapAndPath:
01950 ptype = "BitmapAndPath";
01951 break;
01952 case T_BitmapOrPath:
01953 ptype = "BitmapOrPath";
01954 break;
01955 case T_TidPath:
01956 ptype = "TidScan";
01957 break;
01958 case T_ForeignPath:
01959 ptype = "ForeignScan";
01960 break;
01961 case T_AppendPath:
01962 ptype = "Append";
01963 break;
01964 case T_MergeAppendPath:
01965 ptype = "MergeAppend";
01966 break;
01967 case T_ResultPath:
01968 ptype = "Result";
01969 break;
01970 case T_MaterialPath:
01971 ptype = "Material";
01972 subpath = ((MaterialPath *) path)->subpath;
01973 break;
01974 case T_UniquePath:
01975 ptype = "Unique";
01976 subpath = ((UniquePath *) path)->subpath;
01977 break;
01978 case T_NestPath:
01979 ptype = "NestLoop";
01980 join = true;
01981 break;
01982 case T_MergePath:
01983 ptype = "MergeJoin";
01984 join = true;
01985 break;
01986 case T_HashPath:
01987 ptype = "HashJoin";
01988 join = true;
01989 break;
01990 default:
01991 ptype = "???Path";
01992 break;
01993 }
01994
01995 for (i = 0; i < indent; i++)
01996 printf("\t");
01997 printf("%s", ptype);
01998
01999 if (path->parent)
02000 {
02001 printf("(");
02002 print_relids(path->parent->relids);
02003 printf(") rows=%.0f", path->parent->rows);
02004 }
02005 printf(" cost=%.2f..%.2f\n", path->startup_cost, path->total_cost);
02006
02007 if (path->pathkeys)
02008 {
02009 for (i = 0; i < indent; i++)
02010 printf("\t");
02011 printf(" pathkeys: ");
02012 print_pathkeys(path->pathkeys, root->parse->rtable);
02013 }
02014
02015 if (join)
02016 {
02017 JoinPath *jp = (JoinPath *) path;
02018
02019 for (i = 0; i < indent; i++)
02020 printf("\t");
02021 printf(" clauses: ");
02022 print_restrictclauses(root, jp->joinrestrictinfo);
02023 printf("\n");
02024
02025 if (IsA(path, MergePath))
02026 {
02027 MergePath *mp = (MergePath *) path;
02028
02029 for (i = 0; i < indent; i++)
02030 printf("\t");
02031 printf(" sortouter=%d sortinner=%d materializeinner=%d\n",
02032 ((mp->outersortkeys) ? 1 : 0),
02033 ((mp->innersortkeys) ? 1 : 0),
02034 ((mp->materialize_inner) ? 1 : 0));
02035 }
02036
02037 print_path(root, jp->outerjoinpath, indent + 1);
02038 print_path(root, jp->innerjoinpath, indent + 1);
02039 }
02040
02041 if (subpath)
02042 print_path(root, subpath, indent + 1);
02043 }
02044
02045 void
02046 debug_print_rel(PlannerInfo *root, RelOptInfo *rel)
02047 {
02048 ListCell *l;
02049
02050 printf("RELOPTINFO (");
02051 print_relids(rel->relids);
02052 printf("): rows=%.0f width=%d\n", rel->rows, rel->width);
02053
02054 if (rel->baserestrictinfo)
02055 {
02056 printf("\tbaserestrictinfo: ");
02057 print_restrictclauses(root, rel->baserestrictinfo);
02058 printf("\n");
02059 }
02060
02061 if (rel->joininfo)
02062 {
02063 printf("\tjoininfo: ");
02064 print_restrictclauses(root, rel->joininfo);
02065 printf("\n");
02066 }
02067
02068 printf("\tpath list:\n");
02069 foreach(l, rel->pathlist)
02070 print_path(root, lfirst(l), 1);
02071 if (rel->cheapest_startup_path)
02072 {
02073 printf("\n\tcheapest startup path:\n");
02074 print_path(root, rel->cheapest_startup_path, 1);
02075 }
02076 if (rel->cheapest_total_path)
02077 {
02078 printf("\n\tcheapest total path:\n");
02079 print_path(root, rel->cheapest_total_path, 1);
02080 }
02081 printf("\n");
02082 fflush(stdout);
02083 }
02084
02085 #endif