00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015 #include "postgres.h"
00016
00017 #include <math.h>
00018
00019 #include "executor/executor.h"
00020 #include "optimizer/cost.h"
00021 #include "optimizer/pathnode.h"
00022 #include "optimizer/paths.h"
00023
00024
00025 #define PATH_PARAM_BY_REL(path, rel) \
00026 ((path)->param_info && bms_overlap(PATH_REQ_OUTER(path), (rel)->relids))
00027
00028 static void sort_inner_and_outer(PlannerInfo *root, RelOptInfo *joinrel,
00029 RelOptInfo *outerrel, RelOptInfo *innerrel,
00030 List *restrictlist, List *mergeclause_list,
00031 JoinType jointype, SpecialJoinInfo *sjinfo,
00032 Relids param_source_rels);
00033 static void match_unsorted_outer(PlannerInfo *root, RelOptInfo *joinrel,
00034 RelOptInfo *outerrel, RelOptInfo *innerrel,
00035 List *restrictlist, List *mergeclause_list,
00036 JoinType jointype, SpecialJoinInfo *sjinfo,
00037 SemiAntiJoinFactors *semifactors,
00038 Relids param_source_rels);
00039 static void hash_inner_and_outer(PlannerInfo *root, RelOptInfo *joinrel,
00040 RelOptInfo *outerrel, RelOptInfo *innerrel,
00041 List *restrictlist,
00042 JoinType jointype, SpecialJoinInfo *sjinfo,
00043 SemiAntiJoinFactors *semifactors,
00044 Relids param_source_rels);
00045 static List *select_mergejoin_clauses(PlannerInfo *root,
00046 RelOptInfo *joinrel,
00047 RelOptInfo *outerrel,
00048 RelOptInfo *innerrel,
00049 List *restrictlist,
00050 JoinType jointype,
00051 bool *mergejoin_allowed);
00052
00053
00054
00055
00056
00057
00058
00059
00060
00061
00062
00063
00064
00065
00066
00067
00068
00069
00070
00071
00072
00073
00074
00075
00076
00077 void
00078 add_paths_to_joinrel(PlannerInfo *root,
00079 RelOptInfo *joinrel,
00080 RelOptInfo *outerrel,
00081 RelOptInfo *innerrel,
00082 JoinType jointype,
00083 SpecialJoinInfo *sjinfo,
00084 List *restrictlist)
00085 {
00086 List *mergeclause_list = NIL;
00087 bool mergejoin_allowed = true;
00088 SemiAntiJoinFactors semifactors;
00089 Relids param_source_rels = NULL;
00090 ListCell *lc;
00091
00092
00093
00094
00095
00096
00097
00098 if (enable_mergejoin || jointype == JOIN_FULL)
00099 mergeclause_list = select_mergejoin_clauses(root,
00100 joinrel,
00101 outerrel,
00102 innerrel,
00103 restrictlist,
00104 jointype,
00105 &mergejoin_allowed);
00106
00107
00108
00109
00110
00111 if (jointype == JOIN_SEMI || jointype == JOIN_ANTI)
00112 compute_semi_anti_join_factors(root, outerrel, innerrel,
00113 jointype, sjinfo, restrictlist,
00114 &semifactors);
00115
00116
00117
00118
00119
00120
00121
00122
00123
00124
00125
00126
00127 foreach(lc, root->join_info_list)
00128 {
00129 SpecialJoinInfo *sjinfo = (SpecialJoinInfo *) lfirst(lc);
00130
00131
00132
00133
00134
00135
00136
00137
00138 if (bms_overlap(joinrel->relids, sjinfo->min_righthand) &&
00139 !bms_overlap(joinrel->relids, sjinfo->min_lefthand))
00140 param_source_rels = bms_join(param_source_rels,
00141 bms_difference(root->all_baserels,
00142 sjinfo->min_righthand));
00143
00144
00145 if (sjinfo->jointype == JOIN_FULL &&
00146 bms_overlap(joinrel->relids, sjinfo->min_lefthand) &&
00147 !bms_overlap(joinrel->relids, sjinfo->min_righthand))
00148 param_source_rels = bms_join(param_source_rels,
00149 bms_difference(root->all_baserels,
00150 sjinfo->min_lefthand));
00151 }
00152
00153
00154
00155
00156
00157
00158
00159
00160
00161 foreach(lc, root->lateral_info_list)
00162 {
00163 LateralJoinInfo *ljinfo = (LateralJoinInfo *) lfirst(lc);
00164
00165 if (bms_is_member(ljinfo->lateral_rhs, joinrel->relids))
00166 param_source_rels = bms_join(param_source_rels,
00167 bms_difference(ljinfo->lateral_lhs,
00168 joinrel->relids));
00169 }
00170
00171
00172
00173
00174
00175 if (mergejoin_allowed)
00176 sort_inner_and_outer(root, joinrel, outerrel, innerrel,
00177 restrictlist, mergeclause_list, jointype,
00178 sjinfo, param_source_rels);
00179
00180
00181
00182
00183
00184
00185
00186
00187 if (mergejoin_allowed)
00188 match_unsorted_outer(root, joinrel, outerrel, innerrel,
00189 restrictlist, mergeclause_list, jointype,
00190 sjinfo, &semifactors, param_source_rels);
00191
00192 #ifdef NOT_USED
00193
00194
00195
00196
00197
00198
00199
00200
00201
00202
00203
00204
00205 if (mergejoin_allowed)
00206 match_unsorted_inner(root, joinrel, outerrel, innerrel,
00207 restrictlist, mergeclause_list, jointype,
00208 sjinfo, &semifactors, param_source_rels);
00209 #endif
00210
00211
00212
00213
00214
00215
00216 if (enable_hashjoin || jointype == JOIN_FULL)
00217 hash_inner_and_outer(root, joinrel, outerrel, innerrel,
00218 restrictlist, jointype,
00219 sjinfo, &semifactors, param_source_rels);
00220 }
00221
00222
00223
00224
00225
00226
00227 static void
00228 try_nestloop_path(PlannerInfo *root,
00229 RelOptInfo *joinrel,
00230 JoinType jointype,
00231 SpecialJoinInfo *sjinfo,
00232 SemiAntiJoinFactors *semifactors,
00233 Relids param_source_rels,
00234 Path *outer_path,
00235 Path *inner_path,
00236 List *restrict_clauses,
00237 List *pathkeys)
00238 {
00239 Relids required_outer;
00240 JoinCostWorkspace workspace;
00241
00242
00243
00244
00245
00246 required_outer = calc_nestloop_required_outer(outer_path,
00247 inner_path);
00248 if (required_outer &&
00249 !bms_overlap(required_outer, param_source_rels))
00250 {
00251
00252 bms_free(required_outer);
00253 return;
00254 }
00255
00256
00257
00258
00259
00260
00261
00262
00263
00264
00265 initial_cost_nestloop(root, &workspace, jointype,
00266 outer_path, inner_path,
00267 sjinfo, semifactors);
00268
00269 if (add_path_precheck(joinrel,
00270 workspace.startup_cost, workspace.total_cost,
00271 pathkeys, required_outer))
00272 {
00273 add_path(joinrel, (Path *)
00274 create_nestloop_path(root,
00275 joinrel,
00276 jointype,
00277 &workspace,
00278 sjinfo,
00279 semifactors,
00280 outer_path,
00281 inner_path,
00282 restrict_clauses,
00283 pathkeys,
00284 required_outer));
00285 }
00286 else
00287 {
00288
00289 bms_free(required_outer);
00290 }
00291 }
00292
00293
00294
00295
00296
00297
00298 static void
00299 try_mergejoin_path(PlannerInfo *root,
00300 RelOptInfo *joinrel,
00301 JoinType jointype,
00302 SpecialJoinInfo *sjinfo,
00303 Relids param_source_rels,
00304 Path *outer_path,
00305 Path *inner_path,
00306 List *restrict_clauses,
00307 List *pathkeys,
00308 List *mergeclauses,
00309 List *outersortkeys,
00310 List *innersortkeys)
00311 {
00312 Relids required_outer;
00313 JoinCostWorkspace workspace;
00314
00315
00316
00317
00318
00319 required_outer = calc_non_nestloop_required_outer(outer_path,
00320 inner_path);
00321 if (required_outer &&
00322 !bms_overlap(required_outer, param_source_rels))
00323 {
00324
00325 bms_free(required_outer);
00326 return;
00327 }
00328
00329
00330
00331
00332
00333 if (outersortkeys &&
00334 pathkeys_contained_in(outersortkeys, outer_path->pathkeys))
00335 outersortkeys = NIL;
00336 if (innersortkeys &&
00337 pathkeys_contained_in(innersortkeys, inner_path->pathkeys))
00338 innersortkeys = NIL;
00339
00340
00341
00342
00343 initial_cost_mergejoin(root, &workspace, jointype, mergeclauses,
00344 outer_path, inner_path,
00345 outersortkeys, innersortkeys,
00346 sjinfo);
00347
00348 if (add_path_precheck(joinrel,
00349 workspace.startup_cost, workspace.total_cost,
00350 pathkeys, required_outer))
00351 {
00352 add_path(joinrel, (Path *)
00353 create_mergejoin_path(root,
00354 joinrel,
00355 jointype,
00356 &workspace,
00357 sjinfo,
00358 outer_path,
00359 inner_path,
00360 restrict_clauses,
00361 pathkeys,
00362 required_outer,
00363 mergeclauses,
00364 outersortkeys,
00365 innersortkeys));
00366 }
00367 else
00368 {
00369
00370 bms_free(required_outer);
00371 }
00372 }
00373
00374
00375
00376
00377
00378
00379 static void
00380 try_hashjoin_path(PlannerInfo *root,
00381 RelOptInfo *joinrel,
00382 JoinType jointype,
00383 SpecialJoinInfo *sjinfo,
00384 SemiAntiJoinFactors *semifactors,
00385 Relids param_source_rels,
00386 Path *outer_path,
00387 Path *inner_path,
00388 List *restrict_clauses,
00389 List *hashclauses)
00390 {
00391 Relids required_outer;
00392 JoinCostWorkspace workspace;
00393
00394
00395
00396
00397
00398 required_outer = calc_non_nestloop_required_outer(outer_path,
00399 inner_path);
00400 if (required_outer &&
00401 !bms_overlap(required_outer, param_source_rels))
00402 {
00403
00404 bms_free(required_outer);
00405 return;
00406 }
00407
00408
00409
00410
00411
00412 initial_cost_hashjoin(root, &workspace, jointype, hashclauses,
00413 outer_path, inner_path,
00414 sjinfo, semifactors);
00415
00416 if (add_path_precheck(joinrel,
00417 workspace.startup_cost, workspace.total_cost,
00418 NIL, required_outer))
00419 {
00420 add_path(joinrel, (Path *)
00421 create_hashjoin_path(root,
00422 joinrel,
00423 jointype,
00424 &workspace,
00425 sjinfo,
00426 semifactors,
00427 outer_path,
00428 inner_path,
00429 restrict_clauses,
00430 required_outer,
00431 hashclauses));
00432 }
00433 else
00434 {
00435
00436 bms_free(required_outer);
00437 }
00438 }
00439
00440
00441
00442
00443
00444
00445
00446
00447
00448
00449
00450 static inline bool
00451 clause_sides_match_join(RestrictInfo *rinfo, RelOptInfo *outerrel,
00452 RelOptInfo *innerrel)
00453 {
00454 if (bms_is_subset(rinfo->left_relids, outerrel->relids) &&
00455 bms_is_subset(rinfo->right_relids, innerrel->relids))
00456 {
00457
00458 rinfo->outer_is_left = true;
00459 return true;
00460 }
00461 else if (bms_is_subset(rinfo->left_relids, innerrel->relids) &&
00462 bms_is_subset(rinfo->right_relids, outerrel->relids))
00463 {
00464
00465 rinfo->outer_is_left = false;
00466 return true;
00467 }
00468 return false;
00469 }
00470
00471
00472
00473
00474
00475
00476
00477
00478
00479
00480
00481
00482
00483
00484
00485
00486
00487 static void
00488 sort_inner_and_outer(PlannerInfo *root,
00489 RelOptInfo *joinrel,
00490 RelOptInfo *outerrel,
00491 RelOptInfo *innerrel,
00492 List *restrictlist,
00493 List *mergeclause_list,
00494 JoinType jointype,
00495 SpecialJoinInfo *sjinfo,
00496 Relids param_source_rels)
00497 {
00498 Path *outer_path;
00499 Path *inner_path;
00500 List *all_pathkeys;
00501 ListCell *l;
00502
00503
00504
00505
00506
00507
00508
00509
00510
00511
00512
00513
00514
00515
00516 outer_path = outerrel->cheapest_total_path;
00517 inner_path = innerrel->cheapest_total_path;
00518
00519
00520
00521
00522
00523
00524
00525 if (PATH_PARAM_BY_REL(outer_path, innerrel) ||
00526 PATH_PARAM_BY_REL(inner_path, outerrel))
00527 return;
00528
00529
00530
00531
00532
00533 if (jointype == JOIN_UNIQUE_OUTER)
00534 {
00535 outer_path = (Path *) create_unique_path(root, outerrel,
00536 outer_path, sjinfo);
00537 Assert(outer_path);
00538 jointype = JOIN_INNER;
00539 }
00540 else if (jointype == JOIN_UNIQUE_INNER)
00541 {
00542 inner_path = (Path *) create_unique_path(root, innerrel,
00543 inner_path, sjinfo);
00544 Assert(inner_path);
00545 jointype = JOIN_INNER;
00546 }
00547
00548
00549
00550
00551
00552
00553
00554
00555
00556
00557
00558
00559
00560
00561
00562
00563
00564
00565
00566
00567
00568
00569
00570
00571
00572
00573
00574
00575
00576 all_pathkeys = select_outer_pathkeys_for_merge(root,
00577 mergeclause_list,
00578 joinrel);
00579
00580 foreach(l, all_pathkeys)
00581 {
00582 List *front_pathkey = (List *) lfirst(l);
00583 List *cur_mergeclauses;
00584 List *outerkeys;
00585 List *innerkeys;
00586 List *merge_pathkeys;
00587
00588
00589 if (l != list_head(all_pathkeys))
00590 outerkeys = lcons(front_pathkey,
00591 list_delete_ptr(list_copy(all_pathkeys),
00592 front_pathkey));
00593 else
00594 outerkeys = all_pathkeys;
00595
00596
00597 cur_mergeclauses = find_mergeclauses_for_pathkeys(root,
00598 outerkeys,
00599 true,
00600 mergeclause_list);
00601
00602
00603 Assert(list_length(cur_mergeclauses) == list_length(mergeclause_list));
00604
00605
00606 innerkeys = make_inner_pathkeys_for_merge(root,
00607 cur_mergeclauses,
00608 outerkeys);
00609
00610
00611 merge_pathkeys = build_join_pathkeys(root, joinrel, jointype,
00612 outerkeys);
00613
00614
00615
00616
00617
00618
00619
00620
00621 try_mergejoin_path(root,
00622 joinrel,
00623 jointype,
00624 sjinfo,
00625 param_source_rels,
00626 outer_path,
00627 inner_path,
00628 restrictlist,
00629 merge_pathkeys,
00630 cur_mergeclauses,
00631 outerkeys,
00632 innerkeys);
00633 }
00634 }
00635
00636
00637
00638
00639
00640
00641
00642
00643
00644
00645
00646
00647
00648
00649
00650
00651
00652
00653
00654
00655
00656
00657
00658
00659
00660
00661
00662
00663
00664
00665
00666
00667
00668
00669
00670
00671
00672 static void
00673 match_unsorted_outer(PlannerInfo *root,
00674 RelOptInfo *joinrel,
00675 RelOptInfo *outerrel,
00676 RelOptInfo *innerrel,
00677 List *restrictlist,
00678 List *mergeclause_list,
00679 JoinType jointype,
00680 SpecialJoinInfo *sjinfo,
00681 SemiAntiJoinFactors *semifactors,
00682 Relids param_source_rels)
00683 {
00684 JoinType save_jointype = jointype;
00685 bool nestjoinOK;
00686 bool useallclauses;
00687 Path *inner_cheapest_total = innerrel->cheapest_total_path;
00688 Path *matpath = NULL;
00689 ListCell *lc1;
00690
00691
00692
00693
00694
00695
00696
00697
00698 switch (jointype)
00699 {
00700 case JOIN_INNER:
00701 case JOIN_LEFT:
00702 case JOIN_SEMI:
00703 case JOIN_ANTI:
00704 nestjoinOK = true;
00705 useallclauses = false;
00706 break;
00707 case JOIN_RIGHT:
00708 case JOIN_FULL:
00709 nestjoinOK = false;
00710 useallclauses = true;
00711 break;
00712 case JOIN_UNIQUE_OUTER:
00713 case JOIN_UNIQUE_INNER:
00714 jointype = JOIN_INNER;
00715 nestjoinOK = true;
00716 useallclauses = false;
00717 break;
00718 default:
00719 elog(ERROR, "unrecognized join type: %d",
00720 (int) jointype);
00721 nestjoinOK = false;
00722 useallclauses = false;
00723 break;
00724 }
00725
00726
00727
00728
00729
00730
00731 if (PATH_PARAM_BY_REL(inner_cheapest_total, outerrel))
00732 inner_cheapest_total = NULL;
00733
00734
00735
00736
00737
00738 if (save_jointype == JOIN_UNIQUE_INNER)
00739 {
00740
00741 if (inner_cheapest_total == NULL)
00742 return;
00743 inner_cheapest_total = (Path *)
00744 create_unique_path(root, innerrel, inner_cheapest_total, sjinfo);
00745 Assert(inner_cheapest_total);
00746 }
00747 else if (nestjoinOK)
00748 {
00749
00750
00751
00752
00753
00754 if (enable_material && inner_cheapest_total != NULL &&
00755 !ExecMaterializesOutput(inner_cheapest_total->pathtype))
00756 matpath = (Path *)
00757 create_material_path(innerrel, inner_cheapest_total);
00758 }
00759
00760 foreach(lc1, outerrel->pathlist)
00761 {
00762 Path *outerpath = (Path *) lfirst(lc1);
00763 List *merge_pathkeys;
00764 List *mergeclauses;
00765 List *innersortkeys;
00766 List *trialsortkeys;
00767 Path *cheapest_startup_inner;
00768 Path *cheapest_total_inner;
00769 int num_sortkeys;
00770 int sortkeycnt;
00771
00772
00773
00774
00775 if (PATH_PARAM_BY_REL(outerpath, innerrel))
00776 continue;
00777
00778
00779
00780
00781
00782
00783 if (save_jointype == JOIN_UNIQUE_OUTER)
00784 {
00785 if (outerpath != outerrel->cheapest_total_path)
00786 continue;
00787 outerpath = (Path *) create_unique_path(root, outerrel,
00788 outerpath, sjinfo);
00789 Assert(outerpath);
00790 }
00791
00792
00793
00794
00795
00796
00797 merge_pathkeys = build_join_pathkeys(root, joinrel, jointype,
00798 outerpath->pathkeys);
00799
00800 if (save_jointype == JOIN_UNIQUE_INNER)
00801 {
00802
00803
00804
00805
00806 try_nestloop_path(root,
00807 joinrel,
00808 jointype,
00809 sjinfo,
00810 semifactors,
00811 param_source_rels,
00812 outerpath,
00813 inner_cheapest_total,
00814 restrictlist,
00815 merge_pathkeys);
00816 }
00817 else if (nestjoinOK)
00818 {
00819
00820
00821
00822
00823
00824
00825 ListCell *lc2;
00826
00827 foreach(lc2, innerrel->cheapest_parameterized_paths)
00828 {
00829 Path *innerpath = (Path *) lfirst(lc2);
00830
00831 try_nestloop_path(root,
00832 joinrel,
00833 jointype,
00834 sjinfo,
00835 semifactors,
00836 param_source_rels,
00837 outerpath,
00838 innerpath,
00839 restrictlist,
00840 merge_pathkeys);
00841 }
00842
00843
00844 if (matpath != NULL)
00845 try_nestloop_path(root,
00846 joinrel,
00847 jointype,
00848 sjinfo,
00849 semifactors,
00850 param_source_rels,
00851 outerpath,
00852 matpath,
00853 restrictlist,
00854 merge_pathkeys);
00855 }
00856
00857
00858 if (save_jointype == JOIN_UNIQUE_OUTER)
00859 continue;
00860
00861
00862 if (inner_cheapest_total == NULL)
00863 continue;
00864
00865
00866 mergeclauses = find_mergeclauses_for_pathkeys(root,
00867 outerpath->pathkeys,
00868 true,
00869 mergeclause_list);
00870
00871
00872
00873
00874
00875
00876
00877
00878
00879
00880 if (mergeclauses == NIL)
00881 {
00882 if (jointype == JOIN_FULL)
00883 ;
00884 else
00885 continue;
00886 }
00887 if (useallclauses && list_length(mergeclauses) != list_length(mergeclause_list))
00888 continue;
00889
00890
00891 innersortkeys = make_inner_pathkeys_for_merge(root,
00892 mergeclauses,
00893 outerpath->pathkeys);
00894
00895
00896
00897
00898
00899
00900
00901 try_mergejoin_path(root,
00902 joinrel,
00903 jointype,
00904 sjinfo,
00905 param_source_rels,
00906 outerpath,
00907 inner_cheapest_total,
00908 restrictlist,
00909 merge_pathkeys,
00910 mergeclauses,
00911 NIL,
00912 innersortkeys);
00913
00914
00915 if (save_jointype == JOIN_UNIQUE_INNER)
00916 continue;
00917
00918
00919
00920
00921
00922
00923
00924
00925
00926
00927
00928
00929
00930
00931
00932
00933
00934
00935
00936
00937
00938
00939
00940
00941
00942
00943
00944
00945
00946
00947 if (pathkeys_contained_in(innersortkeys,
00948 inner_cheapest_total->pathkeys))
00949 {
00950
00951 cheapest_startup_inner = inner_cheapest_total;
00952 cheapest_total_inner = inner_cheapest_total;
00953 }
00954 else
00955 {
00956
00957 cheapest_startup_inner = NULL;
00958 cheapest_total_inner = NULL;
00959 }
00960 num_sortkeys = list_length(innersortkeys);
00961 if (num_sortkeys > 1 && !useallclauses)
00962 trialsortkeys = list_copy(innersortkeys);
00963 else
00964 trialsortkeys = innersortkeys;
00965
00966 for (sortkeycnt = num_sortkeys; sortkeycnt > 0; sortkeycnt--)
00967 {
00968 Path *innerpath;
00969 List *newclauses = NIL;
00970
00971
00972
00973
00974
00975
00976 trialsortkeys = list_truncate(trialsortkeys, sortkeycnt);
00977 innerpath = get_cheapest_path_for_pathkeys(innerrel->pathlist,
00978 trialsortkeys,
00979 NULL,
00980 TOTAL_COST);
00981 if (innerpath != NULL &&
00982 (cheapest_total_inner == NULL ||
00983 compare_path_costs(innerpath, cheapest_total_inner,
00984 TOTAL_COST) < 0))
00985 {
00986
00987
00988 if (sortkeycnt < num_sortkeys)
00989 {
00990 newclauses =
00991 find_mergeclauses_for_pathkeys(root,
00992 trialsortkeys,
00993 false,
00994 mergeclauses);
00995 Assert(newclauses != NIL);
00996 }
00997 else
00998 newclauses = mergeclauses;
00999 try_mergejoin_path(root,
01000 joinrel,
01001 jointype,
01002 sjinfo,
01003 param_source_rels,
01004 outerpath,
01005 innerpath,
01006 restrictlist,
01007 merge_pathkeys,
01008 newclauses,
01009 NIL,
01010 NIL);
01011 cheapest_total_inner = innerpath;
01012 }
01013
01014 innerpath = get_cheapest_path_for_pathkeys(innerrel->pathlist,
01015 trialsortkeys,
01016 NULL,
01017 STARTUP_COST);
01018 if (innerpath != NULL &&
01019 (cheapest_startup_inner == NULL ||
01020 compare_path_costs(innerpath, cheapest_startup_inner,
01021 STARTUP_COST) < 0))
01022 {
01023
01024 if (innerpath != cheapest_total_inner)
01025 {
01026
01027
01028
01029
01030 if (newclauses == NIL)
01031 {
01032 if (sortkeycnt < num_sortkeys)
01033 {
01034 newclauses =
01035 find_mergeclauses_for_pathkeys(root,
01036 trialsortkeys,
01037 false,
01038 mergeclauses);
01039 Assert(newclauses != NIL);
01040 }
01041 else
01042 newclauses = mergeclauses;
01043 }
01044 try_mergejoin_path(root,
01045 joinrel,
01046 jointype,
01047 sjinfo,
01048 param_source_rels,
01049 outerpath,
01050 innerpath,
01051 restrictlist,
01052 merge_pathkeys,
01053 newclauses,
01054 NIL,
01055 NIL);
01056 }
01057 cheapest_startup_inner = innerpath;
01058 }
01059
01060
01061
01062
01063 if (useallclauses)
01064 break;
01065 }
01066 }
01067 }
01068
01069
01070
01071
01072
01073
01074
01075
01076
01077
01078
01079
01080
01081
01082
01083
01084 static void
01085 hash_inner_and_outer(PlannerInfo *root,
01086 RelOptInfo *joinrel,
01087 RelOptInfo *outerrel,
01088 RelOptInfo *innerrel,
01089 List *restrictlist,
01090 JoinType jointype,
01091 SpecialJoinInfo *sjinfo,
01092 SemiAntiJoinFactors *semifactors,
01093 Relids param_source_rels)
01094 {
01095 bool isouterjoin = IS_OUTER_JOIN(jointype);
01096 List *hashclauses;
01097 ListCell *l;
01098
01099
01100
01101
01102
01103
01104
01105
01106 hashclauses = NIL;
01107 foreach(l, restrictlist)
01108 {
01109 RestrictInfo *restrictinfo = (RestrictInfo *) lfirst(l);
01110
01111
01112
01113
01114
01115 if (isouterjoin && restrictinfo->is_pushed_down)
01116 continue;
01117
01118 if (!restrictinfo->can_join ||
01119 restrictinfo->hashjoinoperator == InvalidOid)
01120 continue;
01121
01122
01123
01124
01125 if (!clause_sides_match_join(restrictinfo, outerrel, innerrel))
01126 continue;
01127
01128 hashclauses = lappend(hashclauses, restrictinfo);
01129 }
01130
01131
01132 if (hashclauses)
01133 {
01134
01135
01136
01137
01138
01139 Path *cheapest_startup_outer = outerrel->cheapest_startup_path;
01140 Path *cheapest_total_outer = outerrel->cheapest_total_path;
01141 Path *cheapest_total_inner = innerrel->cheapest_total_path;
01142
01143
01144
01145
01146
01147
01148
01149 if (PATH_PARAM_BY_REL(cheapest_total_outer, innerrel) ||
01150 PATH_PARAM_BY_REL(cheapest_total_inner, outerrel))
01151 return;
01152
01153
01154 if (jointype == JOIN_UNIQUE_OUTER)
01155 {
01156 cheapest_total_outer = (Path *)
01157 create_unique_path(root, outerrel,
01158 cheapest_total_outer, sjinfo);
01159 Assert(cheapest_total_outer);
01160 jointype = JOIN_INNER;
01161 try_hashjoin_path(root,
01162 joinrel,
01163 jointype,
01164 sjinfo,
01165 semifactors,
01166 param_source_rels,
01167 cheapest_total_outer,
01168 cheapest_total_inner,
01169 restrictlist,
01170 hashclauses);
01171
01172 }
01173 else if (jointype == JOIN_UNIQUE_INNER)
01174 {
01175 cheapest_total_inner = (Path *)
01176 create_unique_path(root, innerrel,
01177 cheapest_total_inner, sjinfo);
01178 Assert(cheapest_total_inner);
01179 jointype = JOIN_INNER;
01180 try_hashjoin_path(root,
01181 joinrel,
01182 jointype,
01183 sjinfo,
01184 semifactors,
01185 param_source_rels,
01186 cheapest_total_outer,
01187 cheapest_total_inner,
01188 restrictlist,
01189 hashclauses);
01190 if (cheapest_startup_outer != NULL &&
01191 cheapest_startup_outer != cheapest_total_outer)
01192 try_hashjoin_path(root,
01193 joinrel,
01194 jointype,
01195 sjinfo,
01196 semifactors,
01197 param_source_rels,
01198 cheapest_startup_outer,
01199 cheapest_total_inner,
01200 restrictlist,
01201 hashclauses);
01202 }
01203 else
01204 {
01205
01206
01207
01208
01209
01210
01211
01212 ListCell *lc1;
01213 ListCell *lc2;
01214
01215 if (cheapest_startup_outer != NULL)
01216 try_hashjoin_path(root,
01217 joinrel,
01218 jointype,
01219 sjinfo,
01220 semifactors,
01221 param_source_rels,
01222 cheapest_startup_outer,
01223 cheapest_total_inner,
01224 restrictlist,
01225 hashclauses);
01226
01227 foreach(lc1, outerrel->cheapest_parameterized_paths)
01228 {
01229 Path *outerpath = (Path *) lfirst(lc1);
01230
01231
01232
01233
01234
01235 if (PATH_PARAM_BY_REL(outerpath, innerrel))
01236 continue;
01237
01238 foreach(lc2, innerrel->cheapest_parameterized_paths)
01239 {
01240 Path *innerpath = (Path *) lfirst(lc2);
01241
01242
01243
01244
01245
01246 if (PATH_PARAM_BY_REL(innerpath, outerrel))
01247 continue;
01248
01249 if (outerpath == cheapest_startup_outer &&
01250 innerpath == cheapest_total_inner)
01251 continue;
01252
01253 try_hashjoin_path(root,
01254 joinrel,
01255 jointype,
01256 sjinfo,
01257 semifactors,
01258 param_source_rels,
01259 outerpath,
01260 innerpath,
01261 restrictlist,
01262 hashclauses);
01263 }
01264 }
01265 }
01266 }
01267 }
01268
01269
01270
01271
01272
01273
01274
01275
01276
01277
01278
01279
01280
01281
01282
01283
01284
01285
01286
01287
01288
01289
01290
01291 static List *
01292 select_mergejoin_clauses(PlannerInfo *root,
01293 RelOptInfo *joinrel,
01294 RelOptInfo *outerrel,
01295 RelOptInfo *innerrel,
01296 List *restrictlist,
01297 JoinType jointype,
01298 bool *mergejoin_allowed)
01299 {
01300 List *result_list = NIL;
01301 bool isouterjoin = IS_OUTER_JOIN(jointype);
01302 bool have_nonmergeable_joinclause = false;
01303 ListCell *l;
01304
01305 foreach(l, restrictlist)
01306 {
01307 RestrictInfo *restrictinfo = (RestrictInfo *) lfirst(l);
01308
01309
01310
01311
01312
01313
01314
01315 if (isouterjoin && restrictinfo->is_pushed_down)
01316 continue;
01317
01318
01319 if (!restrictinfo->can_join ||
01320 restrictinfo->mergeopfamilies == NIL)
01321 {
01322
01323
01324
01325
01326
01327
01328 if (!restrictinfo->clause || !IsA(restrictinfo->clause, Const))
01329 have_nonmergeable_joinclause = true;
01330 continue;
01331 }
01332
01333
01334
01335
01336 if (!clause_sides_match_join(restrictinfo, outerrel, innerrel))
01337 {
01338 have_nonmergeable_joinclause = true;
01339 continue;
01340 }
01341
01342
01343
01344
01345
01346
01347
01348
01349
01350
01351
01352
01353
01354
01355
01356
01357
01358
01359
01360
01361
01362 update_mergeclause_eclasses(root, restrictinfo);
01363
01364 if (EC_MUST_BE_REDUNDANT(restrictinfo->left_ec) ||
01365 EC_MUST_BE_REDUNDANT(restrictinfo->right_ec))
01366 {
01367 have_nonmergeable_joinclause = true;
01368 continue;
01369 }
01370
01371 result_list = lappend(result_list, restrictinfo);
01372 }
01373
01374
01375
01376
01377 switch (jointype)
01378 {
01379 case JOIN_RIGHT:
01380 case JOIN_FULL:
01381 *mergejoin_allowed = !have_nonmergeable_joinclause;
01382 break;
01383 default:
01384 *mergejoin_allowed = true;
01385 break;
01386 }
01387
01388 return result_list;
01389 }