Location via proxy:   [ UP ]  
[Report a bug]   [Manage cookies]                
Skip to content

Commit 507b53c

Browse files
committed
Fix predicate-proving logic to cope with binary-compatibility cases when
checking whether an IS NULL/IS NOT NULL clause is implied or refuted by a strict function. Per example from Dawid Kuroczko. Backpatch to 8.2 since this is arguably a performance bug.
1 parent f903278 commit 507b53c

File tree

1 file changed

+36
-5
lines changed

1 file changed

+36
-5
lines changed

src/backend/optimizer/util/predtest.c

+36-5
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99
*
1010
*
1111
* IDENTIFICATION
12-
* $PostgreSQL: pgsql/src/backend/optimizer/util/predtest.c,v 1.15 2007/05/12 19:22:35 tgl Exp $
12+
* $PostgreSQL: pgsql/src/backend/optimizer/util/predtest.c,v 1.16 2007/07/24 17:22:07 tgl Exp $
1313
*
1414
*-------------------------------------------------------------------------
1515
*/
@@ -84,6 +84,7 @@ static bool predicate_implied_by_simple_clause(Expr *predicate, Node *clause);
8484
static bool predicate_refuted_by_simple_clause(Expr *predicate, Node *clause);
8585
static bool is_null_contradicts(NullTest *ntest, Node *clause);
8686
static Node *extract_not_arg(Node *clause);
87+
static bool list_member_strip(List *list, Expr *datum);
8788
static bool btree_predicate_proof(Expr *predicate, Node *clause,
8889
bool refute_it);
8990

@@ -961,11 +962,11 @@ predicate_implied_by_simple_clause(Expr *predicate, Node *clause)
961962
if (!type_is_rowtype(exprType((Node *) nonnullarg)))
962963
{
963964
if (is_opclause(clause) &&
964-
list_member(((OpExpr *) clause)->args, nonnullarg) &&
965+
list_member_strip(((OpExpr *) clause)->args, nonnullarg) &&
965966
op_strict(((OpExpr *) clause)->opno))
966967
return true;
967968
if (is_funcclause(clause) &&
968-
list_member(((FuncExpr *) clause)->args, nonnullarg) &&
969+
list_member_strip(((FuncExpr *) clause)->args, nonnullarg) &&
969970
func_strict(((FuncExpr *) clause)->funcid))
970971
return true;
971972
}
@@ -1044,11 +1045,11 @@ is_null_contradicts(NullTest *ntest, Node *clause)
10441045

10451046
/* foo IS NULL contradicts any strict op/func on foo */
10461047
if (is_opclause(clause) &&
1047-
list_member(((OpExpr *) clause)->args, isnullarg) &&
1048+
list_member_strip(((OpExpr *) clause)->args, isnullarg) &&
10481049
op_strict(((OpExpr *) clause)->opno))
10491050
return true;
10501051
if (is_funcclause(clause) &&
1051-
list_member(((FuncExpr *) clause)->args, isnullarg) &&
1052+
list_member_strip(((FuncExpr *) clause)->args, isnullarg) &&
10521053
func_strict(((FuncExpr *) clause)->funcid))
10531054
return true;
10541055

@@ -1091,6 +1092,36 @@ extract_not_arg(Node *clause)
10911092
}
10921093

10931094

1095+
/*
1096+
* Check whether an Expr is equal() to any member of a list, ignoring
1097+
* any top-level RelabelType nodes. This is legitimate for the purposes
1098+
* we use it for (matching IS [NOT] NULL arguments to arguments of strict
1099+
* functions) because RelabelType doesn't change null-ness. It's helpful
1100+
* for cases such as a varchar argument of a strict function on text.
1101+
*/
1102+
static bool
1103+
list_member_strip(List *list, Expr *datum)
1104+
{
1105+
ListCell *cell;
1106+
1107+
if (datum && IsA(datum, RelabelType))
1108+
datum = ((RelabelType *) datum)->arg;
1109+
1110+
foreach(cell, list)
1111+
{
1112+
Expr *elem = (Expr *) lfirst(cell);
1113+
1114+
if (elem && IsA(elem, RelabelType))
1115+
elem = ((RelabelType *) elem)->arg;
1116+
1117+
if (equal(elem, datum))
1118+
return true;
1119+
}
1120+
1121+
return false;
1122+
}
1123+
1124+
10941125
/*
10951126
* Define an "operator implication table" for btree operators ("strategies"),
10961127
* and a similar table for refutation.

0 commit comments

Comments
 (0)