mirror of
https://github.com/postgres/postgres.git
synced 2025-04-24 10:47:04 +03:00
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.
This commit is contained in:
parent
f903278e2d
commit
507b53c833
@ -9,7 +9,7 @@
|
|||||||
*
|
*
|
||||||
*
|
*
|
||||||
* IDENTIFICATION
|
* IDENTIFICATION
|
||||||
* $PostgreSQL: pgsql/src/backend/optimizer/util/predtest.c,v 1.15 2007/05/12 19:22:35 tgl Exp $
|
* $PostgreSQL: pgsql/src/backend/optimizer/util/predtest.c,v 1.16 2007/07/24 17:22:07 tgl Exp $
|
||||||
*
|
*
|
||||||
*-------------------------------------------------------------------------
|
*-------------------------------------------------------------------------
|
||||||
*/
|
*/
|
||||||
@ -84,6 +84,7 @@ static bool predicate_implied_by_simple_clause(Expr *predicate, Node *clause);
|
|||||||
static bool predicate_refuted_by_simple_clause(Expr *predicate, Node *clause);
|
static bool predicate_refuted_by_simple_clause(Expr *predicate, Node *clause);
|
||||||
static bool is_null_contradicts(NullTest *ntest, Node *clause);
|
static bool is_null_contradicts(NullTest *ntest, Node *clause);
|
||||||
static Node *extract_not_arg(Node *clause);
|
static Node *extract_not_arg(Node *clause);
|
||||||
|
static bool list_member_strip(List *list, Expr *datum);
|
||||||
static bool btree_predicate_proof(Expr *predicate, Node *clause,
|
static bool btree_predicate_proof(Expr *predicate, Node *clause,
|
||||||
bool refute_it);
|
bool refute_it);
|
||||||
|
|
||||||
@ -961,11 +962,11 @@ predicate_implied_by_simple_clause(Expr *predicate, Node *clause)
|
|||||||
if (!type_is_rowtype(exprType((Node *) nonnullarg)))
|
if (!type_is_rowtype(exprType((Node *) nonnullarg)))
|
||||||
{
|
{
|
||||||
if (is_opclause(clause) &&
|
if (is_opclause(clause) &&
|
||||||
list_member(((OpExpr *) clause)->args, nonnullarg) &&
|
list_member_strip(((OpExpr *) clause)->args, nonnullarg) &&
|
||||||
op_strict(((OpExpr *) clause)->opno))
|
op_strict(((OpExpr *) clause)->opno))
|
||||||
return true;
|
return true;
|
||||||
if (is_funcclause(clause) &&
|
if (is_funcclause(clause) &&
|
||||||
list_member(((FuncExpr *) clause)->args, nonnullarg) &&
|
list_member_strip(((FuncExpr *) clause)->args, nonnullarg) &&
|
||||||
func_strict(((FuncExpr *) clause)->funcid))
|
func_strict(((FuncExpr *) clause)->funcid))
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@ -1044,11 +1045,11 @@ is_null_contradicts(NullTest *ntest, Node *clause)
|
|||||||
|
|
||||||
/* foo IS NULL contradicts any strict op/func on foo */
|
/* foo IS NULL contradicts any strict op/func on foo */
|
||||||
if (is_opclause(clause) &&
|
if (is_opclause(clause) &&
|
||||||
list_member(((OpExpr *) clause)->args, isnullarg) &&
|
list_member_strip(((OpExpr *) clause)->args, isnullarg) &&
|
||||||
op_strict(((OpExpr *) clause)->opno))
|
op_strict(((OpExpr *) clause)->opno))
|
||||||
return true;
|
return true;
|
||||||
if (is_funcclause(clause) &&
|
if (is_funcclause(clause) &&
|
||||||
list_member(((FuncExpr *) clause)->args, isnullarg) &&
|
list_member_strip(((FuncExpr *) clause)->args, isnullarg) &&
|
||||||
func_strict(((FuncExpr *) clause)->funcid))
|
func_strict(((FuncExpr *) clause)->funcid))
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
@ -1091,6 +1092,36 @@ extract_not_arg(Node *clause)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Check whether an Expr is equal() to any member of a list, ignoring
|
||||||
|
* any top-level RelabelType nodes. This is legitimate for the purposes
|
||||||
|
* we use it for (matching IS [NOT] NULL arguments to arguments of strict
|
||||||
|
* functions) because RelabelType doesn't change null-ness. It's helpful
|
||||||
|
* for cases such as a varchar argument of a strict function on text.
|
||||||
|
*/
|
||||||
|
static bool
|
||||||
|
list_member_strip(List *list, Expr *datum)
|
||||||
|
{
|
||||||
|
ListCell *cell;
|
||||||
|
|
||||||
|
if (datum && IsA(datum, RelabelType))
|
||||||
|
datum = ((RelabelType *) datum)->arg;
|
||||||
|
|
||||||
|
foreach(cell, list)
|
||||||
|
{
|
||||||
|
Expr *elem = (Expr *) lfirst(cell);
|
||||||
|
|
||||||
|
if (elem && IsA(elem, RelabelType))
|
||||||
|
elem = ((RelabelType *) elem)->arg;
|
||||||
|
|
||||||
|
if (equal(elem, datum))
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Define an "operator implication table" for btree operators ("strategies"),
|
* Define an "operator implication table" for btree operators ("strategies"),
|
||||||
* and a similar table for refutation.
|
* and a similar table for refutation.
|
||||||
|
Loading…
x
Reference in New Issue
Block a user