aboutsummaryrefslogtreecommitdiff
path: root/src/backend/optimizer/prep/prepqual.c
diff options
context:
space:
mode:
authorTom Lane <tgl@sss.pgh.pa.us>2005-07-29 21:40:02 +0000
committerTom Lane <tgl@sss.pgh.pa.us>2005-07-29 21:40:02 +0000
commit284e4739ef898807202337f830eee38ad7de18fc (patch)
treea0e5efe0195daf4426bc2c0b3ad255e61ba35594 /src/backend/optimizer/prep/prepqual.c
parent80f6c35833508a793b5b488fb56f52118259eba5 (diff)
downloadpostgresql-284e4739ef898807202337f830eee38ad7de18fc.tar.gz
postgresql-284e4739ef898807202337f830eee38ad7de18fc.zip
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.
Diffstat (limited to 'src/backend/optimizer/prep/prepqual.c')
-rw-r--r--src/backend/optimizer/prep/prepqual.c29
1 files changed, 10 insertions, 19 deletions
diff --git a/src/backend/optimizer/prep/prepqual.c b/src/backend/optimizer/prep/prepqual.c
index c153d312fa6..2c39859a811 100644
--- a/src/backend/optimizer/prep/prepqual.c
+++ b/src/backend/optimizer/prep/prepqual.c
@@ -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;