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 "access/skey.h"
00021 #include "access/sysattr.h"
00022 #include "catalog/pg_am.h"
00023 #include "catalog/pg_collation.h"
00024 #include "catalog/pg_operator.h"
00025 #include "catalog/pg_opfamily.h"
00026 #include "catalog/pg_type.h"
00027 #include "nodes/makefuncs.h"
00028 #include "optimizer/clauses.h"
00029 #include "optimizer/cost.h"
00030 #include "optimizer/pathnode.h"
00031 #include "optimizer/paths.h"
00032 #include "optimizer/predtest.h"
00033 #include "optimizer/restrictinfo.h"
00034 #include "optimizer/var.h"
00035 #include "utils/builtins.h"
00036 #include "utils/bytea.h"
00037 #include "utils/lsyscache.h"
00038 #include "utils/pg_locale.h"
00039 #include "utils/selfuncs.h"
00040
00041
00042 #define IsBooleanOpfamily(opfamily) \
00043 ((opfamily) == BOOL_BTREE_FAM_OID || (opfamily) == BOOL_HASH_FAM_OID)
00044
00045 #define IndexCollMatchesExprColl(idxcollation, exprcollation) \
00046 ((idxcollation) == InvalidOid || (idxcollation) == (exprcollation))
00047
00048
00049 typedef enum
00050 {
00051 SAOP_PER_AM,
00052 SAOP_ALLOW,
00053 SAOP_REQUIRE
00054 } SaOpControl;
00055
00056
00057 typedef enum
00058 {
00059 ST_INDEXSCAN,
00060 ST_BITMAPSCAN,
00061 ST_ANYSCAN
00062 } ScanTypeControl;
00063
00064
00065 typedef struct
00066 {
00067 bool nonempty;
00068
00069 List *indexclauses[INDEX_MAX_KEYS];
00070 } IndexClauseSet;
00071
00072
00073 typedef struct
00074 {
00075 Path *path;
00076 List *quals;
00077 List *preds;
00078 Bitmapset *clauseids;
00079 } PathClauseUsage;
00080
00081
00082 typedef struct
00083 {
00084 IndexOptInfo *index;
00085 int indexcol;
00086 } ec_member_matches_arg;
00087
00088
00089 static void consider_index_join_clauses(PlannerInfo *root, RelOptInfo *rel,
00090 IndexOptInfo *index,
00091 IndexClauseSet *rclauseset,
00092 IndexClauseSet *jclauseset,
00093 IndexClauseSet *eclauseset,
00094 List **bitindexpaths);
00095 static void consider_index_join_outer_rels(PlannerInfo *root, RelOptInfo *rel,
00096 IndexOptInfo *index,
00097 IndexClauseSet *rclauseset,
00098 IndexClauseSet *jclauseset,
00099 IndexClauseSet *eclauseset,
00100 List **bitindexpaths,
00101 List *indexjoinclauses,
00102 int considered_clauses,
00103 List **considered_relids);
00104 static void get_join_index_paths(PlannerInfo *root, RelOptInfo *rel,
00105 IndexOptInfo *index,
00106 IndexClauseSet *rclauseset,
00107 IndexClauseSet *jclauseset,
00108 IndexClauseSet *eclauseset,
00109 List **bitindexpaths,
00110 Relids relids,
00111 List **considered_relids);
00112 static bool eclass_already_used(EquivalenceClass *parent_ec, Relids oldrelids,
00113 List *indexjoinclauses);
00114 static bool bms_equal_any(Relids relids, List *relids_list);
00115 static void get_index_paths(PlannerInfo *root, RelOptInfo *rel,
00116 IndexOptInfo *index, IndexClauseSet *clauses,
00117 List **bitindexpaths);
00118 static List *build_index_paths(PlannerInfo *root, RelOptInfo *rel,
00119 IndexOptInfo *index, IndexClauseSet *clauses,
00120 bool useful_predicate,
00121 SaOpControl saop_control, ScanTypeControl scantype);
00122 static List *build_paths_for_OR(PlannerInfo *root, RelOptInfo *rel,
00123 List *clauses, List *other_clauses);
00124 static List *drop_indexable_join_clauses(RelOptInfo *rel, List *clauses);
00125 static Path *choose_bitmap_and(PlannerInfo *root, RelOptInfo *rel,
00126 List *paths);
00127 static int path_usage_comparator(const void *a, const void *b);
00128 static Cost bitmap_scan_cost_est(PlannerInfo *root, RelOptInfo *rel,
00129 Path *ipath);
00130 static Cost bitmap_and_cost_est(PlannerInfo *root, RelOptInfo *rel,
00131 List *paths);
00132 static PathClauseUsage *classify_index_clause_usage(Path *path,
00133 List **clauselist);
00134 static Relids get_bitmap_tree_required_outer(Path *bitmapqual);
00135 static void find_indexpath_quals(Path *bitmapqual, List **quals, List **preds);
00136 static int find_list_position(Node *node, List **nodelist);
00137 static bool check_index_only(RelOptInfo *rel, IndexOptInfo *index);
00138 static double get_loop_count(PlannerInfo *root, Relids outer_relids);
00139 static void match_restriction_clauses_to_index(RelOptInfo *rel,
00140 IndexOptInfo *index,
00141 IndexClauseSet *clauseset);
00142 static void match_join_clauses_to_index(PlannerInfo *root,
00143 RelOptInfo *rel, IndexOptInfo *index,
00144 Relids lateral_referencers,
00145 IndexClauseSet *clauseset,
00146 List **joinorclauses);
00147 static void match_eclass_clauses_to_index(PlannerInfo *root,
00148 IndexOptInfo *index,
00149 Relids lateral_referencers,
00150 IndexClauseSet *clauseset);
00151 static void match_clauses_to_index(IndexOptInfo *index,
00152 List *clauses,
00153 IndexClauseSet *clauseset);
00154 static void match_clause_to_index(IndexOptInfo *index,
00155 RestrictInfo *rinfo,
00156 IndexClauseSet *clauseset);
00157 static bool match_clause_to_indexcol(IndexOptInfo *index,
00158 int indexcol,
00159 RestrictInfo *rinfo);
00160 static bool is_indexable_operator(Oid expr_op, Oid opfamily,
00161 bool indexkey_on_left);
00162 static bool match_rowcompare_to_indexcol(IndexOptInfo *index,
00163 int indexcol,
00164 Oid opfamily,
00165 Oid idxcollation,
00166 RowCompareExpr *clause);
00167 static void match_pathkeys_to_index(IndexOptInfo *index, List *pathkeys,
00168 List **orderby_clauses_p,
00169 List **clause_columns_p);
00170 static Expr *match_clause_to_ordering_op(IndexOptInfo *index,
00171 int indexcol, Expr *clause, Oid pk_opfamily);
00172 static bool ec_member_matches_indexcol(PlannerInfo *root, RelOptInfo *rel,
00173 EquivalenceClass *ec, EquivalenceMember *em,
00174 void *arg);
00175 static bool match_boolean_index_clause(Node *clause, int indexcol,
00176 IndexOptInfo *index);
00177 static bool match_special_index_operator(Expr *clause,
00178 Oid opfamily, Oid idxcollation,
00179 bool indexkey_on_left);
00180 static Expr *expand_boolean_index_clause(Node *clause, int indexcol,
00181 IndexOptInfo *index);
00182 static List *expand_indexqual_opclause(RestrictInfo *rinfo,
00183 Oid opfamily, Oid idxcollation);
00184 static RestrictInfo *expand_indexqual_rowcompare(RestrictInfo *rinfo,
00185 IndexOptInfo *index,
00186 int indexcol);
00187 static List *prefix_quals(Node *leftop, Oid opfamily, Oid collation,
00188 Const *prefix, Pattern_Prefix_Status pstatus);
00189 static List *network_prefix_quals(Node *leftop, Oid expr_op, Oid opfamily,
00190 Datum rightop);
00191 static Datum string_to_datum(const char *str, Oid datatype);
00192 static Const *string_to_const(const char *str, Oid datatype);
00193
00194
00195
00196
00197
00198
00199
00200
00201
00202
00203
00204
00205
00206
00207
00208
00209
00210
00211
00212
00213
00214
00215
00216
00217
00218
00219
00220
00221
00222
00223
00224
00225
00226
00227
00228
00229
00230
00231
00232 void
00233 create_index_paths(PlannerInfo *root, RelOptInfo *rel)
00234 {
00235 List *indexpaths;
00236 List *bitindexpaths;
00237 List *bitjoinpaths;
00238 List *joinorclauses;
00239 Relids lateral_referencers;
00240 IndexClauseSet rclauseset;
00241 IndexClauseSet jclauseset;
00242 IndexClauseSet eclauseset;
00243 ListCell *lc;
00244
00245
00246 if (rel->indexlist == NIL)
00247 return;
00248
00249
00250
00251
00252
00253
00254
00255
00256 lateral_referencers = NULL;
00257 foreach(lc, root->lateral_info_list)
00258 {
00259 LateralJoinInfo *ljinfo = (LateralJoinInfo *) lfirst(lc);
00260
00261 if (bms_is_member(rel->relid, ljinfo->lateral_lhs))
00262 lateral_referencers = bms_add_member(lateral_referencers,
00263 ljinfo->lateral_rhs);
00264 }
00265
00266
00267 bitindexpaths = bitjoinpaths = joinorclauses = NIL;
00268
00269
00270 foreach(lc, rel->indexlist)
00271 {
00272 IndexOptInfo *index = (IndexOptInfo *) lfirst(lc);
00273
00274
00275 Assert(index->ncolumns <= INDEX_MAX_KEYS);
00276
00277
00278
00279
00280
00281
00282 if (index->indpred != NIL && !index->predOK)
00283 continue;
00284
00285
00286
00287
00288 MemSet(&rclauseset, 0, sizeof(rclauseset));
00289 match_restriction_clauses_to_index(rel, index, &rclauseset);
00290
00291
00292
00293
00294
00295
00296 get_index_paths(root, rel, index, &rclauseset,
00297 &bitindexpaths);
00298
00299
00300
00301
00302
00303
00304
00305 MemSet(&jclauseset, 0, sizeof(jclauseset));
00306 match_join_clauses_to_index(root, rel, index, lateral_referencers,
00307 &jclauseset, &joinorclauses);
00308
00309
00310
00311
00312
00313 MemSet(&eclauseset, 0, sizeof(eclauseset));
00314 match_eclass_clauses_to_index(root, index, lateral_referencers,
00315 &eclauseset);
00316
00317
00318
00319
00320
00321 if (jclauseset.nonempty || eclauseset.nonempty)
00322 consider_index_join_clauses(root, rel, index,
00323 &rclauseset,
00324 &jclauseset,
00325 &eclauseset,
00326 &bitjoinpaths);
00327 }
00328
00329
00330
00331
00332
00333 indexpaths = generate_bitmap_or_paths(root, rel,
00334 rel->baserestrictinfo, NIL,
00335 false);
00336 bitindexpaths = list_concat(bitindexpaths, indexpaths);
00337
00338
00339
00340
00341
00342 indexpaths = generate_bitmap_or_paths(root, rel,
00343 joinorclauses, rel->baserestrictinfo,
00344 false);
00345 bitjoinpaths = list_concat(bitjoinpaths, indexpaths);
00346
00347
00348
00349
00350
00351
00352
00353
00354 if (bitindexpaths != NIL)
00355 {
00356 Path *bitmapqual;
00357 BitmapHeapPath *bpath;
00358
00359 bitmapqual = choose_bitmap_and(root, rel, bitindexpaths);
00360 bpath = create_bitmap_heap_path(root, rel, bitmapqual,
00361 rel->lateral_relids, 1.0);
00362 add_path(rel, (Path *) bpath);
00363 }
00364
00365
00366
00367
00368
00369
00370
00371
00372
00373
00374
00375 if (bitjoinpaths != NIL)
00376 {
00377 List *path_outer;
00378 List *all_path_outers;
00379 ListCell *lc;
00380
00381
00382
00383
00384
00385
00386 path_outer = all_path_outers = NIL;
00387 foreach(lc, bitjoinpaths)
00388 {
00389 Path *path = (Path *) lfirst(lc);
00390 Relids required_outer;
00391
00392 required_outer = get_bitmap_tree_required_outer(path);
00393 path_outer = lappend(path_outer, required_outer);
00394 if (!bms_equal_any(required_outer, all_path_outers))
00395 all_path_outers = lappend(all_path_outers, required_outer);
00396 }
00397
00398
00399 foreach(lc, all_path_outers)
00400 {
00401 Relids max_outers = (Relids) lfirst(lc);
00402 List *this_path_set;
00403 Path *bitmapqual;
00404 Relids required_outer;
00405 double loop_count;
00406 BitmapHeapPath *bpath;
00407 ListCell *lcp;
00408 ListCell *lco;
00409
00410
00411 this_path_set = NIL;
00412 forboth(lcp, bitjoinpaths, lco, path_outer)
00413 {
00414 Path *path = (Path *) lfirst(lcp);
00415 Relids p_outers = (Relids) lfirst(lco);
00416
00417 if (bms_is_subset(p_outers, max_outers))
00418 this_path_set = lappend(this_path_set, path);
00419 }
00420
00421
00422
00423
00424
00425 this_path_set = list_concat(this_path_set, bitindexpaths);
00426
00427
00428 bitmapqual = choose_bitmap_and(root, rel, this_path_set);
00429
00430
00431 required_outer = get_bitmap_tree_required_outer(bitmapqual);
00432 loop_count = get_loop_count(root, required_outer);
00433 bpath = create_bitmap_heap_path(root, rel, bitmapqual,
00434 required_outer, loop_count);
00435 add_path(rel, (Path *) bpath);
00436 }
00437 }
00438 }
00439
00440
00441
00442
00443
00444
00445
00446
00447
00448
00449
00450
00451
00452
00453
00454
00455 static void
00456 consider_index_join_clauses(PlannerInfo *root, RelOptInfo *rel,
00457 IndexOptInfo *index,
00458 IndexClauseSet *rclauseset,
00459 IndexClauseSet *jclauseset,
00460 IndexClauseSet *eclauseset,
00461 List **bitindexpaths)
00462 {
00463 int considered_clauses = 0;
00464 List *considered_relids = NIL;
00465 int indexcol;
00466
00467
00468
00469
00470
00471
00472
00473
00474
00475
00476
00477
00478
00479
00480
00481
00482
00483
00484
00485
00486
00487
00488 for (indexcol = 0; indexcol < index->ncolumns; indexcol++)
00489 {
00490
00491 considered_clauses += list_length(jclauseset->indexclauses[indexcol]);
00492 consider_index_join_outer_rels(root, rel, index,
00493 rclauseset, jclauseset, eclauseset,
00494 bitindexpaths,
00495 jclauseset->indexclauses[indexcol],
00496 considered_clauses,
00497 &considered_relids);
00498
00499 considered_clauses += list_length(eclauseset->indexclauses[indexcol]);
00500 consider_index_join_outer_rels(root, rel, index,
00501 rclauseset, jclauseset, eclauseset,
00502 bitindexpaths,
00503 eclauseset->indexclauses[indexcol],
00504 considered_clauses,
00505 &considered_relids);
00506 }
00507 }
00508
00509
00510
00511
00512
00513
00514
00515
00516
00517
00518
00519
00520
00521 static void
00522 consider_index_join_outer_rels(PlannerInfo *root, RelOptInfo *rel,
00523 IndexOptInfo *index,
00524 IndexClauseSet *rclauseset,
00525 IndexClauseSet *jclauseset,
00526 IndexClauseSet *eclauseset,
00527 List **bitindexpaths,
00528 List *indexjoinclauses,
00529 int considered_clauses,
00530 List **considered_relids)
00531 {
00532 ListCell *lc;
00533
00534
00535 foreach(lc, indexjoinclauses)
00536 {
00537 RestrictInfo *rinfo = (RestrictInfo *) lfirst(lc);
00538 Relids clause_relids = rinfo->clause_relids;
00539 ListCell *lc2;
00540
00541
00542 if (bms_equal_any(clause_relids, *considered_relids))
00543 continue;
00544
00545
00546
00547
00548
00549
00550
00551
00552
00553
00554
00555
00556
00557
00558 foreach(lc2, *considered_relids)
00559 {
00560 Relids oldrelids = (Relids) lfirst(lc2);
00561
00562
00563
00564
00565
00566
00567
00568 if (bms_subset_compare(clause_relids, oldrelids) != BMS_DIFFERENT)
00569 continue;
00570
00571
00572
00573
00574
00575
00576
00577
00578
00579 if (rinfo->parent_ec &&
00580 eclass_already_used(rinfo->parent_ec, oldrelids,
00581 indexjoinclauses))
00582 continue;
00583
00584
00585
00586
00587
00588
00589 if (list_length(*considered_relids) >= 10 * considered_clauses)
00590 break;
00591
00592
00593 get_join_index_paths(root, rel, index,
00594 rclauseset, jclauseset, eclauseset,
00595 bitindexpaths,
00596 bms_union(clause_relids, oldrelids),
00597 considered_relids);
00598 }
00599
00600
00601 get_join_index_paths(root, rel, index,
00602 rclauseset, jclauseset, eclauseset,
00603 bitindexpaths,
00604 clause_relids,
00605 considered_relids);
00606 }
00607 }
00608
00609
00610
00611
00612
00613
00614
00615
00616
00617
00618
00619
00620
00621
00622 static void
00623 get_join_index_paths(PlannerInfo *root, RelOptInfo *rel,
00624 IndexOptInfo *index,
00625 IndexClauseSet *rclauseset,
00626 IndexClauseSet *jclauseset,
00627 IndexClauseSet *eclauseset,
00628 List **bitindexpaths,
00629 Relids relids,
00630 List **considered_relids)
00631 {
00632 IndexClauseSet clauseset;
00633 int indexcol;
00634
00635
00636 if (bms_equal_any(relids, *considered_relids))
00637 return;
00638
00639
00640 MemSet(&clauseset, 0, sizeof(clauseset));
00641
00642 for (indexcol = 0; indexcol < index->ncolumns; indexcol++)
00643 {
00644 ListCell *lc;
00645
00646
00647 foreach(lc, jclauseset->indexclauses[indexcol])
00648 {
00649 RestrictInfo *rinfo = (RestrictInfo *) lfirst(lc);
00650
00651 if (bms_is_subset(rinfo->clause_relids, relids))
00652 clauseset.indexclauses[indexcol] =
00653 lappend(clauseset.indexclauses[indexcol], rinfo);
00654 }
00655
00656
00657
00658
00659
00660
00661
00662 foreach(lc, eclauseset->indexclauses[indexcol])
00663 {
00664 RestrictInfo *rinfo = (RestrictInfo *) lfirst(lc);
00665
00666 if (bms_is_subset(rinfo->clause_relids, relids))
00667 {
00668 clauseset.indexclauses[indexcol] =
00669 lappend(clauseset.indexclauses[indexcol], rinfo);
00670 break;
00671 }
00672 }
00673
00674
00675 clauseset.indexclauses[indexcol] =
00676 list_concat(clauseset.indexclauses[indexcol],
00677 rclauseset->indexclauses[indexcol]);
00678
00679 if (clauseset.indexclauses[indexcol] != NIL)
00680 clauseset.nonempty = true;
00681 }
00682
00683
00684 Assert(clauseset.nonempty);
00685
00686
00687 get_index_paths(root, rel, index, &clauseset, bitindexpaths);
00688
00689
00690
00691
00692
00693 *considered_relids = lcons(relids, *considered_relids);
00694 }
00695
00696
00697
00698
00699
00700
00701 static bool
00702 eclass_already_used(EquivalenceClass *parent_ec, Relids oldrelids,
00703 List *indexjoinclauses)
00704 {
00705 ListCell *lc;
00706
00707 foreach(lc, indexjoinclauses)
00708 {
00709 RestrictInfo *rinfo = (RestrictInfo *) lfirst(lc);
00710
00711 if (rinfo->parent_ec == parent_ec &&
00712 bms_is_subset(rinfo->clause_relids, oldrelids))
00713 return true;
00714 }
00715 return false;
00716 }
00717
00718
00719
00720
00721
00722
00723
00724 static bool
00725 bms_equal_any(Relids relids, List *relids_list)
00726 {
00727 ListCell *lc;
00728
00729 foreach(lc, relids_list)
00730 {
00731 if (bms_equal(relids, (Relids) lfirst(lc)))
00732 return true;
00733 }
00734 return false;
00735 }
00736
00737
00738
00739
00740
00741
00742
00743
00744
00745
00746
00747
00748
00749
00750
00751 static void
00752 get_index_paths(PlannerInfo *root, RelOptInfo *rel,
00753 IndexOptInfo *index, IndexClauseSet *clauses,
00754 List **bitindexpaths)
00755 {
00756 List *indexpaths;
00757 ListCell *lc;
00758
00759
00760
00761
00762
00763 indexpaths = build_index_paths(root, rel,
00764 index, clauses,
00765 index->predOK,
00766 SAOP_PER_AM, ST_ANYSCAN);
00767
00768
00769
00770
00771
00772
00773
00774
00775
00776
00777
00778
00779
00780 foreach(lc, indexpaths)
00781 {
00782 IndexPath *ipath = (IndexPath *) lfirst(lc);
00783
00784 if (index->amhasgettuple)
00785 add_path(rel, (Path *) ipath);
00786
00787 if (index->amhasgetbitmap &&
00788 (ipath->path.pathkeys == NIL ||
00789 ipath->indexselectivity < 1.0))
00790 *bitindexpaths = lappend(*bitindexpaths, ipath);
00791 }
00792
00793
00794
00795
00796
00797
00798 if (!index->amsearcharray)
00799 {
00800 indexpaths = build_index_paths(root, rel,
00801 index, clauses,
00802 false,
00803 SAOP_REQUIRE, ST_BITMAPSCAN);
00804 *bitindexpaths = list_concat(*bitindexpaths, indexpaths);
00805 }
00806 }
00807
00808
00809
00810
00811
00812
00813
00814
00815
00816
00817
00818
00819
00820
00821
00822
00823
00824
00825
00826
00827
00828
00829
00830
00831
00832
00833
00834
00835
00836
00837
00838
00839
00840
00841 static List *
00842 build_index_paths(PlannerInfo *root, RelOptInfo *rel,
00843 IndexOptInfo *index, IndexClauseSet *clauses,
00844 bool useful_predicate,
00845 SaOpControl saop_control, ScanTypeControl scantype)
00846 {
00847 List *result = NIL;
00848 IndexPath *ipath;
00849 List *index_clauses;
00850 List *clause_columns;
00851 Relids outer_relids;
00852 double loop_count;
00853 List *orderbyclauses;
00854 List *orderbyclausecols;
00855 List *index_pathkeys;
00856 List *useful_pathkeys;
00857 bool found_clause;
00858 bool found_lower_saop_clause;
00859 bool pathkeys_possibly_useful;
00860 bool index_is_ordered;
00861 bool index_only_scan;
00862 int indexcol;
00863
00864
00865
00866
00867 switch (scantype)
00868 {
00869 case ST_INDEXSCAN:
00870 if (!index->amhasgettuple)
00871 return NIL;
00872 break;
00873 case ST_BITMAPSCAN:
00874 if (!index->amhasgetbitmap)
00875 return NIL;
00876 break;
00877 case ST_ANYSCAN:
00878
00879 break;
00880 }
00881
00882
00883
00884
00885
00886
00887
00888
00889
00890
00891
00892
00893
00894
00895
00896
00897
00898
00899
00900
00901
00902
00903
00904
00905
00906
00907 index_clauses = NIL;
00908 clause_columns = NIL;
00909 found_clause = false;
00910 found_lower_saop_clause = false;
00911 outer_relids = bms_copy(rel->lateral_relids);
00912 for (indexcol = 0; indexcol < index->ncolumns; indexcol++)
00913 {
00914 ListCell *lc;
00915
00916 foreach(lc, clauses->indexclauses[indexcol])
00917 {
00918 RestrictInfo *rinfo = (RestrictInfo *) lfirst(lc);
00919
00920 if (IsA(rinfo->clause, ScalarArrayOpExpr))
00921 {
00922
00923 if (saop_control == SAOP_PER_AM && !index->amsearcharray)
00924 continue;
00925 found_clause = true;
00926 if (indexcol > 0)
00927 found_lower_saop_clause = true;
00928 }
00929 else
00930 {
00931 if (saop_control != SAOP_REQUIRE)
00932 found_clause = true;
00933 }
00934 index_clauses = lappend(index_clauses, rinfo);
00935 clause_columns = lappend_int(clause_columns, indexcol);
00936 outer_relids = bms_add_members(outer_relids,
00937 rinfo->clause_relids);
00938 }
00939
00940
00941
00942
00943
00944
00945
00946
00947
00948 if (index_clauses == NIL && !index->amoptionalkey)
00949 return NIL;
00950 }
00951
00952
00953 outer_relids = bms_del_member(outer_relids, rel->relid);
00954
00955 if (bms_is_empty(outer_relids))
00956 outer_relids = NULL;
00957
00958
00959 loop_count = get_loop_count(root, outer_relids);
00960
00961
00962
00963
00964
00965
00966
00967 pathkeys_possibly_useful = (scantype != ST_BITMAPSCAN &&
00968 !found_lower_saop_clause &&
00969 has_useful_pathkeys(root, rel));
00970 index_is_ordered = (index->sortopfamily != NULL);
00971 if (index_is_ordered && pathkeys_possibly_useful)
00972 {
00973 index_pathkeys = build_index_pathkeys(root, index,
00974 ForwardScanDirection);
00975 useful_pathkeys = truncate_useless_pathkeys(root, rel,
00976 index_pathkeys);
00977 orderbyclauses = NIL;
00978 orderbyclausecols = NIL;
00979 }
00980 else if (index->amcanorderbyop && pathkeys_possibly_useful)
00981 {
00982
00983 match_pathkeys_to_index(index, root->query_pathkeys,
00984 &orderbyclauses,
00985 &orderbyclausecols);
00986 if (orderbyclauses)
00987 useful_pathkeys = root->query_pathkeys;
00988 else
00989 useful_pathkeys = NIL;
00990 }
00991 else
00992 {
00993 useful_pathkeys = NIL;
00994 orderbyclauses = NIL;
00995 orderbyclausecols = NIL;
00996 }
00997
00998
00999
01000
01001
01002
01003 index_only_scan = (scantype != ST_BITMAPSCAN &&
01004 check_index_only(rel, index));
01005
01006
01007
01008
01009
01010
01011
01012 if (found_clause || useful_pathkeys != NIL || useful_predicate ||
01013 index_only_scan)
01014 {
01015 ipath = create_index_path(root, index,
01016 index_clauses,
01017 clause_columns,
01018 orderbyclauses,
01019 orderbyclausecols,
01020 useful_pathkeys,
01021 index_is_ordered ?
01022 ForwardScanDirection :
01023 NoMovementScanDirection,
01024 index_only_scan,
01025 outer_relids,
01026 loop_count);
01027 result = lappend(result, ipath);
01028 }
01029
01030
01031
01032
01033 if (index_is_ordered && pathkeys_possibly_useful)
01034 {
01035 index_pathkeys = build_index_pathkeys(root, index,
01036 BackwardScanDirection);
01037 useful_pathkeys = truncate_useless_pathkeys(root, rel,
01038 index_pathkeys);
01039 if (useful_pathkeys != NIL)
01040 {
01041 ipath = create_index_path(root, index,
01042 index_clauses,
01043 clause_columns,
01044 NIL,
01045 NIL,
01046 useful_pathkeys,
01047 BackwardScanDirection,
01048 index_only_scan,
01049 outer_relids,
01050 loop_count);
01051 result = lappend(result, ipath);
01052 }
01053 }
01054
01055 return result;
01056 }
01057
01058
01059
01060
01061
01062
01063
01064
01065
01066
01067
01068
01069
01070
01071
01072
01073
01074
01075
01076
01077
01078
01079
01080
01081
01082
01083
01084 static List *
01085 build_paths_for_OR(PlannerInfo *root, RelOptInfo *rel,
01086 List *clauses, List *other_clauses)
01087 {
01088 List *result = NIL;
01089 List *all_clauses = NIL;
01090 ListCell *lc;
01091
01092 foreach(lc, rel->indexlist)
01093 {
01094 IndexOptInfo *index = (IndexOptInfo *) lfirst(lc);
01095 IndexClauseSet clauseset;
01096 List *indexpaths;
01097 bool useful_predicate;
01098
01099
01100 if (!index->amhasgetbitmap)
01101 continue;
01102
01103
01104
01105
01106
01107
01108
01109
01110
01111
01112
01113
01114
01115 useful_predicate = false;
01116 if (index->indpred != NIL)
01117 {
01118 if (index->predOK)
01119 {
01120
01121 }
01122 else
01123 {
01124
01125 if (all_clauses == NIL)
01126 all_clauses = list_concat(list_copy(clauses),
01127 other_clauses);
01128
01129 if (!predicate_implied_by(index->indpred, all_clauses))
01130 continue;
01131
01132 if (!predicate_implied_by(index->indpred, other_clauses))
01133 useful_predicate = true;
01134 }
01135 }
01136
01137
01138
01139
01140 MemSet(&clauseset, 0, sizeof(clauseset));
01141 match_clauses_to_index(index, clauses, &clauseset);
01142
01143
01144
01145
01146
01147 if (!clauseset.nonempty && !useful_predicate)
01148 continue;
01149
01150
01151
01152
01153 match_clauses_to_index(index, other_clauses, &clauseset);
01154
01155
01156
01157
01158 indexpaths = build_index_paths(root, rel,
01159 index, &clauseset,
01160 useful_predicate,
01161 SAOP_ALLOW, ST_BITMAPSCAN);
01162 result = list_concat(result, indexpaths);
01163 }
01164
01165 return result;
01166 }
01167
01168
01169
01170
01171
01172
01173
01174
01175
01176
01177
01178
01179
01180
01181
01182
01183 List *
01184 generate_bitmap_or_paths(PlannerInfo *root, RelOptInfo *rel,
01185 List *clauses, List *other_clauses,
01186 bool restriction_only)
01187 {
01188 List *result = NIL;
01189 List *all_clauses;
01190 ListCell *lc;
01191
01192
01193
01194
01195
01196 all_clauses = list_concat(list_copy(clauses), other_clauses);
01197
01198 foreach(lc, clauses)
01199 {
01200 RestrictInfo *rinfo = (RestrictInfo *) lfirst(lc);
01201 List *pathlist;
01202 Path *bitmapqual;
01203 ListCell *j;
01204
01205 Assert(IsA(rinfo, RestrictInfo));
01206
01207 if (!restriction_is_or_clause(rinfo))
01208 continue;
01209
01210
01211
01212
01213
01214 pathlist = NIL;
01215 foreach(j, ((BoolExpr *) rinfo->orclause)->args)
01216 {
01217 Node *orarg = (Node *) lfirst(j);
01218 List *indlist;
01219
01220
01221 if (and_clause(orarg))
01222 {
01223 List *andargs = ((BoolExpr *) orarg)->args;
01224
01225 if (restriction_only)
01226 andargs = drop_indexable_join_clauses(rel, andargs);
01227
01228 indlist = build_paths_for_OR(root, rel,
01229 andargs,
01230 all_clauses);
01231
01232
01233 indlist = list_concat(indlist,
01234 generate_bitmap_or_paths(root, rel,
01235 andargs,
01236 all_clauses,
01237 restriction_only));
01238 }
01239 else
01240 {
01241 List *orargs;
01242
01243 Assert(IsA(orarg, RestrictInfo));
01244 Assert(!restriction_is_or_clause((RestrictInfo *) orarg));
01245 orargs = list_make1(orarg);
01246
01247 if (restriction_only)
01248 orargs = drop_indexable_join_clauses(rel, orargs);
01249
01250 indlist = build_paths_for_OR(root, rel,
01251 orargs,
01252 all_clauses);
01253 }
01254
01255
01256
01257
01258
01259 if (indlist == NIL)
01260 {
01261 pathlist = NIL;
01262 break;
01263 }
01264
01265
01266
01267
01268
01269 bitmapqual = choose_bitmap_and(root, rel, indlist);
01270 pathlist = lappend(pathlist, bitmapqual);
01271 }
01272
01273
01274
01275
01276
01277 if (pathlist != NIL)
01278 {
01279 bitmapqual = (Path *) create_bitmap_or_path(root, rel, pathlist);
01280 result = lappend(result, bitmapqual);
01281 }
01282 }
01283
01284 return result;
01285 }
01286
01287
01288
01289
01290
01291
01292
01293
01294
01295
01296
01297 static List *
01298 drop_indexable_join_clauses(RelOptInfo *rel, List *clauses)
01299 {
01300 List *result = NIL;
01301 ListCell *lc;
01302
01303 foreach(lc, clauses)
01304 {
01305 RestrictInfo *rinfo = (RestrictInfo *) lfirst(lc);
01306
01307 Assert(IsA(rinfo, RestrictInfo));
01308 if (restriction_is_or_clause(rinfo) ||
01309 bms_is_subset(rinfo->clause_relids, rel->relids))
01310 result = lappend(result, rinfo);
01311 }
01312 return result;
01313 }
01314
01315
01316
01317
01318
01319
01320
01321
01322
01323
01324
01325
01326
01327 static Path *
01328 choose_bitmap_and(PlannerInfo *root, RelOptInfo *rel, List *paths)
01329 {
01330 int npaths = list_length(paths);
01331 PathClauseUsage **pathinfoarray;
01332 PathClauseUsage *pathinfo;
01333 List *clauselist;
01334 List *bestpaths = NIL;
01335 Cost bestcost = 0;
01336 int i,
01337 j;
01338 ListCell *l;
01339
01340 Assert(npaths > 0);
01341 if (npaths == 1)
01342 return (Path *) linitial(paths);
01343
01344
01345
01346
01347
01348
01349
01350
01351
01352
01353
01354
01355
01356
01357
01358
01359
01360
01361
01362
01363
01364
01365
01366
01367
01368
01369
01370
01371
01372
01373
01374
01375
01376
01377
01378
01379
01380
01381
01382
01383
01384
01385
01386
01387
01388
01389
01390
01391
01392
01393
01394
01395
01396
01397
01398 pathinfoarray = (PathClauseUsage **)
01399 palloc(npaths * sizeof(PathClauseUsage *));
01400 clauselist = NIL;
01401 npaths = 0;
01402 foreach(l, paths)
01403 {
01404 Path *ipath = (Path *) lfirst(l);
01405
01406 pathinfo = classify_index_clause_usage(ipath, &clauselist);
01407 for (i = 0; i < npaths; i++)
01408 {
01409 if (bms_equal(pathinfo->clauseids, pathinfoarray[i]->clauseids))
01410 break;
01411 }
01412 if (i < npaths)
01413 {
01414
01415 Cost ncost;
01416 Cost ocost;
01417 Selectivity nselec;
01418 Selectivity oselec;
01419
01420 cost_bitmap_tree_node(pathinfo->path, &ncost, &nselec);
01421 cost_bitmap_tree_node(pathinfoarray[i]->path, &ocost, &oselec);
01422 if (ncost < ocost)
01423 pathinfoarray[i] = pathinfo;
01424 }
01425 else
01426 {
01427
01428 pathinfoarray[npaths++] = pathinfo;
01429 }
01430 }
01431
01432
01433 if (npaths == 1)
01434 return pathinfoarray[0]->path;
01435
01436
01437 qsort(pathinfoarray, npaths, sizeof(PathClauseUsage *),
01438 path_usage_comparator);
01439
01440
01441
01442
01443
01444
01445 for (i = 0; i < npaths; i++)
01446 {
01447 Cost costsofar;
01448 List *qualsofar;
01449 Bitmapset *clauseidsofar;
01450 ListCell *lastcell;
01451
01452 pathinfo = pathinfoarray[i];
01453 paths = list_make1(pathinfo->path);
01454 costsofar = bitmap_scan_cost_est(root, rel, pathinfo->path);
01455 qualsofar = list_concat(list_copy(pathinfo->quals),
01456 list_copy(pathinfo->preds));
01457 clauseidsofar = bms_copy(pathinfo->clauseids);
01458 lastcell = list_head(paths);
01459
01460 for (j = i + 1; j < npaths; j++)
01461 {
01462 Cost newcost;
01463
01464 pathinfo = pathinfoarray[j];
01465
01466 if (bms_overlap(pathinfo->clauseids, clauseidsofar))
01467 continue;
01468 if (pathinfo->preds)
01469 {
01470 bool redundant = false;
01471
01472
01473 foreach(l, pathinfo->preds)
01474 {
01475 Node *np = (Node *) lfirst(l);
01476
01477 if (predicate_implied_by(list_make1(np), qualsofar))
01478 {
01479 redundant = true;
01480 break;
01481 }
01482 }
01483 if (redundant)
01484 continue;
01485 }
01486
01487 paths = lappend(paths, pathinfo->path);
01488 newcost = bitmap_and_cost_est(root, rel, paths);
01489 if (newcost < costsofar)
01490 {
01491
01492 costsofar = newcost;
01493 qualsofar = list_concat(qualsofar,
01494 list_copy(pathinfo->quals));
01495 qualsofar = list_concat(qualsofar,
01496 list_copy(pathinfo->preds));
01497 clauseidsofar = bms_add_members(clauseidsofar,
01498 pathinfo->clauseids);
01499 lastcell = lnext(lastcell);
01500 }
01501 else
01502 {
01503
01504 paths = list_delete_cell(paths, lnext(lastcell), lastcell);
01505 }
01506 Assert(lnext(lastcell) == NULL);
01507 }
01508
01509
01510 if (i == 0 || costsofar < bestcost)
01511 {
01512 bestpaths = paths;
01513 bestcost = costsofar;
01514 }
01515
01516
01517 list_free(qualsofar);
01518 }
01519
01520 if (list_length(bestpaths) == 1)
01521 return (Path *) linitial(bestpaths);
01522 return (Path *) create_bitmap_and_path(root, rel, bestpaths);
01523 }
01524
01525
01526 static int
01527 path_usage_comparator(const void *a, const void *b)
01528 {
01529 PathClauseUsage *pa = *(PathClauseUsage *const *) a;
01530 PathClauseUsage *pb = *(PathClauseUsage *const *) b;
01531 Cost acost;
01532 Cost bcost;
01533 Selectivity aselec;
01534 Selectivity bselec;
01535
01536 cost_bitmap_tree_node(pa->path, &acost, &aselec);
01537 cost_bitmap_tree_node(pb->path, &bcost, &bselec);
01538
01539
01540
01541
01542 if (acost < bcost)
01543 return -1;
01544 if (acost > bcost)
01545 return 1;
01546
01547 if (aselec < bselec)
01548 return -1;
01549 if (aselec > bselec)
01550 return 1;
01551
01552 return 0;
01553 }
01554
01555
01556
01557
01558
01559
01560 static Cost
01561 bitmap_scan_cost_est(PlannerInfo *root, RelOptInfo *rel, Path *ipath)
01562 {
01563 BitmapHeapPath bpath;
01564 Relids required_outer;
01565
01566
01567 required_outer = get_bitmap_tree_required_outer(ipath);
01568
01569
01570 bpath.path.type = T_BitmapHeapPath;
01571 bpath.path.pathtype = T_BitmapHeapScan;
01572 bpath.path.parent = rel;
01573 bpath.path.param_info = get_baserel_parampathinfo(root, rel,
01574 required_outer);
01575 bpath.path.pathkeys = NIL;
01576 bpath.bitmapqual = ipath;
01577
01578 cost_bitmap_heap_scan(&bpath.path, root, rel,
01579 bpath.path.param_info,
01580 ipath,
01581 get_loop_count(root, required_outer));
01582
01583 return bpath.path.total_cost;
01584 }
01585
01586
01587
01588
01589
01590 static Cost
01591 bitmap_and_cost_est(PlannerInfo *root, RelOptInfo *rel, List *paths)
01592 {
01593 BitmapAndPath apath;
01594 BitmapHeapPath bpath;
01595 Relids required_outer;
01596
01597
01598 apath.path.type = T_BitmapAndPath;
01599 apath.path.pathtype = T_BitmapAnd;
01600 apath.path.parent = rel;
01601 apath.path.param_info = NULL;
01602 apath.path.pathkeys = NIL;
01603 apath.bitmapquals = paths;
01604 cost_bitmap_and_node(&apath, root);
01605
01606
01607 required_outer = get_bitmap_tree_required_outer((Path *) &apath);
01608
01609
01610 bpath.path.type = T_BitmapHeapPath;
01611 bpath.path.pathtype = T_BitmapHeapScan;
01612 bpath.path.parent = rel;
01613 bpath.path.param_info = get_baserel_parampathinfo(root, rel,
01614 required_outer);
01615 bpath.path.pathkeys = NIL;
01616 bpath.bitmapqual = (Path *) &apath;
01617
01618
01619 cost_bitmap_heap_scan(&bpath.path, root, rel,
01620 bpath.path.param_info,
01621 (Path *) &apath,
01622 get_loop_count(root, required_outer));
01623
01624 return bpath.path.total_cost;
01625 }
01626
01627
01628
01629
01630
01631
01632
01633
01634
01635
01636
01637
01638
01639
01640
01641
01642 static PathClauseUsage *
01643 classify_index_clause_usage(Path *path, List **clauselist)
01644 {
01645 PathClauseUsage *result;
01646 Bitmapset *clauseids;
01647 ListCell *lc;
01648
01649 result = (PathClauseUsage *) palloc(sizeof(PathClauseUsage));
01650 result->path = path;
01651
01652
01653 result->quals = NIL;
01654 result->preds = NIL;
01655 find_indexpath_quals(path, &result->quals, &result->preds);
01656
01657
01658 clauseids = NULL;
01659 foreach(lc, result->quals)
01660 {
01661 Node *node = (Node *) lfirst(lc);
01662
01663 clauseids = bms_add_member(clauseids,
01664 find_list_position(node, clauselist));
01665 }
01666 foreach(lc, result->preds)
01667 {
01668 Node *node = (Node *) lfirst(lc);
01669
01670 clauseids = bms_add_member(clauseids,
01671 find_list_position(node, clauselist));
01672 }
01673 result->clauseids = clauseids;
01674
01675 return result;
01676 }
01677
01678
01679
01680
01681
01682
01683
01684
01685
01686
01687
01688
01689 static Relids
01690 get_bitmap_tree_required_outer(Path *bitmapqual)
01691 {
01692 Relids result = NULL;
01693 ListCell *lc;
01694
01695 if (IsA(bitmapqual, IndexPath))
01696 {
01697 return bms_copy(PATH_REQ_OUTER(bitmapqual));
01698 }
01699 else if (IsA(bitmapqual, BitmapAndPath))
01700 {
01701 foreach(lc, ((BitmapAndPath *) bitmapqual)->bitmapquals)
01702 {
01703 result = bms_join(result,
01704 get_bitmap_tree_required_outer((Path *) lfirst(lc)));
01705 }
01706 }
01707 else if (IsA(bitmapqual, BitmapOrPath))
01708 {
01709 foreach(lc, ((BitmapOrPath *) bitmapqual)->bitmapquals)
01710 {
01711 result = bms_join(result,
01712 get_bitmap_tree_required_outer((Path *) lfirst(lc)));
01713 }
01714 }
01715 else
01716 elog(ERROR, "unrecognized node type: %d", nodeTag(bitmapqual));
01717
01718 return result;
01719 }
01720
01721
01722
01723
01724
01725
01726
01727
01728
01729
01730
01731
01732
01733
01734
01735
01736
01737
01738 static void
01739 find_indexpath_quals(Path *bitmapqual, List **quals, List **preds)
01740 {
01741 if (IsA(bitmapqual, BitmapAndPath))
01742 {
01743 BitmapAndPath *apath = (BitmapAndPath *) bitmapqual;
01744 ListCell *l;
01745
01746 foreach(l, apath->bitmapquals)
01747 {
01748 find_indexpath_quals((Path *) lfirst(l), quals, preds);
01749 }
01750 }
01751 else if (IsA(bitmapqual, BitmapOrPath))
01752 {
01753 BitmapOrPath *opath = (BitmapOrPath *) bitmapqual;
01754 ListCell *l;
01755
01756 foreach(l, opath->bitmapquals)
01757 {
01758 find_indexpath_quals((Path *) lfirst(l), quals, preds);
01759 }
01760 }
01761 else if (IsA(bitmapqual, IndexPath))
01762 {
01763 IndexPath *ipath = (IndexPath *) bitmapqual;
01764
01765 *quals = list_concat(*quals, get_actual_clauses(ipath->indexclauses));
01766 *preds = list_concat(*preds, list_copy(ipath->indexinfo->indpred));
01767 }
01768 else
01769 elog(ERROR, "unrecognized node type: %d", nodeTag(bitmapqual));
01770 }
01771
01772
01773
01774
01775
01776
01777
01778
01779 static int
01780 find_list_position(Node *node, List **nodelist)
01781 {
01782 int i;
01783 ListCell *lc;
01784
01785 i = 0;
01786 foreach(lc, *nodelist)
01787 {
01788 Node *oldnode = (Node *) lfirst(lc);
01789
01790 if (equal(node, oldnode))
01791 return i;
01792 i++;
01793 }
01794
01795 *nodelist = lappend(*nodelist, node);
01796
01797 return i;
01798 }
01799
01800
01801
01802
01803
01804
01805 static bool
01806 check_index_only(RelOptInfo *rel, IndexOptInfo *index)
01807 {
01808 bool result;
01809 Bitmapset *attrs_used = NULL;
01810 Bitmapset *index_attrs = NULL;
01811 ListCell *lc;
01812 int i;
01813
01814
01815 if (!enable_indexonlyscan)
01816 return false;
01817 if (!index->canreturn)
01818 return false;
01819
01820
01821
01822
01823
01824
01825
01826
01827
01828
01829
01830
01831
01832
01833
01834
01835
01836
01837
01838 pull_varattnos((Node *) rel->reltargetlist, rel->relid, &attrs_used);
01839
01840
01841 foreach(lc, rel->baserestrictinfo)
01842 {
01843 RestrictInfo *rinfo = (RestrictInfo *) lfirst(lc);
01844
01845 pull_varattnos((Node *) rinfo->clause, rel->relid, &attrs_used);
01846 }
01847
01848
01849 for (i = 0; i < index->ncolumns; i++)
01850 {
01851 int attno = index->indexkeys[i];
01852
01853
01854
01855
01856
01857 if (attno == 0)
01858 continue;
01859
01860 index_attrs =
01861 bms_add_member(index_attrs,
01862 attno - FirstLowInvalidHeapAttributeNumber);
01863 }
01864
01865
01866 result = bms_is_subset(attrs_used, index_attrs);
01867
01868 bms_free(attrs_used);
01869 bms_free(index_attrs);
01870
01871 return result;
01872 }
01873
01874
01875
01876
01877
01878
01879
01880
01881
01882
01883
01884
01885
01886
01887
01888
01889
01890
01891
01892
01893
01894 static double
01895 get_loop_count(PlannerInfo *root, Relids outer_relids)
01896 {
01897 double result = 1.0;
01898
01899
01900 if (outer_relids != NULL)
01901 {
01902 int relid;
01903
01904
01905 outer_relids = bms_copy(outer_relids);
01906 while ((relid = bms_first_member(outer_relids)) >= 0)
01907 {
01908 RelOptInfo *outer_rel;
01909
01910
01911 if (relid >= root->simple_rel_array_size)
01912 continue;
01913 outer_rel = root->simple_rel_array[relid];
01914 if (outer_rel == NULL)
01915 continue;
01916 Assert(outer_rel->relid == relid);
01917
01918
01919 if (IS_DUMMY_REL(outer_rel))
01920 continue;
01921
01922
01923 Assert(outer_rel->rows > 0);
01924
01925
01926 if (result == 1.0 || result > outer_rel->rows)
01927 result = outer_rel->rows;
01928 }
01929 bms_free(outer_relids);
01930 }
01931 return result;
01932 }
01933
01934
01935
01936
01937
01938
01939
01940
01941
01942
01943
01944 static void
01945 match_restriction_clauses_to_index(RelOptInfo *rel, IndexOptInfo *index,
01946 IndexClauseSet *clauseset)
01947 {
01948 match_clauses_to_index(index, rel->baserestrictinfo, clauseset);
01949 }
01950
01951
01952
01953
01954
01955
01956
01957 static void
01958 match_join_clauses_to_index(PlannerInfo *root,
01959 RelOptInfo *rel, IndexOptInfo *index,
01960 Relids lateral_referencers,
01961 IndexClauseSet *clauseset,
01962 List **joinorclauses)
01963 {
01964 ListCell *lc;
01965
01966
01967 foreach(lc, rel->joininfo)
01968 {
01969 RestrictInfo *rinfo = (RestrictInfo *) lfirst(lc);
01970
01971
01972 if (!join_clause_is_movable_to(rinfo, rel->relid))
01973 continue;
01974
01975
01976 if (bms_overlap(rinfo->clause_relids, lateral_referencers))
01977 continue;
01978
01979
01980 if (restriction_is_or_clause(rinfo))
01981 *joinorclauses = lappend(*joinorclauses, rinfo);
01982 else
01983 match_clause_to_index(index, rinfo, clauseset);
01984 }
01985 }
01986
01987
01988
01989
01990
01991
01992 static void
01993 match_eclass_clauses_to_index(PlannerInfo *root, IndexOptInfo *index,
01994 Relids lateral_referencers,
01995 IndexClauseSet *clauseset)
01996 {
01997 int indexcol;
01998
01999
02000 if (!index->rel->has_eclass_joins)
02001 return;
02002
02003 for (indexcol = 0; indexcol < index->ncolumns; indexcol++)
02004 {
02005 ec_member_matches_arg arg;
02006 List *clauses;
02007
02008
02009 arg.index = index;
02010 arg.indexcol = indexcol;
02011 clauses = generate_implied_equalities_for_column(root,
02012 index->rel,
02013 ec_member_matches_indexcol,
02014 (void *) &arg,
02015 lateral_referencers);
02016
02017
02018
02019
02020
02021
02022 match_clauses_to_index(index, clauses, clauseset);
02023 }
02024 }
02025
02026
02027
02028
02029
02030
02031 static void
02032 match_clauses_to_index(IndexOptInfo *index,
02033 List *clauses,
02034 IndexClauseSet *clauseset)
02035 {
02036 ListCell *lc;
02037
02038 foreach(lc, clauses)
02039 {
02040 RestrictInfo *rinfo = (RestrictInfo *) lfirst(lc);
02041
02042 Assert(IsA(rinfo, RestrictInfo));
02043 match_clause_to_index(index, rinfo, clauseset);
02044 }
02045 }
02046
02047
02048
02049
02050
02051
02052
02053
02054
02055
02056
02057
02058
02059
02060
02061
02062
02063 static void
02064 match_clause_to_index(IndexOptInfo *index,
02065 RestrictInfo *rinfo,
02066 IndexClauseSet *clauseset)
02067 {
02068 int indexcol;
02069
02070 for (indexcol = 0; indexcol < index->ncolumns; indexcol++)
02071 {
02072 if (match_clause_to_indexcol(index,
02073 indexcol,
02074 rinfo))
02075 {
02076 clauseset->indexclauses[indexcol] =
02077 list_append_unique_ptr(clauseset->indexclauses[indexcol],
02078 rinfo);
02079 clauseset->nonempty = true;
02080 return;
02081 }
02082 }
02083 }
02084
02085
02086
02087
02088
02089
02090
02091
02092
02093
02094
02095
02096
02097
02098
02099
02100
02101
02102
02103
02104
02105
02106
02107
02108
02109
02110
02111
02112
02113
02114
02115
02116
02117
02118
02119
02120
02121
02122
02123
02124
02125
02126
02127
02128
02129
02130
02131
02132
02133
02134
02135
02136
02137
02138
02139
02140
02141
02142
02143
02144
02145
02146
02147 static bool
02148 match_clause_to_indexcol(IndexOptInfo *index,
02149 int indexcol,
02150 RestrictInfo *rinfo)
02151 {
02152 Expr *clause = rinfo->clause;
02153 Index index_relid = index->rel->relid;
02154 Oid opfamily = index->opfamily[indexcol];
02155 Oid idxcollation = index->indexcollations[indexcol];
02156 Node *leftop,
02157 *rightop;
02158 Relids left_relids;
02159 Relids right_relids;
02160 Oid expr_op;
02161 Oid expr_coll;
02162 bool plain_op;
02163
02164
02165
02166
02167
02168
02169
02170 if (rinfo->pseudoconstant)
02171 return false;
02172
02173
02174 if (IsBooleanOpfamily(opfamily))
02175 {
02176 if (match_boolean_index_clause((Node *) clause, indexcol, index))
02177 return true;
02178 }
02179
02180
02181
02182
02183
02184
02185
02186 if (is_opclause(clause))
02187 {
02188 leftop = get_leftop(clause);
02189 rightop = get_rightop(clause);
02190 if (!leftop || !rightop)
02191 return false;
02192 left_relids = rinfo->left_relids;
02193 right_relids = rinfo->right_relids;
02194 expr_op = ((OpExpr *) clause)->opno;
02195 expr_coll = ((OpExpr *) clause)->inputcollid;
02196 plain_op = true;
02197 }
02198 else if (clause && IsA(clause, ScalarArrayOpExpr))
02199 {
02200 ScalarArrayOpExpr *saop = (ScalarArrayOpExpr *) clause;
02201
02202
02203 if (!saop->useOr)
02204 return false;
02205 leftop = (Node *) linitial(saop->args);
02206 rightop = (Node *) lsecond(saop->args);
02207 left_relids = NULL;
02208 right_relids = pull_varnos(rightop);
02209 expr_op = saop->opno;
02210 expr_coll = saop->inputcollid;
02211 plain_op = false;
02212 }
02213 else if (clause && IsA(clause, RowCompareExpr))
02214 {
02215 return match_rowcompare_to_indexcol(index, indexcol,
02216 opfamily, idxcollation,
02217 (RowCompareExpr *) clause);
02218 }
02219 else if (index->amsearchnulls && IsA(clause, NullTest))
02220 {
02221 NullTest *nt = (NullTest *) clause;
02222
02223 if (!nt->argisrow &&
02224 match_index_to_operand((Node *) nt->arg, indexcol, index))
02225 return true;
02226 return false;
02227 }
02228 else
02229 return false;
02230
02231
02232
02233
02234
02235 if (match_index_to_operand(leftop, indexcol, index) &&
02236 !bms_is_member(index_relid, right_relids) &&
02237 !contain_volatile_functions(rightop))
02238 {
02239 if (IndexCollMatchesExprColl(idxcollation, expr_coll) &&
02240 is_indexable_operator(expr_op, opfamily, true))
02241 return true;
02242
02243
02244
02245
02246
02247 if (plain_op &&
02248 match_special_index_operator(clause, opfamily,
02249 idxcollation, true))
02250 return true;
02251 return false;
02252 }
02253
02254 if (plain_op &&
02255 match_index_to_operand(rightop, indexcol, index) &&
02256 !bms_is_member(index_relid, left_relids) &&
02257 !contain_volatile_functions(leftop))
02258 {
02259 if (IndexCollMatchesExprColl(idxcollation, expr_coll) &&
02260 is_indexable_operator(expr_op, opfamily, false))
02261 return true;
02262
02263
02264
02265
02266
02267 if (match_special_index_operator(clause, opfamily,
02268 idxcollation, false))
02269 return true;
02270 return false;
02271 }
02272
02273 return false;
02274 }
02275
02276
02277
02278
02279
02280
02281
02282
02283
02284 static bool
02285 is_indexable_operator(Oid expr_op, Oid opfamily, bool indexkey_on_left)
02286 {
02287
02288 if (!indexkey_on_left)
02289 {
02290 expr_op = get_commutator(expr_op);
02291 if (expr_op == InvalidOid)
02292 return false;
02293 }
02294
02295
02296 return op_in_opfamily(expr_op, opfamily);
02297 }
02298
02299
02300
02301
02302
02303
02304 static bool
02305 match_rowcompare_to_indexcol(IndexOptInfo *index,
02306 int indexcol,
02307 Oid opfamily,
02308 Oid idxcollation,
02309 RowCompareExpr *clause)
02310 {
02311 Index index_relid = index->rel->relid;
02312 Node *leftop,
02313 *rightop;
02314 Oid expr_op;
02315 Oid expr_coll;
02316
02317
02318 if (index->relam != BTREE_AM_OID)
02319 return false;
02320
02321
02322
02323
02324
02325
02326
02327
02328
02329
02330
02331 leftop = (Node *) linitial(clause->largs);
02332 rightop = (Node *) linitial(clause->rargs);
02333 expr_op = linitial_oid(clause->opnos);
02334 expr_coll = linitial_oid(clause->inputcollids);
02335
02336
02337 if (!IndexCollMatchesExprColl(idxcollation, expr_coll))
02338 return false;
02339
02340
02341
02342
02343 if (match_index_to_operand(leftop, indexcol, index) &&
02344 !bms_is_member(index_relid, pull_varnos(rightop)) &&
02345 !contain_volatile_functions(rightop))
02346 {
02347
02348 }
02349 else if (match_index_to_operand(rightop, indexcol, index) &&
02350 !bms_is_member(index_relid, pull_varnos(leftop)) &&
02351 !contain_volatile_functions(leftop))
02352 {
02353
02354 expr_op = get_commutator(expr_op);
02355 if (expr_op == InvalidOid)
02356 return false;
02357 }
02358 else
02359 return false;
02360
02361
02362 switch (get_op_opfamily_strategy(expr_op, opfamily))
02363 {
02364 case BTLessStrategyNumber:
02365 case BTLessEqualStrategyNumber:
02366 case BTGreaterEqualStrategyNumber:
02367 case BTGreaterStrategyNumber:
02368 return true;
02369 }
02370
02371 return false;
02372 }
02373
02374
02375
02376
02377
02378
02379
02380
02381
02382
02383
02384
02385
02386
02387
02388
02389
02390
02391
02392 static void
02393 match_pathkeys_to_index(IndexOptInfo *index, List *pathkeys,
02394 List **orderby_clauses_p,
02395 List **clause_columns_p)
02396 {
02397 List *orderby_clauses = NIL;
02398 List *clause_columns = NIL;
02399 ListCell *lc1;
02400
02401 *orderby_clauses_p = NIL;
02402 *clause_columns_p = NIL;
02403
02404
02405 if (!index->amcanorderbyop)
02406 return;
02407
02408 foreach(lc1, pathkeys)
02409 {
02410 PathKey *pathkey = (PathKey *) lfirst(lc1);
02411 bool found = false;
02412 ListCell *lc2;
02413
02414
02415
02416
02417
02418
02419
02420 if (pathkey->pk_strategy != BTLessStrategyNumber ||
02421 pathkey->pk_nulls_first)
02422 return;
02423
02424
02425 if (pathkey->pk_eclass->ec_has_volatile)
02426 return;
02427
02428
02429
02430
02431
02432
02433
02434
02435
02436 foreach(lc2, pathkey->pk_eclass->ec_members)
02437 {
02438 EquivalenceMember *member = (EquivalenceMember *) lfirst(lc2);
02439 int indexcol;
02440
02441
02442 if (!bms_equal(member->em_relids, index->rel->relids))
02443 continue;
02444
02445
02446
02447
02448
02449
02450
02451
02452 for (indexcol = 0; indexcol < index->ncolumns; indexcol++)
02453 {
02454 Expr *expr;
02455
02456 expr = match_clause_to_ordering_op(index,
02457 indexcol,
02458 member->em_expr,
02459 pathkey->pk_opfamily);
02460 if (expr)
02461 {
02462 orderby_clauses = lappend(orderby_clauses, expr);
02463 clause_columns = lappend_int(clause_columns, indexcol);
02464 found = true;
02465 break;
02466 }
02467 }
02468
02469 if (found)
02470 break;
02471 }
02472
02473 if (!found)
02474 return;
02475 }
02476
02477 *orderby_clauses_p = orderby_clauses;
02478 *clause_columns_p = clause_columns;
02479 }
02480
02481
02482
02483
02484
02485
02486
02487
02488
02489
02490
02491
02492
02493
02494
02495
02496
02497
02498
02499
02500
02501
02502
02503
02504
02505
02506 static Expr *
02507 match_clause_to_ordering_op(IndexOptInfo *index,
02508 int indexcol,
02509 Expr *clause,
02510 Oid pk_opfamily)
02511 {
02512 Oid opfamily = index->opfamily[indexcol];
02513 Oid idxcollation = index->indexcollations[indexcol];
02514 Node *leftop,
02515 *rightop;
02516 Oid expr_op;
02517 Oid expr_coll;
02518 Oid sortfamily;
02519 bool commuted;
02520
02521
02522
02523
02524 if (!is_opclause(clause))
02525 return NULL;
02526 leftop = get_leftop(clause);
02527 rightop = get_rightop(clause);
02528 if (!leftop || !rightop)
02529 return NULL;
02530 expr_op = ((OpExpr *) clause)->opno;
02531 expr_coll = ((OpExpr *) clause)->inputcollid;
02532
02533
02534
02535
02536 if (!IndexCollMatchesExprColl(idxcollation, expr_coll))
02537 return NULL;
02538
02539
02540
02541
02542
02543 if (match_index_to_operand(leftop, indexcol, index) &&
02544 !contain_var_clause(rightop) &&
02545 !contain_volatile_functions(rightop))
02546 {
02547 commuted = false;
02548 }
02549 else if (match_index_to_operand(rightop, indexcol, index) &&
02550 !contain_var_clause(leftop) &&
02551 !contain_volatile_functions(leftop))
02552 {
02553
02554 expr_op = get_commutator(expr_op);
02555 if (expr_op == InvalidOid)
02556 return NULL;
02557 commuted = true;
02558 }
02559 else
02560 return NULL;
02561
02562
02563
02564
02565
02566 sortfamily = get_op_opfamily_sortfamily(expr_op, opfamily);
02567 if (sortfamily != pk_opfamily)
02568 return NULL;
02569
02570
02571 if (commuted)
02572 {
02573 OpExpr *newclause = makeNode(OpExpr);
02574
02575
02576 memcpy(newclause, clause, sizeof(OpExpr));
02577
02578
02579 newclause->opno = expr_op;
02580 newclause->opfuncid = InvalidOid;
02581 newclause->args = list_make2(rightop, leftop);
02582
02583 clause = (Expr *) newclause;
02584 }
02585
02586 return clause;
02587 }
02588
02589
02590
02591
02592
02593
02594
02595
02596
02597
02598
02599
02600
02601
02602
02603 void
02604 check_partial_indexes(PlannerInfo *root, RelOptInfo *rel)
02605 {
02606 List *clauselist;
02607 bool have_partial;
02608 Relids otherrels;
02609 ListCell *lc;
02610
02611
02612
02613
02614
02615 have_partial = false;
02616 foreach(lc, rel->indexlist)
02617 {
02618 IndexOptInfo *index = (IndexOptInfo *) lfirst(lc);
02619
02620 if (index->indpred == NIL)
02621 continue;
02622
02623 if (index->predOK)
02624 continue;
02625
02626 have_partial = true;
02627 break;
02628 }
02629 if (!have_partial)
02630 return;
02631
02632
02633
02634
02635
02636
02637
02638
02639 clauselist = list_copy(rel->baserestrictinfo);
02640
02641
02642 foreach(lc, rel->joininfo)
02643 {
02644 RestrictInfo *rinfo = (RestrictInfo *) lfirst(lc);
02645
02646
02647 if (!join_clause_is_movable_to(rinfo, rel->relid))
02648 continue;
02649
02650 clauselist = lappend(clauselist, rinfo);
02651 }
02652
02653
02654
02655
02656
02657
02658
02659 if (rel->reloptkind == RELOPT_OTHER_MEMBER_REL)
02660 {
02661
02662 AppendRelInfo *appinfo = find_childrel_appendrelinfo(root, rel);
02663
02664 otherrels = bms_difference(root->all_baserels,
02665 bms_make_singleton(appinfo->parent_relid));
02666 }
02667 else
02668 otherrels = bms_difference(root->all_baserels, rel->relids);
02669
02670 if (!bms_is_empty(otherrels))
02671 clauselist =
02672 list_concat(clauselist,
02673 generate_join_implied_equalities(root,
02674 bms_union(rel->relids,
02675 otherrels),
02676 otherrels,
02677 rel));
02678
02679
02680 foreach(lc, rel->indexlist)
02681 {
02682 IndexOptInfo *index = (IndexOptInfo *) lfirst(lc);
02683
02684 if (index->indpred == NIL)
02685 continue;
02686
02687 if (index->predOK)
02688 continue;
02689
02690 index->predOK = predicate_implied_by(index->indpred, clauselist);
02691 }
02692 }
02693
02694
02695
02696
02697
02698
02699
02700
02701
02702
02703
02704 static bool
02705 ec_member_matches_indexcol(PlannerInfo *root, RelOptInfo *rel,
02706 EquivalenceClass *ec, EquivalenceMember *em,
02707 void *arg)
02708 {
02709 IndexOptInfo *index = ((ec_member_matches_arg *) arg)->index;
02710 int indexcol = ((ec_member_matches_arg *) arg)->indexcol;
02711 Oid curFamily = index->opfamily[indexcol];
02712 Oid curCollation = index->indexcollations[indexcol];
02713
02714
02715
02716
02717
02718
02719
02720
02721
02722
02723
02724 if (index->relam == BTREE_AM_OID &&
02725 !list_member_oid(ec->ec_opfamilies, curFamily))
02726 return false;
02727
02728
02729 if (!IndexCollMatchesExprColl(curCollation, ec->ec_collation))
02730 return false;
02731
02732 return match_index_to_operand((Node *) em->em_expr, indexcol, index);
02733 }
02734
02735
02736
02737
02738
02739
02740
02741
02742
02743
02744
02745
02746
02747
02748
02749
02750
02751
02752
02753
02754
02755
02756
02757 bool
02758 relation_has_unique_index_for(PlannerInfo *root, RelOptInfo *rel,
02759 List *restrictlist,
02760 List *exprlist, List *oprlist)
02761 {
02762 ListCell *ic;
02763
02764 Assert(list_length(exprlist) == list_length(oprlist));
02765
02766
02767 if (rel->indexlist == NIL)
02768 return false;
02769
02770
02771
02772
02773
02774 foreach(ic, rel->baserestrictinfo)
02775 {
02776 RestrictInfo *restrictinfo = (RestrictInfo *) lfirst(ic);
02777
02778
02779
02780
02781
02782
02783 if (restrictinfo->mergeopfamilies == NIL)
02784 continue;
02785
02786
02787
02788
02789
02790 if (bms_is_empty(restrictinfo->left_relids))
02791 {
02792
02793 restrictinfo->outer_is_left = true;
02794 }
02795 else if (bms_is_empty(restrictinfo->right_relids))
02796 {
02797
02798 restrictinfo->outer_is_left = false;
02799 }
02800 else
02801 continue;
02802
02803
02804 restrictlist = lappend(restrictlist, restrictinfo);
02805 }
02806
02807
02808 if (restrictlist == NIL && exprlist == NIL)
02809 return false;
02810
02811
02812 foreach(ic, rel->indexlist)
02813 {
02814 IndexOptInfo *ind = (IndexOptInfo *) lfirst(ic);
02815 int c;
02816
02817
02818
02819
02820
02821 if (!ind->unique || !ind->immediate ||
02822 (ind->indpred != NIL && !ind->predOK))
02823 continue;
02824
02825
02826
02827
02828
02829 for (c = 0; c < ind->ncolumns; c++)
02830 {
02831 bool matched = false;
02832 ListCell *lc;
02833 ListCell *lc2;
02834
02835 foreach(lc, restrictlist)
02836 {
02837 RestrictInfo *rinfo = (RestrictInfo *) lfirst(lc);
02838 Node *rexpr;
02839
02840
02841
02842
02843
02844
02845
02846 if (!list_member_oid(rinfo->mergeopfamilies, ind->opfamily[c]))
02847 continue;
02848
02849
02850
02851
02852
02853
02854
02855
02856 if (rinfo->outer_is_left)
02857 rexpr = get_rightop(rinfo->clause);
02858 else
02859 rexpr = get_leftop(rinfo->clause);
02860
02861 if (match_index_to_operand(rexpr, c, ind))
02862 {
02863 matched = true;
02864 break;
02865 }
02866 }
02867
02868 if (matched)
02869 continue;
02870
02871 forboth(lc, exprlist, lc2, oprlist)
02872 {
02873 Node *expr = (Node *) lfirst(lc);
02874 Oid opr = lfirst_oid(lc2);
02875
02876
02877 if (!match_index_to_operand(expr, c, ind))
02878 continue;
02879
02880
02881
02882
02883
02884
02885
02886
02887 if (!op_in_opfamily(opr, ind->opfamily[c]))
02888 continue;
02889
02890
02891
02892
02893
02894
02895
02896 matched = true;
02897 break;
02898 }
02899
02900 if (!matched)
02901 break;
02902 }
02903
02904
02905 if (c == ind->ncolumns)
02906 return true;
02907 }
02908
02909 return false;
02910 }
02911
02912
02913
02914
02915
02916
02917
02918
02919
02920
02921
02922
02923
02924
02925
02926
02927
02928
02929
02930
02931 bool
02932 match_index_to_operand(Node *operand,
02933 int indexcol,
02934 IndexOptInfo *index)
02935 {
02936 int indkey;
02937
02938
02939
02940
02941
02942
02943
02944 if (operand && IsA(operand, RelabelType))
02945 operand = (Node *) ((RelabelType *) operand)->arg;
02946
02947 indkey = index->indexkeys[indexcol];
02948 if (indkey != 0)
02949 {
02950
02951
02952
02953 if (operand && IsA(operand, Var) &&
02954 index->rel->relid == ((Var *) operand)->varno &&
02955 indkey == ((Var *) operand)->varattno)
02956 return true;
02957 }
02958 else
02959 {
02960
02961
02962
02963
02964
02965 ListCell *indexpr_item;
02966 int i;
02967 Node *indexkey;
02968
02969 indexpr_item = list_head(index->indexprs);
02970 for (i = 0; i < indexcol; i++)
02971 {
02972 if (index->indexkeys[i] == 0)
02973 {
02974 if (indexpr_item == NULL)
02975 elog(ERROR, "wrong number of index expressions");
02976 indexpr_item = lnext(indexpr_item);
02977 }
02978 }
02979 if (indexpr_item == NULL)
02980 elog(ERROR, "wrong number of index expressions");
02981 indexkey = (Node *) lfirst(indexpr_item);
02982
02983
02984
02985
02986 if (indexkey && IsA(indexkey, RelabelType))
02987 indexkey = (Node *) ((RelabelType *) indexkey)->arg;
02988
02989 if (equal(indexkey, operand))
02990 return true;
02991 }
02992
02993 return false;
02994 }
02995
02996
02997
02998
02999
03000
03001
03002
03003
03004
03005
03006
03007
03008
03009
03010
03011
03012
03013
03014
03015
03016
03017
03018
03019
03020
03021
03022
03023
03024
03025
03026
03027
03028
03029
03030
03031
03032
03033
03034
03035
03036
03037
03038
03039
03040
03041
03042
03043
03044
03045
03046
03047
03048
03049
03050
03051
03052
03053
03054
03055
03056
03057 static bool
03058 match_boolean_index_clause(Node *clause,
03059 int indexcol,
03060 IndexOptInfo *index)
03061 {
03062
03063 if (match_index_to_operand(clause, indexcol, index))
03064 return true;
03065
03066 if (not_clause(clause))
03067 {
03068 if (match_index_to_operand((Node *) get_notclausearg((Expr *) clause),
03069 indexcol, index))
03070 return true;
03071 }
03072
03073
03074
03075
03076
03077
03078 else if (clause && IsA(clause, BooleanTest))
03079 {
03080 BooleanTest *btest = (BooleanTest *) clause;
03081
03082 if (btest->booltesttype == IS_TRUE ||
03083 btest->booltesttype == IS_FALSE)
03084 if (match_index_to_operand((Node *) btest->arg,
03085 indexcol, index))
03086 return true;
03087 }
03088 return false;
03089 }
03090
03091
03092
03093
03094
03095
03096
03097
03098
03099
03100
03101 static bool
03102 match_special_index_operator(Expr *clause, Oid opfamily, Oid idxcollation,
03103 bool indexkey_on_left)
03104 {
03105 bool isIndexable = false;
03106 Node *rightop;
03107 Oid expr_op;
03108 Oid expr_coll;
03109 Const *patt;
03110 Const *prefix = NULL;
03111 Pattern_Prefix_Status pstatus = Pattern_Prefix_None;
03112
03113
03114
03115
03116
03117
03118 if (!indexkey_on_left)
03119 return false;
03120
03121
03122 rightop = get_rightop(clause);
03123 expr_op = ((OpExpr *) clause)->opno;
03124 expr_coll = ((OpExpr *) clause)->inputcollid;
03125
03126
03127 if (!IsA(rightop, Const) ||
03128 ((Const *) rightop)->constisnull)
03129 return false;
03130 patt = (Const *) rightop;
03131
03132 switch (expr_op)
03133 {
03134 case OID_TEXT_LIKE_OP:
03135 case OID_BPCHAR_LIKE_OP:
03136 case OID_NAME_LIKE_OP:
03137
03138 pstatus = pattern_fixed_prefix(patt, Pattern_Type_Like, expr_coll,
03139 &prefix, NULL);
03140 isIndexable = (pstatus != Pattern_Prefix_None);
03141 break;
03142
03143 case OID_BYTEA_LIKE_OP:
03144 pstatus = pattern_fixed_prefix(patt, Pattern_Type_Like, expr_coll,
03145 &prefix, NULL);
03146 isIndexable = (pstatus != Pattern_Prefix_None);
03147 break;
03148
03149 case OID_TEXT_ICLIKE_OP:
03150 case OID_BPCHAR_ICLIKE_OP:
03151 case OID_NAME_ICLIKE_OP:
03152
03153 pstatus = pattern_fixed_prefix(patt, Pattern_Type_Like_IC, expr_coll,
03154 &prefix, NULL);
03155 isIndexable = (pstatus != Pattern_Prefix_None);
03156 break;
03157
03158 case OID_TEXT_REGEXEQ_OP:
03159 case OID_BPCHAR_REGEXEQ_OP:
03160 case OID_NAME_REGEXEQ_OP:
03161
03162 pstatus = pattern_fixed_prefix(patt, Pattern_Type_Regex, expr_coll,
03163 &prefix, NULL);
03164 isIndexable = (pstatus != Pattern_Prefix_None);
03165 break;
03166
03167 case OID_TEXT_ICREGEXEQ_OP:
03168 case OID_BPCHAR_ICREGEXEQ_OP:
03169 case OID_NAME_ICREGEXEQ_OP:
03170
03171 pstatus = pattern_fixed_prefix(patt, Pattern_Type_Regex_IC, expr_coll,
03172 &prefix, NULL);
03173 isIndexable = (pstatus != Pattern_Prefix_None);
03174 break;
03175
03176 case OID_INET_SUB_OP:
03177 case OID_INET_SUBEQ_OP:
03178 isIndexable = true;
03179 break;
03180 }
03181
03182 if (prefix)
03183 {
03184 pfree(DatumGetPointer(prefix->constvalue));
03185 pfree(prefix);
03186 }
03187
03188
03189 if (!isIndexable)
03190 return false;
03191
03192
03193
03194
03195
03196
03197
03198
03199
03200
03201
03202
03203
03204
03205
03206
03207
03208
03209
03210
03211 switch (expr_op)
03212 {
03213 case OID_TEXT_LIKE_OP:
03214 case OID_TEXT_ICLIKE_OP:
03215 case OID_TEXT_REGEXEQ_OP:
03216 case OID_TEXT_ICREGEXEQ_OP:
03217 isIndexable =
03218 (opfamily == TEXT_PATTERN_BTREE_FAM_OID) ||
03219 (opfamily == TEXT_SPGIST_FAM_OID) ||
03220 (opfamily == TEXT_BTREE_FAM_OID &&
03221 (pstatus == Pattern_Prefix_Exact ||
03222 lc_collate_is_c(idxcollation)));
03223 break;
03224
03225 case OID_BPCHAR_LIKE_OP:
03226 case OID_BPCHAR_ICLIKE_OP:
03227 case OID_BPCHAR_REGEXEQ_OP:
03228 case OID_BPCHAR_ICREGEXEQ_OP:
03229 isIndexable =
03230 (opfamily == BPCHAR_PATTERN_BTREE_FAM_OID) ||
03231 (opfamily == BPCHAR_BTREE_FAM_OID &&
03232 (pstatus == Pattern_Prefix_Exact ||
03233 lc_collate_is_c(idxcollation)));
03234 break;
03235
03236 case OID_NAME_LIKE_OP:
03237 case OID_NAME_ICLIKE_OP:
03238 case OID_NAME_REGEXEQ_OP:
03239 case OID_NAME_ICREGEXEQ_OP:
03240
03241 isIndexable = (opfamily == NAME_BTREE_FAM_OID);
03242 break;
03243
03244 case OID_BYTEA_LIKE_OP:
03245 isIndexable = (opfamily == BYTEA_BTREE_FAM_OID);
03246 break;
03247
03248 case OID_INET_SUB_OP:
03249 case OID_INET_SUBEQ_OP:
03250 isIndexable = (opfamily == NETWORK_BTREE_FAM_OID);
03251 break;
03252 }
03253
03254 return isIndexable;
03255 }
03256
03257
03258
03259
03260
03261
03262
03263
03264
03265
03266
03267
03268
03269
03270
03271
03272
03273
03274
03275
03276
03277 void
03278 expand_indexqual_conditions(IndexOptInfo *index,
03279 List *indexclauses, List *indexclausecols,
03280 List **indexquals_p, List **indexqualcols_p)
03281 {
03282 List *indexquals = NIL;
03283 List *indexqualcols = NIL;
03284 ListCell *lcc,
03285 *lci;
03286
03287 forboth(lcc, indexclauses, lci, indexclausecols)
03288 {
03289 RestrictInfo *rinfo = (RestrictInfo *) lfirst(lcc);
03290 int indexcol = lfirst_int(lci);
03291 Expr *clause = rinfo->clause;
03292 Oid curFamily = index->opfamily[indexcol];
03293 Oid curCollation = index->indexcollations[indexcol];
03294
03295
03296 if (IsBooleanOpfamily(curFamily))
03297 {
03298 Expr *boolqual;
03299
03300 boolqual = expand_boolean_index_clause((Node *) clause,
03301 indexcol,
03302 index);
03303 if (boolqual)
03304 {
03305 indexquals = lappend(indexquals,
03306 make_simple_restrictinfo(boolqual));
03307 indexqualcols = lappend_int(indexqualcols, indexcol);
03308 continue;
03309 }
03310 }
03311
03312
03313
03314
03315
03316 if (is_opclause(clause))
03317 {
03318 indexquals = list_concat(indexquals,
03319 expand_indexqual_opclause(rinfo,
03320 curFamily,
03321 curCollation));
03322
03323 while (list_length(indexqualcols) < list_length(indexquals))
03324 indexqualcols = lappend_int(indexqualcols, indexcol);
03325 }
03326 else if (IsA(clause, ScalarArrayOpExpr))
03327 {
03328
03329 indexquals = lappend(indexquals, rinfo);
03330 indexqualcols = lappend_int(indexqualcols, indexcol);
03331 }
03332 else if (IsA(clause, RowCompareExpr))
03333 {
03334 indexquals = lappend(indexquals,
03335 expand_indexqual_rowcompare(rinfo,
03336 index,
03337 indexcol));
03338 indexqualcols = lappend_int(indexqualcols, indexcol);
03339 }
03340 else if (IsA(clause, NullTest))
03341 {
03342 Assert(index->amsearchnulls);
03343 indexquals = lappend(indexquals, rinfo);
03344 indexqualcols = lappend_int(indexqualcols, indexcol);
03345 }
03346 else
03347 elog(ERROR, "unsupported indexqual type: %d",
03348 (int) nodeTag(clause));
03349 }
03350
03351 *indexquals_p = indexquals;
03352 *indexqualcols_p = indexqualcols;
03353 }
03354
03355
03356
03357
03358
03359
03360
03361
03362 static Expr *
03363 expand_boolean_index_clause(Node *clause,
03364 int indexcol,
03365 IndexOptInfo *index)
03366 {
03367
03368 if (match_index_to_operand(clause, indexcol, index))
03369 {
03370
03371 return make_opclause(BooleanEqualOperator, BOOLOID, false,
03372 (Expr *) clause,
03373 (Expr *) makeBoolConst(true, false),
03374 InvalidOid, InvalidOid);
03375 }
03376
03377 if (not_clause(clause))
03378 {
03379 Node *arg = (Node *) get_notclausearg((Expr *) clause);
03380
03381
03382 Assert(match_index_to_operand(arg, indexcol, index));
03383
03384 return make_opclause(BooleanEqualOperator, BOOLOID, false,
03385 (Expr *) arg,
03386 (Expr *) makeBoolConst(false, false),
03387 InvalidOid, InvalidOid);
03388 }
03389 if (clause && IsA(clause, BooleanTest))
03390 {
03391 BooleanTest *btest = (BooleanTest *) clause;
03392 Node *arg = (Node *) btest->arg;
03393
03394
03395 Assert(match_index_to_operand(arg, indexcol, index));
03396 if (btest->booltesttype == IS_TRUE)
03397 {
03398
03399 return make_opclause(BooleanEqualOperator, BOOLOID, false,
03400 (Expr *) arg,
03401 (Expr *) makeBoolConst(true, false),
03402 InvalidOid, InvalidOid);
03403 }
03404 if (btest->booltesttype == IS_FALSE)
03405 {
03406
03407 return make_opclause(BooleanEqualOperator, BOOLOID, false,
03408 (Expr *) arg,
03409 (Expr *) makeBoolConst(false, false),
03410 InvalidOid, InvalidOid);
03411 }
03412
03413 Assert(false);
03414 }
03415
03416 return NULL;
03417 }
03418
03419
03420
03421
03422
03423
03424
03425
03426
03427
03428 static List *
03429 expand_indexqual_opclause(RestrictInfo *rinfo, Oid opfamily, Oid idxcollation)
03430 {
03431 Expr *clause = rinfo->clause;
03432
03433
03434 Node *leftop = get_leftop(clause);
03435 Node *rightop = get_rightop(clause);
03436 Oid expr_op = ((OpExpr *) clause)->opno;
03437 Oid expr_coll = ((OpExpr *) clause)->inputcollid;
03438 Const *patt = (Const *) rightop;
03439 Const *prefix = NULL;
03440 Pattern_Prefix_Status pstatus;
03441
03442
03443
03444
03445
03446
03447
03448
03449
03450 switch (expr_op)
03451 {
03452 case OID_TEXT_LIKE_OP:
03453 case OID_BPCHAR_LIKE_OP:
03454 case OID_NAME_LIKE_OP:
03455 case OID_BYTEA_LIKE_OP:
03456 if (!op_in_opfamily(expr_op, opfamily))
03457 {
03458 pstatus = pattern_fixed_prefix(patt, Pattern_Type_Like, expr_coll,
03459 &prefix, NULL);
03460 return prefix_quals(leftop, opfamily, idxcollation, prefix, pstatus);
03461 }
03462 break;
03463
03464 case OID_TEXT_ICLIKE_OP:
03465 case OID_BPCHAR_ICLIKE_OP:
03466 case OID_NAME_ICLIKE_OP:
03467 if (!op_in_opfamily(expr_op, opfamily))
03468 {
03469
03470 pstatus = pattern_fixed_prefix(patt, Pattern_Type_Like_IC, expr_coll,
03471 &prefix, NULL);
03472 return prefix_quals(leftop, opfamily, idxcollation, prefix, pstatus);
03473 }
03474 break;
03475
03476 case OID_TEXT_REGEXEQ_OP:
03477 case OID_BPCHAR_REGEXEQ_OP:
03478 case OID_NAME_REGEXEQ_OP:
03479 if (!op_in_opfamily(expr_op, opfamily))
03480 {
03481
03482 pstatus = pattern_fixed_prefix(patt, Pattern_Type_Regex, expr_coll,
03483 &prefix, NULL);
03484 return prefix_quals(leftop, opfamily, idxcollation, prefix, pstatus);
03485 }
03486 break;
03487
03488 case OID_TEXT_ICREGEXEQ_OP:
03489 case OID_BPCHAR_ICREGEXEQ_OP:
03490 case OID_NAME_ICREGEXEQ_OP:
03491 if (!op_in_opfamily(expr_op, opfamily))
03492 {
03493
03494 pstatus = pattern_fixed_prefix(patt, Pattern_Type_Regex_IC, expr_coll,
03495 &prefix, NULL);
03496 return prefix_quals(leftop, opfamily, idxcollation, prefix, pstatus);
03497 }
03498 break;
03499
03500 case OID_INET_SUB_OP:
03501 case OID_INET_SUBEQ_OP:
03502 if (!op_in_opfamily(expr_op, opfamily))
03503 {
03504 return network_prefix_quals(leftop, expr_op, opfamily,
03505 patt->constvalue);
03506 }
03507 break;
03508 }
03509
03510
03511 return list_make1(rinfo);
03512 }
03513
03514
03515
03516
03517
03518
03519
03520
03521
03522 static RestrictInfo *
03523 expand_indexqual_rowcompare(RestrictInfo *rinfo,
03524 IndexOptInfo *index,
03525 int indexcol)
03526 {
03527 RowCompareExpr *clause = (RowCompareExpr *) rinfo->clause;
03528 Expr *newclause;
03529 List *indexcolnos;
03530 bool var_on_left;
03531
03532 newclause = adjust_rowcompare_for_index(clause,
03533 index,
03534 indexcol,
03535 &indexcolnos,
03536 &var_on_left);
03537
03538
03539
03540
03541
03542 if (newclause == (Expr *) clause)
03543 return rinfo;
03544
03545
03546 return make_simple_restrictinfo(newclause);
03547 }
03548
03549
03550
03551
03552
03553
03554
03555
03556
03557
03558
03559
03560
03561
03562
03563
03564
03565
03566
03567
03568
03569
03570
03571
03572
03573
03574
03575 Expr *
03576 adjust_rowcompare_for_index(RowCompareExpr *clause,
03577 IndexOptInfo *index,
03578 int indexcol,
03579 List **indexcolnos,
03580 bool *var_on_left_p)
03581 {
03582 bool var_on_left;
03583 int op_strategy;
03584 Oid op_lefttype;
03585 Oid op_righttype;
03586 int matching_cols;
03587 Oid expr_op;
03588 List *opfamilies;
03589 List *lefttypes;
03590 List *righttypes;
03591 List *new_ops;
03592 ListCell *largs_cell;
03593 ListCell *rargs_cell;
03594 ListCell *opnos_cell;
03595 ListCell *collids_cell;
03596
03597
03598 var_on_left = match_index_to_operand((Node *) linitial(clause->largs),
03599 indexcol, index);
03600 Assert(var_on_left ||
03601 match_index_to_operand((Node *) linitial(clause->rargs),
03602 indexcol, index));
03603 *var_on_left_p = var_on_left;
03604
03605 expr_op = linitial_oid(clause->opnos);
03606 if (!var_on_left)
03607 expr_op = get_commutator(expr_op);
03608 get_op_opfamily_properties(expr_op, index->opfamily[indexcol], false,
03609 &op_strategy,
03610 &op_lefttype,
03611 &op_righttype);
03612
03613
03614 *indexcolnos = list_make1_int(indexcol);
03615
03616
03617 opfamilies = list_make1_oid(index->opfamily[indexcol]);
03618 lefttypes = list_make1_oid(op_lefttype);
03619 righttypes = list_make1_oid(op_righttype);
03620
03621
03622
03623
03624
03625
03626
03627 matching_cols = 1;
03628 largs_cell = lnext(list_head(clause->largs));
03629 rargs_cell = lnext(list_head(clause->rargs));
03630 opnos_cell = lnext(list_head(clause->opnos));
03631 collids_cell = lnext(list_head(clause->inputcollids));
03632
03633 while (largs_cell != NULL)
03634 {
03635 Node *varop;
03636 Node *constop;
03637 int i;
03638
03639 expr_op = lfirst_oid(opnos_cell);
03640 if (var_on_left)
03641 {
03642 varop = (Node *) lfirst(largs_cell);
03643 constop = (Node *) lfirst(rargs_cell);
03644 }
03645 else
03646 {
03647 varop = (Node *) lfirst(rargs_cell);
03648 constop = (Node *) lfirst(largs_cell);
03649
03650 expr_op = get_commutator(expr_op);
03651 if (expr_op == InvalidOid)
03652 break;
03653 }
03654 if (bms_is_member(index->rel->relid, pull_varnos(constop)))
03655 break;
03656 if (contain_volatile_functions(constop))
03657 break;
03658
03659
03660
03661
03662 for (i = 0; i < index->ncolumns; i++)
03663 {
03664 if (match_index_to_operand(varop, i, index) &&
03665 get_op_opfamily_strategy(expr_op,
03666 index->opfamily[i]) == op_strategy &&
03667 IndexCollMatchesExprColl(index->indexcollations[i],
03668 lfirst_oid(collids_cell)))
03669 break;
03670 }
03671 if (i >= index->ncolumns)
03672 break;
03673
03674
03675 *indexcolnos = lappend_int(*indexcolnos, i);
03676
03677
03678 get_op_opfamily_properties(expr_op, index->opfamily[i], false,
03679 &op_strategy,
03680 &op_lefttype,
03681 &op_righttype);
03682 opfamilies = lappend_oid(opfamilies, index->opfamily[i]);
03683 lefttypes = lappend_oid(lefttypes, op_lefttype);
03684 righttypes = lappend_oid(righttypes, op_righttype);
03685
03686
03687 matching_cols++;
03688 largs_cell = lnext(largs_cell);
03689 rargs_cell = lnext(rargs_cell);
03690 opnos_cell = lnext(opnos_cell);
03691 collids_cell = lnext(collids_cell);
03692 }
03693
03694
03695 if (matching_cols == list_length(clause->opnos))
03696 return (Expr *) clause;
03697
03698
03699
03700
03701
03702
03703 if (op_strategy == BTLessEqualStrategyNumber ||
03704 op_strategy == BTGreaterEqualStrategyNumber)
03705 {
03706
03707 new_ops = list_truncate(list_copy(clause->opnos), matching_cols);
03708 }
03709 else
03710 {
03711 ListCell *opfamilies_cell;
03712 ListCell *lefttypes_cell;
03713 ListCell *righttypes_cell;
03714
03715 if (op_strategy == BTLessStrategyNumber)
03716 op_strategy = BTLessEqualStrategyNumber;
03717 else if (op_strategy == BTGreaterStrategyNumber)
03718 op_strategy = BTGreaterEqualStrategyNumber;
03719 else
03720 elog(ERROR, "unexpected strategy number %d", op_strategy);
03721 new_ops = NIL;
03722 lefttypes_cell = list_head(lefttypes);
03723 righttypes_cell = list_head(righttypes);
03724 foreach(opfamilies_cell, opfamilies)
03725 {
03726 Oid opfam = lfirst_oid(opfamilies_cell);
03727 Oid lefttype = lfirst_oid(lefttypes_cell);
03728 Oid righttype = lfirst_oid(righttypes_cell);
03729
03730 expr_op = get_opfamily_member(opfam, lefttype, righttype,
03731 op_strategy);
03732 if (!OidIsValid(expr_op))
03733 elog(ERROR, "could not find member %d(%u,%u) of opfamily %u",
03734 op_strategy, lefttype, righttype, opfam);
03735 if (!var_on_left)
03736 {
03737 expr_op = get_commutator(expr_op);
03738 if (!OidIsValid(expr_op))
03739 elog(ERROR, "could not find commutator of member %d(%u,%u) of opfamily %u",
03740 op_strategy, lefttype, righttype, opfam);
03741 }
03742 new_ops = lappend_oid(new_ops, expr_op);
03743 lefttypes_cell = lnext(lefttypes_cell);
03744 righttypes_cell = lnext(righttypes_cell);
03745 }
03746 }
03747
03748
03749 if (matching_cols > 1)
03750 {
03751 RowCompareExpr *rc = makeNode(RowCompareExpr);
03752
03753 if (var_on_left)
03754 rc->rctype = (RowCompareType) op_strategy;
03755 else
03756 rc->rctype = (op_strategy == BTLessEqualStrategyNumber) ?
03757 ROWCOMPARE_GE : ROWCOMPARE_LE;
03758 rc->opnos = new_ops;
03759 rc->opfamilies = list_truncate(list_copy(clause->opfamilies),
03760 matching_cols);
03761 rc->inputcollids = list_truncate(list_copy(clause->inputcollids),
03762 matching_cols);
03763 rc->largs = list_truncate((List *) copyObject(clause->largs),
03764 matching_cols);
03765 rc->rargs = list_truncate((List *) copyObject(clause->rargs),
03766 matching_cols);
03767 return (Expr *) rc;
03768 }
03769 else
03770 {
03771 return make_opclause(linitial_oid(new_ops), BOOLOID, false,
03772 copyObject(linitial(clause->largs)),
03773 copyObject(linitial(clause->rargs)),
03774 InvalidOid,
03775 linitial_oid(clause->inputcollids));
03776 }
03777 }
03778
03779
03780
03781
03782
03783
03784
03785 static List *
03786 prefix_quals(Node *leftop, Oid opfamily, Oid collation,
03787 Const *prefix_const, Pattern_Prefix_Status pstatus)
03788 {
03789 List *result;
03790 Oid datatype;
03791 Oid oproid;
03792 Expr *expr;
03793 FmgrInfo ltproc;
03794 Const *greaterstr;
03795
03796 Assert(pstatus != Pattern_Prefix_None);
03797
03798 switch (opfamily)
03799 {
03800 case TEXT_BTREE_FAM_OID:
03801 case TEXT_PATTERN_BTREE_FAM_OID:
03802 case TEXT_SPGIST_FAM_OID:
03803 datatype = TEXTOID;
03804 break;
03805
03806 case BPCHAR_BTREE_FAM_OID:
03807 case BPCHAR_PATTERN_BTREE_FAM_OID:
03808 datatype = BPCHAROID;
03809 break;
03810
03811 case NAME_BTREE_FAM_OID:
03812 datatype = NAMEOID;
03813 break;
03814
03815 case BYTEA_BTREE_FAM_OID:
03816 datatype = BYTEAOID;
03817 break;
03818
03819 default:
03820
03821 elog(ERROR, "unexpected opfamily: %u", opfamily);
03822 return NIL;
03823 }
03824
03825
03826
03827
03828
03829 if (prefix_const->consttype != datatype)
03830 {
03831 char *prefix;
03832
03833 switch (prefix_const->consttype)
03834 {
03835 case TEXTOID:
03836 prefix = TextDatumGetCString(prefix_const->constvalue);
03837 break;
03838 case BYTEAOID:
03839 prefix = DatumGetCString(DirectFunctionCall1(byteaout,
03840 prefix_const->constvalue));
03841 break;
03842 default:
03843 elog(ERROR, "unexpected const type: %u",
03844 prefix_const->consttype);
03845 return NIL;
03846 }
03847 prefix_const = string_to_const(prefix, datatype);
03848 pfree(prefix);
03849 }
03850
03851
03852
03853
03854 if (pstatus == Pattern_Prefix_Exact)
03855 {
03856 oproid = get_opfamily_member(opfamily, datatype, datatype,
03857 BTEqualStrategyNumber);
03858 if (oproid == InvalidOid)
03859 elog(ERROR, "no = operator for opfamily %u", opfamily);
03860 expr = make_opclause(oproid, BOOLOID, false,
03861 (Expr *) leftop, (Expr *) prefix_const,
03862 InvalidOid, collation);
03863 result = list_make1(make_simple_restrictinfo(expr));
03864 return result;
03865 }
03866
03867
03868
03869
03870
03871
03872 oproid = get_opfamily_member(opfamily, datatype, datatype,
03873 BTGreaterEqualStrategyNumber);
03874 if (oproid == InvalidOid)
03875 elog(ERROR, "no >= operator for opfamily %u", opfamily);
03876 expr = make_opclause(oproid, BOOLOID, false,
03877 (Expr *) leftop, (Expr *) prefix_const,
03878 InvalidOid, collation);
03879 result = list_make1(make_simple_restrictinfo(expr));
03880
03881
03882
03883
03884
03885
03886
03887
03888
03889 oproid = get_opfamily_member(opfamily, datatype, datatype,
03890 BTLessStrategyNumber);
03891 if (oproid == InvalidOid)
03892 elog(ERROR, "no < operator for opfamily %u", opfamily);
03893 fmgr_info(get_opcode(oproid), <proc);
03894 greaterstr = make_greater_string(prefix_const, <proc, collation);
03895 if (greaterstr)
03896 {
03897 expr = make_opclause(oproid, BOOLOID, false,
03898 (Expr *) leftop, (Expr *) greaterstr,
03899 InvalidOid, collation);
03900 result = lappend(result, make_simple_restrictinfo(expr));
03901 }
03902
03903 return result;
03904 }
03905
03906
03907
03908
03909
03910
03911 static List *
03912 network_prefix_quals(Node *leftop, Oid expr_op, Oid opfamily, Datum rightop)
03913 {
03914 bool is_eq;
03915 Oid datatype;
03916 Oid opr1oid;
03917 Oid opr2oid;
03918 Datum opr1right;
03919 Datum opr2right;
03920 List *result;
03921 Expr *expr;
03922
03923 switch (expr_op)
03924 {
03925 case OID_INET_SUB_OP:
03926 datatype = INETOID;
03927 is_eq = false;
03928 break;
03929 case OID_INET_SUBEQ_OP:
03930 datatype = INETOID;
03931 is_eq = true;
03932 break;
03933 default:
03934 elog(ERROR, "unexpected operator: %u", expr_op);
03935 return NIL;
03936 }
03937
03938
03939
03940
03941
03942 if (is_eq)
03943 {
03944 opr1oid = get_opfamily_member(opfamily, datatype, datatype,
03945 BTGreaterEqualStrategyNumber);
03946 if (opr1oid == InvalidOid)
03947 elog(ERROR, "no >= operator for opfamily %u", opfamily);
03948 }
03949 else
03950 {
03951 opr1oid = get_opfamily_member(opfamily, datatype, datatype,
03952 BTGreaterStrategyNumber);
03953 if (opr1oid == InvalidOid)
03954 elog(ERROR, "no > operator for opfamily %u", opfamily);
03955 }
03956
03957 opr1right = network_scan_first(rightop);
03958
03959 expr = make_opclause(opr1oid, BOOLOID, false,
03960 (Expr *) leftop,
03961 (Expr *) makeConst(datatype, -1,
03962 InvalidOid,
03963 -1, opr1right,
03964 false, false),
03965 InvalidOid, InvalidOid);
03966 result = list_make1(make_simple_restrictinfo(expr));
03967
03968
03969
03970 opr2oid = get_opfamily_member(opfamily, datatype, datatype,
03971 BTLessEqualStrategyNumber);
03972 if (opr2oid == InvalidOid)
03973 elog(ERROR, "no <= operator for opfamily %u", opfamily);
03974
03975 opr2right = network_scan_last(rightop);
03976
03977 expr = make_opclause(opr2oid, BOOLOID, false,
03978 (Expr *) leftop,
03979 (Expr *) makeConst(datatype, -1,
03980 InvalidOid,
03981 -1, opr2right,
03982 false, false),
03983 InvalidOid, InvalidOid);
03984 result = lappend(result, make_simple_restrictinfo(expr));
03985
03986 return result;
03987 }
03988
03989
03990
03991
03992
03993
03994
03995
03996
03997
03998 static Datum
03999 string_to_datum(const char *str, Oid datatype)
04000 {
04001
04002
04003
04004
04005 if (datatype == NAMEOID)
04006 return DirectFunctionCall1(namein, CStringGetDatum(str));
04007 else if (datatype == BYTEAOID)
04008 return DirectFunctionCall1(byteain, CStringGetDatum(str));
04009 else
04010 return CStringGetTextDatum(str);
04011 }
04012
04013
04014
04015
04016 static Const *
04017 string_to_const(const char *str, Oid datatype)
04018 {
04019 Datum conval = string_to_datum(str, datatype);
04020 Oid collation;
04021 int constlen;
04022
04023
04024
04025
04026
04027 switch (datatype)
04028 {
04029 case TEXTOID:
04030 case VARCHAROID:
04031 case BPCHAROID:
04032 collation = DEFAULT_COLLATION_OID;
04033 constlen = -1;
04034 break;
04035
04036 case NAMEOID:
04037 collation = InvalidOid;
04038 constlen = NAMEDATALEN;
04039 break;
04040
04041 case BYTEAOID:
04042 collation = InvalidOid;
04043 constlen = -1;
04044 break;
04045
04046 default:
04047 elog(ERROR, "unexpected datatype in string_to_const: %u",
04048 datatype);
04049 return NULL;
04050 }
04051
04052 return makeConst(datatype, -1, collation, constlen,
04053 conval, false, false);
04054 }