aboutsummaryrefslogtreecommitdiff
path: root/src/backend/optimizer/util/predtest.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/backend/optimizer/util/predtest.c')
-rw-r--r--src/backend/optimizer/util/predtest.c191
1 files changed, 63 insertions, 128 deletions
diff --git a/src/backend/optimizer/util/predtest.c b/src/backend/optimizer/util/predtest.c
index a7e83729b1b..bbfbc7947b1 100644
--- a/src/backend/optimizer/util/predtest.c
+++ b/src/backend/optimizer/util/predtest.c
@@ -1249,6 +1249,7 @@ list_member_strip(List *list, Expr *datum)
* and in addition we use (6) to represent <>. <> is not a btree-indexable
* operator, but we assume here that if an equality operator of a btree
* opfamily has a negator operator, the negator behaves as <> for the opfamily.
+ * (This convention is also known to get_op_btree_interpretation().)
*
* The interpretation of:
*
@@ -1285,7 +1286,7 @@ list_member_strip(List *list, Expr *datum)
#define BTEQ BTEqualStrategyNumber
#define BTGE BTGreaterEqualStrategyNumber
#define BTGT BTGreaterStrategyNumber
-#define BTNE 6
+#define BTNE ROWCOMPARE_NE
static const StrategyNumber BT_implic_table[6][6] = {
/*
@@ -1556,18 +1557,12 @@ get_btree_test_op(Oid pred_op, Oid clause_op, bool refute_it)
OprProofCacheKey key;
OprProofCacheEntry *cache_entry;
bool cfound;
- bool pred_op_negated;
- Oid pred_op_negator,
- clause_op_negator,
- test_op = InvalidOid;
- Oid opfamily_id;
+ Oid test_op = InvalidOid;
bool found = false;
- StrategyNumber pred_strategy,
- clause_strategy,
- test_strategy;
- Oid clause_righttype;
- CatCList *catlist;
- int i;
+ List *pred_op_infos,
+ *clause_op_infos;
+ ListCell *lcp,
+ *lcc;
/*
* Find or make a cache entry for this pair of operators.
@@ -1628,135 +1623,71 @@ get_btree_test_op(Oid pred_op, Oid clause_op, bool refute_it)
* corresponding test operator. This should work for any logically
* consistent opfamilies.
*/
- catlist = SearchSysCacheList1(AMOPOPID, ObjectIdGetDatum(pred_op));
+ clause_op_infos = get_op_btree_interpretation(clause_op);
+ if (clause_op_infos)
+ pred_op_infos = get_op_btree_interpretation(pred_op);
+ else /* no point in looking */
+ pred_op_infos = NIL;
- /*
- * If we couldn't find any opfamily containing the pred_op, perhaps it is
- * a <> operator. See if it has a negator that is in an opfamily.
- */
- pred_op_negated = false;
- if (catlist->n_members == 0)
+ foreach(lcp, pred_op_infos)
{
- pred_op_negator = get_negator(pred_op);
- if (OidIsValid(pred_op_negator))
- {
- pred_op_negated = true;
- ReleaseSysCacheList(catlist);
- catlist = SearchSysCacheList1(AMOPOPID,
- ObjectIdGetDatum(pred_op_negator));
- }
- }
+ OpBtreeInterpretation *pred_op_info = lfirst(lcp);
+ Oid opfamily_id = pred_op_info->opfamily_id;
- /* Also may need the clause_op's negator */
- clause_op_negator = get_negator(clause_op);
+ foreach(lcc, clause_op_infos)
+ {
+ OpBtreeInterpretation *clause_op_info = lfirst(lcc);
+ StrategyNumber pred_strategy,
+ clause_strategy,
+ test_strategy;
- /* Now search the opfamilies */
- for (i = 0; i < catlist->n_members; i++)
- {
- HeapTuple pred_tuple = &catlist->members[i]->tuple;
- Form_pg_amop pred_form = (Form_pg_amop) GETSTRUCT(pred_tuple);
- HeapTuple clause_tuple;
+ /* Must find them in same opfamily */
+ if (opfamily_id != clause_op_info->opfamily_id)
+ continue;
+ /* Lefttypes should match */
+ Assert(clause_op_info->oplefttype == pred_op_info->oplefttype);
- /* Must be btree */
- if (pred_form->amopmethod != BTREE_AM_OID)
- continue;
+ pred_strategy = pred_op_info->strategy;
+ clause_strategy = clause_op_info->strategy;
- /* Get the predicate operator's btree strategy number */
- opfamily_id = pred_form->amopfamily;
- pred_strategy = (StrategyNumber) pred_form->amopstrategy;
- Assert(pred_strategy >= 1 && pred_strategy <= 5);
+ /*
+ * Look up the "test" strategy number in the implication table
+ */
+ if (refute_it)
+ test_strategy = BT_refute_table[clause_strategy - 1][pred_strategy - 1];
+ else
+ test_strategy = BT_implic_table[clause_strategy - 1][pred_strategy - 1];
- if (pred_op_negated)
- {
- /* Only consider negators that are = */
- if (pred_strategy != BTEqualStrategyNumber)
+ if (test_strategy == 0)
+ {
+ /* Can't determine implication using this interpretation */
continue;
- pred_strategy = BTNE;
- }
+ }
- /*
- * From the same opfamily, find a strategy number for the clause_op,
- * if possible
- */
- clause_tuple = SearchSysCache3(AMOPOPID,
- ObjectIdGetDatum(clause_op),
- CharGetDatum(AMOP_SEARCH),
- ObjectIdGetDatum(opfamily_id));
- if (HeapTupleIsValid(clause_tuple))
- {
- Form_pg_amop clause_form = (Form_pg_amop) GETSTRUCT(clause_tuple);
-
- /* Get the restriction clause operator's strategy/datatype */
- clause_strategy = (StrategyNumber) clause_form->amopstrategy;
- Assert(clause_strategy >= 1 && clause_strategy <= 5);
- Assert(clause_form->amoplefttype == pred_form->amoplefttype);
- clause_righttype = clause_form->amoprighttype;
- ReleaseSysCache(clause_tuple);
- }
- else if (OidIsValid(clause_op_negator))
- {
- clause_tuple = SearchSysCache3(AMOPOPID,
- ObjectIdGetDatum(clause_op_negator),
- CharGetDatum(AMOP_SEARCH),
- ObjectIdGetDatum(opfamily_id));
- if (HeapTupleIsValid(clause_tuple))
+ /*
+ * See if opfamily has an operator for the test strategy and the
+ * datatypes.
+ */
+ if (test_strategy == BTNE)
{
- Form_pg_amop clause_form = (Form_pg_amop) GETSTRUCT(clause_tuple);
-
- /* Get the restriction clause operator's strategy/datatype */
- clause_strategy = (StrategyNumber) clause_form->amopstrategy;
- Assert(clause_strategy >= 1 && clause_strategy <= 5);
- Assert(clause_form->amoplefttype == pred_form->amoplefttype);
- clause_righttype = clause_form->amoprighttype;
- ReleaseSysCache(clause_tuple);
-
- /* Only consider negators that are = */
- if (clause_strategy != BTEqualStrategyNumber)
- continue;
- clause_strategy = BTNE;
+ test_op = get_opfamily_member(opfamily_id,
+ pred_op_info->oprighttype,
+ clause_op_info->oprighttype,
+ BTEqualStrategyNumber);
+ if (OidIsValid(test_op))
+ test_op = get_negator(test_op);
}
else
- continue;
- }
- else
- continue;
-
- /*
- * Look up the "test" strategy number in the implication table
- */
- if (refute_it)
- test_strategy = BT_refute_table[clause_strategy - 1][pred_strategy - 1];
- else
- test_strategy = BT_implic_table[clause_strategy - 1][pred_strategy - 1];
+ {
+ test_op = get_opfamily_member(opfamily_id,
+ pred_op_info->oprighttype,
+ clause_op_info->oprighttype,
+ test_strategy);
+ }
- if (test_strategy == 0)
- {
- /* Can't determine implication using this interpretation */
- continue;
- }
+ if (!OidIsValid(test_op))
+ continue;
- /*
- * See if opfamily has an operator for the test strategy and the
- * datatypes.
- */
- if (test_strategy == BTNE)
- {
- test_op = get_opfamily_member(opfamily_id,
- pred_form->amoprighttype,
- clause_righttype,
- BTEqualStrategyNumber);
- if (OidIsValid(test_op))
- test_op = get_negator(test_op);
- }
- else
- {
- test_op = get_opfamily_member(opfamily_id,
- pred_form->amoprighttype,
- clause_righttype,
- test_strategy);
- }
- if (OidIsValid(test_op))
- {
/*
* Last check: test_op must be immutable.
*
@@ -1772,9 +1703,13 @@ get_btree_test_op(Oid pred_op, Oid clause_op, bool refute_it)
break;
}
}
+
+ if (found)
+ break;
}
- ReleaseSysCacheList(catlist);
+ list_free_deep(pred_op_infos);
+ list_free_deep(clause_op_infos);
if (!found)
{