Teach simplify_boolean_equality to simplify the forms foo <> true and
authorTom Lane <[email protected]>
Mon, 20 Jul 2009 00:24:30 +0000 (00:24 +0000)
committerTom Lane <[email protected]>
Mon, 20 Jul 2009 00:24:30 +0000 (00:24 +0000)
foo <> false, along with its previous duties of simplifying foo = true
and foo = false.  (All of these are equivalent to just foo or NOT foo
as the case may be.)  It's not clear how often this is really useful;
but it costs almost nothing to do, and it seems some people think we
should be smart about such cases.  Per recent bug report.

src/backend/optimizer/util/clauses.c
src/include/catalog/pg_operator.h

index 75c5d0c94d095c0d34c1d7df697031f8010014e8..f2038c73af14282d0f52ae3c2d599d07a542f6ec 100644 (file)
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *   $PostgreSQL: pgsql/src/backend/optimizer/util/clauses.c,v 1.277 2009/06/11 14:48:59 momjian Exp $
+ *   $PostgreSQL: pgsql/src/backend/optimizer/util/clauses.c,v 1.278 2009/07/20 00:24:30 tgl Exp $
  *
  * HISTORY
  *   AUTHOR            DATE            MAJOR EVENT
@@ -92,7 +92,7 @@ static List *simplify_or_arguments(List *args,
 static List *simplify_and_arguments(List *args,
                       eval_const_expressions_context *context,
                       bool *haveNull, bool *forceFalse);
-static Expr *simplify_boolean_equality(List *args);
+static Expr *simplify_boolean_equality(Oid opno, List *args);
 static Expr *simplify_function(Oid funcid,
                  Oid result_type, int32 result_typmod, List **args,
                  bool allow_inline,
@@ -2186,12 +2186,14 @@ eval_const_expressions_mutator(Node *node,
            return (Node *) simple;
 
        /*
-        * If the operator is boolean equality, we know how to simplify cases
-        * involving one constant and one non-constant argument.
+        * If the operator is boolean equality or inequality, we know how to
+        * simplify cases involving one constant and one non-constant
+        * argument.
         */
-       if (expr->opno == BooleanEqualOperator)
+       if (expr->opno == BooleanEqualOperator ||
+           expr->opno == BooleanNotEqualOperator)
        {
-           simple = simplify_boolean_equality(args);
+           simple = simplify_boolean_equality(expr->opno, args);
            if (simple)         /* successfully simplified it */
                return (Node *) simple;
        }
@@ -3165,21 +3167,23 @@ simplify_and_arguments(List *args,
 
 /*
  * Subroutine for eval_const_expressions: try to simplify boolean equality
+ * or inequality condition
  *
- * Input is the list of simplified arguments to the operator.
+ * Inputs are the operator OID and the simplified arguments to the operator.
  * Returns a simplified expression if successful, or NULL if cannot
  * simplify the expression.
  *
- * The idea here is to reduce "x = true" to "x" and "x = false" to "NOT x".
+ * The idea here is to reduce "x = true" to "x" and "x = false" to "NOT x",
+ * or similarly "x <> true" to "NOT x" and "x <> false" to "x".
  * This is only marginally useful in itself, but doing it in constant folding
- * ensures that we will recognize the two forms as being equivalent in, for
+ * ensures that we will recognize these forms as being equivalent in, for
  * example, partial index matching.
  *
  * We come here only if simplify_function has failed; therefore we cannot
  * see two constant inputs, nor a constant-NULL input.
  */
 static Expr *
-simplify_boolean_equality(List *args)
+simplify_boolean_equality(Oid opno, List *args)
 {
    Expr       *leftop;
    Expr       *rightop;
@@ -3190,18 +3194,38 @@ simplify_boolean_equality(List *args)
    if (leftop && IsA(leftop, Const))
    {
        Assert(!((Const *) leftop)->constisnull);
-       if (DatumGetBool(((Const *) leftop)->constvalue))
-           return rightop;     /* true = foo */
+       if (opno == BooleanEqualOperator)
+       {
+           if (DatumGetBool(((Const *) leftop)->constvalue))
+               return rightop;     /* true = foo */
+           else
+               return make_notclause(rightop);     /* false = foo */
+       }
        else
-           return make_notclause(rightop);     /* false = foo */
+       {
+           if (DatumGetBool(((Const *) leftop)->constvalue))
+               return make_notclause(rightop);     /* true <> foo */
+           else
+               return rightop;     /* false <> foo */
+       }
    }
    if (rightop && IsA(rightop, Const))
    {
        Assert(!((Const *) rightop)->constisnull);
-       if (DatumGetBool(((Const *) rightop)->constvalue))
-           return leftop;      /* foo = true */
+       if (opno == BooleanEqualOperator)
+       {
+           if (DatumGetBool(((Const *) rightop)->constvalue))
+               return leftop;      /* foo = true */
+           else
+               return make_notclause(leftop);      /* foo = false */
+       }
        else
-           return make_notclause(leftop);      /* foo = false */
+       {
+           if (DatumGetBool(((Const *) rightop)->constvalue))
+               return make_notclause(leftop);      /* foo <> true */
+           else
+               return leftop;      /* foo <> false */
+       }
    }
    return NULL;
 }
index 8cea420cd694f3808ecc39f45dbea569e81c4dc9..e4aef392dea56e963e57f2264d832e06d035c9a8 100644 (file)
@@ -8,7 +8,7 @@
  * Portions Copyright (c) 1996-2009, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- * $PostgreSQL: pgsql/src/include/catalog/pg_operator.h,v 1.166 2009/06/11 14:49:09 momjian Exp $
+ * $PostgreSQL: pgsql/src/include/catalog/pg_operator.h,v 1.167 2009/07/20 00:24:30 tgl Exp $
  *
  * NOTES
  *   the genbki.sh script reads this file and generates .bki
@@ -93,6 +93,7 @@ DATA(insert OID =  82 ( ">="     PGNSP PGUID b f f    23  20  16 420  37 int48ge scalar
 DATA(insert OID =  58 ( "<"           PGNSP PGUID b f f    16  16  16  59  1695 boollt scalarltsel scalarltjoinsel ));
 DATA(insert OID =  59 ( ">"           PGNSP PGUID b f f    16  16  16  58  1694 boolgt scalargtsel scalargtjoinsel ));
 DATA(insert OID =  85 ( "<>"      PGNSP PGUID b f f    16  16  16  85  91 boolne neqsel neqjoinsel ));
+#define BooleanNotEqualOperator   85
 DATA(insert OID =  91 ( "="           PGNSP PGUID b t t    16  16  16  91  85 booleq eqsel eqjoinsel ));
 #define BooleanEqualOperator   91
 DATA(insert OID = 1694 (  "<="    PGNSP PGUID b f f    16  16  16 1695 59 boolle scalarltsel scalarltjoinsel ));