Fix handling of strict non-set functions with NULLs in set-valued inputs.
authorTom Lane
Sun, 12 May 2013 17:08:12 +0000 (13:08 -0400)
committerTom Lane
Sun, 12 May 2013 17:08:12 +0000 (13:08 -0400)
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.

src/backend/executor/execQual.c
src/test/regress/expected/arrays.out
src/test/regress/sql/arrays.sql

index 4ea0cbadadbc14614d5e8182ec1da0ded631ee0f..494208a0320d430da5d7a933eaa5024d00e4d92d 100644 (file)
@@ -1801,12 +1801,20 @@ restart:
                pgstat_end_function_usage(&fcusage,
                                        rsinfo.isDone != ExprMultipleResult);
            }
-           else
+           else if (fcache->func.fn_retset)
            {
+               /* for a strict SRF, result for NULL is an empty set */
                result = (Datum) 0;
                *isNull = true;
                *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? */
            if (rsinfo.returnMode == SFRM_ValuePerCall)
index 051bac92342c477222a9605fe9a006aea9fb1195..76a8c56a76adc7e43dd3bbd841ee4c2e362efb48 100644 (file)
@@ -1542,6 +1542,15 @@ select unnest(array[1,2,3,null,4,null,null,5,6]::text[]);
  6
 (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);
  array_remove 
 --------------
index 04e97254e1456780532e7e52f8c6988a9616ea67..e6df37216b5ca692b74ca1b9ce4ab55e41dcd8f7 100644 (file)
@@ -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,null,4,null,null,5,6]);
 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], 5);
 select array_remove(array[1,NULL,NULL,3], NULL);