diff --git a/src/backend/optimizer/util/clauses.c b/src/backend/optimizer/util/clauses.c index 2d0bad7cde..501b0e9e2d 100644 --- a/src/backend/optimizer/util/clauses.c +++ b/src/backend/optimizer/util/clauses.c @@ -1172,6 +1172,16 @@ contain_nonstrict_functions_walker(Node *node, void *context) return true; if (IsA(node, FieldStore)) return true; + if (IsA(node, CoerceViaIO)) + { + /* + * CoerceViaIO is strict regardless of whether the I/O functions are, + * so just go look at its argument; asking check_functions_in_node is + * useless expense and could deliver the wrong answer. + */ + return contain_nonstrict_functions_walker((Node *) ((CoerceViaIO *) node)->arg, + context); + } if (IsA(node, ArrayCoerceExpr)) { /* diff --git a/src/backend/optimizer/util/predtest.c b/src/backend/optimizer/util/predtest.c index 01f64eeab5..3c9f245e4d 100644 --- a/src/backend/optimizer/util/predtest.c +++ b/src/backend/optimizer/util/predtest.c @@ -1352,6 +1352,27 @@ clause_is_strict_for(Node *clause, Node *subexpr) return false; } + /* + * CoerceViaIO is strict (whether or not the I/O functions it calls are). + * Likewise, ArrayCoerceExpr is strict for its array argument (regardless + * of what the per-element expression is), ConvertRowtypeExpr is strict at + * the row level, and CoerceToDomain is strict too. These are worth + * checking mainly because it saves us having to explain to users why some + * type coercions are known strict and others aren't. + */ + if (IsA(clause, CoerceViaIO)) + return clause_is_strict_for((Node *) ((CoerceViaIO *) clause)->arg, + subexpr); + if (IsA(clause, ArrayCoerceExpr)) + return clause_is_strict_for((Node *) ((ArrayCoerceExpr *) clause)->arg, + subexpr); + if (IsA(clause, ConvertRowtypeExpr)) + return clause_is_strict_for((Node *) ((ConvertRowtypeExpr *) clause)->arg, + subexpr); + if (IsA(clause, CoerceToDomain)) + return clause_is_strict_for((Node *) ((CoerceToDomain *) clause)->arg, + subexpr); + return false; }