OSDN Git Service

When expanding a whole-row Var into a RowExpr during ResolveNew(), attach
authorTom Lane <tgl@sss.pgh.pa.us>
Mon, 6 Oct 2008 17:39:26 +0000 (17:39 +0000)
committerTom Lane <tgl@sss.pgh.pa.us>
Mon, 6 Oct 2008 17:39:26 +0000 (17:39 +0000)
the column alias names of the RTE referenced by the Var to the RowExpr.
This is needed to allow ruleutils.c to correctly deparse FieldSelect nodes
referencing such a construct.  Per my recent bug report.

Adding a field to RowExpr forces initdb (because of stored rules changes)
so this solution is not back-patchable; which is unfortunate because 8.2
and 8.3 have this issue.  But it only affects EXPLAIN for some pretty odd
corner cases, so we can probably live without a solution for the back
branches.

13 files changed:
src/backend/nodes/copyfuncs.c
src/backend/nodes/equalfuncs.c
src/backend/nodes/nodeFuncs.c
src/backend/nodes/outfuncs.c
src/backend/nodes/readfuncs.c
src/backend/optimizer/prep/prepunion.c
src/backend/optimizer/util/var.c
src/backend/parser/parse_coerce.c
src/backend/parser/parse_expr.c
src/backend/rewrite/rewriteManip.c
src/backend/utils/adt/ruleutils.c
src/include/catalog/catversion.h
src/include/nodes/primnodes.h

index 57ef558..1e7eb60 100644 (file)
@@ -15,7 +15,7 @@
  * Portions Copyright (c) 1994, Regents of the University of California
  *
  * IDENTIFICATION
- *       $PostgreSQL: pgsql/src/backend/nodes/copyfuncs.c,v 1.406 2008/10/04 21:56:53 tgl Exp $
+ *       $PostgreSQL: pgsql/src/backend/nodes/copyfuncs.c,v 1.407 2008/10/06 17:39:25 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -1257,6 +1257,7 @@ _copyRowExpr(RowExpr *from)
        COPY_NODE_FIELD(args);
        COPY_SCALAR_FIELD(row_typeid);
        COPY_SCALAR_FIELD(row_format);
+       COPY_NODE_FIELD(colnames);
        COPY_LOCATION_FIELD(location);
 
        return newnode;
index f01ebe3..96eec16 100644 (file)
@@ -22,7 +22,7 @@
  * Portions Copyright (c) 1994, Regents of the University of California
  *
  * IDENTIFICATION
- *       $PostgreSQL: pgsql/src/backend/nodes/equalfuncs.c,v 1.332 2008/10/04 21:56:53 tgl Exp $
+ *       $PostgreSQL: pgsql/src/backend/nodes/equalfuncs.c,v 1.333 2008/10/06 17:39:26 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -511,6 +511,7 @@ _equalRowExpr(RowExpr *a, RowExpr *b)
                b->row_format != COERCE_DONTCARE)
                return false;
 
+       COMPARE_NODE_FIELD(colnames);
        COMPARE_LOCATION_FIELD(location);
 
        return true;
index 0127c6e..baf98b6 100644 (file)
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *       $PostgreSQL: pgsql/src/backend/nodes/nodeFuncs.c,v 1.33 2008/10/04 21:56:53 tgl Exp $
+ *       $PostgreSQL: pgsql/src/backend/nodes/nodeFuncs.c,v 1.34 2008/10/06 17:39:26 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -1172,6 +1172,7 @@ expression_tree_walker(Node *node,
                case T_ArrayExpr:
                        return walker(((ArrayExpr *) node)->elements, context);
                case T_RowExpr:
+                       /* Assume colnames isn't interesting */
                        return walker(((RowExpr *) node)->args, context);
                case T_RowCompareExpr:
                        {
@@ -1735,6 +1736,7 @@ expression_tree_mutator(Node *node,
 
                                FLATCOPY(newnode, rowexpr, RowExpr);
                                MUTATE(newnode->args, rowexpr->args, List *);
+                               /* Assume colnames needn't be duplicated */
                                return (Node *) newnode;
                        }
                        break;
@@ -2174,6 +2176,7 @@ raw_expression_tree_walker(Node *node, bool (*walker) (), void *context)
                        }
                        break;
                case T_RowExpr:
+                       /* Assume colnames isn't interesting */
                        return walker(((RowExpr *) node)->args, context);
                case T_CoalesceExpr:
                        return walker(((CoalesceExpr *) node)->args, context);
index 6d39a51..b25ef4b 100644 (file)
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *       $PostgreSQL: pgsql/src/backend/nodes/outfuncs.c,v 1.340 2008/10/04 21:56:53 tgl Exp $
+ *       $PostgreSQL: pgsql/src/backend/nodes/outfuncs.c,v 1.341 2008/10/06 17:39:26 tgl Exp $
  *
  * NOTES
  *       Every node type that can appear in stored rules' parsetrees *must*
@@ -1037,6 +1037,7 @@ _outRowExpr(StringInfo str, RowExpr *node)
        WRITE_NODE_FIELD(args);
        WRITE_OID_FIELD(row_typeid);
        WRITE_ENUM_FIELD(row_format, CoercionForm);
+       WRITE_NODE_FIELD(colnames);
        WRITE_LOCATION_FIELD(location);
 }
 
