Обсуждение: Functions, composite types and Notice

Поиск
Список
Период
Сортировка

Functions, composite types and Notice

От
"Hakan Kocaman"
Дата:
Hi group,

got a question regarding the different kinds calling a function
returning record.
This is 8.1.3 on gnu/linux.

Consider this function:

CREATE OR REPLACE FUNCTION public.check_notice(
IN in_a int,
IN in_b text,
OUT out_a int,
OUT out_b text
)
RETURNS record as
$BODY$
DECLARE
BEGIN
-- Init
RAISE NOTICE '---- Init';
RAISE NOTICE '---- in_a % ----',in_a;
RAISE NOTICE '---- in_b % ----',in_b;
RAISE NOTICE '---- out_a % ----',out_a;
RAISE NOTICE '---- out_b % ----',out_B;
out_a:=in_a;
out_b:=in_b;
-- assignment
RAISE NOTICE '---- assignment';
RAISE NOTICE '---- in_a % ----',in_a;
RAISE NOTICE '---- in_b % ----',in_b;
RAISE NOTICE '---- out_a % ----',out_a;
RAISE NOTICE '---- out_b % ----',out_B;
RETURN;
END;
$BODY$
LANGUAGE 'plpgsql' VOLATILE;

You can call this function like this :
=# select public.check_notice(2,'hello');
NOTICE: ---- Init
NOTICE: ---- in_a 2 ----
NOTICE: ---- in_b hello ----
NOTICE: ---- out_a <NULL> ----
NOTICE: ---- out_b <NULL> ----
NOTICE: ---- assignment
NOTICE: ---- in_a 2 ----
NOTICE: ---- in_b hello ----
NOTICE: ---- out_a 2 ----
NOTICE: ---- out_b hello ----
check_notice
--------------
(2,hello)
(1 row)

Thats OK.

If you want to get the OUT-Params each as columns, you got to call it
this way:
=# select (public.check_notice(2,'hello')).*;
NOTICE: ---- Init
NOTICE: ---- in_a 2 ----
NOTICE: ---- in_b hello ----
NOTICE: ---- out_a <NULL> ----
NOTICE: ---- out_b <NULL> ----
NOTICE: ---- assignment
NOTICE: ---- in_a 2 ----
NOTICE: ---- in_b hello ----
NOTICE: ---- out_a 2 ----
NOTICE: ---- out_b hello ----
NOTICE: ---- Init
NOTICE: ---- in_a 2 ----
NOTICE: ---- in_b hello ----
NOTICE: ---- out_a <NULL> ----
NOTICE: ---- out_b <NULL> ----
NOTICE: ---- assignment
NOTICE: ---- in_a 2 ----
NOTICE: ---- in_b hello ----
NOTICE: ---- out_a 2 ----
NOTICE: ---- out_b hello ----
out_a | out_b
-------+-------
2 | hello
(1 row)

It looks like the function is evaluated twice.
In general the function seems to got evaluated for each OUT-Param.
Is this intended ?
Are their other ways to get the OUT-Params as columns ?
Any hints to the docs?
This would be very convenient, i got a function with 4 OUT-Params and
don't want to pay this price for convenience.

As a side note:
I'm glad to have problems like this.
With the other product i didnt even got the chance :~)

Best regards

Hakan Kocaman

Re: Functions, composite types and Notice

От
Tom Lane
Дата:
"Hakan Kocaman" <Hakan.Kocaman@digame.de> writes:
> If you want to get the OUT-Params each as columns, you got to call it
> this way:
> =# select (public.check_notice(2,'hello')).*;

Try this way instead:

    select * from public.check_notice(2,'hello');

            regards, tom lane

Re: Functions, composite types and Notice

От
"Hakan Kocaman"
Дата:
> -----Original Message-----
> From: Tom Lane [mailto:tgl@sss.pgh.pa.us]
> Sent: Thursday, February 01, 2007 5:26 PM
> To: Hakan Kocaman
> Cc: pgsql-general@postgresql.org
> Subject: Re: [GENERAL] Functions, composite types and Notice
>
>
> "Hakan Kocaman" <Hakan.Kocaman@digame.de> writes:
> > If you want to get the OUT-Params each as columns, you got
> to call it
> > this way:
> > =# select (public.check_notice(2,'hello')).*;
>
> Try this way instead:
>
>     select * from public.check_notice(2,'hello');
>
>             regards, tom lane
>

Thanks Tom,

i'm a little bit ashamed :~)

Perhaps i can excuse my blindness with the fact,
that i want to feed the function with 3 params,
that i gather from 2 tables.

so i call the function now like this (obfuscated):
select
    public.check_notice(t1.a,t1.b,t2.c)
from
    public.tab1 t1,
    public.tab2 t2

I'm not clear how i can use the mentioned syntax with this kind of
query.
I can't put the function and the tables on the same level(FROM-Clause),
is their any other way?

Thanks a lot

Hakan *goes buying "SQL for dummies"*

Re: Functions, composite types and Notice

От
Tom Lane
Дата:
"Hakan Kocaman" <Hakan.Kocaman@digame.de> writes:
>> Try this way instead:
>> select * from public.check_notice(2,'hello');

> so i call the function now like this (obfuscated):
> select
>     public.check_notice(t1.a,t1.b,t2.c)
> from
>     public.tab1 t1,
>     public.tab2 t2

> I'm not clear how i can use the mentioned syntax with this kind of
> query.

No, you can't at the moment; you have to use the way you're doing it.
There's been some speculation that SQL2003's LATERAL syntax might fix
this problem, but no one's dug into it deeply enough to even be sure
of that, let alone figure out what it'll take to implement it.

If you're trying to avoid multiple evaluation of the function, the best
way is to use "OFFSET 0" as an optimization fence to prevent flattening
of a subquery.  I get what seems to be the right thing from

select (x).* from (select sumprod(f1,f2) as x from foo offset 0) ss;

            regards, tom lane

Re: Functions, composite types and Notice

От
"Hakan Kocaman"
Дата:
Thanks Tom.

That did it.
Theirs always something to learn, when i read you.

Best regards

Hakan



> -----Original Message-----
> From: Tom Lane [mailto:tgl@sss.pgh.pa.us]
> Sent: Friday, February 02, 2007 4:04 PM
> To: Hakan Kocaman
> Cc: pgsql-general@postgresql.org
> Subject: Re: [GENERAL] Functions, composite types and Notice
>
>
> "Hakan Kocaman" <Hakan.Kocaman@digame.de> writes:
> >> Try this way instead:
> >> select * from public.check_notice(2,'hello');
>
> > so i call the function now like this (obfuscated):
> > select
> >     public.check_notice(t1.a,t1.b,t2.c)
> > from
> >     public.tab1 t1,
> >     public.tab2 t2
>
> > I'm not clear how i can use the mentioned syntax with this kind of
> > query.
>
> No, you can't at the moment; you have to use the way you're doing it.
> There's been some speculation that SQL2003's LATERAL syntax might fix
> this problem, but no one's dug into it deeply enough to even be sure
> of that, let alone figure out what it'll take to implement it.
>
> If you're trying to avoid multiple evaluation of the
> function, the best
> way is to use "OFFSET 0" as an optimization fence to prevent
> flattening
> of a subquery.  I get what seems to be the right thing from
>
> select (x).* from (select sumprod(f1,f2) as x from foo offset 0) ss;
>
>             regards, tom lane
>