aboutsummaryrefslogtreecommitdiff
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.c46
1 files changed, 30 insertions, 16 deletions
diff --git a/src/backend/optimizer/util/clauses.c b/src/backend/optimizer/util/clauses.c
index 93add27dbe2..79613622805 100644
--- a/src/backend/optimizer/util/clauses.c
+++ b/src/backend/optimizer/util/clauses.c
@@ -1361,6 +1361,17 @@ contain_nonstrict_functions_walker(Node *node, void *context)
return true;
if (IsA(node, FieldStore))
return true;
+ if (IsA(node, ArrayCoerceExpr))
+ {
+ /*
+ * ArrayCoerceExpr is strict at the array level, regardless of what
+ * the per-element expression is; so we should ignore elemexpr and
+ * recurse only into the arg.
+ */
+ return expression_tree_walker((Node *) ((ArrayCoerceExpr *) node)->arg,
+ contain_nonstrict_functions_walker,
+ context);
+ }
if (IsA(node, CaseExpr))
return true;
if (IsA(node, ArrayExpr))
@@ -1380,14 +1391,11 @@ contain_nonstrict_functions_walker(Node *node, void *context)
if (IsA(node, BooleanTest))
return true;
- /*
- * Check other function-containing nodes; but ArrayCoerceExpr is strict at
- * the array level, regardless of elemfunc.
- */
- if (!IsA(node, ArrayCoerceExpr) &&
- check_functions_in_node(node, contain_nonstrict_functions_checker,
+ /* Check other function-containing nodes */
+ if (check_functions_in_node(node, contain_nonstrict_functions_checker,
context))
return true;
+
return expression_tree_walker(node, contain_nonstrict_functions_walker,
context);
}
@@ -1757,7 +1765,7 @@ find_nonnullable_rels_walker(Node *node, bool top_level)
}
else if (IsA(node, ArrayCoerceExpr))
{
- /* ArrayCoerceExpr is strict at the array level */
+ /* ArrayCoerceExpr is strict at the array level; ignore elemexpr */
ArrayCoerceExpr *expr = (ArrayCoerceExpr *) node;
result = find_nonnullable_rels_walker((Node *) expr->arg, top_level);
@@ -1965,7 +1973,7 @@ find_nonnullable_vars_walker(Node *node, bool top_level)
}
else if (IsA(node, ArrayCoerceExpr))
{
- /* ArrayCoerceExpr is strict at the array level */
+ /* ArrayCoerceExpr is strict at the array level; ignore elemexpr */
ArrayCoerceExpr *expr = (ArrayCoerceExpr *) node;
result = find_nonnullable_vars_walker((Node *) expr->arg, top_level);
@@ -3005,32 +3013,38 @@ eval_const_expressions_mutator(Node *node,
{
ArrayCoerceExpr *expr = (ArrayCoerceExpr *) node;
Expr *arg;
+ Expr *elemexpr;
ArrayCoerceExpr *newexpr;
/*
- * Reduce constants in the ArrayCoerceExpr's argument, then
- * build a new ArrayCoerceExpr.
+ * Reduce constants in the ArrayCoerceExpr's argument and
+ * per-element expressions, then build a new ArrayCoerceExpr.
*/
arg = (Expr *) eval_const_expressions_mutator((Node *) expr->arg,
context);
+ elemexpr = (Expr *) eval_const_expressions_mutator((Node *) expr->elemexpr,
+ context);
newexpr = makeNode(ArrayCoerceExpr);
newexpr->arg = arg;
- newexpr->elemfuncid = expr->elemfuncid;
+ newexpr->elemexpr = elemexpr;
newexpr->resulttype = expr->resulttype;
newexpr->resulttypmod = expr->resulttypmod;
newexpr->resultcollid = expr->resultcollid;
- newexpr->isExplicit = expr->isExplicit;
newexpr->coerceformat = expr->coerceformat;
newexpr->location = expr->location;
/*
- * If constant argument and it's a binary-coercible or
- * immutable conversion, we can simplify it to a constant.
+ * If constant argument and per-element expression is
+ * immutable, we can simplify the whole thing to a constant.
+ * Exception: although contain_mutable_functions considers
+ * CoerceToDomain immutable for historical reasons, let's not
+ * do so here; this ensures coercion to an array-over-domain
+ * does not apply the domain's constraints until runtime.
*/
if (arg && IsA(arg, Const) &&
- (!OidIsValid(newexpr->elemfuncid) ||
- func_volatile(newexpr->elemfuncid) == PROVOLATILE_IMMUTABLE))
+ elemexpr && !IsA(elemexpr, CoerceToDomain) &&
+ !contain_mutable_functions((Node *) elemexpr))
return (Node *) evaluate_expr((Expr *) newexpr,
newexpr->resulttype,
newexpr->resulttypmod,