diff options
author | Peter Eisentraut | 2025-02-02 09:26:04 +0000 |
---|---|---|
committer | Peter Eisentraut | 2025-02-02 09:26:04 +0000 |
commit | c09e5a6a01659a66dd84f3e745694999d3414ddd (patch) | |
tree | 85c7b89405656557e73360aa65216baf91f01a5b | |
parent | 119fc30dd5bd918819b864107ddc8baac51f4d22 (diff) |
Convert strategies to and from compare types
For each Index AM, provide a mapping between operator strategies and
the system-wide generic concept of a comparison type. For example,
for btree, BTLessStrategyNumber maps to and from COMPARE_LT. Numerous
places in the planner and executor think directly in terms of btree
strategy numbers (and a few in terms of hash strategy numbers.) These
should be converted over subsequent commits to think in terms of
CompareType instead. (This commit doesn't make any use of this API
yet.)
Author: Mark Dilger <mark.dilger@enterprisedb.com>
Reviewed-by: Peter Eisentraut <peter@eisentraut.org>
Discussion: https://www.postgresql.org/message-id/flat/E72EAA49-354D-4C2E-8EB9-255197F55330@enterprisedb.com
-rw-r--r-- | contrib/bloom/blutils.c | 2 | ||||
-rw-r--r-- | doc/src/sgml/indexam.sgml | 26 | ||||
-rw-r--r-- | src/backend/access/brin/brin.c | 2 | ||||
-rw-r--r-- | src/backend/access/gist/gist.c | 2 | ||||
-rw-r--r-- | src/backend/access/hash/hash.c | 19 | ||||
-rw-r--r-- | src/backend/access/index/amapi.c | 50 | ||||
-rw-r--r-- | src/backend/access/nbtree/nbtree.c | 43 | ||||
-rw-r--r-- | src/backend/access/spgist/spgutils.c | 2 | ||||
-rw-r--r-- | src/include/access/amapi.h | 14 | ||||
-rw-r--r-- | src/include/access/cmptype.h | 1 | ||||
-rw-r--r-- | src/include/access/hash.h | 3 | ||||
-rw-r--r-- | src/include/access/nbtree.h | 3 | ||||
-rw-r--r-- | src/tools/pgindent/typedefs.list | 2 |
13 files changed, 169 insertions, 0 deletions
diff --git a/contrib/bloom/blutils.c b/contrib/bloom/blutils.c index 3796bea786b..04b61042a57 100644 --- a/contrib/bloom/blutils.c +++ b/contrib/bloom/blutils.c @@ -150,6 +150,8 @@ blhandler(PG_FUNCTION_ARGS) amroutine->amestimateparallelscan = NULL; amroutine->aminitparallelscan = NULL; amroutine->amparallelrescan = NULL; + amroutine->amtranslatestrategy = NULL; + amroutine->amtranslatecmptype = NULL; PG_RETURN_POINTER(amroutine); } diff --git a/doc/src/sgml/indexam.sgml b/doc/src/sgml/indexam.sgml index dc7d14b60dd..d17fcbd5cec 100644 --- a/doc/src/sgml/indexam.sgml +++ b/doc/src/sgml/indexam.sgml @@ -164,6 +164,10 @@ typedef struct IndexAmRoutine amestimateparallelscan_function amestimateparallelscan; /* can be NULL */ aminitparallelscan_function aminitparallelscan; /* can be NULL */ amparallelrescan_function amparallelrescan; /* can be NULL */ + + /* interface functions to support planning */ + amtranslate_strategy_function amtranslatestrategy; /* can be NULL */ + amtranslate_cmptype_function amtranslatecmptype; /* can be NULL */ } IndexAmRoutine; </programlisting> </para> @@ -876,6 +880,28 @@ amparallelrescan (IndexScanDesc scan); the beginning. </para> + <para> +<programlisting> +CompareType +amtranslatestrategy (StrategyNumber strategy, Oid opfamily, Oid opcintype); + +StrategyNumber +amtranslatecmptype (CompareType cmptype, Oid opfamily, Oid opcintype); +</programlisting> + These functions, if implemented, will be called by the planer and executor + to convert between fixed <type>CompareType</type> values and the specific + strategy numbers used by the access method. These functions can be + implemented by access methods that implement functionality similar to the + built-in btree or hash access methods, and by implementing these + translations, the system can learn about the semantics of the access + method's operations and can use them in place of btree or hash indexes in + various places. If the functionality of the access method is not similar + to those built-in access methods, these functions do not need to be + implemented. If the functions are not implemented, the access method will + be ignored for certain planner and executor decisions, but is otherwise + fully functional. + </para> + </sect1> <sect1 id="index-scanning"> diff --git a/src/backend/access/brin/brin.c b/src/backend/access/brin/brin.c index 4289142e20b..ccf824bbdb2 100644 --- a/src/backend/access/brin/brin.c +++ b/src/backend/access/brin/brin.c @@ -298,6 +298,8 @@ brinhandler(PG_FUNCTION_ARGS) amroutine->amestimateparallelscan = NULL; amroutine->aminitparallelscan = NULL; amroutine->amparallelrescan = NULL; + amroutine->amtranslatestrategy = NULL; + amroutine->amtranslatecmptype = NULL; PG_RETURN_POINTER(amroutine); } diff --git a/src/backend/access/gist/gist.c b/src/backend/access/gist/gist.c index b6bc75b44e3..70f8086db7b 100644 --- a/src/backend/access/gist/gist.c +++ b/src/backend/access/gist/gist.c @@ -107,6 +107,8 @@ gisthandler(PG_FUNCTION_ARGS) amroutine->amestimateparallelscan = NULL; amroutine->aminitparallelscan = NULL; amroutine->amparallelrescan = NULL; + amroutine->amtranslatestrategy = NULL; + amroutine->amtranslatecmptype = NULL; PG_RETURN_POINTER(amroutine); } diff --git a/src/backend/access/hash/hash.c b/src/backend/access/hash/hash.c index df8409ab233..63b568e7f24 100644 --- a/src/backend/access/hash/hash.c +++ b/src/backend/access/hash/hash.c @@ -21,6 +21,7 @@ #include "access/hash.h" #include "access/hash_xlog.h" #include "access/relscan.h" +#include "access/stratnum.h" #include "access/tableam.h" #include "access/xloginsert.h" #include "commands/progress.h" @@ -105,6 +106,8 @@ hashhandler(PG_FUNCTION_ARGS) amroutine->amestimateparallelscan = NULL; amroutine->aminitparallelscan = NULL; amroutine->amparallelrescan = NULL; + amroutine->amtranslatestrategy = hashtranslatestrategy; + amroutine->amtranslatecmptype = hashtranslatecmptype; PG_RETURN_POINTER(amroutine); } @@ -922,3 +925,19 @@ hashbucketcleanup(Relation rel, Bucket cur_bucket, Buffer bucket_buf, else LockBuffer(bucket_buf, BUFFER_LOCK_UNLOCK); } + +CompareType +hashtranslatestrategy(StrategyNumber strategy, Oid opfamily, Oid opcintype) +{ + if (strategy == HTEqualStrategyNumber) + return COMPARE_EQ; + return COMPARE_INVALID; +} + +StrategyNumber +hashtranslatecmptype(CompareType cmptype, Oid opfamily, Oid opcintype) +{ + if (cmptype == COMPARE_EQ) + return HTEqualStrategyNumber; + return InvalidStrategy; +} diff --git a/src/backend/access/index/amapi.c b/src/backend/access/index/amapi.c index 3522bcaa401..5f53f49ec32 100644 --- a/src/backend/access/index/amapi.c +++ b/src/backend/access/index/amapi.c @@ -108,6 +108,56 @@ GetIndexAmRoutineByAmId(Oid amoid, bool noerror) /* + * IndexAmTranslateStrategy - given an access method and strategy, get the + * corresponding compare type. + * + * If missing_ok is false, throw an error if no compare type is found. If + * true, just return COMPARE_INVALID. + */ +CompareType +IndexAmTranslateStrategy(StrategyNumber strategy, Oid amoid, Oid opfamily, Oid opcintype, bool missing_ok) +{ + CompareType result; + IndexAmRoutine *amroutine; + + amroutine = GetIndexAmRoutineByAmId(amoid, false); + if (amroutine->amtranslatestrategy) + result = amroutine->amtranslatestrategy(strategy, opfamily, opcintype); + else + result = COMPARE_INVALID; + + if (!missing_ok && result == COMPARE_INVALID) + elog(ERROR, "could not translate strategy number %d for index AM %u", strategy, amoid); + + return result; +} + +/* + * IndexAmTranslateCompareType - given an access method and compare type, get + * the corresponding strategy number. + * + * If missing_ok is false, throw an error if no strategy is found correlating + * to the given cmptype. If true, just return InvalidStrategy. + */ +StrategyNumber +IndexAmTranslateCompareType(CompareType cmptype, Oid amoid, Oid opfamily, Oid opcintype, bool missing_ok) +{ + StrategyNumber result; + IndexAmRoutine *amroutine; + + amroutine = GetIndexAmRoutineByAmId(amoid, false); + if (amroutine->amtranslatecmptype) + result = amroutine->amtranslatecmptype(cmptype, opfamily, opcintype); + else + result = InvalidStrategy; + + if (!missing_ok && result == InvalidStrategy) + elog(ERROR, "could not translate compare type %u for index AM %u", cmptype, amoid); + + return result; +} + +/* * Ask appropriate access method to validate the specified opclass. */ Datum diff --git a/src/backend/access/nbtree/nbtree.c b/src/backend/access/nbtree/nbtree.c index 3d617f168f5..971405e89af 100644 --- a/src/backend/access/nbtree/nbtree.c +++ b/src/backend/access/nbtree/nbtree.c @@ -20,6 +20,7 @@ #include "access/nbtree.h" #include "access/relscan.h" +#include "access/stratnum.h" #include "commands/progress.h" #include "commands/vacuum.h" #include "nodes/execnodes.h" @@ -148,6 +149,8 @@ bthandler(PG_FUNCTION_ARGS) amroutine->amestimateparallelscan = btestimateparallelscan; amroutine->aminitparallelscan = btinitparallelscan; amroutine->amparallelrescan = btparallelrescan; + amroutine->amtranslatestrategy = bttranslatestrategy; + amroutine->amtranslatecmptype = bttranslatecmptype; PG_RETURN_POINTER(amroutine); } @@ -1508,3 +1511,43 @@ btgettreeheight(Relation rel) { return _bt_getrootheight(rel); } + +CompareType +bttranslatestrategy(StrategyNumber strategy, Oid opfamily, Oid opcintype) +{ + switch (strategy) + { + case BTLessStrategyNumber: + return COMPARE_LT; + case BTLessEqualStrategyNumber: + return COMPARE_LE; + case BTEqualStrategyNumber: + return COMPARE_EQ; + case BTGreaterEqualStrategyNumber: + return COMPARE_GE; + case BTGreaterStrategyNumber: + return COMPARE_GT; + default: + return COMPARE_INVALID; + } +} + +StrategyNumber +bttranslatecmptype(CompareType cmptype, Oid opfamily, Oid opcintype) +{ + switch (cmptype) + { + case COMPARE_LT: + return BTLessStrategyNumber; + case COMPARE_LE: + return BTLessEqualStrategyNumber; + case COMPARE_EQ: + return BTEqualStrategyNumber; + case COMPARE_GE: + return BTGreaterEqualStrategyNumber; + case COMPARE_GT: + return BTGreaterStrategyNumber; + default: + return InvalidStrategy; + } +} diff --git a/src/backend/access/spgist/spgutils.c b/src/backend/access/spgist/spgutils.c index 6e968048917..367c36ef9af 100644 --- a/src/backend/access/spgist/spgutils.c +++ b/src/backend/access/spgist/spgutils.c @@ -92,6 +92,8 @@ spghandler(PG_FUNCTION_ARGS) amroutine->amestimateparallelscan = NULL; amroutine->aminitparallelscan = NULL; amroutine->amparallelrescan = NULL; + amroutine->amtranslatestrategy = NULL; + amroutine->amtranslatecmptype = NULL; PG_RETURN_POINTER(amroutine); } diff --git a/src/include/access/amapi.h b/src/include/access/amapi.h index fb94b3d1acf..6723de75a4d 100644 --- a/src/include/access/amapi.h +++ b/src/include/access/amapi.h @@ -12,7 +12,9 @@ #ifndef AMAPI_H #define AMAPI_H +#include "access/cmptype.h" #include "access/genam.h" +#include "access/stratnum.h" /* * We don't wish to include planner header files here, since most of an index @@ -99,6 +101,12 @@ typedef struct OpFamilyMember * Callback function signatures --- see indexam.sgml for more info. */ +/* translate AM-specific strategies to general operator types */ +typedef CompareType (*amtranslate_strategy_function) (StrategyNumber strategy, Oid opfamily, Oid opcintype); + +/* translate general operator types to AM-specific strategies */ +typedef StrategyNumber (*amtranslate_cmptype_function) (CompareType cmptype, Oid opfamily, Oid opcintype); + /* build new index */ typedef IndexBuildResult *(*ambuild_function) (Relation heapRelation, Relation indexRelation, @@ -301,11 +309,17 @@ typedef struct IndexAmRoutine amestimateparallelscan_function amestimateparallelscan; /* can be NULL */ aminitparallelscan_function aminitparallelscan; /* can be NULL */ amparallelrescan_function amparallelrescan; /* can be NULL */ + + /* interface functions to support planning */ + amtranslate_strategy_function amtranslatestrategy; /* can be NULL */ + amtranslate_cmptype_function amtranslatecmptype; /* can be NULL */ } IndexAmRoutine; /* Functions in access/index/amapi.c */ extern IndexAmRoutine *GetIndexAmRoutine(Oid amhandler); extern IndexAmRoutine *GetIndexAmRoutineByAmId(Oid amoid, bool noerror); +extern CompareType IndexAmTranslateStrategy(StrategyNumber strategy, Oid amoid, Oid opfamily, Oid opcintype, bool missing_ok); +extern StrategyNumber IndexAmTranslateCompareType(CompareType cmptype, Oid amoid, Oid opfamily, Oid opcintype, bool missing_ok); #endif /* AMAPI_H */ diff --git a/src/include/access/cmptype.h b/src/include/access/cmptype.h index 2b964227d60..ed6da1eada1 100644 --- a/src/include/access/cmptype.h +++ b/src/include/access/cmptype.h @@ -30,6 +30,7 @@ */ typedef enum CompareType { + COMPARE_INVALID = 0, COMPARE_LT = 1, /* BTLessStrategyNumber */ COMPARE_LE = 2, /* BTLessEqualStrategyNumber */ COMPARE_EQ = 3, /* BTEqualStrategyNumber */ diff --git a/src/include/access/hash.h b/src/include/access/hash.h index 0f09f35a9fd..e91f2b00ad9 100644 --- a/src/include/access/hash.h +++ b/src/include/access/hash.h @@ -387,6 +387,9 @@ extern void hashadjustmembers(Oid opfamilyoid, List *operators, List *functions); +extern CompareType hashtranslatestrategy(StrategyNumber strategy, Oid opfamily, Oid opcintype); +extern StrategyNumber hashtranslatecmptype(CompareType cmptype, Oid opfamily, Oid opcintype); + /* private routines */ /* hashinsert.c */ diff --git a/src/include/access/nbtree.h b/src/include/access/nbtree.h index 6a501537e1e..000c7289b80 100644 --- a/src/include/access/nbtree.h +++ b/src/include/access/nbtree.h @@ -1183,6 +1183,9 @@ extern IndexBulkDeleteResult *btvacuumcleanup(IndexVacuumInfo *info, extern bool btcanreturn(Relation index, int attno); extern int btgettreeheight(Relation rel); +extern CompareType bttranslatestrategy(StrategyNumber strategy, Oid opfamily, Oid opcintype); +extern StrategyNumber bttranslatecmptype(CompareType cmptype, Oid opfamily, Oid opcintype); + /* * prototypes for internal functions in nbtree.c */ diff --git a/src/tools/pgindent/typedefs.list b/src/tools/pgindent/typedefs.list index a2644a2e653..9a3bee93dec 100644 --- a/src/tools/pgindent/typedefs.list +++ b/src/tools/pgindent/typedefs.list @@ -3318,6 +3318,8 @@ amparallelrescan_function amproperty_function amrescan_function amrestrpos_function +amtranslate_strategy_function amtranslatestrategy; +amtranslate_cmptype_function amtranslatecmptype; amvacuumcleanup_function amvalidate_function array_iter |