improve-message-for-unwanted-coldeflist.patch
text/x-diff
Filename: improve-message-for-unwanted-coldeflist.patch
Type: text/x-diff
Part: 0
Patch
Format: unified
| File | + | − |
|---|---|---|
| src/backend/parser/parse_relation.c | 37 | 7 |
| src/test/regress/expected/rangefuncs.out | 13 | 0 |
| src/test/regress/sql/rangefuncs.sql | 5 | 0 |
diff --git a/src/backend/parser/parse_relation.c b/src/backend/parser/parse_relation.c
index b875a50646..a56bd86181 100644
--- a/src/backend/parser/parse_relation.c
+++ b/src/backend/parser/parse_relation.c
@@ -1737,16 +1737,46 @@ addRangeTableEntryForFunction(ParseState *pstate,
/*
* A coldeflist is required if the function returns RECORD and hasn't
- * got a predetermined record type, and is prohibited otherwise.
+ * got a predetermined record type, and is prohibited otherwise. This
+ * can be a bit confusing, so we expend some effort on delivering a
+ * relevant error message.
*/
if (coldeflist != NIL)
{
- if (functypclass != TYPEFUNC_RECORD)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("a column definition list is only allowed for functions returning \"record\""),
- parser_errposition(pstate,
- exprLocation((Node *) coldeflist))));
+ switch (functypclass)
+ {
+ case TYPEFUNC_RECORD:
+ /* ok */
+ break;
+ case TYPEFUNC_COMPOSITE:
+ case TYPEFUNC_COMPOSITE_DOMAIN:
+
+ /*
+ * If the function's raw result type is RECORD, we must
+ * have resolved it using its OUT parameters. Otherwise,
+ * it must have a named composite type.
+ */
+ if (exprType(funcexpr) == RECORDOID)
+ ereport(ERROR,
+ (errcode(ERRCODE_SYNTAX_ERROR),
+ errmsg("a column definition list is redundant for a function with OUT parameters"),
+ parser_errposition(pstate,
+ exprLocation((Node *) coldeflist))));
+ else
+ ereport(ERROR,
+ (errcode(ERRCODE_SYNTAX_ERROR),
+ errmsg("a column definition list is redundant for a function returning a named composite type"),
+ parser_errposition(pstate,
+ exprLocation((Node *) coldeflist))));
+ break;
+ default:
+ ereport(ERROR,
+ (errcode(ERRCODE_SYNTAX_ERROR),
+ errmsg("a column definition list is only allowed for functions returning \"record\""),
+ parser_errposition(pstate,
+ exprLocation((Node *) coldeflist))));
+ break;
+ }
}
else
{
diff --git a/src/test/regress/expected/rangefuncs.out b/src/test/regress/expected/rangefuncs.out
index 7eced28452..e618aec2eb 100644
--- a/src/test/regress/expected/rangefuncs.out
+++ b/src/test/regress/expected/rangefuncs.out
@@ -2109,6 +2109,19 @@ select * from testrngfunc();
7.136178 | 7.14
(1 row)
+-- Check a couple of error cases while we're here
+select * from testrngfunc() as t(f1 int8,f2 int8); -- fail, composite result
+ERROR: a column definition list is redundant for a function returning a named composite type
+LINE 1: select * from testrngfunc() as t(f1 int8,f2 int8);
+ ^
+select * from pg_get_keywords() as t(f1 int8,f2 int8); -- fail, OUT params
+ERROR: a column definition list is redundant for a function with OUT parameters
+LINE 1: select * from pg_get_keywords() as t(f1 int8,f2 int8);
+ ^
+select * from sin(3) as t(f1 int8,f2 int8); -- fail, scalar result type
+ERROR: a column definition list is only allowed for functions returning "record"
+LINE 1: select * from sin(3) as t(f1 int8,f2 int8);
+ ^
drop type rngfunc_type cascade;
NOTICE: drop cascades to function testrngfunc()
--
diff --git a/src/test/regress/sql/rangefuncs.sql b/src/test/regress/sql/rangefuncs.sql
index ae3119a959..5f41cb2d8d 100644
--- a/src/test/regress/sql/rangefuncs.sql
+++ b/src/test/regress/sql/rangefuncs.sql
@@ -629,6 +629,11 @@ explain (verbose, costs off)
select * from testrngfunc();
select * from testrngfunc();
+-- Check a couple of error cases while we're here
+select * from testrngfunc() as t(f1 int8,f2 int8); -- fail, composite result
+select * from pg_get_keywords() as t(f1 int8,f2 int8); -- fail, OUT params
+select * from sin(3) as t(f1 int8,f2 int8); -- fail, scalar result type
+
drop type rngfunc_type cascade;
--