]> granicus.if.org Git - postgresql/commitdiff
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 57ef558c404c4304256fcd18a43720909cf2ba26..1e7eb605f5ffb79a4706f6a87c8c14b193b525e9 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 f01ebe33e87775342bf39970e83e11dc03dd7446..96eec16ebc1f985be5fd4538e62622b97fcd03c0 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 0127c6e14b2be1319fa8bbbb262a2221b42ac2b7..baf98b67634fb05b5bcfcc3b6fb25e02b210ca38 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 6d39a51a9839351e79e955500b67d1983cc2a49c..b25ef4b577a0a190434ef05466a785a208e2c7c9 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 3f7ce455df230439fbbf147f8209ee38dca53ab6..d48715d36bb18dd5a888f3533f4c8965361b4552 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 0836fde517b40e3af28753347fada355a2c06101..e8b78509475240fa5575f3863c02a543d2d91150 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 748a3cb93ac567e9e1a9e99d57ff3b4663d660b0..2e230913965064815c351e9d2c89a693134cd0bf 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 86e47661aa0888e8821752e395b02cb8fe595d89..69efaddfecf4dce8797c85459794f1b81b8fe49c 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 1091d87473ddb444d1dc6f5b66d32e47dc8aef36..ddd041818a54450b8e8e86bac74783e93fede28e 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 b5d82dd0e7f99f411c27750e6b52812b08c2a3fa..2a9645bf423c1ddb64eb9db19cab4c97c2457728 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 fd21152b4950f4a360c8c651442df5a81e9e1b06..72b7e3c3d84dd89b81d8a6204fdbf9d4cacb2d00 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 $
  *
  *-------------------------------------------------------------------------
  */
@@ -3236,6 +3236,18 @@ get_name_for_var_field(Var *var, int fieldno,
        TupleDesc       tupleDesc;
        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
index cdd9fa272ea3f8cd03fdb3113435f842c6f2e08e..3f27787992224b9acfbc80b42108f30f6b29738d 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 e8614492fe4231ac345e2c8b46906ffd5601fe8c..2a2ea18520fa844d54a44608e8c510f6cf38a3e9 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;