diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/backend/executor/functions.c | 5 | ||||
| -rw-r--r-- | src/backend/optimizer/util/clauses.c | 5 | ||||
| -rw-r--r-- | src/test/regress/expected/rangefuncs.out | 20 | ||||
| -rw-r--r-- | src/test/regress/sql/rangefuncs.sql | 19 | 
4 files changed, 49 insertions, 0 deletions
| diff --git a/src/backend/executor/functions.c b/src/backend/executor/functions.c index ea2cfc9e66b..75fc1730eb4 100644 --- a/src/backend/executor/functions.c +++ b/src/backend/executor/functions.c @@ -1171,6 +1171,11 @@ check_sql_fn_retval(Oid func_id, Oid rettype, List *queryTreeList,  		 * This can happen, for example, where the body of the function is  		 * 'SELECT func2()', where func2 has the same composite return type as  		 * the function that's calling it. +		 * +		 * XXX Note that if rettype is RECORD, the IsBinaryCoercible check +		 * will succeed for any composite restype.  For the moment we rely on +		 * runtime type checking to catch any discrepancy, but it'd be nice to +		 * do better at parse time.  		 */  		if (tlistlen == 1)  		{ diff --git a/src/backend/optimizer/util/clauses.c b/src/backend/optimizer/util/clauses.c index e046632d6ed..c270b735fec 100644 --- a/src/backend/optimizer/util/clauses.c +++ b/src/backend/optimizer/util/clauses.c @@ -3689,6 +3689,10 @@ evaluate_function(Oid funcid, Oid result_type, int32 result_typmod, List *args,   * We must also beware of changing the volatility or strictness status of   * functions by inlining them.   * + * Also, at the moment we can't inline functions returning RECORD.  This + * doesn't work in the general case because it discards information such + * as OUT-parameter declarations. + *   * Returns a simplified expression if successful, or NULL if cannot   * simplify the function.   */ @@ -3721,6 +3725,7 @@ inline_function(Oid funcid, Oid result_type, List *args,  	if (funcform->prolang != SQLlanguageId ||  		funcform->prosecdef ||  		funcform->proretset || +		funcform->prorettype == RECORDOID ||  		!heap_attisnull(func_tuple, Anum_pg_proc_proconfig) ||  		funcform->pronargs != list_length(args))  		return NULL; diff --git a/src/test/regress/expected/rangefuncs.out b/src/test/regress/expected/rangefuncs.out index 66736a3564c..c6a3e575afb 100644 --- a/src/test/regress/expected/rangefuncs.out +++ b/src/test/regress/expected/rangefuncs.out @@ -898,3 +898,23 @@ select * from foobar();  (2 rows)  drop function foobar(); +-- check handling of a SQL function with multiple OUT params (bug #5777) +create or replace function foobar(out integer, out numeric) as +$$ select (1, 2.1) $$ language sql; +select * from foobar(); + column1 | column2  +---------+--------- +       1 |     2.1 +(1 row) + +create or replace function foobar(out integer, out numeric) as +$$ select (1, 2) $$ language sql; +select * from foobar();  -- fail +ERROR:  function return row and query-specified return row do not match +DETAIL:  Returned type integer at ordinal position 2, but query expects numeric. +create or replace function foobar(out integer, out numeric) as +$$ select (1, 2.1, 3) $$ language sql; +select * from foobar();  -- fail +ERROR:  function return row and query-specified return row do not match +DETAIL:  Returned row contains 3 attributes, but query expects 2. +drop function foobar(); diff --git a/src/test/regress/sql/rangefuncs.sql b/src/test/regress/sql/rangefuncs.sql index db74770228d..46aaf335d09 100644 --- a/src/test/regress/sql/rangefuncs.sql +++ b/src/test/regress/sql/rangefuncs.sql @@ -429,3 +429,22 @@ select foobar();  select * from foobar();  drop function foobar(); + +-- check handling of a SQL function with multiple OUT params (bug #5777) + +create or replace function foobar(out integer, out numeric) as +$$ select (1, 2.1) $$ language sql; + +select * from foobar(); + +create or replace function foobar(out integer, out numeric) as +$$ select (1, 2) $$ language sql; + +select * from foobar();  -- fail + +create or replace function foobar(out integer, out numeric) as +$$ select (1, 2.1, 3) $$ language sql; + +select * from foobar();  -- fail + +drop function foobar(); | 
