Обсуждение: tuple return from function

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

tuple return from function

От
jwieck@debis.com (Jan Wieck)
Дата:
Hi,

    I  really  wonder  if  anybody  ever used functions returning
    tuples or sets of tuples. If so, be careful!

    Let's have a look at the following test:

create table emp (name text, salary money);
create table sal_log (empname text, salchg money, who text, when datetime);

create function change_sal(text, money) returns emp as '
    update emp set salary = salary + $2 where name = $1;
    insert into sal_log values ($1, $2, getpgusername(), ''now'');
    select * from emp where name = $1;' language 'sql';
    -- ****                                       ^^^
    -- ****                                       |||

insert into emp values ('Jan', '0.00');
select change_sal('Jan', '1000.00');
CREATE
CREATE
CREATE
INSERT 18423 1
change_sal
----------
 136044880
(1 row)
    -- **** 136044880 is the memory address of the tuple table slot
    -- **** returned by the function change_sal() - very useful :-)

select * from emp;
name|salary
----+---------
Jan |$1,000.00
(1 row)

select * from sal_log;
empname|salchg   |who  |when
-------+---------+-----+--------------------------------
Jan    |$1,000.00|pgsql|Thu Aug 13 12:46:28 1998 MET DST
(1 row)
    -- **** But the result is OK so far

    -- **** Now we use the so called nested dot notation to get
    -- **** the name from the returned tuple
select name(change_sal('Jan', '1000.00'));
name
----
Jan
(1 row)
    -- **** That's right

select * from emp;
name|salary
----+------
Jan |
(1 row)

select * from sal_log;
empname|salchg   |who  |when
-------+---------+-----+--------------------------------
Jan    |$1,000.00|pgsql|Thu Aug 13 12:46:28 1998 MET DST
Jan    |$1,000.00|pgsql|Thu Aug 13 12:46:28 1998 MET DST
Jan    |         |pgsql|Thu Aug 13 12:46:28 1998 MET DST
(3 rows)
EOF
    -- **** But this isn't what anyone would expect

    Background:

    I'm not really sure if I used the correct syntax to access  a
    field from the returned tuple. If not, please correct me.

    The  reason for the behaviour is the generated querytree.  It
    is a nested function call of two times  change_sal().   There
    is  a  func  node  for change_sal() with one argument that is
    change_sal('Jan', '1000.0') func node.  Both func nodes  have
    the same targetlist about 'name'.

    At  the  beginning  of  ExecMakeFunctionResult() the argument
    from the outer is evaluated and causes the call of the  inner
    one. When the inner one finishes, it returns the name (due to
    the target list).  This single return value then replaces the
    argument    vector    for    the   outer   func   node.   Now
    postquel_function() is called but with only one argument, the
    second  expected  argument now is a NULL value. That explains
    the behaviour above.

    But don't expect

        select salary(change_sal('Jan', '1000.00'))

    to work. It causes an

        ERROR:  Tuple is too big: size 200064

    Even if  you  have  a  function  not  updating  or  inserting
    something,  the generated querytree causes the function to be
    called twice. So a simple function just doing one select  and
    returning a tuple type causes two scans.

    What  I absolutely don't know is, what is it good for? How is
    the correct syntax to access more than  one  field  from  the
    returned tuple?

    Shouldn't  the  call  of a function returning a tuple without
    the surrounding attrname(...) have a targetlist too?  If  so,
    the  complete  targetlist  must  be  used  when  building the
    projection tuple, not only the first TLE as it is implemented
    now.

    And  I think the parser/planner must not generate nested func
    nodes.

    I'm really willing to dive into, but should I do it before or
    after  6.4?  Doing it before would mean 6.4 NOT AT THE END OF
    THIS MONTH!


Jan

--

#======================================================================#
# It's easier to get forgiveness for being wrong than for being right. #
# Let's break this rule - forgive me.                                  #
#======================================== jwieck@debis.com (Jan Wieck) #

Re: [HACKERS] tuple return from function

