Thread: Unexpected function behaviour with NULL and/or default NULL parameters

Unexpected function behaviour with NULL and/or default NULL parameters

From
"Gunnar \"Nick\" Bluth"
Date:
-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1

Hello,

I'm experiencing odd behaviour with a function I wrote yesterday.

Background: function is supposed to deliver some "terms and
conditions" from a table; when the "locale" is found, deliver the
highest version of that, otherwise, deliver the highest version of the
"default" locale.

CREATE OR REPLACE FUNCTION
public.get_current_tac(userid bigint, sessionid uuid, locale character
varying, OUT current_tac json)
 RETURNS json
 LANGUAGE sql
 IMMUTABLE STRICT SECURITY DEFINER
AS $function$
SELECT json_agg(selected) FROM (
  SELECT * FROM (
    SELECT *, 1 AS locale_specific FROM terms_and_conditions WHERE
locale = $3 ORDER BY version DESC LIMIT 1
  ) specific
UNION
  SELECT * FROM (
    SELECT *, 0 AS locale_specific FROM terms_and_conditions WHERE
locale = 'default' ORDER BY version DESC LIMIT 1
  ) unspecific
ORDER BY locale_specific DESC
LIMIT 1
) selected;
$function$

This works fine when I give valid userid, sessionid and locale:
=# select
get_current_tac(userid:=38,sessionid:='79993643-ec3c-0359-f603-069b543ce4a8'::uuid,locale:='en');

get_current_tac
-

----------------------------------------------------------------------------------------------------------------------------------------------------------
 [{"locale":"default","version":1,"updated_at":"2015-05-05T14:04:17.246684+02:00","terms_and_conditions":"Hier kommen
dieAGB rein","locale_specific":0}] 
(1 row)


Then I realised I don't really need those first two parameters and
applied default values (NULL). As $1 and $2 are not used, it should
still work, right? Well, it returns one empty (!) row (behaviour is
the same when declaring NULL as default values in the function header,
can't show as there's another version with only "locale" as parameter):

# select get_current_tac(userid:=null, sessionid:=null::uuid,
locale:='en');
 get_current_tac
- ------------------------
 <NULL>
(1 row)

I'm completely puzzled by this behaviour; at least it should cast the
"locale_specific" value into the JSON output, shouldn't it?

What am I missing? Any hints appreciated!
- --
Gunnar "Nick" Bluth
RHCE/SCLA

Mobil +49 172 8853339
Email: gunnar.bluth@pro-open.de
_____________________________________________________________
In 1984 mainstream users were choosing VMS over UNIX.
Ten years later they are choosing Windows over UNIX.
What part of that message aren't you getting? - Tom Payne

-----BEGIN PGP SIGNATURE-----
Version: GnuPG v2.0.22 (MingW32)

iQEcBAEBAgAGBQJVScPtAAoJEBAQrmsyiTOMRpwIANOALdxqB3V35IaYyXg/BLJz
Vnfgz6tsq97vDPvlCq7J/3ratnsJJqB218tGWX9jNr5Jcs/Ak0ZfZFcGHBE/YFxJ
2H6+30CHFeHVdGRkAF4Lu0rDcXoABhe0vIwfpQpRileXPpukQL9+oyE7nNI5H5dn
cb6UzqjxLEu/LgEZUgh5M3P680gPWm2gx1ojBu/a1I6i7pZiBVGxH0dtcFn1Gwsh
CFb5iByrGl+ghuxge4N1Kc02RhgDhdgedV0Rfj5oD6PuGuTmFarfbdZpc057y553
eo8jllZFE1Qoj1pWvZSL+gLQVp3bzoy3XxtbDGFZXNB7wfSSCs5t61HjaoMM7lk=
=ae0S
-----END PGP SIGNATURE-----

Attachment

Re: Unexpected function behaviour with NULL and/or default NULL parameters

From
"David G. Johnston"
Date:
On Wednesday, May 6, 2015, Gunnar "Nick" Bluth <gunnar.bluth@pro-open.de> wrote:
-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1

Hello,

I'm experiencing odd behaviour with a function I wrote yesterday.

Background: function is supposed to deliver some "terms and
conditions" from a table; when the "locale" is found, deliver the
highest version of that, otherwise, deliver the highest version of the
"default" locale.

CREATE OR REPLACE FUNCTION
public.get_current_tac(userid bigint, sessionid uuid, locale character
varying, OUT current_tac json)
 RETURNS json
 LANGUAGE sql
 IMMUTABLE STRICT SECURITY DEFINER
AS $function$


Then I realised I don't really need those first two parameters and
applied default values (NULL). As $1 and $2 are not used, it should
still work, right? Well, it returns one empty (!) row (behaviour is
the same when declaring NULL as default values in the function header,
can't show as there's another version with only "locale" as parameter):

# select get_current_tac(userid:=null, sessionid:=null::uuid,
locale:='en');
 get_current_tac
- ------------------------
 <NULL>
(1 row)


