00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018 #include "postgres.h"
00019
00020 #include "access/skey.h"
00021 #include "nodes/makefuncs.h"
00022 #include "nodes/nodeFuncs.h"
00023 #include "nodes/plannodes.h"
00024 #include "optimizer/clauses.h"
00025 #include "optimizer/pathnode.h"
00026 #include "optimizer/paths.h"
00027 #include "optimizer/tlist.h"
00028 #include "utils/lsyscache.h"
00029
00030
00031 static PathKey *make_canonical_pathkey(PlannerInfo *root,
00032 EquivalenceClass *eclass, Oid opfamily,
00033 int strategy, bool nulls_first);
00034 static bool pathkey_is_redundant(PathKey *new_pathkey, List *pathkeys);
00035 static bool right_merge_direction(PlannerInfo *root, PathKey *pathkey);
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046
00047
00048
00049
00050
00051
00052
00053 static PathKey *
00054 make_canonical_pathkey(PlannerInfo *root,
00055 EquivalenceClass *eclass, Oid opfamily,
00056 int strategy, bool nulls_first)
00057 {
00058 PathKey *pk;
00059 ListCell *lc;
00060 MemoryContext oldcontext;
00061
00062
00063 while (eclass->ec_merged)
00064 eclass = eclass->ec_merged;
00065
00066 foreach(lc, root->canon_pathkeys)
00067 {
00068 pk = (PathKey *) lfirst(lc);
00069 if (eclass == pk->pk_eclass &&
00070 opfamily == pk->pk_opfamily &&
00071 strategy == pk->pk_strategy &&
00072 nulls_first == pk->pk_nulls_first)
00073 return pk;
00074 }
00075
00076
00077
00078
00079
00080 oldcontext = MemoryContextSwitchTo(root->planner_cxt);
00081
00082 pk = makeNode(PathKey);
00083 pk->pk_eclass = eclass;
00084 pk->pk_opfamily = opfamily;
00085 pk->pk_strategy = strategy;
00086 pk->pk_nulls_first = nulls_first;
00087
00088 root->canon_pathkeys = lappend(root->canon_pathkeys, pk);
00089
00090 MemoryContextSwitchTo(oldcontext);
00091
00092 return pk;
00093 }
00094
00095
00096
00097
00098
00099
00100
00101
00102
00103
00104
00105
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 static bool
00131 pathkey_is_redundant(PathKey *new_pathkey, List *pathkeys)
00132 {
00133 EquivalenceClass *new_ec = new_pathkey->pk_eclass;
00134 ListCell *lc;
00135
00136
00137 if (EC_MUST_BE_REDUNDANT(new_ec))
00138 return true;
00139
00140
00141 foreach(lc, pathkeys)
00142 {
00143 PathKey *old_pathkey = (PathKey *) lfirst(lc);
00144
00145 if (new_ec == old_pathkey->pk_eclass)
00146 return true;
00147 }
00148
00149 return false;
00150 }
00151
00152
00153
00154
00155
00156
00157
00158
00159
00160
00161
00162
00163
00164
00165
00166
00167
00168
00169 static PathKey *
00170 make_pathkey_from_sortinfo(PlannerInfo *root,
00171 Expr *expr,
00172 Oid opfamily,
00173 Oid opcintype,
00174 Oid collation,
00175 bool reverse_sort,
00176 bool nulls_first,
00177 Index sortref,
00178 Relids rel,
00179 bool create_it)
00180 {
00181 int16 strategy;
00182 Oid equality_op;
00183 List *opfamilies;
00184 EquivalenceClass *eclass;
00185
00186 strategy = reverse_sort ? BTGreaterStrategyNumber : BTLessStrategyNumber;
00187
00188
00189
00190
00191
00192
00193
00194 equality_op = get_opfamily_member(opfamily,
00195 opcintype,
00196 opcintype,
00197 BTEqualStrategyNumber);
00198 if (!OidIsValid(equality_op))
00199 elog(ERROR, "could not find equality operator for opfamily %u",
00200 opfamily);
00201 opfamilies = get_mergejoin_opfamilies(equality_op);
00202 if (!opfamilies)
00203 elog(ERROR, "could not find opfamilies for equality operator %u",
00204 equality_op);
00205
00206
00207 eclass = get_eclass_for_sort_expr(root, expr, opfamilies,
00208 opcintype, collation,
00209 sortref, rel, create_it);
00210
00211
00212 if (!eclass)
00213 return NULL;
00214
00215
00216 return make_canonical_pathkey(root, eclass, opfamily,
00217 strategy, nulls_first);
00218 }
00219
00220
00221
00222
00223
00224
00225
00226
00227 static PathKey *
00228 make_pathkey_from_sortop(PlannerInfo *root,
00229 Expr *expr,
00230 Oid ordering_op,
00231 bool nulls_first,
00232 Index sortref,
00233 bool create_it)
00234 {
00235 Oid opfamily,
00236 opcintype,
00237 collation;
00238 int16 strategy;
00239
00240
00241 if (!get_ordering_op_properties(ordering_op,
00242 &opfamily, &opcintype, &strategy))
00243 elog(ERROR, "operator %u is not a valid ordering operator",
00244 ordering_op);
00245
00246
00247 collation = exprCollation((Node *) expr);
00248
00249 return make_pathkey_from_sortinfo(root,
00250 expr,
00251 opfamily,
00252 opcintype,
00253 collation,
00254 (strategy == BTGreaterStrategyNumber),
00255 nulls_first,
00256 sortref,
00257 NULL,
00258 create_it);
00259 }
00260
00261
00262
00263
00264
00265
00266
00267
00268
00269
00270
00271
00272
00273
00274 PathKeysComparison
00275 compare_pathkeys(List *keys1, List *keys2)
00276 {
00277 ListCell *key1,
00278 *key2;
00279
00280
00281
00282
00283
00284
00285 if (keys1 == keys2)
00286 return PATHKEYS_EQUAL;
00287
00288 forboth(key1, keys1, key2, keys2)
00289 {
00290 PathKey *pathkey1 = (PathKey *) lfirst(key1);
00291 PathKey *pathkey2 = (PathKey *) lfirst(key2);
00292
00293 if (pathkey1 != pathkey2)
00294 return PATHKEYS_DIFFERENT;
00295 }
00296
00297
00298
00299
00300
00301 if (key1 != NULL)
00302 return PATHKEYS_BETTER1;
00303 if (key2 != NULL)
00304 return PATHKEYS_BETTER2;
00305 return PATHKEYS_EQUAL;
00306 }
00307
00308
00309
00310
00311
00312
00313 bool
00314 pathkeys_contained_in(List *keys1, List *keys2)
00315 {
00316 switch (compare_pathkeys(keys1, keys2))
00317 {
00318 case PATHKEYS_EQUAL:
00319 case PATHKEYS_BETTER2:
00320 return true;
00321 default:
00322 break;
00323 }
00324 return false;
00325 }
00326
00327
00328
00329
00330
00331
00332
00333
00334
00335
00336
00337
00338 Path *
00339 get_cheapest_path_for_pathkeys(List *paths, List *pathkeys,
00340 Relids required_outer,
00341 CostSelector cost_criterion)
00342 {
00343 Path *matched_path = NULL;
00344 ListCell *l;
00345
00346 foreach(l, paths)
00347 {
00348 Path *path = (Path *) lfirst(l);
00349
00350
00351
00352
00353
00354 if (matched_path != NULL &&
00355 compare_path_costs(matched_path, path, cost_criterion) <= 0)
00356 continue;
00357
00358 if (pathkeys_contained_in(pathkeys, path->pathkeys) &&
00359 bms_is_subset(PATH_REQ_OUTER(path), required_outer))
00360 matched_path = path;
00361 }
00362 return matched_path;
00363 }
00364
00365
00366
00367
00368
00369
00370
00371
00372
00373
00374
00375
00376
00377
00378
00379 Path *
00380 get_cheapest_fractional_path_for_pathkeys(List *paths,
00381 List *pathkeys,
00382 Relids required_outer,
00383 double fraction)
00384 {
00385 Path *matched_path = NULL;
00386 ListCell *l;
00387
00388 foreach(l, paths)
00389 {
00390 Path *path = (Path *) lfirst(l);
00391
00392
00393
00394
00395
00396 if (matched_path != NULL &&
00397 compare_fractional_path_costs(matched_path, path, fraction) <= 0)
00398 continue;
00399
00400 if (pathkeys_contained_in(pathkeys, path->pathkeys) &&
00401 bms_is_subset(PATH_REQ_OUTER(path), required_outer))
00402 matched_path = path;
00403 }
00404 return matched_path;
00405 }
00406
00407
00408
00409
00410
00411
00412
00413
00414
00415
00416
00417
00418
00419
00420
00421
00422
00423
00424
00425
00426
00427
00428
00429 List *
00430 build_index_pathkeys(PlannerInfo *root,
00431 IndexOptInfo *index,
00432 ScanDirection scandir)
00433 {
00434 List *retval = NIL;
00435 ListCell *lc;
00436 int i;
00437
00438 if (index->sortopfamily == NULL)
00439 return NIL;
00440
00441 i = 0;
00442 foreach(lc, index->indextlist)
00443 {
00444 TargetEntry *indextle = (TargetEntry *) lfirst(lc);
00445 Expr *indexkey;
00446 bool reverse_sort;
00447 bool nulls_first;
00448 PathKey *cpathkey;
00449
00450
00451 indexkey = indextle->expr;
00452
00453 if (ScanDirectionIsBackward(scandir))
00454 {
00455 reverse_sort = !index->reverse_sort[i];
00456 nulls_first = !index->nulls_first[i];
00457 }
00458 else
00459 {
00460 reverse_sort = index->reverse_sort[i];
00461 nulls_first = index->nulls_first[i];
00462 }
00463
00464
00465 cpathkey = make_pathkey_from_sortinfo(root,
00466 indexkey,
00467 index->sortopfamily[i],
00468 index->opcintype[i],
00469 index->indexcollations[i],
00470 reverse_sort,
00471 nulls_first,
00472 0,
00473 index->rel->relids,
00474 false);
00475
00476
00477
00478
00479
00480
00481 if (!cpathkey)
00482 break;
00483
00484
00485 if (!pathkey_is_redundant(cpathkey, retval))
00486 retval = lappend(retval, cpathkey);
00487
00488 i++;
00489 }
00490
00491 return retval;
00492 }
00493
00494
00495
00496
00497
00498
00499
00500
00501
00502
00503
00504
00505
00506
00507 List *
00508 convert_subquery_pathkeys(PlannerInfo *root, RelOptInfo *rel,
00509 List *subquery_pathkeys)
00510 {
00511 List *retval = NIL;
00512 int retvallen = 0;
00513 int outer_query_keys = list_length(root->query_pathkeys);
00514 List *sub_tlist = rel->subplan->targetlist;
00515 ListCell *i;
00516
00517 foreach(i, subquery_pathkeys)
00518 {
00519 PathKey *sub_pathkey = (PathKey *) lfirst(i);
00520 EquivalenceClass *sub_eclass = sub_pathkey->pk_eclass;
00521 PathKey *best_pathkey = NULL;
00522
00523 if (sub_eclass->ec_has_volatile)
00524 {
00525
00526
00527
00528
00529
00530 TargetEntry *tle;
00531
00532 if (sub_eclass->ec_sortref == 0)
00533 elog(ERROR, "volatile EquivalenceClass has no sortref");
00534 tle = get_sortgroupref_tle(sub_eclass->ec_sortref, sub_tlist);
00535 Assert(tle);
00536
00537 if (!tle->resjunk)
00538 {
00539
00540 EquivalenceMember *sub_member;
00541 Expr *outer_expr;
00542 EquivalenceClass *outer_ec;
00543
00544 Assert(list_length(sub_eclass->ec_members) == 1);
00545 sub_member = (EquivalenceMember *) linitial(sub_eclass->ec_members);
00546 outer_expr = (Expr *) makeVarFromTargetEntry(rel->relid, tle);
00547
00548
00549
00550
00551
00552
00553
00554
00555
00556 outer_ec =
00557 get_eclass_for_sort_expr(root,
00558 outer_expr,
00559 sub_eclass->ec_opfamilies,
00560 sub_member->em_datatype,
00561 sub_eclass->ec_collation,
00562 0,
00563 rel->relids,
00564 false);
00565
00566
00567
00568
00569
00570 if (outer_ec)
00571 best_pathkey =
00572 make_canonical_pathkey(root,
00573 outer_ec,
00574 sub_pathkey->pk_opfamily,
00575 sub_pathkey->pk_strategy,
00576 sub_pathkey->pk_nulls_first);
00577 }
00578 }
00579 else
00580 {
00581
00582
00583
00584
00585
00586
00587
00588
00589
00590
00591
00592
00593
00594
00595
00596
00597 int best_score = -1;
00598 ListCell *j;
00599
00600 foreach(j, sub_eclass->ec_members)
00601 {
00602 EquivalenceMember *sub_member = (EquivalenceMember *) lfirst(j);
00603 Expr *sub_expr = sub_member->em_expr;
00604 Oid sub_expr_type = sub_member->em_datatype;
00605 Oid sub_expr_coll = sub_eclass->ec_collation;
00606 ListCell *k;
00607
00608 if (sub_member->em_is_child)
00609 continue;
00610
00611 foreach(k, sub_tlist)
00612 {
00613 TargetEntry *tle = (TargetEntry *) lfirst(k);
00614 Expr *tle_expr;
00615 Expr *outer_expr;
00616 EquivalenceClass *outer_ec;
00617 PathKey *outer_pk;
00618 int score;
00619
00620
00621 if (tle->resjunk)
00622 continue;
00623
00624
00625
00626
00627
00628
00629
00630 tle_expr = canonicalize_ec_expression(tle->expr,
00631 sub_expr_type,
00632 sub_expr_coll);
00633 if (!equal(tle_expr, sub_expr))
00634 continue;
00635
00636
00637
00638
00639
00640 outer_expr = (Expr *) makeVarFromTargetEntry(rel->relid,
00641 tle);
00642
00643
00644 outer_ec = get_eclass_for_sort_expr(root,
00645 outer_expr,
00646 sub_eclass->ec_opfamilies,
00647 sub_expr_type,
00648 sub_expr_coll,
00649 0,
00650 rel->relids,
00651 false);
00652
00653
00654
00655
00656
00657 if (!outer_ec)
00658 continue;
00659
00660 outer_pk = make_canonical_pathkey(root,
00661 outer_ec,
00662 sub_pathkey->pk_opfamily,
00663 sub_pathkey->pk_strategy,
00664 sub_pathkey->pk_nulls_first);
00665
00666 score = list_length(outer_ec->ec_members) - 1;
00667
00668 if (retvallen < outer_query_keys &&
00669 list_nth(root->query_pathkeys, retvallen) == outer_pk)
00670 score++;
00671 if (score > best_score)
00672 {
00673 best_pathkey = outer_pk;
00674 best_score = score;
00675 }
00676 }
00677 }
00678 }
00679
00680
00681
00682
00683
00684 if (!best_pathkey)
00685 break;
00686
00687
00688
00689
00690
00691 if (!pathkey_is_redundant(best_pathkey, retval))
00692 {
00693 retval = lappend(retval, best_pathkey);
00694 retvallen++;
00695 }
00696 }
00697
00698 return retval;
00699 }
00700
00701
00702
00703
00704
00705
00706
00707
00708
00709
00710
00711
00712
00713
00714
00715
00716
00717
00718 List *
00719 build_join_pathkeys(PlannerInfo *root,
00720 RelOptInfo *joinrel,
00721 JoinType jointype,
00722 List *outer_pathkeys)
00723 {
00724 if (jointype == JOIN_FULL || jointype == JOIN_RIGHT)
00725 return NIL;
00726
00727
00728
00729
00730
00731
00732
00733
00734
00735
00736 return truncate_useless_pathkeys(root, joinrel, outer_pathkeys);
00737 }
00738
00739
00740
00741
00742
00743
00744
00745
00746
00747
00748
00749
00750
00751
00752
00753
00754 List *
00755 make_pathkeys_for_sortclauses(PlannerInfo *root,
00756 List *sortclauses,
00757 List *tlist)
00758 {
00759 List *pathkeys = NIL;
00760 ListCell *l;
00761
00762 foreach(l, sortclauses)
00763 {
00764 SortGroupClause *sortcl = (SortGroupClause *) lfirst(l);
00765 Expr *sortkey;
00766 PathKey *pathkey;
00767
00768 sortkey = (Expr *) get_sortgroupclause_expr(sortcl, tlist);
00769 Assert(OidIsValid(sortcl->sortop));
00770 pathkey = make_pathkey_from_sortop(root,
00771 sortkey,
00772 sortcl->sortop,
00773 sortcl->nulls_first,
00774 sortcl->tleSortGroupRef,
00775 true);
00776
00777
00778 if (!pathkey_is_redundant(pathkey, pathkeys))
00779 pathkeys = lappend(pathkeys, pathkey);
00780 }
00781 return pathkeys;
00782 }
00783
00784
00785
00786
00787
00788
00789
00790
00791
00792
00793
00794
00795
00796
00797
00798
00799
00800
00801
00802
00803
00804
00805
00806
00807 void
00808 initialize_mergeclause_eclasses(PlannerInfo *root, RestrictInfo *restrictinfo)
00809 {
00810 Expr *clause = restrictinfo->clause;
00811 Oid lefttype,
00812 righttype;
00813
00814
00815 Assert(restrictinfo->mergeopfamilies != NIL);
00816
00817 Assert(restrictinfo->left_ec == NULL);
00818 Assert(restrictinfo->right_ec == NULL);
00819
00820
00821 op_input_types(((OpExpr *) clause)->opno, &lefttype, &righttype);
00822
00823
00824 restrictinfo->left_ec =
00825 get_eclass_for_sort_expr(root,
00826 (Expr *) get_leftop(clause),
00827 restrictinfo->mergeopfamilies,
00828 lefttype,
00829 ((OpExpr *) clause)->inputcollid,
00830 0,
00831 NULL,
00832 true);
00833 restrictinfo->right_ec =
00834 get_eclass_for_sort_expr(root,
00835 (Expr *) get_rightop(clause),
00836 restrictinfo->mergeopfamilies,
00837 righttype,
00838 ((OpExpr *) clause)->inputcollid,
00839 0,
00840 NULL,
00841 true);
00842 }
00843
00844
00845
00846
00847
00848
00849
00850
00851
00852
00853
00854 void
00855 update_mergeclause_eclasses(PlannerInfo *root, RestrictInfo *restrictinfo)
00856 {
00857
00858 Assert(restrictinfo->mergeopfamilies != NIL);
00859
00860 Assert(restrictinfo->left_ec != NULL);
00861 Assert(restrictinfo->right_ec != NULL);
00862
00863
00864 while (restrictinfo->left_ec->ec_merged)
00865 restrictinfo->left_ec = restrictinfo->left_ec->ec_merged;
00866 while (restrictinfo->right_ec->ec_merged)
00867 restrictinfo->right_ec = restrictinfo->right_ec->ec_merged;
00868 }
00869
00870
00871
00872
00873
00874
00875
00876
00877
00878
00879
00880
00881
00882
00883
00884
00885
00886
00887
00888
00889 List *
00890 find_mergeclauses_for_pathkeys(PlannerInfo *root,
00891 List *pathkeys,
00892 bool outer_keys,
00893 List *restrictinfos)
00894 {
00895 List *mergeclauses = NIL;
00896 ListCell *i;
00897
00898
00899 foreach(i, restrictinfos)
00900 {
00901 RestrictInfo *rinfo = (RestrictInfo *) lfirst(i);
00902
00903 update_mergeclause_eclasses(root, rinfo);
00904 }
00905
00906 foreach(i, pathkeys)
00907 {
00908 PathKey *pathkey = (PathKey *) lfirst(i);
00909 EquivalenceClass *pathkey_ec = pathkey->pk_eclass;
00910 List *matched_restrictinfos = NIL;
00911 ListCell *j;
00912
00913
00914
00915
00916
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
00948
00949 foreach(j, restrictinfos)
00950 {
00951 RestrictInfo *rinfo = (RestrictInfo *) lfirst(j);
00952 EquivalenceClass *clause_ec;
00953
00954 if (outer_keys)
00955 clause_ec = rinfo->outer_is_left ?
00956 rinfo->left_ec : rinfo->right_ec;
00957 else
00958 clause_ec = rinfo->outer_is_left ?
00959 rinfo->right_ec : rinfo->left_ec;
00960 if (clause_ec == pathkey_ec)
00961 matched_restrictinfos = lappend(matched_restrictinfos, rinfo);
00962 }
00963
00964
00965
00966
00967
00968
00969 if (matched_restrictinfos == NIL)
00970 break;
00971
00972
00973
00974
00975
00976 mergeclauses = list_concat(mergeclauses, matched_restrictinfos);
00977 }
00978
00979 return mergeclauses;
00980 }
00981
00982
00983
00984
00985
00986
00987
00988
00989
00990
00991
00992
00993
00994
00995
00996
00997
00998
00999
01000
01001
01002
01003
01004
01005
01006 List *
01007 select_outer_pathkeys_for_merge(PlannerInfo *root,
01008 List *mergeclauses,
01009 RelOptInfo *joinrel)
01010 {
01011 List *pathkeys = NIL;
01012 int nClauses = list_length(mergeclauses);
01013 EquivalenceClass **ecs;
01014 int *scores;
01015 int necs;
01016 ListCell *lc;
01017 int j;
01018
01019
01020 if (nClauses == 0)
01021 return NIL;
01022
01023
01024
01025
01026
01027 ecs = (EquivalenceClass **) palloc(nClauses * sizeof(EquivalenceClass *));
01028 scores = (int *) palloc(nClauses * sizeof(int));
01029 necs = 0;
01030
01031 foreach(lc, mergeclauses)
01032 {
01033 RestrictInfo *rinfo = (RestrictInfo *) lfirst(lc);
01034 EquivalenceClass *oeclass;
01035 int score;
01036 ListCell *lc2;
01037
01038
01039 update_mergeclause_eclasses(root, rinfo);
01040
01041 if (rinfo->outer_is_left)
01042 oeclass = rinfo->left_ec;
01043 else
01044 oeclass = rinfo->right_ec;
01045
01046
01047 for (j = 0; j < necs; j++)
01048 {
01049 if (ecs[j] == oeclass)
01050 break;
01051 }
01052 if (j < necs)
01053 continue;
01054
01055
01056 score = 0;
01057 foreach(lc2, oeclass->ec_members)
01058 {
01059 EquivalenceMember *em = (EquivalenceMember *) lfirst(lc2);
01060
01061
01062 if (!em->em_is_const && !em->em_is_child &&
01063 !bms_overlap(em->em_relids, joinrel->relids))
01064 score++;
01065 }
01066
01067 ecs[necs] = oeclass;
01068 scores[necs] = score;
01069 necs++;
01070 }
01071
01072
01073
01074
01075
01076
01077 if (root->query_pathkeys)
01078 {
01079 foreach(lc, root->query_pathkeys)
01080 {
01081 PathKey *query_pathkey = (PathKey *) lfirst(lc);
01082 EquivalenceClass *query_ec = query_pathkey->pk_eclass;
01083
01084 for (j = 0; j < necs; j++)
01085 {
01086 if (ecs[j] == query_ec)
01087 break;
01088 }
01089 if (j >= necs)
01090 break;
01091 }
01092
01093 if (lc == NULL)
01094 {
01095
01096 pathkeys = list_copy(root->query_pathkeys);
01097
01098 foreach(lc, root->query_pathkeys)
01099 {
01100 PathKey *query_pathkey = (PathKey *) lfirst(lc);
01101 EquivalenceClass *query_ec = query_pathkey->pk_eclass;
01102
01103 for (j = 0; j < necs; j++)
01104 {
01105 if (ecs[j] == query_ec)
01106 {
01107 scores[j] = -1;
01108 break;
01109 }
01110 }
01111 }
01112 }
01113 }
01114
01115
01116
01117
01118
01119
01120 for (;;)
01121 {
01122 int best_j;
01123 int best_score;
01124 EquivalenceClass *ec;
01125 PathKey *pathkey;
01126
01127 best_j = 0;
01128 best_score = scores[0];
01129 for (j = 1; j < necs; j++)
01130 {
01131 if (scores[j] > best_score)
01132 {
01133 best_j = j;
01134 best_score = scores[j];
01135 }
01136 }
01137 if (best_score < 0)
01138 break;
01139 ec = ecs[best_j];
01140 scores[best_j] = -1;
01141 pathkey = make_canonical_pathkey(root,
01142 ec,
01143 linitial_oid(ec->ec_opfamilies),
01144 BTLessStrategyNumber,
01145 false);
01146
01147 Assert(!pathkey_is_redundant(pathkey, pathkeys));
01148 pathkeys = lappend(pathkeys, pathkey);
01149 }
01150
01151 pfree(ecs);
01152 pfree(scores);
01153
01154 return pathkeys;
01155 }
01156
01157
01158
01159
01160
01161
01162
01163
01164
01165
01166
01167
01168
01169
01170
01171
01172
01173
01174
01175
01176
01177
01178 List *
01179 make_inner_pathkeys_for_merge(PlannerInfo *root,
01180 List *mergeclauses,
01181 List *outer_pathkeys)
01182 {
01183 List *pathkeys = NIL;
01184 EquivalenceClass *lastoeclass;
01185 PathKey *opathkey;
01186 ListCell *lc;
01187 ListCell *lop;
01188
01189 lastoeclass = NULL;
01190 opathkey = NULL;
01191 lop = list_head(outer_pathkeys);
01192
01193 foreach(lc, mergeclauses)
01194 {
01195 RestrictInfo *rinfo = (RestrictInfo *) lfirst(lc);
01196 EquivalenceClass *oeclass;
01197 EquivalenceClass *ieclass;
01198 PathKey *pathkey;
01199
01200 update_mergeclause_eclasses(root, rinfo);
01201
01202 if (rinfo->outer_is_left)
01203 {
01204 oeclass = rinfo->left_ec;
01205 ieclass = rinfo->right_ec;
01206 }
01207 else
01208 {
01209 oeclass = rinfo->right_ec;
01210 ieclass = rinfo->left_ec;
01211 }
01212
01213
01214
01215 if (oeclass != lastoeclass)
01216 {
01217 if (!lop)
01218 elog(ERROR, "too few pathkeys for mergeclauses");
01219 opathkey = (PathKey *) lfirst(lop);
01220 lop = lnext(lop);
01221 lastoeclass = opathkey->pk_eclass;
01222 if (oeclass != lastoeclass)
01223 elog(ERROR, "outer pathkeys do not match mergeclause");
01224 }
01225
01226
01227
01228
01229
01230
01231 if (ieclass == oeclass)
01232 pathkey = opathkey;
01233 else
01234 pathkey = make_canonical_pathkey(root,
01235 ieclass,
01236 opathkey->pk_opfamily,
01237 opathkey->pk_strategy,
01238 opathkey->pk_nulls_first);
01239
01240
01241
01242
01243
01244 if (!pathkey_is_redundant(pathkey, pathkeys))
01245 pathkeys = lappend(pathkeys, pathkey);
01246 }
01247
01248 return pathkeys;
01249 }
01250
01251
01252
01253
01254
01255
01256
01257
01258
01259
01260
01261
01262
01263
01264
01265
01266
01267
01268
01269
01270
01271
01272
01273
01274
01275
01276
01277
01278
01279 static int
01280 pathkeys_useful_for_merging(PlannerInfo *root, RelOptInfo *rel, List *pathkeys)
01281 {
01282 int useful = 0;
01283 ListCell *i;
01284
01285 foreach(i, pathkeys)
01286 {
01287 PathKey *pathkey = (PathKey *) lfirst(i);
01288 bool matched = false;
01289 ListCell *j;
01290
01291
01292 if (!right_merge_direction(root, pathkey))
01293 break;
01294
01295
01296
01297
01298
01299
01300 if (rel->has_eclass_joins &&
01301 eclass_useful_for_merging(pathkey->pk_eclass, rel))
01302 matched = true;
01303 else
01304 {
01305
01306
01307
01308
01309
01310 foreach(j, rel->joininfo)
01311 {
01312 RestrictInfo *restrictinfo = (RestrictInfo *) lfirst(j);
01313
01314 if (restrictinfo->mergeopfamilies == NIL)
01315 continue;
01316 update_mergeclause_eclasses(root, restrictinfo);
01317
01318 if (pathkey->pk_eclass == restrictinfo->left_ec ||
01319 pathkey->pk_eclass == restrictinfo->right_ec)
01320 {
01321 matched = true;
01322 break;
01323 }
01324 }
01325 }
01326
01327
01328
01329
01330
01331
01332 if (matched)
01333 useful++;
01334 else
01335 break;
01336 }
01337
01338 return useful;
01339 }
01340
01341
01342
01343
01344
01345
01346 static bool
01347 right_merge_direction(PlannerInfo *root, PathKey *pathkey)
01348 {
01349 ListCell *l;
01350
01351 foreach(l, root->query_pathkeys)
01352 {
01353 PathKey *query_pathkey = (PathKey *) lfirst(l);
01354
01355 if (pathkey->pk_eclass == query_pathkey->pk_eclass &&
01356 pathkey->pk_opfamily == query_pathkey->pk_opfamily)
01357 {
01358
01359
01360
01361
01362
01363
01364
01365 return (pathkey->pk_strategy == query_pathkey->pk_strategy);
01366 }
01367 }
01368
01369
01370 return (pathkey->pk_strategy == BTLessStrategyNumber);
01371 }
01372
01373
01374
01375
01376
01377
01378
01379
01380
01381
01382 static int
01383 pathkeys_useful_for_ordering(PlannerInfo *root, List *pathkeys)
01384 {
01385 if (root->query_pathkeys == NIL)
01386 return 0;
01387
01388 if (pathkeys == NIL)
01389 return 0;
01390
01391 if (pathkeys_contained_in(root->query_pathkeys, pathkeys))
01392 {
01393
01394 return list_length(root->query_pathkeys);
01395 }
01396
01397 return 0;
01398 }
01399
01400
01401
01402
01403
01404 List *
01405 truncate_useless_pathkeys(PlannerInfo *root,
01406 RelOptInfo *rel,
01407 List *pathkeys)
01408 {
01409 int nuseful;
01410 int nuseful2;
01411
01412 nuseful = pathkeys_useful_for_merging(root, rel, pathkeys);
01413 nuseful2 = pathkeys_useful_for_ordering(root, pathkeys);
01414 if (nuseful2 > nuseful)
01415 nuseful = nuseful2;
01416
01417
01418
01419
01420
01421 if (nuseful == 0)
01422 return NIL;
01423 else if (nuseful == list_length(pathkeys))
01424 return pathkeys;
01425 else
01426 return list_truncate(list_copy(pathkeys), nuseful);
01427 }
01428
01429
01430
01431
01432
01433
01434
01435
01436
01437
01438
01439
01440
01441
01442
01443
01444 bool
01445 has_useful_pathkeys(PlannerInfo *root, RelOptInfo *rel)
01446 {
01447 if (rel->joininfo != NIL || rel->has_eclass_joins)
01448 return true;
01449 if (root->query_pathkeys != NIL)
01450 return true;
01451 return false;
01452 }