index 3f7ce45..d48715d 100644 (file)
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *       $PostgreSQL: pgsql/src/backend/nodes/readfuncs.c,v 1.215 2008/10/04 21:56:53 tgl Exp $
+ *       $PostgreSQL: pgsql/src/backend/nodes/readfuncs.c,v 1.216 2008/10/06 17:39:26 tgl Exp $
  *
  * NOTES
  *       Path and Plan nodes do not have any readfuncs support, because we
@@ -744,6 +744,7 @@ _readRowExpr(void)
        READ_NODE_FIELD(args);
        READ_OID_FIELD(row_typeid);
        READ_ENUM_FIELD(row_format, CoercionForm);
+       READ_NODE_FIELD(colnames);
        READ_LOCATION_FIELD(location);
 
        READ_DONE();
index 0836fde..e8b7850 100644 (file)
@@ -22,7 +22,7 @@
  *
  *
  * IDENTIFICATION
- *       $PostgreSQL: pgsql/src/backend/optimizer/prep/prepunion.c,v 1.156 2008/10/04 21:56:53 tgl Exp $
+ *       $PostgreSQL: pgsql/src/backend/optimizer/prep/prepunion.c,v 1.157 2008/10/06 17:39:26 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -1493,6 +1493,7 @@ adjust_appendrel_attrs_mutator(Node *node, AppendRelInfo *context)
                                        rowexpr->args = fields;
                                        rowexpr->row_typeid = var->vartype;
                                        rowexpr->row_format = COERCE_IMPLICIT_CAST;
+                                       rowexpr->colnames = NIL;
                                        rowexpr->location = -1;
 
                                        return (Node *) rowexpr;
