Thread: [GENERAL] Two variable passed to PL/Function and on is NULL

[GENERAL] Two variable passed to PL/Function and on is NULL

From
Stuart Rison
Date:
Dear All,

I have written a PL/pgSQL fucntion which takes two arguments and returns a
boolean on the basis of a few (string) comparaisons.

The function works fine as long as BOTH passed variables are non-NULL but
behaves strangely if one of the variables is non-NULL.

Looking at previous postings, I found:

>Very observant of you.  The postgres function system doesn't have a way
>to tell which parameter is null, so the function just returns null.
>I don't like it and we hope to get it changed for PGv6.5 (at least I
>do).

Now that example was with a 'c' function but presumably, function are
handled the same way internally whatever the function language?

SO my question are:

i) Is it the case that if you pass to variables to a postgres function and
one is NULL, the function cannot tell which one?
ii) Is there a workaround of some kind (in particular in pl/pgsql)?
[Currently I am copying the table into a temp table and updating all NULL
values to a token value.]

regards,

Stuart.


+-------------------------+--------------------------------------+
| Stuart Rison            | Ludwig Institute for Cancer Research |
+-------------------------+ 91 Riding House Street               |
| Tel. (0171) 878 4041    | London, W1P 8BT, UNITED KINGDOM.     |
| Fax. (0171) 878 4040    | stuart@ludwig.ucl.ac.uk              |
+-------------------------+--------------------------------------+

Re: [GENERAL] Two variable passed to PL/Function and on is NULL

From
Herouth Maoz
Date:
At 15:44 +0300 on 14/06/1999, Stuart Rison wrote:


> i) Is it the case that if you pass to variables to a postgres function and
> one is NULL, the function cannot tell which one?
> ii) Is there a workaround of some kind (in particular in pl/pgsql)?
> [Currently I am copying the table into a temp table and updating all NULL
> values to a token value.]

I think you will do alright in pl/pgsql. Take for example the following
function which returns 1000 when its argument is null:

create function null1000( int4 ) returns int4 as '
DECLARE
  the_arg alias for $1;
BEGIN
  IF the_arg IS NULL THEN
     RETURN 1000;
  ELSE
     RETURN the_arg;
  END IF;
END;
' language 'plpgsql';

I tested it on the following table:

testing=> select * from test1;
nm
--
 4
 8

16
32

(6 rows)

And this is the result I got:

testing=> select null1000( nm ) from test1;
null1000
--------
       4
       8
    1000
      16
      32
    1000
(6 rows)

The problem arises if you try to pass a literal NULL to the function:

testing=> select null1000( NULL );
ERROR:  typeidTypeRelid: Invalid type - oid = 0

This is because the NULL doesn't have a type of int4. I am not even sure
this is a bug. In any case, it should work alright for normal NULLS. In the
same vein, you can ask whether the arguments in your function are null and
return your boolean properly.

Herouth

--
Herouth Maoz, Internet developer.
Open University of Israel - Telem project
http://telem.openu.ac.il/~herutma



Re: [GENERAL] Two variable passed to PL/Function and on is NULL

From
Stuart Rison
Date:
Hi Herouth,

>At 15:44 +0300 on 14/06/1999, Stuart Rison wrote:
>
>
>> i) Is it the case that if you pass to variables to a postgres function and
>> one is NULL, the function cannot tell which one?
>> ii) Is there a workaround of some kind (in particular in pl/pgsql)?
>> [Currently I am copying the table into a temp table and updating all NULL
>> values to a token value.]
>
>I think you will do alright in pl/pgsql. Take for example the following
>function which returns 1000 when its argument is null:
>

<snip - a function that works fine but take only one argument>

The problem only occur when you have a function which takes more than one
argument.

e.g.

create function null1000(int4,int4) returns int4 as '
DECLARE
  first_arg alias for $1;
  second_arg alias for $2;
BEGIN
        IF first_arg IS NULL THEN
                RETURN 1000;
  ELSE
                RETURN first_arg;
        END IF;
END;
'
language 'plpgsql';

cgh=> select * from test1;
 nm|nm_two
---+------
  4|
  8|
   |
 16|
 32|
 64|     6
128|     7
256|     8
512|     9
   |    10
(10 rows)

cgh=> select nm,nm_two,null1000(nm,nm_two) from test1;
 nm|nm_two|null1000
---+------+--------
  4|      |    1000
  8|      |    1000
   |      |    1000
 16|      |    1000
 32|      |    1000
 64|     6|      64
128|     7|     128
256|     8|     256
512|     9|     512
   |    10|    1000
(10 rows)

as soon a NULL is passed as an argument, both values are treated as NULL by
the function.  I think the problem occurs before you even enter the
function itself; in other words, both values become NULL 'internally' and
not within the function so you can't trap them in the function itself with
'IS NULL' checks.

