Skip to content

Commit 14f6719

Browse files
committed
Remove assumptions that not-equals operators cannot be in any opclass.
get_op_btree_interpretation assumed this in order to save some duplication of code, but it's not true in general anymore because we added <> support to btree_gist. (We still assume it for btree opclasses, though.) Also, essentially the same logic was baked into predtest.c. Get rid of that duplication by generalizing get_op_btree_interpretation so that it can be used by predtest.c. Per bug report from Denis de Bernardy and investigation by Jeff Davis, though I didn't use Jeff's patch exactly as-is. Back-patch to 9.1; we do not support this usage before that.
1 parent c7f2349 commit 14f6719

File tree

4 files changed

+145
-181
lines changed

4 files changed

+145
-181
lines changed

src/backend/optimizer/util/predtest.c

Lines changed: 63 additions & 128 deletions
Original file line numberDiff line numberDiff line change
@@ -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

12911292
static 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
{

src/backend/parser/parse_expr.c

Lines changed: 13 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -2170,8 +2170,7 @@ make_row_comparison_op(ParseState *pstate, List *opname,
21702170
List *opfamilies;
21712171
ListCell *l,
21722172
*r;
2173-
List **opfamily_lists;
2174-
List **opstrat_lists;
2173+
List **opinfo_lists;
21752174
Bitmapset *strats;
21762175
int nopers;
21772176
int i;
@@ -2241,8 +2240,7 @@ make_row_comparison_op(ParseState *pstate, List *opname,
22412240
* containing the operators, and see which interpretations (strategy
22422241
* numbers) exist for each operator.
22432242
*/
2244-
opfamily_lists = (List **) palloc(nopers * sizeof(List *));
2245-
opstrat_lists = (List **) palloc(nopers * sizeof(List *));
2243+
opinfo_lists = (List **) palloc(nopers * sizeof(List *));
22462244
strats = NULL;
22472245
i = 0;
22482246
foreach(l, opexprs)
@@ -2251,17 +2249,18 @@ make_row_comparison_op(ParseState *pstate, List *opname,
22512249
Bitmapset *this_strats;
22522250
ListCell *j;
22532251

2254-
get_op_btree_interpretation(opno,
2255-
&opfamily_lists[i], &opstrat_lists[i]);
2252+
opinfo_lists[i] = get_op_btree_interpretation(opno);
22562253

22572254
/*
2258-
* convert strategy number list to a Bitmapset to make the
2255+
* convert strategy numbers into a Bitmapset to make the
22592256
* intersection calculation easy.
22602257
*/
22612258
this_strats = NULL;
2262-
foreach(j, opstrat_lists[i])
2259+
foreach(j, opinfo_lists[i])
22632260
{
2264-
this_strats = bms_add_member(this_strats, lfirst_int(j));
2261+
OpBtreeInterpretation *opinfo = lfirst(j);
2262+
2263+
this_strats = bms_add_member(this_strats, opinfo->strategy);
22652264
}
22662265
if (i == 0)
22672266
strats = this_strats;
@@ -2309,14 +2308,15 @@ make_row_comparison_op(ParseState *pstate, List *opname,
23092308
for (i = 0; i < nopers; i++)
23102309
{
23112310
Oid opfamily = InvalidOid;
2311+
ListCell *j;
23122312

2313-
forboth(l, opfamily_lists[i], r, opstrat_lists[i])
2313+
foreach(j, opinfo_lists[i])
23142314
{
2315-
int opstrat = lfirst_int(r);
2315+
OpBtreeInterpretation *opinfo = lfirst(j);
23162316

2317-
if (opstrat == rctype)
2317+
if (opinfo->strategy == rctype)
23182318
{
2319-
opfamily = lfirst_oid(l);
2319+
opfamily = opinfo->opfamily_id;
23202320
break;
23212321
}
23222322
}

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy