aboutsummaryrefslogtreecommitdiff
path: root/src/backend/rewrite/rewriteHandler.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/backend/rewrite/rewriteHandler.c')
-rw-r--r--src/backend/rewrite/rewriteHandler.c31
1 files changed, 31 insertions, 0 deletions
diff --git a/src/backend/rewrite/rewriteHandler.c b/src/backend/rewrite/rewriteHandler.c
index f3c75261951..6b79c697955 100644
--- a/src/backend/rewrite/rewriteHandler.c
+++ b/src/backend/rewrite/rewriteHandler.c
@@ -934,6 +934,7 @@ process_matched_tle(TargetEntry *src_tle,
const char *attrName)
{
TargetEntry *result;
+ CoerceToDomain *coerce_expr = NULL;
Node *src_expr;
Node *prior_expr;
Node *src_input;
@@ -970,10 +971,30 @@ process_matched_tle(TargetEntry *src_tle,
* For FieldStore, instead of nesting we can generate a single
* FieldStore with multiple target fields. We must nest when
* ArrayRefs are involved though.
+ *
+ * As a further complication, the destination column might be a domain,
+ * resulting in each assignment containing a CoerceToDomain node over a
+ * FieldStore or ArrayRef. These should have matching target domains,
+ * so we strip them and reconstitute a single CoerceToDomain over the
+ * combined FieldStore/ArrayRef nodes. (Notice that this has the result
+ * that the domain's checks are applied only after we do all the field or
+ * element updates, not after each one. This is arguably desirable.)
*----------
*/
src_expr = (Node *) src_tle->expr;
prior_expr = (Node *) prior_tle->expr;
+
+ if (src_expr && IsA(src_expr, CoerceToDomain) &&
+ prior_expr && IsA(prior_expr, CoerceToDomain) &&
+ ((CoerceToDomain *) src_expr)->resulttype ==
+ ((CoerceToDomain *) prior_expr)->resulttype)
+ {
+ /* we assume without checking that resulttypmod/resultcollid match */
+ coerce_expr = (CoerceToDomain *) src_expr;
+ src_expr = (Node *) ((CoerceToDomain *) src_expr)->arg;
+ prior_expr = (Node *) ((CoerceToDomain *) prior_expr)->arg;
+ }
+
src_input = get_assignment_input(src_expr);
prior_input = get_assignment_input(prior_expr);
if (src_input == NULL ||
@@ -1042,6 +1063,16 @@ process_matched_tle(TargetEntry *src_tle,
newexpr = NULL;
}
+ if (coerce_expr)
+ {
+ /* put back the CoerceToDomain */
+ CoerceToDomain *newcoerce = makeNode(CoerceToDomain);
+
+ memcpy(newcoerce, coerce_expr, sizeof(CoerceToDomain));
+ newcoerce->arg = (Expr *) newexpr;
+ newexpr = (Node *) newcoerce;
+ }
+
result = flatCopyTargetEntry(src_tle);
result->expr = (Expr *) newexpr;
return result;