Re: Alias for function return buffer in pl/pgsql?

From: "Pavel Stehule" <pavel(dot)stehule(at)gmail(dot)com>
To: "Bart Grantham" <bg(at)logicworks(dot)net>
Cc: "pgsql-general(at)postgresql(dot)org" <pgsql-general(at)postgresql(dot)org>
Subject: Re: Alias for function return buffer in pl/pgsql?
Date: 2008-08-13 11:29:09
Message-ID: 162867790808130429n12242c46s5ca4608739fa04cb@mail.gmail.com
Views: Raw Message | Whole Thread | Download mbox | Resend email
Thread:
Lists: pgsql-general

Hello

array_append is relative slow. You can use SRF function for someone (I
am not sure if it's your case, but maybe).
postgres=# create or replace function buida(m int) returns int[] as
$$declare r int[] = '{}'; begin for i in 1..m loop r := r || i; end
loop; return r; end $$ language plpgsql strict immutable;
CREATE FUNCTION

postgres=# SELECT array_upper(buida(10000),1);
array_upper
-------------
10000
(1 row)

Time: 324,388 ms
postgres=# create or replace function buida(m int) returns int[] as
$$begin return array(select * from _buida($1)); end $$ language
plpgsql strict immutable;
CREATE FUNCTION
postgres=# create or replace function _buida(m int) returns setof int
as $$begin for i in 1..m loop return next i; end loop; return; end $$
language plpgsql strict immutable;
CREATE FUNCTION
postgres=# SELECT array_upper(buida(10000),1);
array_upper
-------------
10000
(1 row)

Time: 24,191 ms

2008/8/13 Bart Grantham <bg(at)logicworks(dot)net>:
> Hello all, long time no chit-chat on the PG mailing list. We're upgrading
> from 8.0.3 to 8.3 and found that some stored procedures utilizing int_agg
> that we had left over from 7.3 had terrible performance. No problem, using
> ANY() we're able to regain that performance, more or less, and at the same
> time greatly simplify our stored procedures. But things can never be fast
> enough, can they? So I have a question or two. Here's my function for
> reference:
>
>
>
> CREATE OR REPLACE FUNCTION bg_nodes2descendants(INT[], INT) RETURNS SETOF
> connection_generation AS
>
> '
>
>
>
> DECLARE
>
> _row connection_generation%ROWTYPE;
>
> _children INT[];
>
>
>
> BEGIN
>
>
>
> -- this is faster than constructing in the loop below
>
> --_children = array(SELECT connectee_node_id FROM connections WHERE
> connection_type_id = 1 AND connector_node_id = ANY($1));
>
>
>
> FOR _row IN
>
> SELECT connection_id, connection_type_id, connector_node_id,
> connector_node_type_id, connectee_node_id,
>
> connectee_node_type_id, current, timestamp, $2 + 1
>
> FROM connections WHERE connection_type_id = 1 AND connector_node_id
> = ANY($1)
>
> LOOP
>
> _children := _children || _row.connectee_node_id;
>
> RETURN NEXT _row;
>
> END LOOP;
>
>
>
> IF FOUND THEN
>
> RETURN QUERY SELECT * FROM bg_nodes2descendants(_children, $2+1);
>
> END IF;
>
>
>
> RETURN;
>
> END
>
>
>
> ' LANGUAGE 'plpgsql';
>
>
>
> So, my concern is alluded to in the comment above. When I use this
> function in places where it returns large results, building the _children
> array directly (in the commented out line) is about 25% faster. But I'd
> like to avoid building the children array altogether and would instead like
> to generate that array from the already collected output rows. For example,
> right before the recursive call, I'd like to select a column of the buffered
> output rows, cast it to an integer[], and pass it into the recursive call.
> Is there an internal value I can access for this such as:
>
>
>
> _children := array(SELECT connectee_node_id FROM $output);
>
>
>
> Bonus question - if I rewrite the first FOR loop as:
>
>
>
> RETURN QUERY SELECT connection_id, connection_type_id, connector_node_id,
> connector_node_type_id, connectee_node_id,
>
> connectee_node_type_id, current, timestamp, $2
> + 1 FROM connections
>
> WHERE connection_type_id = 1 AND connector_node_id =
> ANY($1);
>
>
>
> I get "ERROR: structure of query does not match function result type", even
> though the type signatures of the returned columns match the
> "connection_generation" rowtype. I am pretty sure this could be resolved by
> casting the resulting columns to that row type, but I am lost as to how the
> syntax to do such a thing would look.

this syntax is correct, it's probably postgresql bug

regards
pavel stehule

>
>
>
> Thanks in advance for the help, and keep up the great work. PG8.3 is an
> amazing piece of software and it blows me away how much more advanced it
> gets with every release.
>
>
>
> Bart Grantham
>
> VP of R&D
>
> Logicworks Inc. – Complex and Managed Hosting

In response to

Browse pgsql-general by date

  From Date Subject
Next Message Pavel Stehule 2008-08-13 11:51:25 Re: Alias for function return buffer in pl/pgsql?
Previous Message Reid Thompson 2008-08-13 11:27:13 Re: Disk space occupied by a table in postgresql