1
0
mirror of https://github.com/postgres/postgres.git synced 2025-06-13 07:41:39 +03:00

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.
This commit is contained in:
Tom Lane
2015-11-15 14:41:09 -05:00
parent f1b898759f
commit d33ab56b0e
3 changed files with 139 additions and 5 deletions

View File

@ -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