From a2320b3374db8400123b01335fe691fa89d7ed7b Mon Sep 17 00:00:00 2001 From: Tom Lane Date: Wed, 12 Jul 2017 18:00:04 -0400 Subject: Fix ruleutils.c for domain-over-array cases, too. Further investigation shows that ruleutils isn't quite up to speed either for cases where we have a domain-over-array: it needs to be prepared to look past a CoerceToDomain at the top level of field and element assignments, else it decompiles them incorrectly. Potentially this would result in failure to dump/reload a rule, if it looked like the one in the new test case. (I also added a test for EXPLAIN; that output isn't broken, but clearly we need more test coverage here.) Like commit b1cb32fb6, this bug is reachable in cases we already support, so back-patch all the way. --- src/backend/utils/adt/ruleutils.c | 25 ++++++++++++++++++++++++- 1 file changed, 24 insertions(+), 1 deletion(-) (limited to 'src/backend/utils/adt/ruleutils.c') diff --git a/src/backend/utils/adt/ruleutils.c b/src/backend/utils/adt/ruleutils.c index 4bb8b7c76ff..5ba2550b823 100644 --- a/src/backend/utils/adt/ruleutils.c +++ b/src/backend/utils/adt/ruleutils.c @@ -8910,12 +8910,17 @@ get_opclass_name(Oid opclass, Oid actual_datatype, * We strip any top-level FieldStore or assignment ArrayRef nodes that * appear in the input, and return the subexpression that's to be assigned. * If printit is true, we also print out the appropriate decoration for the - * base column name (that the caller just printed). + * base column name (that the caller just printed). We might also need to + * strip CoerceToDomain nodes, but only ones that appear above assignment + * nodes. + * + * Returns the subexpression that's to be assigned. */ static Node * processIndirection(Node *node, deparse_context *context, bool printit) { StringInfo buf = context->buf; + CoerceToDomain *cdomain = NULL; for (;;) { @@ -8965,10 +8970,28 @@ processIndirection(Node *node, deparse_context *context, bool printit) */ node = (Node *) aref->refassgnexpr; } + else if (IsA(node, CoerceToDomain)) + { + cdomain = (CoerceToDomain *) node; + /* If it's an explicit domain coercion, we're done */ + if (cdomain->coercionformat != COERCE_IMPLICIT_CAST) + break; + /* Tentatively descend past the CoerceToDomain */ + node = (Node *) cdomain->arg; + } else break; } + /* + * If we descended past a CoerceToDomain whose argument turned out not to + * be a FieldStore or array assignment, back up to the CoerceToDomain. + * (This is not enough to be fully correct if there are nested implicit + * CoerceToDomains, but such cases shouldn't ever occur.) + */ + if (cdomain && node == (Node *) cdomain->arg) + node = (Node *) cdomain; + return node; } -- cgit v1.2.3