OSDN Git Service

Fix display of whole-row Var appearing at the top level of a SELECT list.
authorTom Lane <tgl@sss.pgh.pa.us>
Thu, 26 Jan 2006 17:08:19 +0000 (17:08 +0000)
committerTom Lane <tgl@sss.pgh.pa.us>
Thu, 26 Jan 2006 17:08:19 +0000 (17:08 +0000)
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.

src/backend/utils/adt/ruleutils.c

index 7c47054..05e817e 100644 (file)
@@ -3,7 +3,7 @@
  *                             back to source text
  *
  * IDENTIFICATION
- *       $PostgreSQL: pgsql/src/backend/utils/adt/ruleutils.c,v 1.212 2005/12/30 18:34:22 tgl Exp $
+ *       $PostgreSQL: pgsql/src/backend/utils/adt/ruleutils.c,v 1.213 2006/01/26 17:08:19 tgl Exp $
  *
  *       This software is copyrighted by Jan Wieck - Hamburg.
  *
@@ -2018,6 +2018,7 @@ get_basic_select_query(Query *query, deparse_context *context,
        {
                TargetEntry *tle = (TargetEntry *) lfirst(l);
                char       *colname;
+               char       *attname;
 
                if (tle->resjunk)
                        continue;                       /* ignore junk entries */
@@ -2026,7 +2027,55 @@ get_basic_select_query(Query *query, deparse_context *context,
                sep = ", ";
                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
@@ -2039,28 +2088,10 @@ get_basic_select_query(Query *query, deparse_context *context,
                else
                        colname = tle->resname;
 
+               /* Show AS unless the column's name is correct as-is */
                if (colname)                    /* resname could be NULL */
                {
-                       /* Check if we must say AS ... */
-                       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)
+                       if (attname == NULL || strcmp(attname, colname) != 0)
                                appendStringInfo(buf, " AS %s", quote_identifier(colname));
                }
        }
@@ -3098,9 +3129,9 @@ get_rule_expr(Node *node, deparse_context *context,
                                                                                 quote_identifier(schemaname));
 
                                        if (strcmp(refname, "*NEW*") == 0)
-                                               appendStringInfo(buf, "new.");
+                                               appendStringInfoString(buf, "new.");
                                        else if (strcmp(refname, "*OLD*") == 0)
-                                               appendStringInfo(buf, "old.");
+                                               appendStringInfoString(buf, "old.");
                                        else
                                                appendStringInfo(buf, "%s.",
                                                                                 quote_identifier(refname));
@@ -3108,7 +3139,7 @@ get_rule_expr(Node *node, deparse_context *context,
                                if (attname)
                                        appendStringInfoString(buf, quote_identifier(attname));
                                else
-                                       appendStringInfo(buf, "*");
+                                       appendStringInfoString(buf, "*");
                        }
                        break;