summaryrefslogtreecommitdiff
path: root/src/backend/optimizer/util/clauses.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/backend/optimizer/util/clauses.c')
-rw-r--r--src/backend/optimizer/util/clauses.c97
1 files changed, 86 insertions, 11 deletions
diff --git a/src/backend/optimizer/util/clauses.c b/src/backend/optimizer/util/clauses.c
index 71b5909d207..40e440a3754 100644
--- a/src/backend/optimizer/util/clauses.c
+++ b/src/backend/optimizer/util/clauses.c
@@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/backend/optimizer/util/clauses.c,v 1.129 2003/02/09 06:56:27 tgl Exp $
+ * $Header: /cvsroot/pgsql/src/backend/optimizer/util/clauses.c,v 1.130 2003/02/16 02:30:38 tgl Exp $
*
* HISTORY
* AUTHOR DATE MAJOR EVENT
@@ -451,24 +451,22 @@ expression_returns_set_walker(Node *node, void *context)
return true;
/* else fall through to check args */
}
- if (IsA(node, DistinctExpr))
- {
- DistinctExpr *expr = (DistinctExpr *) node;
-
- if (expr->opretset)
- return true;
- /* else fall through to check args */
- }
/* Avoid recursion for some cases that can't return a set */
- if (IsA(node, BoolExpr))
- return false;
if (IsA(node, Aggref))
return false;
+ if (IsA(node, DistinctExpr))
+ return false;
+ if (IsA(node, BoolExpr))
+ return false;
if (IsA(node, SubLink))
return false;
if (IsA(node, SubPlan))
return false;
+ if (IsA(node, CoalesceExpr))
+ return false;
+ if (IsA(node, NullIfExpr))
+ return false;
return expression_tree_walker(node, expression_returns_set_walker,
context);
@@ -559,6 +557,14 @@ contain_mutable_functions_walker(Node *node, void *context)
return true;
/* else fall through to check args */
}
+ if (IsA(node, NullIfExpr))
+ {
+ NullIfExpr *expr = (NullIfExpr *) node;
+
+ if (op_volatile(expr->opno) != PROVOLATILE_IMMUTABLE)
+ return true;
+ /* else fall through to check args */
+ }
if (IsA(node, SubLink))
{
SubLink *sublink = (SubLink *) node;
@@ -626,6 +632,14 @@ contain_volatile_functions_walker(Node *node, void *context)
return true;
/* else fall through to check args */
}
+ if (IsA(node, NullIfExpr))
+ {
+ NullIfExpr *expr = (NullIfExpr *) node;
+
+ if (op_volatile(expr->opno) == PROVOLATILE_VOLATILE)
+ return true;
+ /* else fall through to check args */
+ }
if (IsA(node, SubLink))
{
SubLink *sublink = (SubLink *) node;
@@ -707,6 +721,10 @@ contain_nonstrict_functions_walker(Node *node, void *context)
}
if (IsA(node, CaseExpr))
return true;
+ if (IsA(node, CoalesceExpr))
+ return true;
+ if (IsA(node, NullIfExpr))
+ return true;
if (IsA(node, NullTest))
return true;
if (IsA(node, BooleanTest))
@@ -1446,6 +1464,39 @@ eval_const_expressions_mutator(Node *node, List *active_fns)
newcase->defresult = (Expr *) defresult;
return (Node *) newcase;
}
+ if (IsA(node, CoalesceExpr))
+ {
+ CoalesceExpr *coalesceexpr = (CoalesceExpr *) node;
+ CoalesceExpr *newcoalesce;
+ List *newargs = NIL;
+ List *arg;
+
+ foreach(arg, coalesceexpr->args)
+ {
+ Node *e;
+
+ e = eval_const_expressions_mutator((Node *) lfirst(arg),
+ active_fns);
+ /*
+ * We can remove null constants from the list.
+ * For a non-null constant, if it has not been preceded by any
+ * other non-null-constant expressions then that is the result.
+ */
+ if (IsA(e, Const))
+ {
+ if (((Const *) e)->constisnull)
+ continue; /* drop null constant */
+ if (newargs == NIL)
+ return e; /* first expr */
+ }
+ newargs = lappend(newargs, e);
+ }
+
+ newcoalesce = makeNode(CoalesceExpr);
+ newcoalesce->coalescetype = coalesceexpr->coalescetype;
+ newcoalesce->args = newargs;
+ return (Node *) newcoalesce;
+ }
/*
* For any node type not handled above, we recurse using
@@ -2109,6 +2160,10 @@ expression_tree_walker(Node *node,
return true;
}
break;
+ case T_CoalesceExpr:
+ return walker(((CoalesceExpr *) node)->args, context);
+ case T_NullIfExpr:
+ return walker(((NullIfExpr *) node)->args, context);
case T_NullTest:
return walker(((NullTest *) node)->arg, context);
case T_BooleanTest:
@@ -2481,6 +2536,26 @@ expression_tree_mutator(Node *node,
return (Node *) newnode;
}
break;
+ case T_CoalesceExpr:
+ {
+ CoalesceExpr *coalesceexpr = (CoalesceExpr *) node;
+ CoalesceExpr *newnode;
+
+ FLATCOPY(newnode, coalesceexpr, CoalesceExpr);
+ MUTATE(newnode->args, coalesceexpr->args, List *);
+ return (Node *) newnode;
+ }
+ break;
+ case T_NullIfExpr:
+ {
+ NullIfExpr *expr = (NullIfExpr *) node;
+ NullIfExpr *newnode;
+
+ FLATCOPY(newnode, expr, NullIfExpr);
+ MUTATE(newnode->args, expr->args, List *);
+ return (Node *) newnode;
+ }
+ break;
case T_NullTest:
{
NullTest *ntest = (NullTest *) node;