Thread: Inconsistent behavior on select * from void_function()?

Inconsistent behavior on select * from void_function()?

From
Josh Berkus
Date:
Folks,

This seems wrong to me:

postgres=# create table test1 ( testy int );
CREATE TABLE
postgres=# insert into test1 values ( 5 );
INSERT 0 1

postgres=# create function void_func ( IN theval int ) returns void as $f$
postgres$# update test1 set testy = $1;
postgres$# $f$ language sql;
CREATE FUNCTION                     ^
postgres=# select * from void_func( 9 );void_func
-----------

(1 row)

postgres=# select void_func( 10 ) is null;?column?
----------t
(1 row)

postgres=# create function void_func2( IN theval int )
postgres-# returns void as $f$
postgres$# begin
postgres$# update test1 set testy = theval;
postgres$# return;
postgres$# end;$f$ language plpgsql;
CREATE FUNCTION
postgres=# select * from void_func2(19);void_func2
------------

(1 row)


postgres=# select void_func2(19) is null;?column?
----------f
(1 row)


Why is a function which returns void returning a row?   Why is that row 
NULL if it's a SQL function and empty if it's a PLPGSQL function?

(version 8.2.3)

-- 
--Josh

Josh Berkus
PostgreSQL @ Sun
San Francisco


Re: Inconsistent behavior on select * from void_function()?

From
Gregory Stark
Date:
"Josh Berkus" <josh@agliodbs.com> writes:

> postgres=# select * from void_func2(19);
>  void_func2
> ------------
>
> (1 row)
>
>
> postgres=# select void_func2(19) is null;
>  ?column?
> ----------
>  f
> (1 row)
>
>
> Why is a function which returns void returning a row?   Why is that row 
> NULL if it's a SQL function and empty if it's a PLPGSQL function?

Generally you can treat functions that return a data type as if they returned
a set of rows of that data type. I get the impression this is a considered a
quirk of the implementation and not an advertised feature though: 


postgres=# create function foo() returns integer as 'select 1' language sql;
CREATE FUNCTION
postgres=# select foo();foo 
-----  1
(1 row)

postgres=# select * from foo();foo 
-----  1
(1 row)



I can't speak to the handling of IS NULL though. It is a bit curious.

--  Gregory Stark EnterpriseDB          http://www.enterprisedb.com


Re: Inconsistent behavior on select * from void_function()?

From
Tom Lane
Date:
Josh Berkus <josh@agliodbs.com> writes:
> Why is a function which returns void returning a row?

Returning a scalar result that happens to be of type VOID is an entirely
different thing from returning a set result that contains no rows.

> Why is that row 
> NULL if it's a SQL function and empty if it's a PLPGSQL function?

I'd say that the SQL function is probably doing the right thing.  It
appears that plpgsql has hacked this specially "for backward
compatibility":
   /*    * Special hack for function returning VOID: instead of NULL, return a    * non-null VOID value.  This is of
dubiousimportance but is kept for    * backwards compatibility.  Note that the only other way to get here is    * to
havewritten "RETURN NULL" in a function returning tuple.    */   if (estate->fn_rettype == VOIDOID)   {
estate->retval= (Datum) 0;       estate->retisnull = false;       estate->rettype = VOIDOID;   }
 

I haven't tested, but I think that diking out this section would make
the result be a null (still of type void).
        regards, tom lane