aboutsummaryrefslogtreecommitdiff
path: root/src/backend/optimizer
diff options
context:
space:
mode:
Diffstat (limited to 'src/backend/optimizer')
-rw-r--r--src/backend/optimizer/path/costsize.c13
-rw-r--r--src/backend/optimizer/plan/setrefs.c6
-rw-r--r--src/backend/optimizer/prep/preptlist.c2
-rw-r--r--src/backend/optimizer/util/clauses.c46
4 files changed, 39 insertions, 28 deletions
diff --git a/src/backend/optimizer/path/costsize.c b/src/backend/optimizer/path/costsize.c
index 0baf9785c98..f76da490447 100644
--- a/src/backend/optimizer/path/costsize.c
+++ b/src/backend/optimizer/path/costsize.c
@@ -3632,11 +3632,14 @@ cost_qual_eval_walker(Node *node, cost_qual_eval_context *context)
else if (IsA(node, ArrayCoerceExpr))
{
ArrayCoerceExpr *acoerce = (ArrayCoerceExpr *) node;
- Node *arraynode = (Node *) acoerce->arg;
-
- if (OidIsValid(acoerce->elemfuncid))
- context->total.per_tuple += get_func_cost(acoerce->elemfuncid) *
- cpu_operator_cost * estimate_array_length(arraynode);
+ QualCost perelemcost;
+
+ cost_qual_eval_node(&perelemcost, (Node *) acoerce->elemexpr,
+ context->root);
+ context->total.startup += perelemcost.startup;
+ if (perelemcost.per_tuple > 0)
+ context->total.per_tuple += perelemcost.per_tuple *
+ estimate_array_length((Node *) acoerce->arg);
}
else if (IsA(node, RowCompareExpr))
{
diff --git a/src/backend/optimizer/plan/setrefs.c b/src/backend/optimizer/plan/setrefs.c
index b0c9e944597..dee4414cec2 100644
--- a/src/backend/optimizer/plan/setrefs.c
+++ b/src/backend/optimizer/plan/setrefs.c
@@ -1395,12 +1395,6 @@ fix_expr_common(PlannerInfo *root, Node *node)
record_plan_function_dependency(root,
((ScalarArrayOpExpr *) node)->opfuncid);
}
- else if (IsA(node, ArrayCoerceExpr))
- {
- if (OidIsValid(((ArrayCoerceExpr *) node)->elemfuncid))
- record_plan_function_dependency(root,
- ((ArrayCoerceExpr *) node)->elemfuncid);
- }
else if (IsA(node, Const))
{
Const *con = (Const *) node;
diff --git a/src/backend/optimizer/prep/preptlist.c b/src/backend/optimizer/prep/preptlist.c
index 9d75e8612ae..d7db32ebf5e 100644
--- a/src/backend/optimizer/prep/preptlist.c
+++ b/src/backend/optimizer/prep/preptlist.c
@@ -306,9 +306,9 @@ expand_targetlist(List *tlist, int command_type,
new_expr = coerce_to_domain(new_expr,
InvalidOid, -1,
atttype,
+ COERCION_IMPLICIT,
COERCE_IMPLICIT_CAST,
-1,
- false,
false);
}
else
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,