diff options
author | Tom Lane <tgl@sss.pgh.pa.us> | 2017-07-12 18:00:04 -0400 |
---|---|---|
committer | Tom Lane <tgl@sss.pgh.pa.us> | 2017-07-12 18:00:04 -0400 |
commit | bc2d716ad09fceeb391c755f78c256ddac9d3b9f (patch) | |
tree | ae0a40ddfbc1da7d4b58e2fdd2584a7db3f6f910 /src/backend/utils/adt/ruleutils.c | |
parent | da11977de9c685ef808d3a293727f9ce26753ec4 (diff) | |
download | postgresql-bc2d716ad09fceeb391c755f78c256ddac9d3b9f.tar.gz postgresql-bc2d716ad09fceeb391c755f78c256ddac9d3b9f.zip |
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.
Diffstat (limited to 'src/backend/utils/adt/ruleutils.c')
-rw-r--r-- | src/backend/utils/adt/ruleutils.c | 41 |
1 files changed, 37 insertions, 4 deletions
diff --git a/src/backend/utils/adt/ruleutils.c b/src/backend/utils/adt/ruleutils.c index 18d9e27d1ed..5a4adbdc52e 100644 --- a/src/backend/utils/adt/ruleutils.c +++ b/src/backend/utils/adt/ruleutils.c @@ -6206,8 +6206,11 @@ get_update_query_targetlist_def(Query *query, List *targetList, /* * We must dig down into the expr to see if it's a PARAM_MULTIEXPR * Param. That could be buried under FieldStores and ArrayRefs - * (cf processIndirection()), and underneath those there could be - * an implicit type coercion. + * and CoerceToDomains (cf processIndirection()), and underneath + * those there could be an implicit type coercion. Because we + * would ignore implicit type coercions anyway, we don't need to + * be as careful as processIndirection() is about descending past + * implicit CoerceToDomains. */ expr = (Node *) tle->expr; while (expr) @@ -6226,6 +6229,14 @@ get_update_query_targetlist_def(Query *query, List *targetList, break; expr = (Node *) aref->refassgnexpr; } + else if (IsA(expr, CoerceToDomain)) + { + CoerceToDomain *cdomain = (CoerceToDomain *) expr; + + if (cdomain->coercionformat != COERCE_IMPLICIT_CAST) + break; + expr = (Node *) cdomain->arg; + } else break; } @@ -10185,13 +10196,17 @@ get_opclass_name(Oid opclass, Oid actual_datatype, * * We strip any top-level FieldStore or assignment ArrayRef nodes that * appear in the input, printing them as decoration for the base column - * name (which we assume the caller just printed). Return the subexpression - * that's to be assigned. + * name (which we assume 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) { StringInfo buf = context->buf; + CoerceToDomain *cdomain = NULL; for (;;) { @@ -10239,10 +10254,28 @@ processIndirection(Node *node, deparse_context *context) */ 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; } |