I think this is a know issue with 6.4 but there was some suggestion it may
have been corrected in 6.5 (fact, fiction?)

furthermore, I'm unlikely to be moving to 6.5 in the near future so has
anyone got a workaround?

cheers,

S.

+-------------------------+--------------------------------------+
| Stuart Rison            | Ludwig Institute for Cancer Research |
+-------------------------+ 91 Riding House Street               |
| Tel. (0171) 878 4041    | London, W1P 8BT, UNITED KINGDOM.     |
| Fax. (0171) 878 4040    | stuart@ludwig.ucl.ac.uk              |
+-------------------------+--------------------------------------+

RE: [GENERAL] Two variable passed to PL/Function and on is NULL

From
Michael J Davis
Date:
Create an nz(int4) or nvl(int4) function that returns 0 if $1 is null.  You
could also create nz(text) that returns '' when $1 is null.  Then do:

    select my_function(nz(value1), nz(value2));

This has worked for me.

> -----Original Message-----
> From:    Stuart Rison [SMTP:stuart@ludwig.ucl.ac.uk]
> Sent:    Monday, June 14, 1999 10:50 AM
> To:    Herouth Maoz; pgsql-general@postgreSQL.org
> Subject:    Re: [GENERAL] Two variable passed to PL/Function and on is
> NULL
>
> Hi Herouth,
>
> >At 15:44 +0300 on 14/06/1999, Stuart Rison wrote:
> >
> >
> >> i) Is it the case that if you pass to variables to a postgres function
> and
> >> one is NULL, the function cannot tell which one?
> >> ii) Is there a workaround of some kind (in particular in pl/pgsql)?
> >> [Currently I am copying the table into a temp table and updating all
> NULL
> >> values to a token value.]
> >
> >I think you will do alright in pl/pgsql. Take for example the following
> >function which returns 1000 when its argument is null:
> >
>
> <snip - a function that works fine but take only one argument>
>
> The problem only occur when you have a function which takes more than one
> argument.
>
> e.g.
>
> create function null1000(int4,int4) returns int4 as '
> DECLARE
>   first_arg alias for $1;
>   second_arg alias for $2;
> BEGIN
>         IF first_arg IS NULL THEN
>                 RETURN 1000;
>   ELSE
>                 RETURN first_arg;
>         END IF;
> END;
> '
> language 'plpgsql';
>
> cgh=> select * from test1;
>  nm|nm_two
> ---+------
>   4|
>   8|
>    |
>  16|
>  32|
>  64|     6
> 128|     7
> 256|     8
> 512|     9
>    |    10
> (10 rows)
>
> cgh=> select nm,nm_two,null1000(nm,nm_two) from test1;
>  nm|nm_two|null1000
> ---+------+--------
>   4|      |    1000
>   8|      |    1000
>    |      |    1000
>  16|      |    1000
>  32|      |    1000
>  64|     6|      64
> 128|     7|     128
> 256|     8|     256
> 512|     9|     512
>    |    10|    1000
> (10 rows)
>
> as soon a NULL is passed as an argument, both values are treated as NULL
> by
> the function.  I think the problem occurs before you even enter the
> function itself; in other words, both values become NULL 'internally' and
> not within the function so you can't trap them in the function itself with
> 'IS NULL' checks.
>
> I think this is a know issue with 6.4 but there was some suggestion it may
> have been corrected in 6.5 (fact, fiction?)
>
> furthermore, I'm unlikely to be moving to 6.5 in the near future so has
> anyone got a workaround?
>
> cheers,
>
> S.
>
> +-------------------------+--------------------------------------+
> | Stuart Rison            | Ludwig Institute for Cancer Research |
> +-------------------------+ 91 Riding House Street               |
> | Tel. (0171) 878 4041    | London, W1P 8BT, UNITED KINGDOM.     |
> | Fax. (0171) 878 4040    | stuart@ludwig.ucl.ac.uk              |
> +-------------------------+--------------------------------------+

Michael J Davis <michael.j.davis@tvguide.com> writes:
> Create an nz(int4) or nvl(int4) function that returns 0 if $1 is null.
> You could also create nz(text) that returns '' when $1 is null.

Also, you can use the COALESCE() standard function to handle this sort
of thing: COALESCE(a,b,...) basically returns the first non-null value
in its argument list.  So COALESCE(x,0) or COALESCE(x,'') would handle
the above requirements.

COALESCE is a shorthand form of a CASE expression, which allows for
even more general if-then-else calculations.

CASE is present but a tad buggy in 6.4 (IIRC, it fails if used in a
SELECT that joins more than one table).  There are no known problems
with it in 6.5.

            regards, tom lane