diff options
author | Tom Lane <tgl@sss.pgh.pa.us> | 2015-11-15 14:41:09 -0500 |
---|---|---|
committer | Tom Lane <tgl@sss.pgh.pa.us> | 2015-11-15 14:41:09 -0500 |
commit | d33ab56b0ee3dbb5a353bf07804820f1daa199d5 (patch) | |
tree | 6bce0de7fb875b20383e10212462180776ef8539 /src/backend/utils/adt/ruleutils.c | |
parent | f1b898759f4936e9185698e8624da832a99b933e (diff) | |
download | postgresql-d33ab56b0ee3dbb5a353bf07804820f1daa199d5.tar.gz postgresql-d33ab56b0ee3dbb5a353bf07804820f1daa199d5.zip |
Fix ruleutils.c's dumping of whole-row Vars in ROW() and VALUES() contexts.
Normally ruleutils prints a whole-row Var as "foo.*". We already knew that
that doesn't work at top level of a SELECT list, because the parser would
treat the "*" as a directive to expand the reference into separate columns,
not a whole-row Var. However, Joshua Yanovski points out in bug #13776
that the same thing happens at top level of a ROW() construct; and some
nosing around in the parser shows that the same is true in VALUES().
Hence, apply the same workaround already devised for the SELECT-list case,
namely to add a forced cast to the appropriate rowtype in these cases.
(The alternative of just printing "foo" was rejected because it is
difficult to avoid ambiguity against plain columns named "foo".)
Back-patch to all supported branches.
Diffstat (limited to 'src/backend/utils/adt/ruleutils.c')
-rw-r--r-- | src/backend/utils/adt/ruleutils.c | 35 |
1 files changed, 30 insertions, 5 deletions
diff --git a/src/backend/utils/adt/ruleutils.c b/src/backend/utils/adt/ruleutils.c index 6400fa0de3d..2942fc96d13 100644 --- a/src/backend/utils/adt/ruleutils.c +++ b/src/backend/utils/adt/ruleutils.c @@ -380,6 +380,8 @@ static void appendContextKeyword(deparse_context *context, const char *str, static void removeStringInfoSpaces(StringInfo str); static void get_rule_expr(Node *node, deparse_context *context, bool showimplicit); +static void get_rule_expr_toplevel(Node *node, deparse_context *context, + bool showimplicit); static void get_oper_expr(OpExpr *expr, deparse_context *context); static void get_func_expr(FuncExpr *expr, deparse_context *context, bool showimplicit); @@ -4297,10 +4299,10 @@ get_values_def(List *values_lists, deparse_context *context) /* * Strip any top-level nodes representing indirection assignments, - * then print the result. + * then print the result. Whole-row Vars need special treatment. */ - get_rule_expr(processIndirection(col, context, false), - context, false); + get_rule_expr_toplevel(processIndirection(col, context, false), + context, false); } appendStringInfoChar(buf, ')'); } @@ -4691,7 +4693,8 @@ get_target_list(List *targetList, deparse_context *context, * the top level of a SELECT list it's not right (the parser will * expand that notation into multiple columns, yielding behavior * different from a whole-row Var). We need to call get_variable - * directly so that we can tell it to do the right thing. + * directly so that we can tell it to do the right thing, and so that + * we can get the attribute name which is the default AS label. */ if (tle->expr && IsA(tle->expr, Var)) { @@ -7180,7 +7183,8 @@ get_rule_expr(Node *node, deparse_context *context, !tupdesc->attrs[i]->attisdropped) { appendStringInfoString(buf, sep); - get_rule_expr(e, context, true); + /* Whole-row Vars need special treatment here */ + get_rule_expr_toplevel(e, context, true); sep = ", "; } i++; @@ -7560,6 +7564,27 @@ get_rule_expr(Node *node, deparse_context *context, } } +/* + * get_rule_expr_toplevel - Parse back a toplevel expression + * + * Same as get_rule_expr(), except that if the expr is just a Var, we pass + * istoplevel = true not false to get_variable(). This causes whole-row Vars + * to get printed with decoration that will prevent expansion of "*". + * We need to use this in contexts such as ROW() and VALUES(), where the + * parser would expand "foo.*" appearing at top level. (In principle we'd + * use this in get_target_list() too, but that has additional worries about + * whether to print AS, so it needs to invoke get_variable() directly anyway.) + */ +static void +get_rule_expr_toplevel(Node *node, deparse_context *context, + bool showimplicit) +{ + if (node && IsA(node, Var)) + (void) get_variable((Var *) node, 0, true, context); + else + get_rule_expr(node, context, showimplicit); +} + /* * get_oper_expr - Parse back an OpExpr node |