mirror of
https://github.com/postgres/postgres.git
synced 2025-04-25 21:42:33 +03:00
Fix display of whole-row Var appearing at the top level of a SELECT list.
While we normally prefer the notation "foo.*" for a whole-row Var, that does not work at SELECT top level, because in that context the parser will assume that what is wanted is to expand the "*" into a list of separate target columns, yielding behavior different from a whole-row Var. We have to emit just "foo" instead in that context. Per report from Sokolov Yura.
This commit is contained in:
parent
f31a58481c
commit
108a2e51c9
@ -3,7 +3,7 @@
|
|||||||
* back to source text
|
* back to source text
|
||||||
*
|
*
|
||||||
* IDENTIFICATION
|
* IDENTIFICATION
|
||||||
* $PostgreSQL: pgsql/src/backend/utils/adt/ruleutils.c,v 1.207.2.4 2006/01/17 17:33:21 tgl Exp $
|
* $PostgreSQL: pgsql/src/backend/utils/adt/ruleutils.c,v 1.207.2.5 2006/01/26 17:08:26 tgl Exp $
|
||||||
*
|
*
|
||||||
* This software is copyrighted by Jan Wieck - Hamburg.
|
* This software is copyrighted by Jan Wieck - Hamburg.
|
||||||
*
|
*
|
||||||
@ -2019,6 +2019,7 @@ get_basic_select_query(Query *query, deparse_context *context,
|
|||||||
{
|
{
|
||||||
TargetEntry *tle = (TargetEntry *) lfirst(l);
|
TargetEntry *tle = (TargetEntry *) lfirst(l);
|
||||||
char *colname;
|
char *colname;
|
||||||
|
char *attname;
|
||||||
|
|
||||||
if (tle->resjunk)
|
if (tle->resjunk)
|
||||||
continue; /* ignore junk entries */
|
continue; /* ignore junk entries */
|
||||||
@ -2027,7 +2028,55 @@ get_basic_select_query(Query *query, deparse_context *context,
|
|||||||
sep = ", ";
|
sep = ", ";
|
||||||
colno++;
|
colno++;
|
||||||
|
|
||||||
get_rule_expr((Node *) tle->expr, context, true);
|
/*
|
||||||
|
* We special-case Var nodes rather than using get_rule_expr.
|
||||||
|
* This is needed because get_rule_expr will display a whole-row Var
|
||||||
|
* as "foo.*", which is the preferred notation in most contexts, but
|
||||||
|
* at 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 want just "foo", instead.
|
||||||
|
*/
|
||||||
|
if (tle->expr && IsA(tle->expr, Var))
|
||||||
|
{
|
||||||
|
Var *var = (Var *) (tle->expr);
|
||||||
|
char *schemaname;
|
||||||
|
char *refname;
|
||||||
|
|
||||||
|
get_names_for_var(var, 0, context,
|
||||||
|
&schemaname, &refname, &attname);
|
||||||
|
if (refname && (context->varprefix || attname == NULL))
|
||||||
|
{
|
||||||
|
if (schemaname)
|
||||||
|
appendStringInfo(buf, "%s.",
|
||||||
|
quote_identifier(schemaname));
|
||||||
|
|
||||||
|
if (strcmp(refname, "*NEW*") == 0)
|
||||||
|
appendStringInfoString(buf, "new");
|
||||||
|
else if (strcmp(refname, "*OLD*") == 0)
|
||||||
|
appendStringInfoString(buf, "old");
|
||||||
|
else
|
||||||
|
appendStringInfoString(buf, quote_identifier(refname));
|
||||||
|
|
||||||
|
if (attname)
|
||||||
|
appendStringInfoChar(buf, '.');
|
||||||
|
}
|
||||||
|
if (attname)
|
||||||
|
appendStringInfoString(buf, quote_identifier(attname));
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
* In the whole-row Var case, refname is what the default AS
|
||||||
|
* name would be.
|
||||||
|
*/
|
||||||
|
attname = refname;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
get_rule_expr((Node *) tle->expr, context, true);
|
||||||
|
/* We'll show the AS name unless it's this: */
|
||||||
|
attname = "?column?";
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Figure out what the result column should be called. In the context
|
* Figure out what the result column should be called. In the context
|
||||||
@ -2040,28 +2089,10 @@ get_basic_select_query(Query *query, deparse_context *context,
|
|||||||
else
|
else
|
||||||
colname = tle->resname;
|
colname = tle->resname;
|
||||||
|
|
||||||
|
/* Show AS unless the column's name is correct as-is */
|
||||||
if (colname) /* resname could be NULL */
|
if (colname) /* resname could be NULL */
|
||||||
{
|
{
|
||||||
/* Check if we must say AS ... */
|
if (attname == NULL || strcmp(attname, colname) != 0)
|
||||||
bool tell_as;
|
|
||||||
|
|
||||||
if (!IsA(tle->expr, Var))
|
|
||||||
tell_as = (strcmp(colname, "?column?") != 0);
|
|
||||||
else
|
|
||||||
{
|
|
||||||
Var *var = (Var *) (tle->expr);
|
|
||||||
char *schemaname;
|
|
||||||
char *refname;
|
|
||||||
char *attname;
|
|
||||||
|
|
||||||
get_names_for_var(var, 0, context,
|
|
||||||
&schemaname, &refname, &attname);
|
|
||||||
tell_as = (attname == NULL ||
|
|
||||||
strcmp(attname, colname) != 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* and do if so */
|
|
||||||
if (tell_as)
|
|
||||||
appendStringInfo(buf, " AS %s", quote_identifier(colname));
|
appendStringInfo(buf, " AS %s", quote_identifier(colname));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -3099,9 +3130,9 @@ get_rule_expr(Node *node, deparse_context *context,
|
|||||||
quote_identifier(schemaname));
|
quote_identifier(schemaname));
|
||||||
|
|
||||||
if (strcmp(refname, "*NEW*") == 0)
|
if (strcmp(refname, "*NEW*") == 0)
|
||||||
appendStringInfo(buf, "new.");
|
appendStringInfoString(buf, "new.");
|
||||||
else if (strcmp(refname, "*OLD*") == 0)
|
else if (strcmp(refname, "*OLD*") == 0)
|
||||||
appendStringInfo(buf, "old.");
|
appendStringInfoString(buf, "old.");
|
||||||
else
|
else
|
||||||
appendStringInfo(buf, "%s.",
|
appendStringInfo(buf, "%s.",
|
||||||
quote_identifier(refname));
|
quote_identifier(refname));
|
||||||
@ -3109,7 +3140,7 @@ get_rule_expr(Node *node, deparse_context *context,
|
|||||||
if (attname)
|
if (attname)
|
||||||
appendStringInfoString(buf, quote_identifier(attname));
|
appendStringInfoString(buf, quote_identifier(attname));
|
||||||
else
|
else
|
||||||
appendStringInfo(buf, "*");
|
appendStringInfoString(buf, "*");
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user