Improve the error message for an inappropriate column definition list.

The existing message about "a column definition list is only allowed for
functions returning "record"" could be given in some cases where it was
fairly confusing; in particular, a function with multiple OUT parameters
*does* return record according to pg_proc.  Break it down into a couple
more cases to deliver a more on-point complaint.  Per complaint from
Bruce Momjian.

Discussion: https://postgr.es/m/798909.1600562993@sss.pgh.pa.us
This commit is contained in:
Tom Lane 2020-09-22 10:49:11 -04:00
parent f859c2ffa0
commit ce90f075f0
3 changed files with 55 additions and 7 deletions

View File

@ -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
{

View File

@ -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()
--

View File

@ -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;
--