От
Bruce Momjian
Дата:
>
>     But don't expect
>
>         select salary(change_sal('Jan', '1000.00'))
>
>     to work. It causes an
>
>         ERROR:  Tuple is too big: size 200064
>
>     Even if  you  have  a  function  not  updating  or  inserting
>     something,  the generated querytree causes the function to be
>     called twice. So a simple function just doing one select  and
>     returning a tuple type causes two scans.
>
>     What  I absolutely don't know is, what is it good for? How is
>     the correct syntax to access more than  one  field  from  the
>     returned tuple?
>
>     Shouldn't  the  call  of a function returning a tuple without
>     the surrounding attrname(...) have a targetlist too?  If  so,
>     the  complete  targetlist  must  be  used  when  building the
>     projection tuple, not only the first TLE as it is implemented
>     now.
>
>     And  I think the parser/planner must not generate nested func
>     nodes.
>
>     I'm really willing to dive into, but should I do it before or
>     after  6.4?  Doing it before would mean 6.4 NOT AT THE END OF
>     THIS MONTH!

I have felt that the 'return set' has only worked in limited cases.
Vadim seems to know there are problems, particularly with free'ing
memory.

My question is whether this relates to the rules system rewrite or the
PL/SQL language module?

--
Bruce Momjian                          |  830 Blythe Avenue
maillist@candle.pha.pa.us              |  Drexel Hill, Pennsylvania 19026
  +  If your life is a hard drive,     |  (610) 353-9879(w)
  +  Christ can be your backup.        |  (610) 853-3000(h)

Re: [HACKERS] tuple return from function

От
jwieck@debis.com (Jan Wieck)
Дата:
> I have felt that the 'return set' has only worked in limited cases.
> Vadim seems to know there are problems, particularly with free'ing
> memory.
>
> My question is whether this relates to the rules system rewrite or the
> PL/SQL language module?
>
> --
> Bruce Momjian                          |  830 Blythe Avenue

    It does not relate to the rule system.

    But it relates to the procedural language functions. It would
    be nice to enable tuples and setof tuples as return type  for
    PL/pgSQL and other languages. Currently this is restricted to
    'sql' functions and the return type of tuple (not  setof)  is
    broken.

    In  the  case  of  a  function  returning SETOF tupletype, it
    works.  The function

        create function f1(int4) returns setof t1 as '
            insert into t2 values (''now'');
            select * from t1 where a < $1;
        ' language 'sql';

    when called as

        select a(f1(5));

    produces a RESULT plan with one  entry  in  the  qptargetlist
    that  contains  an ITER->EXPR->FUNC where the FUNC node has a
    targetlist with one entry for attribute a.  The  function  is
    only executed once.

    But when called as

        select a(f1(5)), b(f1(5));

    produces  a  RESULT plan with two entries in the qptargetlist
    where each contains an ITER->EXPR->FUNC where the  FUNC  node
    has  again  a  targetlist  with  one  entry. The result looks
    right, but the function is executed two times (this time  two
    new  entries  in  t2).  This  might  be  right,  because  the
    arguments to f1() could differ. What I haven't found  is  the
    ability  to  evaluate  the  function  once  and  use multiple
    attributes from the return set.

    So you cannot do something like

        insert into t3 select f1(5);

    What this demonstrates clearly to me is that return types  of
    tuple or sets don't really do what they should.

    First I think the call to a function returning one tuple with
    attribute specification must be fixed. It must  not  generate
    the  same  function  call twice (one time inside the argument
    list of the outer one).

    Second the plain tuple return value must  be  useful  in  any
    way.  Currently you cannot have functions f1(int4) returns t1
    and f2(t1) and then do something like f2(f1(5)). It tells 'f2
    has bad return type ...'.

    Third  there  should be an enhancement to specify some or all
    of the attributes like

        select F.a, F.c, F.e from f1(5) F;

    or

        select * from f1(5);

    If this is done, ExecMakeFunctionResult() can be extended. If
    there  is  a targetlist in the func node of a C function (for
    ExecMake...  there is no  difference  between  C,  PL/TCL  or
    PL/pgSQL),  it  knows  that  the  return  value is a tuple or
    tupletable or temp relation or whatever and it can manage for
    the  requested  projection and for the iteration (if function
    isset).

    But should we do that all (and the rule stuff) before 6.4?