If you want to allow null to be passed to a function you shouldn't declare it as STRICT...

David J. 

Re: Unexpected function behaviour with NULL and/or default NULL parameters

From
"David G. Johnston"
Date:
 Wednesday, May 6, 2015, Gunnar "Nick" Bluth <gunnar.bluth@pro-open.de> wrote:
-----BEGIN PGP SIGNED MESSAGE-----
CREATE OR REPLACE FUNCTION
public.get_current_tac(userid bigint, sessionid uuid, locale character
varying, OUT current_tac json)
 RETURNS json
 LANGUAGE sql
 IMMUTABLE STRICT SECURITY DEFINER
AS $function$
SELECT json_agg(selected) FROM (
  SELECT * FROM (
    SELECT *, 1 AS locale_specific FROM terms_and_conditions WHERE
locale = $3 ORDER BY version DESC LIMIT 1
  ) specific
UNION
  SELECT * FROM (
    SELECT *, 0 AS locale_specific FROM terms_and_conditions WHERE
locale = 'default' ORDER BY version DESC LIMIT 1
  ) unspecific
ORDER BY locale_specific DESC
LIMIT 1
) selected;
$function$


Also, I don't know why you would need "security definer" but defining the functions as being "immutable" is a flat out lie.  Combined with your misuse of "strict" I would suggest you read up on function creation and usage in the documentation.

It also looks odd to define the OUT parameter along with "RETURNS json" - unless it is giving you some kind of output column name benefit that I cannot remember at the moment.

David J.

Re: Unexpected function behaviour with NULL and/or default NULL parameters

From
"Gunnar \"Nick\" Bluth"
Date:
-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1

Am 06.05.2015 um 09:57 schrieb David G. Johnston:

Ooops, accidentaly replied to David directly...

> Wednesday, May 6, 2015, Gunnar "Nick" Bluth
> <gunnar.bluth@pro-open.de <mailto:gunnar.bluth@pro-open.de>>
> wrote:
>
> -----BEGIN PGP SIGNED MESSAGE----- CREATE OR REPLACE FUNCTION
> public.get_current_tac(userid bigint, sessionid uuid, locale
> character varying, OUT current_tac json) RETURNS json LANGUAGE sql
> IMMUTABLE STRICT SECURITY DEFINER AS $function$ SELECT
> json_agg(selected) FROM ( SELECT * FROM ( SELECT *, 1 AS
> locale_specific FROM terms_and_conditions WHERE locale = $3 ORDER
> BY version DESC LIMIT 1 ) specific UNION SELECT * FROM ( SELECT *,
> 0 AS locale_specific FROM terms_and_conditions WHERE locale =
> 'default' ORDER BY version DESC LIMIT 1 ) unspecific ORDER BY
> locale_specific DESC LIMIT 1 ) selected; $function$
>
>
> Also, I don't know why you would need "security definer" but
> defining

Nothing in the DB is accessible to the apache user directly, thus the
security definer.

> the functions as being "immutable" is a flat out lie.  Combined
> with your misuse of "strict" I would suggest you read up on
> function creation and usage in the documentation.

Well, you're of course right... wrote a bunch of real immutable strict
functions these last days, so that just sticked. Always think before
writing... w/out the two, the function behaves as expected. I'll
review the other functions as well now!


> It also looks odd to define the OUT parameter along with "RETURNS
> json" - unless it is giving you some kind of output column name
> benefit that I cannot remember at the moment.

That's how it was put into my vim when doing an "\ef"...

Cheers,
- --
Gunnar "Nick" Bluth
RHCE/SCLA

Mobil +49 172 8853339
Email: gunnar.bluth@pro-open.de
_____________________________________________________________
In 1984 mainstream users were choosing VMS over UNIX.
Ten years later they are choosing Windows over UNIX.
What part of that message aren't you getting? - Tom Payne

-----BEGIN PGP SIGNATURE-----
Version: GnuPG v2.0.22 (MingW32)

iQEcBAEBAgAGBQJVSfdIAAoJEBAQrmsyiTOMN84IAMhgo3blO5oZqTJjyHnfznYW
MvKx5NuZkTQ4xphzlD2XdEGEASzb1FEUShKw1OB7TQ7E8O0aq19oXqdVIOyL0oVi
GCZgT5uDEY7WpIsP98qaO0GEZ/Tc6hUUbH6DLB6fhRdnrNQPoSssi682HgIvg83e
PDjgkS4+Zi2CWquF4jDPeaMGjp/+hFUtecZaYl3XqoD3GWtbj9T3LidFBfZPj0iV
V7qGvbcpu1r0bYRmA5dXiVkaFtq2xqBZn2T1S2uzd2giqCIm8L1uXTAEFt/fNlvC
wyu9mzfQUA0lyPLyIbUFfSb1Csgb7uSZXVOGgc++rgps5wZ+ZssCcx+4VcdF09A=
=1i6y
-----END PGP SIGNATURE-----

Attachment