diff options
Diffstat (limited to 'src/backend/optimizer')
-rw-r--r-- | src/backend/optimizer/util/clauses.c | 81 | ||||
-rw-r--r-- | src/backend/optimizer/util/predtest.c | 43 |
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... */ } |