Commit 904af8db authored by Tom Lane's avatar Tom Lane

Fix handling of strict non-set functions with NULLs in set-valued inputs.

In a construct like "select plain_function(set_returning_function(...))",
the plain function is applied to each output row of the SRF successively.
If some of the SRF outputs are NULL, and the plain function is strict,
you'd expect to get NULL results for such rows ... but what actually
happened was that such rows were omitted entirely from the result set.
This was due to confusion of this case with what should happen for nested
set-returning functions; a strict SRF is indeed supposed to yield an empty
set for null input.  Per bug #8150 from Erwin Brandstetter.

Although this has been broken forever, we're not back-patching because
of the possibility that some apps out there expect the incorrect behavior.
This change should be listed as a possible incompatibility in the 9.3
release notes.
parent f0ed3a8a
...@@ -1801,12 +1801,20 @@ restart: ...@@ -1801,12 +1801,20 @@ restart:
pgstat_end_function_usage(&fcusage, pgstat_end_function_usage(&fcusage,
rsinfo.isDone != ExprMultipleResult); rsinfo.isDone != ExprMultipleResult);
} }
else else if (fcache->func.fn_retset)
{ {
/* for a strict SRF, result for NULL is an empty set */
result = (Datum) 0; result = (Datum) 0;
*isNull = true; *isNull = true;
*isDone = ExprEndResult; *isDone = ExprEndResult;
} }
else
{
/* for a strict non-SRF, result for NULL is a NULL */
result = (Datum) 0;
*isNull = true;
*isDone = ExprSingleResult;
}
/* Which protocol does function want to use? */ /* Which protocol does function want to use? */
if (rsinfo.returnMode == SFRM_ValuePerCall) if (rsinfo.returnMode == SFRM_ValuePerCall)
......
...@@ -1542,6 +1542,15 @@ select unnest(array[1,2,3,null,4,null,null,5,6]::text[]); ...@@ -1542,6 +1542,15 @@ select unnest(array[1,2,3,null,4,null,null,5,6]::text[]);
6 6
(9 rows) (9 rows)
select abs(unnest(array[1,2,null,-3]));
abs
-----
1
2
3
(4 rows)
select array_remove(array[1,2,2,3], 2); select array_remove(array[1,2,2,3], 2);
array_remove array_remove
-------------- --------------
......
...@@ -432,6 +432,7 @@ select unnest(array[1,2,3,4.5]::float8[]); ...@@ -432,6 +432,7 @@ select unnest(array[1,2,3,4.5]::float8[]);
select unnest(array[1,2,3,4.5]::numeric[]); select unnest(array[1,2,3,4.5]::numeric[]);
select unnest(array[1,2,3,null,4,null,null,5,6]); select unnest(array[1,2,3,null,4,null,null,5,6]);
select unnest(array[1,2,3,null,4,null,null,5,6]::text[]); select unnest(array[1,2,3,null,4,null,null,5,6]::text[]);
select abs(unnest(array[1,2,null,-3]));
select array_remove(array[1,2,2,3], 2); select array_remove(array[1,2,2,3], 2);
select array_remove(array[1,2,2,3], 5); select array_remove(array[1,2,2,3], 5);
select array_remove(array[1,NULL,NULL,3], NULL); select array_remove(array[1,NULL,NULL,3], NULL);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment