aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/backend/utils/fmgr/funcapi.c32
-rw-r--r--src/test/regress/expected/rowtypes.out39
-rw-r--r--src/test/regress/sql/rowtypes.sql9
3 files changed, 80 insertions, 0 deletions
diff --git a/src/backend/utils/fmgr/funcapi.c b/src/backend/utils/fmgr/funcapi.c
index 8632b1a2963..9ce5fa9f6be 100644
--- a/src/backend/utils/fmgr/funcapi.c
+++ b/src/backend/utils/fmgr/funcapi.c
@@ -236,6 +236,38 @@ get_expr_result_type(Node *expr,
NULL,
resultTypeId,
resultTupleDesc);
+ else if (expr && IsA(expr, RowExpr) &&
+ ((RowExpr *) expr)->row_typeid == RECORDOID)
+ {
+ /* We can resolve the record type by generating the tupdesc directly */
+ RowExpr *rexpr = (RowExpr *) expr;
+ TupleDesc tupdesc;
+ AttrNumber i = 1;
+ ListCell *lcc,
+ *lcn;
+
+ tupdesc = CreateTemplateTupleDesc(list_length(rexpr->args));
+ Assert(list_length(rexpr->args) == list_length(rexpr->colnames));
+ forboth(lcc, rexpr->args, lcn, rexpr->colnames)
+ {
+ Node *col = (Node *) lfirst(lcc);
+ char *colname = strVal(lfirst(lcn));
+
+ TupleDescInitEntry(tupdesc, i,
+ colname,
+ exprType(col),
+ exprTypmod(col),
+ 0);
+ TupleDescInitEntryCollation(tupdesc, i,
+ exprCollation(col));
+ i++;
+ }
+ if (resultTypeId)
+ *resultTypeId = rexpr->row_typeid;
+ if (resultTupleDesc)
+ *resultTupleDesc = BlessTupleDesc(tupdesc);
+ return TYPEFUNC_COMPOSITE;
+ }
else
{
/* handle as a generic expression; no chance to resolve RECORD */
diff --git a/src/test/regress/expected/rowtypes.out b/src/test/regress/expected/rowtypes.out
index 69058244fcc..4ac4e08baf3 100644
--- a/src/test/regress/expected/rowtypes.out
+++ b/src/test/regress/expected/rowtypes.out
@@ -445,6 +445,45 @@ where i8 in (row(123,456)::int8_tbl, '(4567890123456789,123)');
4567890123456789 | 123
(2 rows)
+-- Check ability to select columns from an anonymous rowtype
+select (row(1, 2.0)).f1;
+ f1
+----
+ 1
+(1 row)
+
+select (row(1, 2.0)).f2;
+ f2
+-----
+ 2.0
+(1 row)
+
+select (row(1, 2.0)).nosuch; -- fail
+ERROR: could not identify column "nosuch" in record data type
+LINE 1: select (row(1, 2.0)).nosuch;
+ ^
+select (row(1, 2.0)).*;
+ f1 | f2
+----+-----
+ 1 | 2.0
+(1 row)
+
+select (r).f1 from (select row(1, 2.0) as r) ss;
+ f1
+----
+ 1
+(1 row)
+
+select (r).f3 from (select row(1, 2.0) as r) ss; -- fail
+ERROR: could not identify column "f3" in record data type
+LINE 1: select (r).f3 from (select row(1, 2.0) as r) ss;
+ ^
+select (r).* from (select row(1, 2.0) as r) ss;
+ f1 | f2
+----+-----
+ 1 | 2.0
+(1 row)
+
-- Check some corner cases involving empty rowtypes
select ROW();
row
diff --git a/src/test/regress/sql/rowtypes.sql b/src/test/regress/sql/rowtypes.sql
index efd5610785e..5e1b4b557ee 100644
--- a/src/test/regress/sql/rowtypes.sql
+++ b/src/test/regress/sql/rowtypes.sql
@@ -176,6 +176,15 @@ where i8 in (row(123,456)::int8_tbl, '(4567890123456789,123)');
select * from int8_tbl i8
where i8 in (row(123,456)::int8_tbl, '(4567890123456789,123)');
+-- Check ability to select columns from an anonymous rowtype
+select (row(1, 2.0)).f1;
+select (row(1, 2.0)).f2;
+select (row(1, 2.0)).nosuch; -- fail
+select (row(1, 2.0)).*;
+select (r).f1 from (select row(1, 2.0) as r) ss;
+select (r).f3 from (select row(1, 2.0) as r) ss; -- fail
+select (r).* from (select row(1, 2.0) as r) ss;
+
-- Check some corner cases involving empty rowtypes
select ROW();
select ROW() IS NULL;