diff options
Diffstat (limited to 'src/backend/optimizer')
-rw-r--r-- | src/backend/optimizer/path/costsize.c | 13 | ||||
-rw-r--r-- | src/backend/optimizer/plan/setrefs.c | 6 | ||||
-rw-r--r-- | src/backend/optimizer/prep/preptlist.c | 2 | ||||
-rw-r--r-- | src/backend/optimizer/util/clauses.c | 46 |
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, |