Quan Zongliang <[email protected]> writes:
> New patch attached.
> It seems that partitions do not use AM other than btree and hash.
> Rewrite only indxpath.c and check if it is a custom AM.
This seems drastically underdocumented, and the test you're using
for extension opclasses is wrong. What we need to know before
applying match_boolean_index_clause is that a clause using
BooleanEqualOperator will be valid for the index. That's got next
door to nothing to do with whether the opclass is default for
the index AM. A non-default opclass might support that operator,
and conversely a default one might not (although I concede it's
not that easy to imagine what other set of operators-on-boolean
an extension opclass might be interested in).
I think we need something more like the attached.
regards, tom lane
diff --git a/src/backend/optimizer/path/indxpath.c b/src/backend/optimizer/path/indxpath.c
index 045ff2e487..63a8eef45c 100644
--- a/src/backend/optimizer/path/indxpath.c
+++ b/src/backend/optimizer/path/indxpath.c
@@ -153,6 +153,7 @@ static IndexClause *match_clause_to_indexcol(PlannerInfo *root,
RestrictInfo *rinfo,
int indexcol,
IndexOptInfo *index);
+static bool IsBooleanOpfamily(Oid opfamily);
static IndexClause *match_boolean_index_clause(PlannerInfo *root,
RestrictInfo *rinfo,
int indexcol, IndexOptInfo *index);
@@ -2342,6 +2343,23 @@ match_clause_to_indexcol(PlannerInfo *root,
return NULL;
}
+/*
+ * IsBooleanOpfamily
+ * Detect whether an opfamily supports boolean equality as an operator.
+ *
+ * If the opfamily OID is in the range of built-in objects, we can rely
+ * on hard-wired knowledge of which built-in opfamilies support this.
+ * For extension opfamilies, there's no choice but to do a catcache lookup.
+ */
+static bool
+IsBooleanOpfamily(Oid opfamily)
+{
+ if (opfamily < FirstNormalObjectId)
+ return IsBuiltinBooleanOpfamily(opfamily);
+ else
+ return op_in_opfamily(BooleanEqualOperator, opfamily);
+}
+
/*
* match_boolean_index_clause
* Recognize restriction clauses that can be matched to a boolean index.
diff --git a/src/backend/optimizer/path/pathkeys.c b/src/backend/optimizer/path/pathkeys.c
index 1fa7fc99b5..b9c1ce0a64 100644
--- a/src/backend/optimizer/path/pathkeys.c
+++ b/src/backend/optimizer/path/pathkeys.c
@@ -1191,8 +1191,13 @@ partkey_is_bool_constant_for_query(RelOptInfo *partrel, int partkeycol)
PartitionScheme partscheme = partrel->part_scheme;
ListCell *lc;
- /* If the partkey isn't boolean, we can't possibly get a match */
- if (!IsBooleanOpfamily(partscheme->partopfamily[partkeycol]))
+ /*
+ * If the partkey isn't boolean, we can't possibly get a match.
+ *
+ * Partitioning currently can only use built-in AMs, so checking for
+ * built-in boolean opclasses is good enough.
+ */
+ if (!IsBuiltinBooleanOpfamily(partscheme->partopfamily[partkeycol]))
return false;
/* Check each restriction clause for the partitioned rel */
diff --git a/src/backend/partitioning/partprune.c b/src/backend/partitioning/partprune.c
index bf9fe5b7aa..b5403149d7 100644
--- a/src/backend/partitioning/partprune.c
+++ b/src/backend/partitioning/partprune.c
@@ -3596,7 +3596,11 @@ match_boolean_partition_clause(Oid partopfamily, Expr *clause, Expr *partkey,
*outconst = NULL;
- if (!IsBooleanOpfamily(partopfamily))
+ /*
+ * Partitioning currently can only use built-in AMs, so checking for
+ * built-in boolean opclasses is good enough.
+ */
+ if (!IsBuiltinBooleanOpfamily(partopfamily))
return PARTCLAUSE_UNSUPPORTED;
if (IsA(clause, BooleanTest))
diff --git a/src/include/catalog/pg_opfamily.h b/src/include/catalog/pg_opfamily.h
index 8dc9ce01bb..b56d714322 100644
--- a/src/include/catalog/pg_opfamily.h
+++ b/src/include/catalog/pg_opfamily.h
@@ -55,7 +55,8 @@ DECLARE_UNIQUE_INDEX_PKEY(pg_opfamily_oid_index, 2755, OpfamilyOidIndexId, on pg
#ifdef EXPOSE_TO_CLIENT_CODE
-#define IsBooleanOpfamily(opfamily) \
+/* This does not account for non-core opclasses that might accept boolean */
+#define IsBuiltinBooleanOpfamily(opfamily) \
((opfamily) == BOOL_BTREE_FAM_OID || (opfamily) == BOOL_HASH_FAM_OID)
#endif /* EXPOSE_TO_CLIENT_CODE */