aboutsummaryrefslogtreecommitdiff
path: root/src/backend/optimizer
diff options
context:
space:
mode:
Diffstat (limited to 'src/backend/optimizer')
-rw-r--r--src/backend/optimizer/util/clauses.c81
-rw-r--r--src/backend/optimizer/util/predtest.c43
2 files changed, 106 insertions, 18 deletions
diff --git a/src/backend/optimizer/util/clauses.c b/src/backend/optimizer/util/clauses.c
index 48b125a774c..99d3147aeb5 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.220 2006/09/06 20:40:47 tgl Exp $
+ * $PostgreSQL: pgsql/src/backend/optimizer/util/clauses.c,v 1.221 2006/09/28 20:51:41 tgl Exp $
*
* HISTORY
* AUTHOR DATE MAJOR EVENT
@@ -2099,6 +2099,85 @@ eval_const_expressions_mutator(Node *node,
newfselect->resulttypmod = fselect->resulttypmod;
return (Node *) newfselect;
}
+ if (IsA(node, NullTest))
+ {
+ NullTest *ntest = (NullTest *) node;
+ NullTest *newntest;
+ Node *arg;
+
+ arg = eval_const_expressions_mutator((Node *) ntest->arg,
+ context);
+ if (arg && IsA(arg, RowExpr))
+ {
+ RowExpr *rarg = (RowExpr *) arg;
+ List *newargs = NIL;
+ ListCell *l;
+
+ /*
+ * We break ROW(...) IS [NOT] NULL into separate tests on its
+ * component fields. This form is usually more efficient to
+ * evaluate, as well as being more amenable to optimization.
+ */
+ foreach(l, rarg->args)
+ {
+ Node *relem = (Node *) lfirst(l);
+
+ /*
+ * A constant field refutes the whole NullTest if it's of
+ * the wrong nullness; else we can discard it.
+ */
+ if (relem && IsA(relem, Const))
+ {
+ Const *carg = (Const *) relem;
+
+ if (carg->constisnull ?
+ (ntest->nulltesttype == IS_NOT_NULL) :
+ (ntest->nulltesttype == IS_NULL))
+ return makeBoolConst(false, false);
+ continue;
+ }
+ newntest = makeNode(NullTest);
+ newntest->arg = (Expr *) relem;
+ newntest->nulltesttype = ntest->nulltesttype;
+ newargs = lappend(newargs, newntest);
+ }
+ /* If all the inputs were constants, result is TRUE */
+ if (newargs == NIL)
+ return makeBoolConst(true, false);
+ /* If only one nonconst input, it's the result */
+ if (list_length(newargs) == 1)
+ return (Node *) linitial(newargs);
+ /* Else we need an AND node */
+ return (Node *) make_andclause(newargs);
+ }
+ if (arg && IsA(arg, Const))
+ {
+ Const *carg = (Const *) arg;
+ bool result;
+
+ switch (ntest->nulltesttype)
+ {
+ case IS_NULL:
+ result = carg->constisnull;
+ break;
+ case IS_NOT_NULL:
+ result = !carg->constisnull;
+ break;
+ default:
+ elog(ERROR, "unrecognized nulltesttype: %d",
+ (int) ntest->nulltesttype);
+ result = false; /* keep compiler quiet */
+ break;
+ }
+
+ return makeBoolConst(result, false);
+ }
+
+ newntest = makeNode(NullTest);
+ newntest->arg = (Expr *) arg;
+ newntest->nulltesttype = ntest->nulltesttype;
+ return (Node *) newntest;
+ }
if (IsA(node, BooleanTest))
{
BooleanTest *btest = (BooleanTest *) node;
diff --git a/src/backend/optimizer/util/predtest.c b/src/backend/optimizer/util/predtest.c
index 418c7614121..b909e6d4bf2 100644
--- a/src/backend/optimizer/util/predtest.c
+++ b/src/backend/optimizer/util/predtest.c
@@ -9,7 +9,7 @@
*
*
* IDENTIFICATION
- * $PostgreSQL: pgsql/src/backend/optimizer/util/predtest.c,v 1.8 2006/08/05 00:21:14 tgl Exp $
+ * $PostgreSQL: pgsql/src/backend/optimizer/util/predtest.c,v 1.9 2006/09/28 20:51:42 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -21,6 +21,7 @@
#include "executor/executor.h"
#include "optimizer/clauses.h"
#include "optimizer/predtest.h"
+#include "parser/parse_expr.h"
#include "utils/array.h"
#include "utils/lsyscache.h"
#include "utils/syscache.h"
@@ -931,14 +932,18 @@ predicate_implied_by_simple_clause(Expr *predicate, Node *clause)
{
Expr *nonnullarg = ((NullTest *) predicate)->arg;
- if (is_opclause(clause) &&
- list_member(((OpExpr *) clause)->args, nonnullarg) &&
- op_strict(((OpExpr *) clause)->opno))
- return true;
- if (is_funcclause(clause) &&
- list_member(((FuncExpr *) clause)->args, nonnullarg) &&
- func_strict(((FuncExpr *) clause)->funcid))
- return true;
+ /* row IS NOT NULL does not act in the simple way we have in mind */
+ if (!type_is_rowtype(exprType((Node *) nonnullarg)))
+ {
+ if (is_opclause(clause) &&
+ list_member(((OpExpr *) clause)->args, nonnullarg) &&
+ op_strict(((OpExpr *) clause)->opno))
+ return true;
+ if (is_funcclause(clause) &&
+ list_member(((FuncExpr *) clause)->args, nonnullarg) &&
+ func_strict(((FuncExpr *) clause)->funcid))
+ return true;
+ }
return false; /* we can't succeed below... */
}
@@ -978,14 +983,18 @@ predicate_refuted_by_simple_clause(Expr *predicate, Node *clause)
{
Expr *isnullarg = ((NullTest *) predicate)->arg;
- if (is_opclause(clause) &&
- list_member(((OpExpr *) clause)->args, isnullarg) &&
- op_strict(((OpExpr *) clause)->opno))
- return true;
- if (is_funcclause(clause) &&
- list_member(((FuncExpr *) clause)->args, isnullarg) &&
- func_strict(((FuncExpr *) clause)->funcid))
- return true;
+ /* row IS NULL does not act in the simple way we have in mind */
+ if (!type_is_rowtype(exprType((Node *) isnullarg)))
+ {
+ if (is_opclause(clause) &&
+ list_member(((OpExpr *) clause)->args, isnullarg) &&
+ op_strict(((OpExpr *) clause)->opno))
+ return true;
+ if (is_funcclause(clause) &&
+ list_member(((FuncExpr *) clause)->args, isnullarg) &&
+ func_strict(((FuncExpr *) clause)->funcid))
+ return true;
+ }
return false; /* we can't succeed below... */
}