Drop opcintype from index AM strategy translation API

The type argument wasn't actually really necessary.  It was a remnant
of converting the API of the gist strategy translation from using
opclass to using opfamily+opcintype (commits c09e5a6a016,
622f678c102).  For looking up the gist translation function, we used
the convention "amproclefttype = amprocrighttype = opclass's
opcintype" (see pg_amproc.h).  But each operator family should only
have one translation function, and getting the right type for the
lookup is sometimes cumbersome and fragile, so this is all
unnecessarily complicated.

To simplify this, change the gist stategy support procedure to take
"any", "any" as argument.  (This is arbitrary but seems intuitive.
The alternative of using InvalidOid as argument(s) upsets various DDL
commands, so it's not practical.)  Then we don't need opcintype for
the lookup, and we can remove it from all the API layers introduced by
commit c09e5a6a016.

This also adds some more documentation about the correct signature of
the gist support function and adds more checks in gistvalidate().
This was previously underspecified.  (It relied implicitly on
convention mentioned above.)

Discussion: https://www.postgresql.org/message-id/flat/E72EAA49-354D-4C2E-8EB9-255197F55330@enterprisedb.com
This commit is contained in:
Peter Eisentraut 2025-02-21 08:34:35 +01:00
parent 7202d72787
commit 7d6d2c4bbd
18 changed files with 72 additions and 67 deletions

View File

@ -9,79 +9,79 @@ AS 'MODULE_PATHNAME'
LANGUAGE C IMMUTABLE PARALLEL SAFE STRICT;
ALTER OPERATOR FAMILY gist_oid_ops USING gist ADD
FUNCTION 12 (oid, oid) gist_stratnum_btree (int) ;
FUNCTION 12 ("any", "any") gist_stratnum_btree (int) ;
ALTER OPERATOR FAMILY gist_int2_ops USING gist ADD
FUNCTION 12 (int2, int2) gist_stratnum_btree (int) ;
FUNCTION 12 ("any", "any") gist_stratnum_btree (int) ;
ALTER OPERATOR FAMILY gist_int4_ops USING gist ADD
FUNCTION 12 (int4, int4) gist_stratnum_btree (int) ;
FUNCTION 12 ("any", "any") gist_stratnum_btree (int) ;
ALTER OPERATOR FAMILY gist_int8_ops USING gist ADD
FUNCTION 12 (int8, int8) gist_stratnum_btree (int) ;
FUNCTION 12 ("any", "any") gist_stratnum_btree (int) ;
ALTER OPERATOR FAMILY gist_float4_ops USING gist ADD
FUNCTION 12 (float4, float4) gist_stratnum_btree (int) ;
FUNCTION 12 ("any", "any") gist_stratnum_btree (int) ;
ALTER OPERATOR FAMILY gist_float8_ops USING gist ADD
FUNCTION 12 (float8, float8) gist_stratnum_btree (int) ;
FUNCTION 12 ("any", "any") gist_stratnum_btree (int) ;
ALTER OPERATOR FAMILY gist_timestamp_ops USING gist ADD
FUNCTION 12 (timestamp, timestamp) gist_stratnum_btree (int) ;
FUNCTION 12 ("any", "any") gist_stratnum_btree (int) ;
ALTER OPERATOR FAMILY gist_timestamptz_ops USING gist ADD
FUNCTION 12 (timestamptz, timestamptz) gist_stratnum_btree (int) ;
FUNCTION 12 ("any", "any") gist_stratnum_btree (int) ;
ALTER OPERATOR FAMILY gist_time_ops USING gist ADD
FUNCTION 12 (time, time) gist_stratnum_btree (int) ;
FUNCTION 12 ("any", "any") gist_stratnum_btree (int) ;
ALTER OPERATOR FAMILY gist_date_ops USING gist ADD
FUNCTION 12 (date, date) gist_stratnum_btree (int) ;
FUNCTION 12 ("any", "any") gist_stratnum_btree (int) ;
ALTER OPERATOR FAMILY gist_interval_ops USING gist ADD
FUNCTION 12 (interval, interval) gist_stratnum_btree (int) ;
FUNCTION 12 ("any", "any") gist_stratnum_btree (int) ;
ALTER OPERATOR FAMILY gist_cash_ops USING gist ADD
FUNCTION 12 (money, money) gist_stratnum_btree (int) ;
FUNCTION 12 ("any", "any") gist_stratnum_btree (int) ;
ALTER OPERATOR FAMILY gist_macaddr_ops USING gist ADD
FUNCTION 12 (macaddr, macaddr) gist_stratnum_btree (int) ;
FUNCTION 12 ("any", "any") gist_stratnum_btree (int) ;
ALTER OPERATOR FAMILY gist_text_ops USING gist ADD
FUNCTION 12 (text, text) gist_stratnum_btree (int) ;
FUNCTION 12 ("any", "any") gist_stratnum_btree (int) ;
ALTER OPERATOR FAMILY gist_bpchar_ops USING gist ADD
FUNCTION 12 (bpchar, bpchar) gist_stratnum_btree (int) ;
FUNCTION 12 ("any", "any") gist_stratnum_btree (int) ;
ALTER OPERATOR FAMILY gist_bytea_ops USING gist ADD
FUNCTION 12 (bytea, bytea) gist_stratnum_btree (int) ;
FUNCTION 12 ("any", "any") gist_stratnum_btree (int) ;
ALTER OPERATOR FAMILY gist_numeric_ops USING gist ADD
FUNCTION 12 (numeric, numeric) gist_stratnum_btree (int) ;
FUNCTION 12 ("any", "any") gist_stratnum_btree (int) ;
ALTER OPERATOR FAMILY gist_bit_ops USING gist ADD
FUNCTION 12 (bit, bit) gist_stratnum_btree (int) ;
FUNCTION 12 ("any", "any") gist_stratnum_btree (int) ;
ALTER OPERATOR FAMILY gist_vbit_ops USING gist ADD
FUNCTION 12 (varbit, varbit) gist_stratnum_btree (int) ;
FUNCTION 12 ("any", "any") gist_stratnum_btree (int) ;
ALTER OPERATOR FAMILY gist_inet_ops USING gist ADD
FUNCTION 12 (inet, inet) gist_stratnum_btree (int) ;
FUNCTION 12 ("any", "any") gist_stratnum_btree (int) ;
ALTER OPERATOR FAMILY gist_cidr_ops USING gist ADD
FUNCTION 12 (cidr, cidr) gist_stratnum_btree (int) ;
FUNCTION 12 ("any", "any") gist_stratnum_btree (int) ;
ALTER OPERATOR FAMILY gist_timetz_ops USING gist ADD
FUNCTION 12 (timetz, timetz) gist_stratnum_btree (int) ;
FUNCTION 12 ("any", "any") gist_stratnum_btree (int) ;
ALTER OPERATOR FAMILY gist_uuid_ops USING gist ADD
FUNCTION 12 (uuid, uuid) gist_stratnum_btree (int) ;
FUNCTION 12 ("any", "any") gist_stratnum_btree (int) ;
ALTER OPERATOR FAMILY gist_macaddr8_ops USING gist ADD
FUNCTION 12 (macaddr8, macaddr8) gist_stratnum_btree (int) ;
FUNCTION 12 ("any", "any") gist_stratnum_btree (int) ;
ALTER OPERATOR FAMILY gist_enum_ops USING gist ADD
FUNCTION 12 (anyenum, anyenum) gist_stratnum_btree (int) ;
FUNCTION 12 ("any", "any") gist_stratnum_btree (int) ;
ALTER OPERATOR FAMILY gist_bool_ops USING gist ADD
FUNCTION 12 (bool, bool) gist_stratnum_btree (int) ;
FUNCTION 12 ("any", "any") gist_stratnum_btree (int) ;

View File

@ -1197,6 +1197,12 @@ CREATE OR REPLACE FUNCTION my_stratnum(integer)
RETURNS smallint
AS 'MODULE_PATHNAME'
LANGUAGE C STRICT;
</programlisting>
And the operator family registration must look like this:
<programlisting>
ALTER OPERATOR FAMILY my_opfamily USING gist ADD
FUNCTION 12 ("any", "any") my_stratnum(int);
</programlisting>
</para>

View File

@ -1095,13 +1095,13 @@ gist_stratnum_common(PG_FUNCTION_ARGS)
* Returns InvalidStrategy if the function is not defined.
*/
StrategyNumber
gisttranslatecmptype(CompareType cmptype, Oid opfamily, Oid opcintype)
gisttranslatecmptype(CompareType cmptype, Oid opfamily)
{
Oid funcid;
Datum result;
/* Check whether the function is provided. */
funcid = get_opfamily_proc(opfamily, opcintype, opcintype, GIST_STRATNUM_PROC);
funcid = get_opfamily_proc(opfamily, ANYOID, ANYOID, GIST_STRATNUM_PROC);
if (!OidIsValid(funcid))
return InvalidStrategy;

View File

@ -140,7 +140,9 @@ gistvalidate(Oid opclassoid)
break;
case GIST_STRATNUM_PROC:
ok = check_amproc_signature(procform->amproc, INT2OID, true,
1, 1, INT4OID);
1, 1, INT4OID) &&
procform->amproclefttype == ANYOID &&
procform->amprocrighttype == ANYOID;
break;
default:
ereport(INFO,

View File

@ -927,7 +927,7 @@ hashbucketcleanup(Relation rel, Bucket cur_bucket, Buffer bucket_buf,
}
CompareType
hashtranslatestrategy(StrategyNumber strategy, Oid opfamily, Oid opcintype)
hashtranslatestrategy(StrategyNumber strategy, Oid opfamily)
{
if (strategy == HTEqualStrategyNumber)
return COMPARE_EQ;
@ -935,7 +935,7 @@ hashtranslatestrategy(StrategyNumber strategy, Oid opfamily, Oid opcintype)
}
StrategyNumber
hashtranslatecmptype(CompareType cmptype, Oid opfamily, Oid opcintype)
hashtranslatecmptype(CompareType cmptype, Oid opfamily)
{
if (cmptype == COMPARE_EQ)
return HTEqualStrategyNumber;

View File

@ -115,14 +115,14 @@ GetIndexAmRoutineByAmId(Oid amoid, bool noerror)
* true, just return COMPARE_INVALID.
*/
CompareType
IndexAmTranslateStrategy(StrategyNumber strategy, Oid amoid, Oid opfamily, Oid opcintype, bool missing_ok)
IndexAmTranslateStrategy(StrategyNumber strategy, Oid amoid, Oid opfamily, bool missing_ok)
{
CompareType result;
IndexAmRoutine *amroutine;
amroutine = GetIndexAmRoutineByAmId(amoid, false);
if (amroutine->amtranslatestrategy)
result = amroutine->amtranslatestrategy(strategy, opfamily, opcintype);
result = amroutine->amtranslatestrategy(strategy, opfamily);
else
result = COMPARE_INVALID;
@ -140,14 +140,14 @@ IndexAmTranslateStrategy(StrategyNumber strategy, Oid amoid, Oid opfamily, Oid o
* to the given cmptype. If true, just return InvalidStrategy.
*/
StrategyNumber
IndexAmTranslateCompareType(CompareType cmptype, Oid amoid, Oid opfamily, Oid opcintype, bool missing_ok)
IndexAmTranslateCompareType(CompareType cmptype, Oid amoid, Oid opfamily, bool missing_ok)
{
StrategyNumber result;
IndexAmRoutine *amroutine;
amroutine = GetIndexAmRoutineByAmId(amoid, false);
if (amroutine->amtranslatecmptype)
result = amroutine->amtranslatecmptype(cmptype, opfamily, opcintype);
result = amroutine->amtranslatecmptype(cmptype, opfamily);
else
result = InvalidStrategy;

View File

@ -1513,7 +1513,7 @@ btgettreeheight(Relation rel)
}
CompareType
bttranslatestrategy(StrategyNumber strategy, Oid opfamily, Oid opcintype)
bttranslatestrategy(StrategyNumber strategy, Oid opfamily)
{
switch (strategy)
{
@ -1533,7 +1533,7 @@ bttranslatestrategy(StrategyNumber strategy, Oid opfamily, Oid opcintype)
}
StrategyNumber
bttranslatecmptype(CompareType cmptype, Oid opfamily, Oid opcintype)
bttranslatecmptype(CompareType cmptype, Oid opfamily)
{
switch (cmptype)
{

View File

@ -2692,7 +2692,6 @@ BuildSpeculativeIndexInfo(Relation index, IndexInfo *ii)
IndexAmTranslateCompareType(COMPARE_EQ,
index->rd_rel->relam,
index->rd_opfamily[i],
index->rd_opcintype[i],
false);
ii->ii_UniqueOps[i] =
get_opfamily_member(index->rd_opfamily[i],

View File

@ -2468,7 +2468,7 @@ GetOperatorFromCompareType(Oid opclass, Oid rhstype, CompareType cmptype,
/*
* Ask the index AM to translate to its internal stratnum
*/
*strat = IndexAmTranslateCompareType(cmptype, amid, opfamily, opcintype, true);
*strat = IndexAmTranslateCompareType(cmptype, amid, opfamily, true);
if (*strat == InvalidStrategy)
ereport(ERROR,
errcode(ERRCODE_UNDEFINED_OBJECT),

View File

@ -10113,7 +10113,7 @@ ATAddForeignKeyConstraint(List **wqueue, AlteredTableInfo *tab, Relation rel,
*/
for_overlaps = with_period && i == numpks - 1;
cmptype = for_overlaps ? COMPARE_OVERLAP : COMPARE_EQ;
eqstrategy = IndexAmTranslateCompareType(cmptype, amid, opfamily, opcintype, true);
eqstrategy = IndexAmTranslateCompareType(cmptype, amid, opfamily, true);
if (eqstrategy == InvalidStrategy)
ereport(ERROR,
errcode(ERRCODE_UNDEFINED_OBJECT),

View File

@ -91,7 +91,7 @@ build_replindex_scan_key(ScanKey skey, Relation rel, Relation idxrel,
*/
optype = get_opclass_input_type(opclass->values[index_attoff]);
opfamily = get_opclass_family(opclass->values[index_attoff]);
eq_strategy = IndexAmTranslateCompareType(COMPARE_EQ, idxrel->rd_rel->relam, opfamily, optype, false);
eq_strategy = IndexAmTranslateCompareType(COMPARE_EQ, idxrel->rd_rel->relam, opfamily, false);
operator = get_opfamily_member(opfamily, optype,
optype,
eq_strategy);

View File

@ -837,11 +837,9 @@ IsIndexUsableForReplicaIdentityFull(Relation idxrel, AttrMap *attrmap)
for (int i = 0; i < idxrel->rd_index->indnkeyatts; i++)
{
Oid opfamily;
Oid opcintype;
if (!get_opclass_opfamily_and_input_type(indclass->values[i], &opfamily, &opcintype))
return false;
if (IndexAmTranslateCompareType(COMPARE_EQ, idxrel->rd_rel->relam, opfamily, opcintype, true) == InvalidStrategy)
opfamily = get_opclass_family(indclass->values[i]);
if (IndexAmTranslateCompareType(COMPARE_EQ, idxrel->rd_rel->relam, opfamily, true) == InvalidStrategy)
return false;
}

View File

@ -102,10 +102,10 @@ typedef struct OpFamilyMember
*/
/* translate AM-specific strategies to general operator types */
typedef CompareType (*amtranslate_strategy_function) (StrategyNumber strategy, Oid opfamily, Oid opcintype);
typedef CompareType (*amtranslate_strategy_function) (StrategyNumber strategy, Oid opfamily);
/* translate general operator types to AM-specific strategies */
typedef StrategyNumber (*amtranslate_cmptype_function) (CompareType cmptype, Oid opfamily, Oid opcintype);
typedef StrategyNumber (*amtranslate_cmptype_function) (CompareType cmptype, Oid opfamily);
/* build new index */
typedef IndexBuildResult *(*ambuild_function) (Relation heapRelation,
@ -319,7 +319,7 @@ typedef struct 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);
extern CompareType IndexAmTranslateStrategy(StrategyNumber strategy, Oid amoid, Oid opfamily, bool missing_ok);
extern StrategyNumber IndexAmTranslateCompareType(CompareType cmptype, Oid amoid, Oid opfamily, bool missing_ok);
#endif /* AMAPI_H */

View File

@ -248,6 +248,6 @@ typedef struct
do { (e).key = (k); (e).rel = (r); (e).page = (pg); \
(e).offset = (o); (e).leafkey = (l); } while (0)
extern StrategyNumber gisttranslatecmptype(CompareType cmptype, Oid opfamily, Oid opcintype);
extern StrategyNumber gisttranslatecmptype(CompareType cmptype, Oid opfamily);
#endif /* GIST_H */

View File

@ -387,8 +387,8 @@ 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);
extern CompareType hashtranslatestrategy(StrategyNumber strategy, Oid opfamily);
extern StrategyNumber hashtranslatecmptype(CompareType cmptype, Oid opfamily);
/* private routines */

View File

@ -1183,8 +1183,8 @@ 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);
extern CompareType bttranslatestrategy(StrategyNumber strategy, Oid opfamily);
extern StrategyNumber bttranslatecmptype(CompareType cmptype, Oid opfamily);
/*
* prototypes for internal functions in nbtree.c

View File

@ -57,6 +57,6 @@
*/
/* yyyymmddN */
#define CATALOG_VERSION_NO 202502112
#define CATALOG_VERSION_NO 202502211
#endif

View File

@ -506,8 +506,8 @@
amprocrighttype => 'box', amprocnum => '7', amproc => 'gist_box_same' },
{ amprocfamily => 'gist/box_ops', amproclefttype => 'box',
amprocrighttype => 'box', amprocnum => '8', amproc => 'gist_box_distance' },
{ amprocfamily => 'gist/box_ops', amproclefttype => 'box',
amprocrighttype => 'box', amprocnum => '12',
{ amprocfamily => 'gist/box_ops', amproclefttype => 'any',
amprocrighttype => 'any', amprocnum => '12',
amproc => 'gist_stratnum_common' },
{ amprocfamily => 'gist/poly_ops', amproclefttype => 'polygon',
amprocrighttype => 'polygon', amprocnum => '1',
@ -528,8 +528,8 @@
{ amprocfamily => 'gist/poly_ops', amproclefttype => 'polygon',
amprocrighttype => 'polygon', amprocnum => '8',
amproc => 'gist_poly_distance' },
{ amprocfamily => 'gist/poly_ops', amproclefttype => 'polygon',
amprocrighttype => 'polygon', amprocnum => '12',
{ amprocfamily => 'gist/poly_ops', amproclefttype => 'any',
amprocrighttype => 'any', amprocnum => '12',
amproc => 'gist_stratnum_common' },
{ amprocfamily => 'gist/circle_ops', amproclefttype => 'circle',
amprocrighttype => 'circle', amprocnum => '1',
@ -549,8 +549,8 @@
{ amprocfamily => 'gist/circle_ops', amproclefttype => 'circle',
amprocrighttype => 'circle', amprocnum => '8',
amproc => 'gist_circle_distance' },
{ amprocfamily => 'gist/circle_ops', amproclefttype => 'circle',
amprocrighttype => 'circle', amprocnum => '12',
{ amprocfamily => 'gist/circle_ops', amproclefttype => 'any',
amprocrighttype => 'any', amprocnum => '12',
amproc => 'gist_stratnum_common' },
{ amprocfamily => 'gist/tsvector_ops', amproclefttype => 'tsvector',
amprocrighttype => 'tsvector', amprocnum => '1',
@ -606,8 +606,8 @@
{ amprocfamily => 'gist/range_ops', amproclefttype => 'anyrange',
amprocrighttype => 'anyrange', amprocnum => '7',
amproc => 'range_gist_same' },
{ amprocfamily => 'gist/range_ops', amproclefttype => 'anyrange',
amprocrighttype => 'anyrange', amprocnum => '12',
{ amprocfamily => 'gist/range_ops', amproclefttype => 'any',
amprocrighttype => 'any', amprocnum => '12',
amproc => 'gist_stratnum_common' },
{ amprocfamily => 'gist/network_ops', amproclefttype => 'inet',
amprocrighttype => 'inet', amprocnum => '1',
@ -625,8 +625,8 @@
amprocrighttype => 'inet', amprocnum => '7', amproc => 'inet_gist_same' },
{ amprocfamily => 'gist/network_ops', amproclefttype => 'inet',
amprocrighttype => 'inet', amprocnum => '9', amproc => 'inet_gist_fetch' },
{ amprocfamily => 'gist/network_ops', amproclefttype => 'inet',
amprocrighttype => 'inet', amprocnum => '12',
{ amprocfamily => 'gist/network_ops', amproclefttype => 'any',
amprocrighttype => 'any', amprocnum => '12',
amproc => 'gist_stratnum_common' },
{ amprocfamily => 'gist/multirange_ops', amproclefttype => 'anymultirange',
amprocrighttype => 'anymultirange', amprocnum => '1',
@ -646,8 +646,8 @@
{ amprocfamily => 'gist/multirange_ops', amproclefttype => 'anymultirange',
amprocrighttype => 'anymultirange', amprocnum => '7',
amproc => 'range_gist_same' },
{ amprocfamily => 'gist/multirange_ops', amproclefttype => 'anymultirange',
amprocrighttype => 'anymultirange', amprocnum => '12',
{ amprocfamily => 'gist/multirange_ops', amproclefttype => 'any',
amprocrighttype => 'any', amprocnum => '12',
amproc => 'gist_stratnum_common' },
# gin