Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit cb1cc30

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 f8bd267 commit cb1cc30

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
@@ -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

12901291
static 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)
15561557
OprProofCacheKey key;
15571558
OprProofCacheEntry *cache_entry;
15581559
bool 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;
15641561
bool 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 */
16731664
continue;
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
}
17181680
else
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)
17721703
break;
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

17791714
if (!found)
17801715
{

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)