From 31d1f2330277a91f59fe050cc85ced25ee55f95d Mon Sep 17 00:00:00 2001 From: Tom Lane Date: Mon, 20 Jul 2009 00:24:30 +0000 Subject: [PATCH] Teach simplify_boolean_equality to simplify the forms foo <> true and 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 | 56 ++++++++++++++++++++-------- src/include/catalog/pg_operator.h | 3 +- 2 files changed, 42 insertions(+), 17 deletions(-) diff --git a/src/backend/optimizer/util/clauses.c b/src/backend/optimizer/util/clauses.c index 75c5d0c94d..f2038c73af 100644 --- a/src/backend/optimizer/util/clauses.c +++ b/src/backend/optimizer/util/clauses.c @@ -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; } diff --git a/src/include/catalog/pg_operator.h b/src/include/catalog/pg_operator.h index 8cea420cd6..e4aef392de 100644 --- a/src/include/catalog/pg_operator.h +++ b/src/include/catalog/pg_operator.h @@ -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 )); -- 2.40.0