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:
@ -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
|
||||
|
Reference in New Issue
Block a user