diff --git a/src/backend/nodes/copyfuncs.c b/src/backend/nodes/copyfuncs.c index 57ef558c404c4304256fcd18a43720909cf2ba26..1e7eb605f5ffb79a4706f6a87c8c14b193b525e9 100644 --- a/src/backend/nodes/copyfuncs.c +++ b/src/backend/nodes/copyfuncs.c @@ -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; diff --git a/src/backend/nodes/equalfuncs.c b/src/backend/nodes/equalfuncs.c index f01ebe33e87775342bf39970e83e11dc03dd7446..96eec16ebc1f985be5fd4538e62622b97fcd03c0 100644 --- a/src/backend/nodes/equalfuncs.c +++ b/src/backend/nodes/equalfuncs.c @@ -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; diff --git a/src/backend/nodes/nodeFuncs.c b/src/backend/nodes/nodeFuncs.c index 0127c6e14b2be1319fa8bbbb262a2221b42ac2b7..baf98b67634fb05b5bcfcc3b6fb25e02b210ca38 100644 --- a/src/backend/nodes/nodeFuncs.c +++ b/src/backend/nodes/nodeFuncs.c @@ -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); diff --git a/src/backend/nodes/outfuncs.c b/src/backend/nodes/outfuncs.c index 6d39a51a9839351e79e955500b67d1983cc2a49c..b25ef4b577a0a190434ef05466a785a208e2c7c9 100644 --- a/src/backend/nodes/outfuncs.c +++ b/src/backend/nodes/outfuncs.c @@ -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); } diff --git a/src/backend/nodes/readfuncs.c b/src/backend/nodes/readfuncs.c index 3f7ce455df230439fbbf147f8209ee38dca53ab6..d48715d36bb18dd5a888f3533f4c8965361b4552 100644 --- a/src/backend/nodes/readfuncs.c +++ b/src/backend/nodes/readfuncs.c @@ -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(); diff --git a/src/backend/optimizer/prep/prepunion.c b/src/backend/optimizer/prep/prepunion.c index 0836fde517b40e3af28753347fada355a2c06101..e8b78509475240fa5575f3863c02a543d2d91150 100644 --- a/src/backend/optimizer/prep/prepunion.c +++ b/src/backend/optimizer/prep/prepunion.c @@ -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; diff --git a/src/backend/optimizer/util/var.c b/src/backend/optimizer/util/var.c index 748a3cb93ac567e9e1a9e99d57ff3b4663d660b0..2e230913965064815c351e9d2c89a693134cd0bf 100644 --- a/src/backend/optimizer/util/var.c +++ b/src/backend/optimizer/util/var.c @@ -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; diff --git a/src/backend/parser/parse_coerce.c b/src/backend/parser/parse_coerce.c index 86e47661aa0888e8821752e395b02cb8fe595d89..69efaddfecf4dce8797c85459794f1b81b8fe49c 100644 --- a/src/backend/parser/parse_coerce.c +++ b/src/backend/parser/parse_coerce.c @@ -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; } diff --git a/src/backend/parser/parse_expr.c b/src/backend/parser/parse_expr.c index 1091d87473ddb444d1dc6f5b66d32e47dc8aef36..ddd041818a54450b8e8e86bac74783e93fede28e 100644 --- a/src/backend/parser/parse_expr.c +++ b/src/backend/parser/parse_expr.c @@ -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; diff --git a/src/backend/rewrite/rewriteManip.c b/src/backend/rewrite/rewriteManip.c index b5d82dd0e7f99f411c27750e6b52812b08c2a3fa..2a9645bf423c1ddb64eb9db19cab4c97c2457728 100644 --- a/src/backend/rewrite/rewriteManip.c +++ b/src/backend/rewrite/rewriteManip.c @@ -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; diff --git a/src/backend/utils/adt/ruleutils.c b/src/backend/utils/adt/ruleutils.c index fd21152b4950f4a360c8c651442df5a81e9e1b06..72b7e3c3d84dd89b81d8a6204fdbf9d4cacb2d00 100644 --- a/src/backend/utils/adt/ruleutils.c +++ b/src/backend/utils/adt/ruleutils.c @@ -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 diff --git a/src/include/catalog/catversion.h b/src/include/catalog/catversion.h index cdd9fa272ea3f8cd03fdb3113435f842c6f2e08e..3f27787992224b9acfbc80b42108f30f6b29738d 100644 --- a/src/include/catalog/catversion.h +++ b/src/include/catalog/catversion.h @@ -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 diff --git a/src/include/nodes/primnodes.h b/src/include/nodes/primnodes.h index e8614492fe4231ac345e2c8b46906ffd5601fe8c..2a2ea18520fa844d54a44608e8c510f6cf38a3e9 100644 --- a/src/include/nodes/primnodes.h +++ b/src/include/nodes/primnodes.h @@ -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;