v19.2-0005-Convert-strategies-to-and-from-compare-types.patch

text/plain

Filename: v19.2-0005-Convert-strategies-to-and-from-compare-types.patch
Type: text/plain
Part: 4
Message: Re: Index AM API cleanup

Patch

Same data as JSON: GET /api/v1/attachments/:id/patch the parsed metadata as JSON — format, series position, per-file stats; never the diff bytes. API reference →
Format: format-patch
Series: patch v19-0005
Subject: Convert strategies to and from compare types
File+
contrib/bloom/blutils.c 2 0
doc/src/sgml/indexam.sgml 26 0
src/backend/access/brin/brin.c 2 0
src/backend/access/gist/gist.c 2 0
src/backend/access/hash/hash.c 19 0
src/backend/access/index/amapi.c 50 0
src/backend/access/nbtree/nbtree.c 43 0
src/backend/access/spgist/spgutils.c 2 0
src/include/access/amapi.h 14 0
src/include/access/hash.h 3 0
src/include/access/nbtree.h 3 0
src/tools/pgindent/typedefs.list 2 0
From 84db7de83afbf35b95687baa2893b42183fa872e Mon Sep 17 00:00:00 2001
From: Peter Eisentraut <peter@eisentraut.org>
Date: Fri, 24 Jan 2025 16:12:38 +0100
Subject: [PATCH v19.2 5/6] 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.

Author: Mark Dilger <mark.dilger@enterprisedb.com>
Discussion: https://www.postgresql.org/message-id/flat/E72EAA49-354D-4C2E-8EB9-255197F55330@enterprisedb.com
---
 contrib/bloom/blutils.c              |  2 ++
 doc/src/sgml/indexam.sgml            | 26 +++++++++++++++
 src/backend/access/brin/brin.c       |  2 ++
 src/backend/access/gist/gist.c       |  2 ++
 src/backend/access/hash/hash.c       | 19 +++++++++++
 src/backend/access/index/amapi.c     | 50 ++++++++++++++++++++++++++++
 src/backend/access/nbtree/nbtree.c   | 43 ++++++++++++++++++++++++
 src/backend/access/spgist/spgutils.c |  2 ++
 src/include/access/amapi.h           | 14 ++++++++
 src/include/access/hash.h            |  3 ++
 src/include/access/nbtree.h          |  3 ++
 src/tools/pgindent/typedefs.list     |  2 ++
 12 files changed, 168 insertions(+)

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 @@ <title>Basic API Structure for Indexes</title>
     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 @@ <title>Index Access Method Functions</title>
    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 f950b9925f5..504991215ea 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
@@ -107,6 +107,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.
  */
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/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
-- 
2.48.1