@@ -1249,6 +1249,7 @@ list_member_strip(List *list, Expr *datum)
12491249 * and in addition we use (6) to represent <>.<> is not a btree-indexable
12501250 * operator, but we assume here that if an equality operator of a btree
12511251 * opfamily has a negator operator, the negator behaves as <> for the opfamily.
1252+ * (This convention is also known to get_op_btree_interpretation().)
12521253 *
12531254 * The interpretation of:
12541255 *
@@ -1285,7 +1286,7 @@ list_member_strip(List *list, Expr *datum)
12851286#define BTEQ BTEqualStrategyNumber
12861287#define BTGE BTGreaterEqualStrategyNumber
12871288#define BTGT BTGreaterStrategyNumber
1288- #define BTNE 6
1289+ #define BTNE ROWCOMPARE_NE
12891290
12901291static const StrategyNumber BT_implic_table [6 ][6 ]= {
12911292/*
@@ -1556,18 +1557,12 @@ get_btree_test_op(Oid pred_op, Oid clause_op, bool refute_it)
15561557OprProofCacheKey key ;
15571558OprProofCacheEntry * cache_entry ;
15581559bool cfound ;
1559- bool pred_op_negated ;
1560- Oid pred_op_negator ,
1561- clause_op_negator ,
1562- test_op = InvalidOid ;
1563- Oid opfamily_id ;
1560+ Oid test_op = InvalidOid ;
15641561bool found = false;
1565- StrategyNumber pred_strategy ,
1566- clause_strategy ,
1567- test_strategy ;
1568- Oid clause_righttype ;
1569- CatCList * catlist ;
1570- int i ;
1562+ List * pred_op_infos ,
1563+ * clause_op_infos ;
1564+ ListCell * lcp ,
1565+ * lcc ;
15711566
15721567/*
15731568 * 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)
16281623 * corresponding test operator. This should work for any logically
16291624 * consistent opfamilies.
16301625 */
1631- catlist = SearchSysCacheList1 (AMOPOPID ,ObjectIdGetDatum (pred_op ));
1626+ clause_op_infos = get_op_btree_interpretation (clause_op );
1627+ if (clause_op_infos )
1628+ pred_op_infos = get_op_btree_interpretation (pred_op );
1629+ else /* no point in looking */
1630+ pred_op_infos = NIL ;
16321631
1633- /*
1634- * If we couldn't find any opfamily containing the pred_op, perhaps it is
1635- * a <> operator. See if it has a negator that is in an opfamily.
1636- */
1637- pred_op_negated = false;
1638- if (catlist -> n_members == 0 )
1632+ foreach (lcp ,pred_op_infos )
16391633{
1640- pred_op_negator = get_negator (pred_op );
1641- if (OidIsValid (pred_op_negator ))
1642- {
1643- pred_op_negated = true;
1644- ReleaseSysCacheList (catlist );
1645- catlist = SearchSysCacheList1 (AMOPOPID ,
1646- ObjectIdGetDatum (pred_op_negator ));
1647- }
1648- }
1634+ OpBtreeInterpretation * pred_op_info = lfirst (lcp );
1635+ Oid opfamily_id = pred_op_info -> opfamily_id ;
16491636
1650- /* Also may need the clause_op's negator */
1651- clause_op_negator = get_negator (clause_op );
1637+ foreach (lcc ,clause_op_infos )
1638+ {
1639+ OpBtreeInterpretation * clause_op_info = lfirst (lcc );
1640+ StrategyNumber pred_strategy ,
1641+ clause_strategy ,
1642+ test_strategy ;
16521643
1653- /* Now search the opfamilies */
1654- for (i = 0 ;i < catlist -> n_members ;i ++ )
1655- {
1656- HeapTuple pred_tuple = & catlist -> members [i ]-> tuple ;
1657- Form_pg_amop pred_form = (Form_pg_amop )GETSTRUCT (pred_tuple );
1658- HeapTuple clause_tuple ;
1644+ /* Must find them in same opfamily */
1645+ if (opfamily_id != clause_op_info -> opfamily_id )
1646+ continue ;
1647+ /* Lefttypes should match */
1648+ Assert (clause_op_info -> oplefttype == pred_op_info -> oplefttype );
16591649
1660- /* Must be btree */
1661- if (pred_form -> amopmethod != BTREE_AM_OID )
1662- continue ;
1650+ pred_strategy = pred_op_info -> strategy ;
1651+ clause_strategy = clause_op_info -> strategy ;
16631652
1664- /* Get the predicate operator's btree strategy number */
1665- opfamily_id = pred_form -> amopfamily ;
1666- pred_strategy = (StrategyNumber )pred_form -> amopstrategy ;
1667- Assert (pred_strategy >=1 && pred_strategy <=5 );
1653+ /*
1654+ * Look up the "test" strategy number in the implication table
1655+ */
1656+ if (refute_it )
1657+ test_strategy = BT_refute_table [clause_strategy - 1 ][pred_strategy - 1 ];
1658+ else
1659+ test_strategy = BT_implic_table [clause_strategy - 1 ][pred_strategy - 1 ];
16681660
1669- if (pred_op_negated )
1670- {
1671- /* Only consider negators that are = */
1672- if (pred_strategy != BTEqualStrategyNumber )
1661+ if (test_strategy == 0 )
1662+ {
1663+ /* Can't determine implication using this interpretation */
16731664continue ;
1674- pred_strategy = BTNE ;
1675- }
1665+ }
16761666
1677- /*
1678- * From the same opfamily, find a strategy number for the clause_op,
1679- * if possible
1680- */
1681- clause_tuple = SearchSysCache3 (AMOPOPID ,
1682- ObjectIdGetDatum (clause_op ),
1683- CharGetDatum (AMOP_SEARCH ),
1684- ObjectIdGetDatum (opfamily_id ));
1685- if (HeapTupleIsValid (clause_tuple ))
1686- {
1687- Form_pg_amop clause_form = (Form_pg_amop )GETSTRUCT (clause_tuple );
1688-
1689- /* Get the restriction clause operator's strategy/datatype */
1690- clause_strategy = (StrategyNumber )clause_form -> amopstrategy ;
1691- Assert (clause_strategy >=1 && clause_strategy <=5 );
1692- Assert (clause_form -> amoplefttype == pred_form -> amoplefttype );
1693- clause_righttype = clause_form -> amoprighttype ;
1694- ReleaseSysCache (clause_tuple );
1695- }
1696- else if (OidIsValid (clause_op_negator ))
1697- {
1698- clause_tuple = SearchSysCache3 (AMOPOPID ,
1699- ObjectIdGetDatum (clause_op_negator ),
1700- CharGetDatum (AMOP_SEARCH ),
1701- ObjectIdGetDatum (opfamily_id ));
1702- if (HeapTupleIsValid (clause_tuple ))
1667+ /*
1668+ * See if opfamily has an operator for the test strategy and the
1669+ * datatypes.
1670+ */
1671+ if (test_strategy == BTNE )
17031672{
1704- Form_pg_amop clause_form = (Form_pg_amop )GETSTRUCT (clause_tuple );
1705-
1706- /* Get the restriction clause operator's strategy/datatype */
1707- clause_strategy = (StrategyNumber )clause_form -> amopstrategy ;
1708- Assert (clause_strategy >=1 && clause_strategy <=5 );
1709- Assert (clause_form -> amoplefttype == pred_form -> amoplefttype );
1710- clause_righttype = clause_form -> amoprighttype ;
1711- ReleaseSysCache (clause_tuple );
1712-
1713- /* Only consider negators that are = */
1714- if (clause_strategy != BTEqualStrategyNumber )
1715- continue ;
1716- clause_strategy = BTNE ;
1673+ test_op = get_opfamily_member (opfamily_id ,
1674+ pred_op_info -> oprighttype ,
1675+ clause_op_info -> oprighttype ,
1676+ BTEqualStrategyNumber );
1677+ if (OidIsValid (test_op ))
1678+ test_op = get_negator (test_op );
17171679}
17181680else
1719- continue ;
1720- }
1721- else
1722- continue ;
1723-
1724- /*
1725- * Look up the "test" strategy number in the implication table
1726- */
1727- if (refute_it )
1728- test_strategy = BT_refute_table [clause_strategy - 1 ][pred_strategy - 1 ];
1729- else
1730- test_strategy = BT_implic_table [clause_strategy - 1 ][pred_strategy - 1 ];
1681+ {
1682+ test_op = get_opfamily_member (opfamily_id ,
1683+ pred_op_info -> oprighttype ,
1684+ clause_op_info -> oprighttype ,
1685+ test_strategy );
1686+ }
17311687
1732- if (test_strategy == 0 )
1733- {
1734- /* Can't determine implication using this interpretation */
1735- continue ;
1736- }
1688+ if (!OidIsValid (test_op ))
1689+ continue ;
17371690
1738- /*
1739- * See if opfamily has an operator for the test strategy and the
1740- * datatypes.
1741- */
1742- if (test_strategy == BTNE )
1743- {
1744- test_op = get_opfamily_member (opfamily_id ,
1745- pred_form -> amoprighttype ,
1746- clause_righttype ,
1747- BTEqualStrategyNumber );
1748- if (OidIsValid (test_op ))
1749- test_op = get_negator (test_op );
1750- }
1751- else
1752- {
1753- test_op = get_opfamily_member (opfamily_id ,
1754- pred_form -> amoprighttype ,
1755- clause_righttype ,
1756- test_strategy );
1757- }
1758- if (OidIsValid (test_op ))
1759- {
17601691/*
17611692 * Last check: test_op must be immutable.
17621693 *
@@ -1772,9 +1703,13 @@ get_btree_test_op(Oid pred_op, Oid clause_op, bool refute_it)
17721703break ;
17731704}
17741705}
1706+
1707+ if (found )
1708+ break ;
17751709}
17761710
1777- ReleaseSysCacheList (catlist );
1711+ list_free_deep (pred_op_infos );
1712+ list_free_deep (clause_op_infos );
17781713
17791714if (!found )
17801715{