index ea2cfc9e66b510735769c7d003394813e6656965..75fc1730eb447efbc19a6f748695b73d2d63882f 100644 (file)
@@ -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)
{
index e046632d6edbaf4c1a65ec6570ae21f68d33b80f..c270b735fecaac40daff3cc8e7bd37ffc45ec453 100644 (file)
@@ -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;
index 66736a3564c41e6c74f120f54a21634c953ca994..c6a3e575afb6603eb32ec5f21e1ffb12e9b65bb5 100644 (file)
(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();
index db74770228d291bcaa93b0efdccc349bb05f59c8..46aaf335d09164dba2a8791760c155cbd7330dc9 100644 (file)
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();