40 #define IndexCollMatchesExprColl(idxcollation, exprcollation) \ 41 ((idxcollation) == InvalidOid || (idxcollation) == (exprcollation)) 82 List **bitindexpaths);
89 List *indexjoinclauses,
90 int considered_clauses,
91 List **considered_relids);
99 List **considered_relids);
101 List *indexjoinclauses);
105 List **bitindexpaths);
108 bool useful_predicate,
110 bool *skip_nonnative_saop,
111 bool *skip_lower_saop);
113 List *clauses,
List *other_clauses);
115 List *clauses,
List *other_clauses);
140 List **joinorclauses);
184 List **orderby_clauses_p,
185 List **clause_columns_p);
187 int indexcol,
Expr *clause,
Oid pk_opfamily);
247 bitindexpaths = bitjoinpaths = joinorclauses =
NIL;
268 MemSet(&rclauseset, 0,
sizeof(rclauseset));
285 MemSet(&jclauseset, 0,
sizeof(jclauseset));
287 &jclauseset, &joinorclauses);
293 MemSet(&eclauseset, 0,
sizeof(eclauseset));
315 bitindexpaths =
list_concat(bitindexpaths, indexpaths);
323 bitjoinpaths =
list_concat(bitjoinpaths, indexpaths);
332 if (bitindexpaths !=
NIL)
357 if (bitjoinpaths !=
NIL)
359 List *all_path_outers;
363 all_path_outers =
NIL;
364 foreach(lc, bitjoinpaths)
370 all_path_outers =
lappend(all_path_outers, required_outer);
374 foreach(lc, all_path_outers)
386 foreach(lcp, bitjoinpaths)
391 this_path_set =
lappend(this_path_set, path);
398 this_path_set =
list_concat(this_path_set, bitindexpaths);
407 required_outer, loop_count, 0);
434 List **bitindexpaths)
436 int considered_clauses = 0;
461 for (indexcol = 0; indexcol < index->
nkeycolumns; indexcol++)
466 rclauseset, jclauseset, eclauseset,
474 rclauseset, jclauseset, eclauseset,
500 List **bitindexpaths,
501 List *indexjoinclauses,
502 int considered_clauses,
503 List **considered_relids)
508 foreach(lc, indexjoinclauses)
513 int num_considered_relids;
532 num_considered_relids =
list_length(*considered_relids);
533 for (
int pos = 0; pos < num_considered_relids; pos++)
564 if (
list_length(*considered_relids) >= 10 * considered_clauses)
569 rclauseset, jclauseset, eclauseset,
577 rclauseset, jclauseset, eclauseset,
603 List **bitindexpaths,
605 List **considered_relids)
615 MemSet(&clauseset, 0,
sizeof(clauseset));
617 for (indexcol = 0; indexcol < index->
nkeycolumns; indexcol++)
667 *considered_relids =
lappend(*considered_relids, relids);
677 List *indexjoinclauses)
681 foreach(lc, indexjoinclauses)
704 foreach(lc, relids_list)
731 List **bitindexpaths)
734 bool skip_nonnative_saop =
false;
735 bool skip_lower_saop =
false;
748 &skip_nonnative_saop,
763 &skip_nonnative_saop,
779 foreach(lc, indexpaths)
788 ipath->indexselectivity < 1.0))
789 *bitindexpaths =
lappend(*bitindexpaths, ipath);
797 if (skip_nonnative_saop)
805 *bitindexpaths =
list_concat(*bitindexpaths, indexpaths);
853 bool useful_predicate,
855 bool *skip_nonnative_saop,
856 bool *skip_lower_saop)
863 List *orderbyclauses;
864 List *orderbyclausecols;
865 List *index_pathkeys;
866 List *useful_pathkeys;
867 bool found_lower_saop_clause;
868 bool pathkeys_possibly_useful;
869 bool index_is_ordered;
870 bool index_only_scan;
911 found_lower_saop_clause =
false;
913 for (indexcol = 0; indexcol < index->
nkeycolumns; indexcol++)
927 if (skip_nonnative_saop)
930 *skip_nonnative_saop =
true;
941 *skip_lower_saop =
true;
944 found_lower_saop_clause =
true;
949 index_clauses =
lappend(index_clauses, iclause);
982 !found_lower_saop_clause &&
985 if (index_is_ordered && pathkeys_possibly_useful)
991 orderbyclauses =
NIL;
992 orderbyclausecols =
NIL;
1003 useful_pathkeys =
NIL;
1007 useful_pathkeys =
NIL;
1008 orderbyclauses =
NIL;
1009 orderbyclausecols =
NIL;
1026 if (index_clauses !=
NIL || useful_pathkeys !=
NIL || useful_predicate ||
1041 result =
lappend(result, ipath);
1058 NoMovementScanDirection,
1078 if (index_is_ordered && pathkeys_possibly_useful)
1084 if (useful_pathkeys !=
NIL)
1096 result =
lappend(result, ipath);
1157 List *clauses,
List *other_clauses)
1168 bool useful_predicate;
1186 useful_predicate =
false;
1196 if (all_clauses ==
NIL)
1203 useful_predicate =
true;
1210 MemSet(&clauseset, 0,
sizeof(clauseset));
1217 if (!clauseset.
nonempty && !useful_predicate)
1252 List *clauses,
List *other_clauses)
1264 foreach(lc, clauses)
1328 pathlist =
lappend(pathlist, bitmapqual);
1335 if (pathlist !=
NIL)
1338 result =
lappend(result, bitmapqual);
1442 pathinfoarray[npaths++] = pathinfo;
1446 for (i = 0; i < npaths; i++)
1448 if (!pathinfoarray[i]->unclassifiable &&
1463 pathinfoarray[
i] = pathinfo;
1468 pathinfoarray[npaths++] = pathinfo;
1474 return pathinfoarray[0]->
path;
1489 for (i = 0; i < npaths; i++)
1495 pathinfo = pathinfoarray[
i];
1501 for (j = i + 1; j < npaths; j++)
1505 pathinfo = pathinfoarray[j];
1509 if (pathinfo->
preds)
1511 bool redundant =
false;
1514 foreach(l, pathinfo->
preds)
1530 if (newcost < costsofar)
1533 costsofar = newcost;
1547 if (i == 0 || costsofar < bestcost)
1550 bestcost = costsofar;
1584 if (aselec < bselec)
1586 if (aselec > bselec)
1667 result->
path = path;
1691 foreach(lc, result->
quals)
1698 foreach(lc, result->
preds)
1781 foreach(lc, *nodelist)
1785 if (
equal(node, oldnode))
1790 *nodelist =
lappend(*nodelist, node);
1805 Bitmapset *index_canreturn_attrs = NULL;
1806 Bitmapset *index_cannotreturn_attrs = NULL;
1852 for (i = 0; i < index->
ncolumns; i++)
1864 index_canreturn_attrs =
1868 index_cannotreturn_attrs =
1874 index_cannotreturn_attrs);
1881 bms_free(index_cannotreturn_attrs);
1919 if (outer_relids == NULL)
1924 while ((outer_relid =
bms_next_member(outer_relids, outer_relid)) >= 0)
1933 if (outer_rel == NULL)
1951 if (result == 0.0 || result > rowcount)
1955 return (result > 0.0) ? result : 1.0;
1990 if (rowcount > nunique)
2011 double rowcount = 1.0;
2035 rowcount *= rel->
rows;
2069 List **joinorclauses)
2084 *joinorclauses =
lappend(*joinorclauses, rinfo);
2105 for (indexcol = 0; indexcol < index->
nkeycolumns; indexcol++)
2141 foreach(lc, clauses)
2191 for (indexcol = 0; indexcol < index->
nkeycolumns; indexcol++)
2201 if (iclause->
rinfo == rinfo)
2295 Assert(indexcol < index->nkeycolumns);
2305 opfamily = index->
opfamily[indexcol];
2306 if (IsBooleanOpfamily(opfamily))
2342 iclause->
rinfo = rinfo;
2344 iclause->
lossy =
false;
2440 iclause->
rinfo = rinfo;
2442 iclause->
lossy =
false;
2482 expr_op = clause->
opno;
2486 opfamily = index->
opfamily[indexcol];
2506 iclause->
rinfo = rinfo;
2508 iclause->
lossy =
false;
2545 iclause->
rinfo = rinfo;
2547 iclause->
lossy =
false;
2596 foreach(lc, clause->
args)
2662 foreach(lc, sresult)
2669 iclause->
rinfo = rinfo;
2707 expr_op = saop->
opno;
2711 opfamily = index->
opfamily[indexcol];
2726 iclause->
rinfo = rinfo;
2728 iclause->
lossy =
false;
2769 if (index->
relam != BTREE_AM_OID)
2773 opfamily = index->
opfamily[indexcol];
2813 var_on_left =
false;
2879 iclause->
rinfo = rinfo;
2884 var_args = clause->
largs;
2885 non_var_args = clause->
rargs;
2889 var_args = clause->
rargs;
2890 non_var_args = clause->
largs;
2941 index->
opfamily[i]) == op_strategy &&
2961 righttypes =
lappend_oid(righttypes, op_righttype);
2974 if (var_on_left && !iclause->
lossy)
2983 if (!iclause->
lossy)
3005 elog(
ERROR,
"unexpected strategy number %d", op_strategy);
3007 forthree(opfamilies_cell, opfamilies,
3008 lefttypes_cell, lefttypes,
3009 righttypes_cell, righttypes)
3018 elog(
ERROR,
"missing operator %d(%u,%u) in opfamily %u",
3019 op_strategy, lefttype, righttype, opfam);
3025 if (matching_cols > 1)
3030 rc->
opnos = new_ops;
3080 List **orderby_clauses_p,
3081 List **clause_columns_p)
3087 *orderby_clauses_p =
NIL;
3088 *clause_columns_p =
NIL;
3094 foreach(lc1, pathkeys)
3139 for (indexcol = 0; indexcol < index->
nkeycolumns; indexcol++)
3149 orderby_clauses =
lappend(orderby_clauses, expr);
3150 clause_columns =
lappend_int(clause_columns, indexcol);
3164 *orderby_clauses_p = orderby_clauses;
3165 *clause_columns_p = clause_columns;
3208 Assert(indexcol < index->nkeycolumns);
3210 opfamily = index->
opfamily[indexcol];
3220 if (!leftop || !rightop)
3222 expr_op = ((
OpExpr *) clause)->opno;
3223 expr_coll = ((
OpExpr *) clause)->inputcollid;
3259 if (sortfamily != pk_opfamily)
3268 memcpy(newclause, clause,
sizeof(
OpExpr));
3271 newclause->
opno = expr_op;
3275 clause = (
Expr *) newclause;
3324 have_partial =
false;
3331 have_partial =
true;
3354 clauselist =
lappend(clauselist, rinfo);
3450 Assert(indexcol < index->nkeycolumns);
3452 curFamily = index->
opfamily[indexcol];
3465 if (index->
relam == BTREE_AM_OID &&
3545 restrictlist =
lappend(restrictlist, restrictinfo);
3549 if (restrictlist ==
NIL && exprlist ==
NIL)
3572 bool matched =
false;
3576 foreach(lc, restrictlist)
3612 forboth(lc, exprlist, lc2, oprlist)
3675 if (!IsBooleanOpfamily(index->
opfamily[indexcol]))
3740 if (operand &&
IsA(operand,
Var) &&
3742 indkey == ((
Var *) operand)->varattno)
3757 for (i = 0; i < indexcol; i++)
3761 if (indexpr_item == NULL)
3762 elog(
ERROR,
"wrong number of index expressions");
3766 if (indexpr_item == NULL)
3767 elog(
ERROR,
"wrong number of index expressions");
3776 if (
equal(indexkey, operand))
#define list_make2(x1, x2)
static int find_list_position(Node *node, List **nodelist)
static IndexClause * match_boolean_index_clause(RestrictInfo *rinfo, int indexcol, IndexOptInfo *index)
bool op_in_opfamily(Oid opno, Oid opfamily)
double estimate_num_groups(PlannerInfo *root, List *groupExprs, double input_rows, List **pgset)
#define IsA(nodeptr, _type_)
void cost_bitmap_heap_scan(Path *path, PlannerInfo *root, RelOptInfo *baserel, ParamPathInfo *param_info, Path *bitmapqual, double loop_count)
Oid get_commutator(Oid opno)
#define BTGreaterStrategyNumber
#define forboth(cell1, list1, cell2, list2)
void add_path(RelOptInfo *parent_rel, Path *new_path)
Bitmapset * bms_copy(const Bitmapset *a)
static void match_pathkeys_to_index(IndexOptInfo *index, List *pathkeys, List **orderby_clauses_p, List **clause_columns_p)
Oid get_op_opfamily_sortfamily(Oid opno, Oid opfamily)
static IndexClause * match_clause_to_indexcol(PlannerInfo *root, RestrictInfo *rinfo, int indexcol, IndexOptInfo *index)
static double adjust_rowcount_for_semijoins(PlannerInfo *root, Index cur_relid, Index outer_relid, double rowcount)
static ListCell * lnext(const List *l, const ListCell *c)
bool equal(const void *a, const void *b)
#define castNode(_type_, nodeptr)
static bool check_index_only(RelOptInfo *rel, IndexOptInfo *index)
#define PointerGetDatum(X)
bool match_index_to_operand(Node *operand, int indexcol, IndexOptInfo *index)
List * build_index_pathkeys(PlannerInfo *root, IndexOptInfo *index, ScanDirection scandir)
#define forthree(cell1, list1, cell2, list2, cell3, list3)
static List * build_index_paths(PlannerInfo *root, RelOptInfo *rel, IndexOptInfo *index, IndexClauseSet *clauses, bool useful_predicate, ScanTypeControl scantype, bool *skip_nonnative_saop, bool *skip_lower_saop)
BitmapOrPath * create_bitmap_or_path(PlannerInfo *root, RelOptInfo *rel, List *bitmapquals)
static double approximate_joinrel_size(PlannerInfo *root, Relids relids)
void create_index_paths(PlannerInfo *root, RelOptInfo *rel)
int bms_next_member(const Bitmapset *a, int prevbit)
static void match_clause_to_index(PlannerInfo *root, RestrictInfo *rinfo, IndexOptInfo *index, IndexClauseSet *clauseset)
static bool is_andclause(const void *clause)
Bitmapset * bms_difference(const Bitmapset *a, const Bitmapset *b)
List * list_truncate(List *list, int new_size)
ParamPathInfo * param_info
List * list_copy(const List *oldlist)
static void match_clauses_to_index(PlannerInfo *root, List *clauses, IndexOptInfo *index, IndexClauseSet *clauseset)
static IndexClause * get_index_clause_from_support(PlannerInfo *root, RestrictInfo *rinfo, Oid funcid, int indexarg, int indexcol, IndexOptInfo *index)
List * list_concat(List *list1, const List *list2)
#define MemSet(start, val, len)
static IndexClause * match_funcclause_to_indexcol(PlannerInfo *root, RestrictInfo *rinfo, int indexcol, IndexOptInfo *index)
#define FirstLowInvalidHeapAttributeNumber
static Expr * match_clause_to_ordering_op(IndexOptInfo *index, int indexcol, Expr *clause, Oid pk_opfamily)
bool contain_var_clause(Node *node)
bool contain_volatile_functions(Node *clause)
static bool ec_member_matches_indexcol(PlannerInfo *root, RelOptInfo *rel, EquivalenceClass *ec, EquivalenceMember *em, void *arg)
static Cost bitmap_scan_cost_est(PlannerInfo *root, RelOptInfo *rel, Path *ipath)
List * lappend_oid(List *list, Oid datum)
List * truncate_useless_pathkeys(PlannerInfo *root, RelOptInfo *rel, List *pathkeys)
#define OidIsValid(objectId)
Expr * make_opclause(Oid opno, Oid opresulttype, bool opretset, Expr *leftop, Expr *rightop, Oid opcollid, Oid inputcollid)
bool is_pseudo_constant_for_index(Node *expr, IndexOptInfo *index)
bool restriction_is_or_clause(RestrictInfo *restrictinfo)
#define IS_SIMPLE_REL(rel)
void pull_varattnos(Node *node, Index varno, Bitmapset **varattnos)
#define BTLessEqualStrategyNumber
struct RelOptInfo ** simple_rel_array
static Oid list_nth_oid(const List *list, int n)
static void find_indexpath_quals(Path *bitmapqual, List **quals, List **preds)
static bool bms_equal_any(Relids relids, List *relids_list)
struct IndexOptInfo * index
static void match_eclass_clauses_to_index(PlannerInfo *root, IndexOptInfo *index, IndexClauseSet *clauseset)
void pfree(void *pointer)
static void get_index_paths(PlannerInfo *root, RelOptInfo *rel, IndexOptInfo *index, IndexClauseSet *clauses, List **bitindexpaths)
List * generate_join_implied_equalities(PlannerInfo *root, Relids join_relids, Relids outer_relids, RelOptInfo *inner_rel)
static void * list_nth(const List *list, int n)
Node * makeBoolConst(bool value, bool isnull)
EquivalenceClass * parent_ec
#define OidFunctionCall1(functionId, arg1)
bool bms_is_subset(const Bitmapset *a, const Bitmapset *b)
#define lfirst_node(type, lc)
void check_index_predicates(PlannerInfo *root, RelOptInfo *rel)
RestrictInfo * commute_restrictinfo(RestrictInfo *rinfo, Oid comm_op)
IndexPath * create_index_path(PlannerInfo *root, IndexOptInfo *index, List *indexclauses, List *indexorderbys, List *indexorderbycols, List *pathkeys, ScanDirection indexscandir, bool indexonly, Relids required_outer, double loop_count, bool partial_path)
static Path * choose_bitmap_and(PlannerInfo *root, RelOptInfo *rel, List *paths)
#define PATH_REQ_OUTER(path)
#define IndexCollMatchesExprColl(idxcollation, exprcollation)
struct RestrictInfo * rinfo
static int path_usage_comparator(const void *a, const void *b)
List * list_concat_copy(const List *list1, const List *list2)
static void get_join_index_paths(PlannerInfo *root, RelOptInfo *rel, IndexOptInfo *index, IndexClauseSet *rclauseset, IndexClauseSet *jclauseset, IndexClauseSet *eclauseset, List **bitindexpaths, Relids relids, List **considered_relids)
Oid get_opfamily_member(Oid opfamily, Oid lefttype, Oid righttype, int16 strategy)
List * indexclauses[INDEX_MAX_KEYS]
static ListCell * list_head(const List *l)
static Node * get_leftop(const void *clause)
#define list_make1_int(x1)
int simple_rel_array_size
static IndexClause * match_opclause_to_indexcol(PlannerInfo *root, RestrictInfo *rinfo, int indexcol, IndexOptInfo *index)
Relids pull_varnos(Node *node)
static Cost bitmap_and_cost_est(PlannerInfo *root, RelOptInfo *rel, List *paths)
List * lappend_int(List *list, int datum)
static IndexClause * match_saopclause_to_indexcol(RestrictInfo *rinfo, int indexcol, IndexOptInfo *index)
List * lappend(List *list, void *datum)
Relids lateral_referencers
bool bms_is_empty(const Bitmapset *a)
static IndexClause * expand_indexqual_rowcompare(RestrictInfo *rinfo, int indexcol, IndexOptInfo *index, Oid expr_op, bool var_on_left)
static bool is_notclause(const void *clause)
BitmapAndPath * create_bitmap_and_path(PlannerInfo *root, RelOptInfo *rel, List *bitmapquals)
static double get_loop_count(PlannerInfo *root, Index cur_relid, Relids outer_relids)
BoolTestType booltesttype
static void consider_index_join_outer_rels(PlannerInfo *root, RelOptInfo *rel, IndexOptInfo *index, IndexClauseSet *rclauseset, IndexClauseSet *jclauseset, IndexClauseSet *eclauseset, List **bitindexpaths, List *indexjoinclauses, int considered_clauses, List **considered_relids)
#define list_make1_oid(x1)
static List * build_paths_for_OR(PlannerInfo *root, RelOptInfo *rel, List *clauses, List *other_clauses)
static List * generate_bitmap_or_paths(PlannerInfo *root, RelOptInfo *rel, List *clauses, List *other_clauses)
Relids find_childrel_parents(PlannerInfo *root, RelOptInfo *rel)
static Node * get_rightop(const void *clause)
BMS_Comparison bms_subset_compare(const Bitmapset *a, const Bitmapset *b)
static Expr * get_notclausearg(const void *notclause)
void bms_free(Bitmapset *a)
RegProcedure get_func_support(Oid funcid)
bool list_member_oid(const List *list, Oid datum)
#define Assert(condition)
static PathClauseUsage * classify_index_clause_usage(Path *path, List **clauselist)
bool restriction_is_securely_promotable(RestrictInfo *restrictinfo, RelOptInfo *rel)
EquivalenceClass * pk_eclass
Bitmapset * bms_union(const Bitmapset *a, const Bitmapset *b)
static int list_length(const List *l)
Bitmapset * bms_add_member(Bitmapset *a, int x)
bool indexcol_is_bool_constant_for_query(IndexOptInfo *index, int indexcol)
#define DatumGetPointer(X)
bool join_clause_is_movable_to(RestrictInfo *rinfo, RelOptInfo *baserel)
Bitmapset * bms_del_members(Bitmapset *a, const Bitmapset *b)
bool bms_overlap(const Bitmapset *a, const Bitmapset *b)
int get_op_opfamily_strategy(Oid opno, Oid opfamily)
static bool eclass_already_used(EquivalenceClass *parent_ec, Relids oldrelids, List *indexjoinclauses)
void get_op_opfamily_properties(Oid opno, Oid opfamily, bool ordering_op, int *strategy, Oid *lefttype, Oid *righttype)
void add_partial_path(RelOptInfo *parent_rel, Path *new_path)
void set_opfuncid(OpExpr *opexpr)
static void match_join_clauses_to_index(PlannerInfo *root, RelOptInfo *rel, IndexOptInfo *index, IndexClauseSet *clauseset, List **joinorclauses)
void list_free(List *list)
PlanRowMark * get_plan_rowmark(List *rowmarks, Index rtindex)
bool has_useful_pathkeys(PlannerInfo *root, RelOptInfo *rel)
bool contain_mutable_functions(Node *clause)
static bool is_opclause(const void *clause)
bool relation_has_unique_index_for(PlannerInfo *root, RelOptInfo *rel, List *restrictlist, List *exprlist, List *oprlist)
#define qsort(a, b, c, d)
#define BTLessStrategyNumber
void create_partial_bitmap_paths(PlannerInfo *root, RelOptInfo *rel, Path *bitmapqual)
Bitmapset * bms_del_member(Bitmapset *a, int x)
bool predicate_implied_by(List *predicate_list, List *clause_list, bool weak)
bool bms_is_member(int x, const Bitmapset *a)
struct PathTarget * reltarget
bool enable_indexonlyscan
#define make_simple_restrictinfo(clause)
#define BTGreaterEqualStrategyNumber
Bitmapset * bms_add_members(Bitmapset *a, const Bitmapset *b)
static IndexClause * match_rowcompare_to_indexcol(RestrictInfo *rinfo, int indexcol, IndexOptInfo *index)
static void match_restriction_clauses_to_index(PlannerInfo *root, IndexOptInfo *index, IndexClauseSet *clauseset)
bool bms_equal(const Bitmapset *a, const Bitmapset *b)
BitmapHeapPath * create_bitmap_heap_path(PlannerInfo *root, RelOptInfo *rel, Path *bitmapqual, Relids required_outer, double loop_count, int parallel_degree)
List * generate_implied_equalities_for_column(PlannerInfo *root, RelOptInfo *rel, ec_matches_callback_type callback, void *callback_arg, Relids prohibited_rels)
struct PlannerInfo * root
void cost_bitmap_tree_node(Path *path, Cost *cost, Selectivity *selec)
static void consider_index_join_clauses(PlannerInfo *root, RelOptInfo *rel, IndexOptInfo *index, IndexClauseSet *rclauseset, IndexClauseSet *jclauseset, IndexClauseSet *eclauseset, List **bitindexpaths)