amroutine->aminitparallelscan = NULL;
amroutine->amparallelrescan = NULL;
amroutine->amtranslatestrategy = NULL;
- amroutine->amtranslatecmptype = NULL;
+ amroutine->amtranslatecmptype = gisttranslatecmptype;
PG_RETURN_POINTER(amroutine);
}
* Returns InvalidStrategy if the function is not defined.
*/
StrategyNumber
-GistTranslateCompareType(Oid opclass, CompareType cmptype)
+gisttranslatecmptype(CompareType cmptype, Oid opfamily, Oid opcintype)
{
- Oid opfamily;
- Oid opcintype;
Oid funcid;
Datum result;
- /* Look up the opclass family and input datatype. */
- if (!get_opclass_opfamily_and_input_type(opclass, &opfamily, &opcintype))
- return InvalidStrategy;
-
/* Check whether the function is provided. */
funcid = get_opfamily_proc(opfamily, opcintype, opcintype, GIST_STRATNUM_PROC);
if (!OidIsValid(funcid))
GetOperatorFromCompareType(Oid opclass, Oid rhstype, CompareType cmptype,
Oid *opid, StrategyNumber *strat)
{
+ Oid amid;
Oid opfamily;
Oid opcintype;
Assert(cmptype == COMPARE_EQ || cmptype == COMPARE_OVERLAP || cmptype == COMPARE_CONTAINED_BY);
+ amid = get_opclass_method(opclass);
+
*opid = InvalidOid;
if (get_opclass_opfamily_and_input_type(opclass, &opfamily, &opcintype))
{
/*
- * Ask the opclass to translate to its internal stratnum
- *
- * For now we only need GiST support, but this could support other
- * indexams if we wanted.
+ * Ask the index AM to translate to its internal stratnum
*/
- *strat = GistTranslateCompareType(opclass, cmptype);
+ *strat = IndexAmTranslateCompareType(cmptype, amid, opfamily, opcintype, true);
if (*strat == InvalidStrategy)
- {
- HeapTuple tuple;
-
- tuple = SearchSysCache1(CLAOID, ObjectIdGetDatum(opclass));
- if (!HeapTupleIsValid(tuple))
- elog(ERROR, "cache lookup failed for operator class %u", opclass);
-
ereport(ERROR,
errcode(ERRCODE_UNDEFINED_OBJECT),
cmptype = COMPARE_EQ ? errmsg("could not identify an equality operator for type %s", format_type_be(opcintype)) :
cmptype == COMPARE_OVERLAP ? errmsg("could not identify an overlaps operator for type %s", format_type_be(opcintype)) :
cmptype == COMPARE_CONTAINED_BY ? errmsg("could not identify a contained-by operator for type %s", format_type_be(opcintype)) : 0,
- errdetail("Could not translate compare type %d for operator class \"%s\" for access method \"%s\".",
- cmptype, NameStr(((Form_pg_opclass) GETSTRUCT(tuple))->opcname), "gist"));
- }
+ errdetail("Could not translate compare type %d for operator family \"%s\", input type %s, access method \"%s\".",
+ cmptype, get_opfamily_name(opfamily, false), format_type_be(opcintype), get_am_name(amid)));
/*
* We parameterize rhstype so foreign keys can ask for a <@ operator
cmptype == COMPARE_OVERLAP ? errmsg("could not identify an overlaps operator for type %s", format_type_be(opcintype)) :
cmptype == COMPARE_CONTAINED_BY ? errmsg("could not identify a contained-by operator for type %s", format_type_be(opcintype)) : 0,
errdetail("There is no suitable operator in operator family \"%s\" for access method \"%s\".",
- get_opfamily_name(opfamily, false), "gist"));
+ get_opfamily_name(opfamily, false), get_am_name(amid)));
}
/*
CompareType cmptype;
bool for_overlaps = with_period && i == numpks - 1;
- /*
- * GiST indexes are required to support temporal foreign keys
- * because they combine equals and overlaps.
- */
- if (amid != GIST_AM_OID)
- elog(ERROR, "only GiST indexes are supported for temporal foreign keys");
-
cmptype = for_overlaps ? COMPARE_OVERLAP : COMPARE_EQ;
/*
- * An opclass can use whatever strategy numbers it wants, so we
- * ask the opclass what number it actually uses instead of our RT*
- * constants.
+ * An index AM can use whatever strategy numbers it wants, so we
+ * ask it what number it actually uses.
*/
- eqstrategy = GistTranslateCompareType(opclasses[i], cmptype);
+ eqstrategy = IndexAmTranslateCompareType(cmptype, amid, opfamily, opcintype, true);
if (eqstrategy == InvalidStrategy)
- {
- HeapTuple tuple;
-
- tuple = SearchSysCache1(CLAOID, ObjectIdGetDatum(opclasses[i]));
- if (!HeapTupleIsValid(tuple))
- elog(ERROR, "cache lookup failed for operator class %u", opclasses[i]);
-
ereport(ERROR,
errcode(ERRCODE_UNDEFINED_OBJECT),
for_overlaps
? errmsg("could not identify an overlaps operator for foreign key")
: errmsg("could not identify an equality operator for foreign key"),
- errdetail("Could not translate compare type %d for operator class \"%s\" for access method \"%s\".",
- cmptype, NameStr(((Form_pg_opclass) GETSTRUCT(tuple))->opcname), "gist"));
- }
+ errdetail("Could not translate compare type %d for operator family \"%s\", input type %s, access method \"%s\".",
+ cmptype, get_opfamily_name(opfamily, false), format_type_be(opcintype), get_am_name(amid)));
}
else
{
* other index AMs support unique indexes. If we ever did have
* other types of unique indexes, we'd need a way to determine
* which operator strategy number is equality. (We could use
- * something like GistTranslateCompareType.)
+ * IndexAmTranslateCompareType.)
*/
if (amid != BTREE_AM_OID)
elog(ERROR, "only b-tree indexes are supported for foreign keys");
static bool tuples_equal(TupleTableSlot *slot1, TupleTableSlot *slot2,
TypeCacheEntry **eq);
-/*
- * Returns the fixed strategy number, if any, of the equality operator for the
- * given operator class, otherwise, InvalidStrategy.
- */
-StrategyNumber
-get_equal_strategy_number(Oid opclass)
-{
- Oid am = get_opclass_method(opclass);
- int ret;
-
- switch (am)
- {
- case BTREE_AM_OID:
- ret = BTEqualStrategyNumber;
- break;
- case HASH_AM_OID:
- ret = HTEqualStrategyNumber;
- break;
- case GIST_AM_OID:
- ret = GistTranslateCompareType(opclass, COMPARE_EQ);
- break;
- default:
- ret = InvalidStrategy;
- break;
- }
-
- return ret;
-}
-
/*
* Setup a ScanKey for a search in the relation 'rel' for a tuple 'key' that
* is setup to match 'rel' (*NOT* idxrel!).
*/
optype = get_opclass_input_type(opclass->values[index_attoff]);
opfamily = get_opclass_family(opclass->values[index_attoff]);
- eq_strategy = get_equal_strategy_number(opclass->values[index_attoff]);
- if (!eq_strategy)
- elog(ERROR, "missing equal strategy for opclass %u", opclass->values[index_attoff]);
-
+ eq_strategy = IndexAmTranslateCompareType(COMPARE_EQ, idxrel->rd_rel->relam, opfamily, optype, false);
operator = get_opfamily_member(opfamily, optype,
optype,
eq_strategy);
#include "replication/logicalrelation.h"
#include "replication/worker_internal.h"
#include "utils/inval.h"
+#include "utils/lsyscache.h"
#include "utils/syscache.h"
/* Ensure that the index has a valid equal strategy for each key column */
for (int i = 0; i < idxrel->rd_index->indnkeyatts; i++)
{
- if (get_equal_strategy_number(indclass->values[i]) == InvalidStrategy)
+ 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)
return false;
}
do { (e).key = (k); (e).rel = (r); (e).page = (pg); \
(e).offset = (o); (e).leafkey = (l); } while (0)
-extern StrategyNumber GistTranslateCompareType(Oid opclass, CompareType cmptype);
+extern StrategyNumber gisttranslatecmptype(CompareType cmptype, Oid opfamily, Oid opcintype);
#endif /* GIST_H */
/*
* prototypes from functions in execReplication.c
*/
-extern StrategyNumber get_equal_strategy_number(Oid opclass);
extern bool RelationFindReplTupleByIndex(Relation rel, Oid idxoid,
LockTupleMode lockmode,
TupleTableSlot *searchslot,