@@ -1250,6 +1250,7 @@ list_member_strip(List *list, Expr *datum)
12501250 * and in addition we use (6) to represent <>. <> is not a btree-indexable
12511251 * operator, but we assume here that if an equality operator of a btree
12521252 * opfamily has a negator operator, the negator behaves as <> for the opfamily.
1253+ * (This convention is also known to get_op_btree_interpretation().)
12531254 *
12541255 * The interpretation of:
12551256 *
@@ -1286,7 +1287,7 @@ list_member_strip(List *list, Expr *datum)
12861287#define BTEQ BTEqualStrategyNumber
12871288#define BTGE BTGreaterEqualStrategyNumber
12881289#define BTGT BTGreaterStrategyNumber
1289- #define BTNE 6
1290+ #define BTNE ROWCOMPARE_NE
12901291
12911292static const StrategyNumber BT_implic_table [6 ][6 ] = {
12921293/*
@@ -1557,18 +1558,12 @@ get_btree_test_op(Oid pred_op, Oid clause_op, bool refute_it)
15571558 OprProofCacheKey key ;
15581559 OprProofCacheEntry * cache_entry ;
15591560 bool cfound ;
1560- bool pred_op_negated ;
1561- Oid pred_op_negator ,
1562- clause_op_negator ,
1563- test_op = InvalidOid ;
1564- Oid opfamily_id ;
1561+ Oid test_op = InvalidOid ;
15651562 bool found = false;
1566- StrategyNumber pred_strategy ,
1567- clause_strategy ,
1568- test_strategy ;
1569- Oid clause_righttype ;
1570- CatCList * catlist ;
1571- int i ;
1563+ List * pred_op_infos ,
1564+ * clause_op_infos ;
1565+ ListCell * lcp ,
1566+ * lcc ;
15721567
15731568 /*
15741569 * Find or make a cache entry for this pair of operators.
@@ -1629,135 +1624,71 @@ get_btree_test_op(Oid pred_op, Oid clause_op, bool refute_it)
16291624 * corresponding test operator. This should work for any logically
16301625 * consistent opfamilies.
16311626 */
1632- catlist = SearchSysCacheList1 (AMOPOPID , ObjectIdGetDatum (pred_op ));
1627+ clause_op_infos = get_op_btree_interpretation (clause_op );
1628+ if (clause_op_infos )
1629+ pred_op_infos = get_op_btree_interpretation (pred_op );
1630+ else /* no point in looking */
1631+ pred_op_infos = NIL ;
16331632
1634- /*
1635- * If we couldn't find any opfamily containing the pred_op, perhaps it is
1636- * a <> operator. See if it has a negator that is in an opfamily.
1637- */
1638- pred_op_negated = false;
1639- if (catlist -> n_members == 0 )
1633+ foreach (lcp , pred_op_infos )
16401634 {
1641- pred_op_negator = get_negator (pred_op );
1642- if (OidIsValid (pred_op_negator ))
1643- {
1644- pred_op_negated = true;
1645- ReleaseSysCacheList (catlist );
1646- catlist = SearchSysCacheList1 (AMOPOPID ,
1647- ObjectIdGetDatum (pred_op_negator ));
1648- }
1649- }
1635+ OpBtreeInterpretation * pred_op_info = lfirst (lcp );
1636+ Oid opfamily_id = pred_op_info -> opfamily_id ;
16501637
1651- /* Also may need the clause_op's negator */
1652- clause_op_negator = get_negator (clause_op );
1638+ foreach (lcc , clause_op_infos )
1639+ {
1640+ OpBtreeInterpretation * clause_op_info = lfirst (lcc );
1641+ StrategyNumber pred_strategy ,
1642+ clause_strategy ,
1643+ test_strategy ;
16531644
1654- /* Now search the opfamilies */
1655- for (i = 0 ; i < catlist -> n_members ; i ++ )
1656- {
1657- HeapTuple pred_tuple = & catlist -> members [i ]-> tuple ;
1658- Form_pg_amop pred_form = (Form_pg_amop ) GETSTRUCT (pred_tuple );
1659- HeapTuple clause_tuple ;
1645+ /* Must find them in same opfamily */
1646+ if (opfamily_id != clause_op_info -> opfamily_id )
1647+ continue ;
1648+ /* Lefttypes should match */
1649+ Assert (clause_op_info -> oplefttype == pred_op_info -> oplefttype );
16601650
1661- /* Must be btree */
1662- if (pred_form -> amopmethod != BTREE_AM_OID )
1663- continue ;
1651+ pred_strategy = pred_op_info -> strategy ;
1652+ clause_strategy = clause_op_info -> strategy ;
16641653
1665- /* Get the predicate operator's btree strategy number */
1666- opfamily_id = pred_form -> amopfamily ;
1667- pred_strategy = (StrategyNumber ) pred_form -> amopstrategy ;
1668- Assert (pred_strategy >= 1 && pred_strategy <= 5 );
1654+ /*
1655+ * Look up the "test" strategy number in the implication table
1656+ */
1657+ if (refute_it )
1658+ test_strategy = BT_refute_table [clause_strategy - 1 ][pred_strategy - 1 ];
1659+ else
1660+ test_strategy = BT_implic_table [clause_strategy - 1 ][pred_strategy - 1 ];
16691661
1670- if (pred_op_negated )
1671- {
1672- /* Only consider negators that are = */
1673- if (pred_strategy != BTEqualStrategyNumber )
1662+ if (test_strategy == 0 )
1663+ {
1664+ /* Can't determine implication using this interpretation */
16741665 continue ;
1675- pred_strategy = BTNE ;
1676- }
1666+ }
16771667
1678- /*
1679- * From the same opfamily, find a strategy number for the clause_op,
1680- * if possible
1681- */
1682- clause_tuple = SearchSysCache3 (AMOPOPID ,
1683- ObjectIdGetDatum (clause_op ),
1684- CharGetDatum (AMOP_SEARCH ),
1685- ObjectIdGetDatum (opfamily_id ));
1686- if (HeapTupleIsValid (clause_tuple ))
1687- {
1688- Form_pg_amop clause_form = (Form_pg_amop ) GETSTRUCT (clause_tuple );
1689-
1690- /* Get the restriction clause operator's strategy/datatype */
1691- clause_strategy = (StrategyNumber ) clause_form -> amopstrategy ;
1692- Assert (clause_strategy >= 1 && clause_strategy <= 5 );
1693- Assert (clause_form -> amoplefttype == pred_form -> amoplefttype );
1694- clause_righttype = clause_form -> amoprighttype ;
1695- ReleaseSysCache (clause_tuple );
1696- }
1697- else if (OidIsValid (clause_op_negator ))
1698- {
1699- clause_tuple = SearchSysCache3 (AMOPOPID ,
1700- ObjectIdGetDatum (clause_op_negator ),
1701- CharGetDatum (AMOP_SEARCH ),
1702- ObjectIdGetDatum (opfamily_id ));
1703- if (HeapTupleIsValid (clause_tuple ))
1668+ /*
1669+ * See if opfamily has an operator for the test strategy and the
1670+ * datatypes.
1671+ */
1672+ if (test_strategy == BTNE )
17041673 {
1705- Form_pg_amop clause_form = (Form_pg_amop ) GETSTRUCT (clause_tuple );
1706-
1707- /* Get the restriction clause operator's strategy/datatype */
1708- clause_strategy = (StrategyNumber ) clause_form -> amopstrategy ;
1709- Assert (clause_strategy >= 1 && clause_strategy <= 5 );
1710- Assert (clause_form -> amoplefttype == pred_form -> amoplefttype );
1711- clause_righttype = clause_form -> amoprighttype ;
1712- ReleaseSysCache (clause_tuple );
1713-
1714- /* Only consider negators that are = */
1715- if (clause_strategy != BTEqualStrategyNumber )
1716- continue ;
1717- clause_strategy = BTNE ;
1674+ test_op = get_opfamily_member (opfamily_id ,
1675+ pred_op_info -> oprighttype ,
1676+ clause_op_info -> oprighttype ,
1677+ BTEqualStrategyNumber );
1678+ if (OidIsValid (test_op ))
1679+ test_op = get_negator (test_op );
17181680 }
17191681 else
1720- continue ;
1721- }
1722- else
1723- continue ;
1724-
1725- /*
1726- * Look up the "test" strategy number in the implication table
1727- */
1728- if (refute_it )
1729- test_strategy = BT_refute_table [clause_strategy - 1 ][pred_strategy - 1 ];
1730- else
1731- test_strategy = BT_implic_table [clause_strategy - 1 ][pred_strategy - 1 ];
1682+ {
1683+ test_op = get_opfamily_member (opfamily_id ,
1684+ pred_op_info -> oprighttype ,
1685+ clause_op_info -> oprighttype ,
1686+ test_strategy );
1687+ }
17321688
1733- if (test_strategy == 0 )
1734- {
1735- /* Can't determine implication using this interpretation */
1736- continue ;
1737- }
1689+ if (!OidIsValid (test_op ))
1690+ continue ;
17381691
1739- /*
1740- * See if opfamily has an operator for the test strategy and the
1741- * datatypes.
1742- */
1743- if (test_strategy == BTNE )
1744- {
1745- test_op = get_opfamily_member (opfamily_id ,
1746- pred_form -> amoprighttype ,
1747- clause_righttype ,
1748- BTEqualStrategyNumber );
1749- if (OidIsValid (test_op ))
1750- test_op = get_negator (test_op );
1751- }
1752- else
1753- {
1754- test_op = get_opfamily_member (opfamily_id ,
1755- pred_form -> amoprighttype ,
1756- clause_righttype ,
1757- test_strategy );
1758- }
1759- if (OidIsValid (test_op ))
1760- {
17611692 /*
17621693 * Last check: test_op must be immutable.
17631694 *
@@ -1773,9 +1704,13 @@ get_btree_test_op(Oid pred_op, Oid clause_op, bool refute_it)
17731704 break ;
17741705 }
17751706 }
1707+
1708+ if (found )
1709+ break ;
17761710 }
17771711
1778- ReleaseSysCacheList (catlist );
1712+ list_free_deep (pred_op_infos );
1713+ list_free_deep (clause_op_infos );
17791714
17801715 if (!found )
17811716 {
0 commit comments