index 748a3cb..2e23091 100644 (file)
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *       $PostgreSQL: pgsql/src/backend/optimizer/util/var.c,v 1.79 2008/09/01 20:42:44 tgl Exp $
+ *       $PostgreSQL: pgsql/src/backend/optimizer/util/var.c,v 1.80 2008/10/06 17:39:26 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -663,6 +663,7 @@ flatten_join_alias_vars_mutator(Node *node,
                        rowexpr->args = fields;
                        rowexpr->row_typeid = var->vartype;
                        rowexpr->row_format = COERCE_IMPLICIT_CAST;
+                       rowexpr->colnames = NIL;
                        rowexpr->location = -1;
 
                        return (Node *) rowexpr;
index 86e4766..69efadd 100644 (file)
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *       $PostgreSQL: pgsql/src/backend/parser/parse_coerce.c,v 2.167 2008/09/10 18:29:40 tgl Exp $
+ *       $PostgreSQL: pgsql/src/backend/parser/parse_coerce.c,v 2.168 2008/10/06 17:39:26 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -926,6 +926,7 @@ coerce_record_to_complex(ParseState *pstate, Node *node,
        rowexpr->args = newargs;
        rowexpr->row_typeid = targetTypeId;
        rowexpr->row_format = cformat;
+       rowexpr->colnames = NIL;        /* not needed for named target type */
        rowexpr->location = location;
        return (Node *) rowexpr;
 }
index 1091d87..ddd0418 100644 (file)
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *       $PostgreSQL: pgsql/src/backend/parser/parse_expr.c,v 1.234 2008/09/01 20:42:44 tgl Exp $
+ *       $PostgreSQL: pgsql/src/backend/parser/parse_expr.c,v 1.235 2008/10/06 17:39:26 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -1534,6 +1534,7 @@ transformRowExpr(ParseState *pstate, RowExpr *r)
        /* Barring later casting, we consider the type RECORD */
        newr->row_typeid = RECORDOID;
        newr->row_format = COERCE_IMPLICIT_CAST;
+       newr->colnames = NIL;           /* ROW() has anonymous columns */
        newr->location = r->location;
 
        return (Node *) newr;
index b5d82dd..2a9645b 100644 (file)
@@ -7,7 +7,7 @@
  *
  *
  * IDENTIFICATION
- *       $PostgreSQL: pgsql/src/backend/rewrite/rewriteManip.c,v 1.114 2008/10/04 21:56:54 tgl Exp $
+ *       $PostgreSQL: pgsql/src/backend/rewrite/rewriteManip.c,v 1.115 2008/10/06 17:39:26 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -1057,18 +1057,20 @@ ResolveNew_mutator(Node *node, ResolveNew_context *context)
                        {
                                /* Must expand whole-tuple reference into RowExpr */
                                RowExpr    *rowexpr;
+                               List       *colnames;
                                List       *fields;
 
                                /*
                                 * If generating an expansion for a var of a named rowtype
                                 * (ie, this is a plain relation RTE), then we must include
                                 * dummy items for dropped columns.  If the var is RECORD (ie,
-                                * this is a JOIN), then omit dropped columns.
+                                * this is a JOIN), then omit dropped columns.  Either way,
+                                * attach column names to the RowExpr for use of ruleutils.c.
                                 */
                                expandRTE(context->target_rte,
                                                  this_varno, this_varlevelsup, var->location,
                                                  (var->vartype != RECORDOID),
-                                                 NULL, &fields);
+                                                 &colnames, &fields);
                                /* Adjust the generated per-field Vars... */
                                fields = (List *) ResolveNew_mutator((Node *) fields,
                                                                                                         context);
@@ -1076,6 +1078,7 @@ ResolveNew_mutator(Node *node, ResolveNew_context *context)
                                rowexpr->args = fields;
                                rowexpr->row_typeid = var->vartype;
                                rowexpr->row_format = COERCE_IMPLICIT_CAST;
+                               rowexpr->colnames = colnames;
                                rowexpr->location = -1;
 
                                return (Node *) rowexpr;
index fd21152..72b7e3c 100644 (file)
@@ -9,7 +9,7 @@
  *
  *
  * IDENTIFICATION
- *       $PostgreSQL: pgsql/src/backend/utils/adt/ruleutils.c,v 1.285 2008/10/04 21:56:54 tgl Exp $
+ *       $PostgreSQL: pgsql/src/backend/utils/adt/ruleutils.c,v 1.286 2008/10/06 17:39:26 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -3237,6 +3237,18 @@ get_name_for_var_field(Var *var, int fieldno,
        Node       *expr;
 
        /*
+        * If it's a RowExpr that was expanded from a whole-row Var, use the
+        * column names attached to it.
+        */
+       if (IsA(var, RowExpr))
+       {
+               RowExpr    *r = (RowExpr *) var;
+
+               if (fieldno > 0 && fieldno <= list_length(r->colnames))
+                       return strVal(list_nth(r->colnames, fieldno - 1));
+       }
+
+       /*
         * If it's a Var of type RECORD, we have to find what the Var refers to;
         * if not, we can use get_expr_result_type. If that fails, we try
         * lookup_rowtype_tupdesc, which will probably fail too, but will ereport
index cdd9fa2..3f27787 100644 (file)
@@ -37,7 +37,7 @@
  * Portions Copyright (c) 1996-2008, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- * $PostgreSQL: pgsql/src/include/catalog/catversion.h,v 1.495 2008/10/06 14:13:17 heikki Exp $
+ * $PostgreSQL: pgsql/src/include/catalog/catversion.h,v 1.496 2008/10/06 17:39:26 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -53,6 +53,6 @@
  */
 
 /*                                                     yyyymmddN */
-#define CATALOG_VERSION_NO     200810062
+#define CATALOG_VERSION_NO     200810063
 
 #endif
index e861449..2a2ea18 100644 (file)
@@ -10,7 +10,7 @@
  * Portions Copyright (c) 1996-2008, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- * $PostgreSQL: pgsql/src/include/nodes/primnodes.h,v 1.142 2008/10/04 21:56:55 tgl Exp $
+ * $PostgreSQL: pgsql/src/include/nodes/primnodes.h,v 1.143 2008/10/06 17:39:26 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -740,6 +740,12 @@ typedef struct ArrayExpr
  * not RECORD types, since those are built from the RowExpr itself rather
  * than vice versa.)  It is important not to assume that length(args) is
  * the same as the number of columns logically present in the rowtype.
+ *
+ * colnames is NIL in a RowExpr built from an ordinary ROW() expression.
+ * It is provided in cases where we expand a whole-row Var into a RowExpr,
+ * to retain the column alias names of the RTE that the Var referenced
+ * (which would otherwise be very difficult to extract from the parsetree).
+ * Like the args list, it is one-for-one with physical fields of the rowtype.
  */
 typedef struct RowExpr
 {
@@ -754,6 +760,7 @@ typedef struct RowExpr
         * parsetrees.  We must assume typmod -1 for a RowExpr node.
         */
        CoercionForm row_format;        /* how to display this node */
+       List       *colnames;           /* list of String, or NIL */
        int                     location;               /* token location, or -1 if unknown */
 } RowExpr;