Jan

--

#======================================================================#
# It's easier to get forgiveness for being wrong than for being right. #
# Let's break this rule - forgive me.                                  #
#======================================== jwieck@debis.com (Jan Wieck) #

Re: [HACKERS] tuple return from function

От
Bruce Momjian
Дата:
>     there  is  a targetlist in the func node of a C function (for
>     ExecMake...  there is no  difference  between  C,  PL/TCL  or
>     PL/pgSQL),  it  knows  that  the  return  value is a tuple or
>     tupletable or temp relation or whatever and it can manage for
>     the  requested  projection and for the iteration (if function
>     isset).
>
>     But should we do that all (and the rule stuff) before 6.4?

Sorry to say this, but I think we need the rewrite stuff done for 6.4.
Too many bugs and limited features.

The PL/pgSQL perhaps can be started now, but not ready until 6.5?  I
don't think we should delay 6.4 for PL/pgSQL, do you?



--
Bruce Momjian                          |  830 Blythe Avenue
maillist@candle.pha.pa.us              |  Drexel Hill, Pennsylvania 19026
  +  If your life is a hard drive,     |  (610) 353-9879(w)
  +  Christ can be your backup.        |  (610) 853-3000(h)

Re: [HACKERS] tuple return from function

От
jwieck@debis.com (Jan Wieck)
Дата:
Bruce Momjian wrote:

> Sorry to say this, but I think we need the rewrite stuff done for 6.4.
> Too many bugs and limited features.

    Thats right. Do you also agree in that only the instead rules
    should be left?

>
> The PL/pgSQL perhaps can be started now, but not ready until 6.5?  I
> don't think we should delay 6.4 for PL/pgSQL, do you?

    It is in a good, stable state now. I would like  to  have  it
    shipped with 6.4, because removing the non-instead rules is a
    loss of functionality and at least we  must  provide  another
    way.  Someone  might  currently  use  rules  for  some  extra
    actions. But this is subject to trigger procedures. Up to now
    there's only C and Tcl available for it. Not anyone likes Tcl
    -  and  writing  the  triggers  in  C  isn't  fun   for   SQL
    programmers.

    I'll  pack  it  and  send it to you after a last check of the
    code.


Jan

--

#======================================================================#
# It's easier to get forgiveness for being wrong than for being right. #
# Let's break this rule - forgive me.                                  #
#======================================== jwieck@debis.com (Jan Wieck) #

Re: [HACKERS] tuple return from function

От
Bruce Momjian
Дата:
> Bruce Momjian wrote:
>
> > Sorry to say this, but I think we need the rewrite stuff done for 6.4.
> > Too many bugs and limited features.
>
>     Thats right. Do you also agree in that only the instead rules
>     should be left?

Beats me.  Whatever the other developers think.

>
> >
> > The PL/pgSQL perhaps can be started now, but not ready until 6.5?  I
> > don't think we should delay 6.4 for PL/pgSQL, do you?
>
>     It is in a good, stable state now. I would like  to  have  it
>     shipped with 6.4, because removing the non-instead rules is a
>     loss of functionality and at least we  must  provide  another
>     way.  Someone  might  currently  use  rules  for  some  extra
>     actions. But this is subject to trigger procedures. Up to now
>     there's only C and Tcl available for it. Not anyone likes Tcl
>     -  and  writing  the  triggers  in  C  isn't  fun   for   SQL
>     programmers.
>
>     I'll  pack  it  and  send it to you after a last check of the
>     code.

Sure, we will ship whatever you have, even if it is not perfect.

--
Bruce Momjian                          |  830 Blythe Avenue
maillist@candle.pha.pa.us              |  Drexel Hill, Pennsylvania 19026
  +  If your life is a hard drive,     |  (610) 353-9879(w)
  +  Christ can be your backup.        |  (610) 853-3000(h)