mirror of
https://git.postgresql.org/git/postgresql.git
synced 2025-01-24 18:55:04 +08:00
Fix an oversight I introduced on 2003-12-28: find_nots/push_nots should
continue to recurse after eliminating a NOT-below-a-NOT, since the contained subexpression will now be part of the top-level AND/OR structure and so deserves to be simplified. The real-world impact of this is probably minimal, since it'd require at least three levels of NOT to make a difference, but it's still a bug. Also remove some redundant tests for NULL subexpressions.
This commit is contained in:
parent
80f6c35833
commit
284e4739ef
@ -25,7 +25,7 @@
|
||||
*
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $PostgreSQL: pgsql/src/backend/optimizer/prep/prepqual.c,v 1.49 2005/03/28 00:58:23 tgl Exp $
|
||||
* $PostgreSQL: pgsql/src/backend/optimizer/prep/prepqual.c,v 1.50 2005/07/29 21:40:02 tgl Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@ -167,9 +167,6 @@ pull_ors(List *orlist)
|
||||
static Expr *
|
||||
find_nots(Expr *qual)
|
||||
{
|
||||
if (qual == NULL)
|
||||
return NULL;
|
||||
|
||||
if (and_clause((Node *) qual))
|
||||
{
|
||||
List *t_list = NIL;
|
||||
@ -204,17 +201,13 @@ find_nots(Expr *qual)
|
||||
static Expr *
|
||||
push_nots(Expr *qual)
|
||||
{
|
||||
if (qual == NULL)
|
||||
return make_notclause(qual); /* XXX is this right? Or
|
||||
* possible? */
|
||||
|
||||
/*
|
||||
* Negate an operator clause if possible: (NOT (< A B)) => (>= A B)
|
||||
* Otherwise, retain the clause as it is (the NOT can't be pushed down
|
||||
* any farther).
|
||||
*/
|
||||
if (is_opclause(qual))
|
||||
{
|
||||
/*
|
||||
* Negate an operator clause if possible: (NOT (< A B)) => (>= A B)
|
||||
* Otherwise, retain the clause as it is (the NOT can't be pushed down
|
||||
* any farther).
|
||||
*/
|
||||
OpExpr *opexpr = (OpExpr *) qual;
|
||||
Oid negator = get_negator(opexpr->opno);
|
||||
|
||||
@ -256,15 +249,16 @@ push_nots(Expr *qual)
|
||||
{
|
||||
/*
|
||||
* Another NOT cancels this NOT, so eliminate the NOT and stop
|
||||
* negating this branch.
|
||||
* negating this branch. But search the subexpression for more
|
||||
* NOTs to simplify.
|
||||
*/
|
||||
return get_notclausearg(qual);
|
||||
return find_nots(get_notclausearg(qual));
|
||||
}
|
||||
else
|
||||
{
|
||||
/*
|
||||
* We don't know how to negate anything else, place a NOT at this
|
||||
* level.
|
||||
* level. No point in recursing deeper, either.
|
||||
*/
|
||||
return make_notclause(qual);
|
||||
}
|
||||
@ -303,9 +297,6 @@ push_nots(Expr *qual)
|
||||
static Expr *
|
||||
find_duplicate_ors(Expr *qual)
|
||||
{
|
||||
if (qual == NULL)
|
||||
return NULL;
|
||||
|
||||
if (or_clause((Node *) qual))
|
||||
{
|
||||
List *orlist = NIL;
|
||||
|
Loading…
Reference in New Issue
Block a user