diff options
Diffstat (limited to 'src/backend/optimizer/util/predtest.c')
-rw-r--r-- | src/backend/optimizer/util/predtest.c | 191 |
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) { |