mirror of
https://github.com/postgres/postgres.git
synced 2025-05-12 00:01:58 -04:00
Convert PathKey to use CompareType
Change the PathKey struct to use CompareType to record the sort direction instead of hardcoding btree strategy numbers. The CompareType is then converted to the index-type-specific strategy when the plan is created. This reduces the number of places btree strategy numbers are hardcoded, and it's a self-contained subset of a larger effort to allow non-btree indexes to behave like btrees. Author: Mark Dilger <mark.dilger@enterprisedb.com> Co-authored-by: Peter Eisentraut <peter@eisentraut.org> Discussion: https://www.postgresql.org/message-id/flat/E72EAA49-354D-4C2E-8EB9-255197F55330@enterprisedb.com
This commit is contained in:
parent
daa16893fa
commit
8123e91f5a
@ -3969,17 +3969,17 @@ appendOrderByClause(List *pathkeys, bool has_final_sort,
|
||||
appendStringInfoString(buf, ", ");
|
||||
|
||||
/*
|
||||
* Lookup the operator corresponding to the strategy in the opclass.
|
||||
* The datatype used by the opfamily is not necessarily the same as
|
||||
* the expression type (for array types for example).
|
||||
* Lookup the operator corresponding to the compare type in the
|
||||
* opclass. The datatype used by the opfamily is not necessarily the
|
||||
* same as the expression type (for array types for example).
|
||||
*/
|
||||
oprid = get_opfamily_member(pathkey->pk_opfamily,
|
||||
em->em_datatype,
|
||||
em->em_datatype,
|
||||
pathkey->pk_strategy);
|
||||
oprid = get_opfamily_member_for_cmptype(pathkey->pk_opfamily,
|
||||
em->em_datatype,
|
||||
em->em_datatype,
|
||||
pathkey->pk_cmptype);
|
||||
if (!OidIsValid(oprid))
|
||||
elog(ERROR, "missing operator %d(%u,%u) in opfamily %u",
|
||||
pathkey->pk_strategy, em->em_datatype, em->em_datatype,
|
||||
pathkey->pk_cmptype, em->em_datatype, em->em_datatype,
|
||||
pathkey->pk_opfamily);
|
||||
|
||||
deparseExpr(em_expr, context);
|
||||
|
@ -999,7 +999,7 @@ get_useful_pathkeys_for_relation(PlannerInfo *root, RelOptInfo *rel)
|
||||
/* Looks like we can generate a pathkey, so let's do it. */
|
||||
pathkey = make_canonical_pathkey(root, cur_ec,
|
||||
linitial_oid(cur_ec->ec_opfamilies),
|
||||
BTLessStrategyNumber,
|
||||
COMPARE_LT,
|
||||
false);
|
||||
useful_pathkeys_list = lappend(useful_pathkeys_list,
|
||||
list_make1(pathkey));
|
||||
|
@ -3608,7 +3608,7 @@ initial_cost_mergejoin(PlannerInfo *root, JoinCostWorkspace *workspace,
|
||||
/* debugging check */
|
||||
if (opathkey->pk_opfamily != ipathkey->pk_opfamily ||
|
||||
opathkey->pk_eclass->ec_collation != ipathkey->pk_eclass->ec_collation ||
|
||||
opathkey->pk_strategy != ipathkey->pk_strategy ||
|
||||
opathkey->pk_cmptype != ipathkey->pk_cmptype ||
|
||||
opathkey->pk_nulls_first != ipathkey->pk_nulls_first)
|
||||
elog(ERROR, "left and right pathkeys do not match in mergejoin");
|
||||
|
||||
@ -4093,7 +4093,7 @@ cached_scansel(PlannerInfo *root, RestrictInfo *rinfo, PathKey *pathkey)
|
||||
cache = (MergeScanSelCache *) lfirst(lc);
|
||||
if (cache->opfamily == pathkey->pk_opfamily &&
|
||||
cache->collation == pathkey->pk_eclass->ec_collation &&
|
||||
cache->strategy == pathkey->pk_strategy &&
|
||||
cache->cmptype == pathkey->pk_cmptype &&
|
||||
cache->nulls_first == pathkey->pk_nulls_first)
|
||||
return cache;
|
||||
}
|
||||
@ -4102,7 +4102,7 @@ cached_scansel(PlannerInfo *root, RestrictInfo *rinfo, PathKey *pathkey)
|
||||
mergejoinscansel(root,
|
||||
(Node *) rinfo->clause,
|
||||
pathkey->pk_opfamily,
|
||||
pathkey->pk_strategy,
|
||||
pathkey->pk_cmptype,
|
||||
pathkey->pk_nulls_first,
|
||||
&leftstartsel,
|
||||
&leftendsel,
|
||||
@ -4115,7 +4115,7 @@ cached_scansel(PlannerInfo *root, RestrictInfo *rinfo, PathKey *pathkey)
|
||||
cache = (MergeScanSelCache *) palloc(sizeof(MergeScanSelCache));
|
||||
cache->opfamily = pathkey->pk_opfamily;
|
||||
cache->collation = pathkey->pk_eclass->ec_collation;
|
||||
cache->strategy = pathkey->pk_strategy;
|
||||
cache->cmptype = pathkey->pk_cmptype;
|
||||
cache->nulls_first = pathkey->pk_nulls_first;
|
||||
cache->leftstartsel = leftstartsel;
|
||||
cache->leftendsel = leftendsel;
|
||||
|
@ -3817,8 +3817,7 @@ match_pathkeys_to_index(IndexOptInfo *index, List *pathkeys,
|
||||
|
||||
|
||||
/* Pathkey must request default sort order for the target opfamily */
|
||||
if (pathkey->pk_strategy != BTLessStrategyNumber ||
|
||||
pathkey->pk_nulls_first)
|
||||
if (pathkey->pk_cmptype != COMPARE_LT || pathkey->pk_nulls_first)
|
||||
return;
|
||||
|
||||
/* If eclass is volatile, no hope of using an indexscan */
|
||||
|
@ -55,7 +55,7 @@ static bool right_merge_direction(PlannerInfo *root, PathKey *pathkey);
|
||||
PathKey *
|
||||
make_canonical_pathkey(PlannerInfo *root,
|
||||
EquivalenceClass *eclass, Oid opfamily,
|
||||
int strategy, bool nulls_first)
|
||||
CompareType cmptype, bool nulls_first)
|
||||
{
|
||||
PathKey *pk;
|
||||
ListCell *lc;
|
||||
@ -74,7 +74,7 @@ make_canonical_pathkey(PlannerInfo *root,
|
||||
pk = (PathKey *) lfirst(lc);
|
||||
if (eclass == pk->pk_eclass &&
|
||||
opfamily == pk->pk_opfamily &&
|
||||
strategy == pk->pk_strategy &&
|
||||
cmptype == pk->pk_cmptype &&
|
||||
nulls_first == pk->pk_nulls_first)
|
||||
return pk;
|
||||
}
|
||||
@ -88,7 +88,7 @@ make_canonical_pathkey(PlannerInfo *root,
|
||||
pk = makeNode(PathKey);
|
||||
pk->pk_eclass = eclass;
|
||||
pk->pk_opfamily = opfamily;
|
||||
pk->pk_strategy = strategy;
|
||||
pk->pk_cmptype = cmptype;
|
||||
pk->pk_nulls_first = nulls_first;
|
||||
|
||||
root->canon_pathkeys = lappend(root->canon_pathkeys, pk);
|
||||
@ -206,12 +206,12 @@ make_pathkey_from_sortinfo(PlannerInfo *root,
|
||||
Relids rel,
|
||||
bool create_it)
|
||||
{
|
||||
int16 strategy;
|
||||
CompareType cmptype;
|
||||
Oid equality_op;
|
||||
List *opfamilies;
|
||||
EquivalenceClass *eclass;
|
||||
|
||||
strategy = reverse_sort ? BTGreaterStrategyNumber : BTLessStrategyNumber;
|
||||
cmptype = reverse_sort ? COMPARE_GT : COMPARE_LT;
|
||||
|
||||
/*
|
||||
* EquivalenceClasses need to contain opfamily lists based on the family
|
||||
@ -242,7 +242,7 @@ make_pathkey_from_sortinfo(PlannerInfo *root,
|
||||
|
||||
/* And finally we can find or create a PathKey node */
|
||||
return make_canonical_pathkey(root, eclass, opfamily,
|
||||
strategy, nulls_first);
|
||||
cmptype, nulls_first);
|
||||
}
|
||||
|
||||
/*
|
||||
@ -1118,7 +1118,7 @@ convert_subquery_pathkeys(PlannerInfo *root, RelOptInfo *rel,
|
||||
make_canonical_pathkey(root,
|
||||
outer_ec,
|
||||
sub_pathkey->pk_opfamily,
|
||||
sub_pathkey->pk_strategy,
|
||||
sub_pathkey->pk_cmptype,
|
||||
sub_pathkey->pk_nulls_first);
|
||||
}
|
||||
}
|
||||
@ -1200,7 +1200,7 @@ convert_subquery_pathkeys(PlannerInfo *root, RelOptInfo *rel,
|
||||
outer_pk = make_canonical_pathkey(root,
|
||||
outer_ec,
|
||||
sub_pathkey->pk_opfamily,
|
||||
sub_pathkey->pk_strategy,
|
||||
sub_pathkey->pk_cmptype,
|
||||
sub_pathkey->pk_nulls_first);
|
||||
/* score = # of equivalence peers */
|
||||
score = list_length(outer_ec->ec_members) - 1;
|
||||
@ -1816,7 +1816,7 @@ select_outer_pathkeys_for_merge(PlannerInfo *root,
|
||||
pathkey = make_canonical_pathkey(root,
|
||||
ec,
|
||||
linitial_oid(ec->ec_opfamilies),
|
||||
BTLessStrategyNumber,
|
||||
COMPARE_LT,
|
||||
false);
|
||||
/* can't be redundant because no duplicate ECs */
|
||||
Assert(!pathkey_is_redundant(pathkey, pathkeys));
|
||||
@ -1909,7 +1909,7 @@ make_inner_pathkeys_for_merge(PlannerInfo *root,
|
||||
pathkey = make_canonical_pathkey(root,
|
||||
ieclass,
|
||||
opathkey->pk_opfamily,
|
||||
opathkey->pk_strategy,
|
||||
opathkey->pk_cmptype,
|
||||
opathkey->pk_nulls_first);
|
||||
|
||||
/*
|
||||
@ -2134,12 +2134,12 @@ right_merge_direction(PlannerInfo *root, PathKey *pathkey)
|
||||
* want to prefer only one of the two possible directions, and we
|
||||
* might as well use this one.
|
||||
*/
|
||||
return (pathkey->pk_strategy == query_pathkey->pk_strategy);
|
||||
return (pathkey->pk_cmptype == query_pathkey->pk_cmptype);
|
||||
}
|
||||
}
|
||||
|
||||
/* If no matching ORDER BY request, prefer the ASC direction */
|
||||
return (pathkey->pk_strategy == BTLessStrategyNumber);
|
||||
return (pathkey->pk_cmptype == COMPARE_LT);
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -3129,13 +3129,13 @@ create_indexscan_plan(PlannerInfo *root,
|
||||
Oid sortop;
|
||||
|
||||
/* Get sort operator from opfamily */
|
||||
sortop = get_opfamily_member(pathkey->pk_opfamily,
|
||||
exprtype,
|
||||
exprtype,
|
||||
pathkey->pk_strategy);
|
||||
sortop = get_opfamily_member_for_cmptype(pathkey->pk_opfamily,
|
||||
exprtype,
|
||||
exprtype,
|
||||
pathkey->pk_cmptype);
|
||||
if (!OidIsValid(sortop))
|
||||
elog(ERROR, "missing operator %d(%u,%u) in opfamily %u",
|
||||
pathkey->pk_strategy, exprtype, exprtype, pathkey->pk_opfamily);
|
||||
pathkey->pk_cmptype, exprtype, exprtype, pathkey->pk_opfamily);
|
||||
indexorderbyops = lappend_oid(indexorderbyops, sortop);
|
||||
}
|
||||
}
|
||||
@ -4739,14 +4739,14 @@ create_mergejoin_plan(PlannerInfo *root,
|
||||
opathkey->pk_eclass->ec_collation != ipathkey->pk_eclass->ec_collation)
|
||||
elog(ERROR, "left and right pathkeys do not match in mergejoin");
|
||||
if (first_inner_match &&
|
||||
(opathkey->pk_strategy != ipathkey->pk_strategy ||
|
||||
(opathkey->pk_cmptype != ipathkey->pk_cmptype ||
|
||||
opathkey->pk_nulls_first != ipathkey->pk_nulls_first))
|
||||
elog(ERROR, "left and right pathkeys do not match in mergejoin");
|
||||
|
||||
/* OK, save info for executor */
|
||||
mergefamilies[i] = opathkey->pk_opfamily;
|
||||
mergecollations[i] = opathkey->pk_eclass->ec_collation;
|
||||
mergereversals[i] = (opathkey->pk_strategy == BTGreaterStrategyNumber ? true : false);
|
||||
mergereversals[i] = (opathkey->pk_cmptype == COMPARE_GT ? true : false);
|
||||
mergenullsfirst[i] = opathkey->pk_nulls_first;
|
||||
i++;
|
||||
}
|
||||
@ -6374,13 +6374,13 @@ prepare_sort_from_pathkeys(Plan *lefttree, List *pathkeys,
|
||||
* Look up the correct sort operator from the PathKey's slightly
|
||||
* abstracted representation.
|
||||
*/
|
||||
sortop = get_opfamily_member(pathkey->pk_opfamily,
|
||||
pk_datatype,
|
||||
pk_datatype,
|
||||
pathkey->pk_strategy);
|
||||
sortop = get_opfamily_member_for_cmptype(pathkey->pk_opfamily,
|
||||
pk_datatype,
|
||||
pk_datatype,
|
||||
pathkey->pk_cmptype);
|
||||
if (!OidIsValid(sortop)) /* should not happen */
|
||||
elog(ERROR, "missing operator %d(%u,%u) in opfamily %u",
|
||||
pathkey->pk_strategy, pk_datatype, pk_datatype,
|
||||
pathkey->pk_cmptype, pk_datatype, pk_datatype,
|
||||
pathkey->pk_opfamily);
|
||||
|
||||
/* Add the column to the sort arrays */
|
||||
|
@ -1506,9 +1506,7 @@ typedef struct EquivalenceMember
|
||||
* equivalent and closely-related orderings. (See optimizer/README for more
|
||||
* information.)
|
||||
*
|
||||
* Note: pk_strategy is either BTLessStrategyNumber (for ASC) or
|
||||
* BTGreaterStrategyNumber (for DESC). We assume that all ordering-capable
|
||||
* index types will use btree-compatible strategy numbers.
|
||||
* Note: pk_strategy is either COMPARE_LT (for ASC) or COMPARE_GT (for DESC).
|
||||
*/
|
||||
typedef struct PathKey
|
||||
{
|
||||
@ -1518,8 +1516,8 @@ typedef struct PathKey
|
||||
|
||||
/* the value that is ordered */
|
||||
EquivalenceClass *pk_eclass pg_node_attr(copy_as_scalar, equal_as_scalar);
|
||||
Oid pk_opfamily; /* btree opfamily defining the ordering */
|
||||
int pk_strategy; /* sort direction (ASC or DESC) */
|
||||
Oid pk_opfamily; /* index opfamily defining the ordering */
|
||||
CompareType pk_cmptype; /* sort direction (ASC or DESC) */
|
||||
bool pk_nulls_first; /* do NULLs come before normal values? */
|
||||
} PathKey;
|
||||
|
||||
@ -2784,9 +2782,9 @@ typedef struct RestrictInfo
|
||||
typedef struct MergeScanSelCache
|
||||
{
|
||||
/* Ordering details (cache lookup key) */
|
||||
Oid opfamily; /* btree opfamily defining the ordering */
|
||||
Oid opfamily; /* index opfamily defining the ordering */
|
||||
Oid collation; /* collation for the ordering */
|
||||
int strategy; /* sort direction (ASC or DESC) */
|
||||
CompareType cmptype; /* sort direction (ASC or DESC) */
|
||||
bool nulls_first; /* do NULLs come before normal values? */
|
||||
/* Results */
|
||||
Selectivity leftstartsel; /* first-join fraction for clause left side */
|
||||
|
@ -272,7 +272,7 @@ extern bool has_useful_pathkeys(PlannerInfo *root, RelOptInfo *rel);
|
||||
extern List *append_pathkeys(List *target, List *source);
|
||||
extern PathKey *make_canonical_pathkey(PlannerInfo *root,
|
||||
EquivalenceClass *eclass, Oid opfamily,
|
||||
int strategy, bool nulls_first);
|
||||
CompareType cmptype, bool nulls_first);
|
||||
extern void add_paths_to_append_rel(PlannerInfo *root, RelOptInfo *rel,
|
||||
List *live_childrels);
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user