Re: HOWTO caching data across function calls: temporary tables, cursor?

From: "Albe Laurenz" <laurenz(dot)albe(at)wien(dot)gv(dot)at>
To: "Ivan Sergio Borgonovo *EXTERN*" <mail(at)webthatworks(dot)it>, <pgsql-general(at)postgresql(dot)org>
Subject: Re: HOWTO caching data across function calls: temporary tables, cursor?
Date: 2008-04-01 14:08:45
Message-ID: D960CB61B694CF459DCFB4B0128514C201ED287B@exadv11.host.magwien.gv.at
Views: Raw Message | Whole Thread | Download mbox | Resend email
Thread:
Lists: pgsql-general

Ivan Sergio Borgonovo wrote:
[wants to cache query results in a temporary table for use in
several functions]

> yes... but it is not just a matter of caching the data but rather
> being able to exploit them with SQL.

Oh, I see, you want to select/join with the cached data.

Then neither arrays nor cursors can help; you need a temporary table.

> A possible way could be to encapsulate the temp table in a function,
> but still I'd like to find a tutorial/howto etc... that will point
> out the troubles I'm going to meet with uniqueness of the name,
> visibility, garbage collection...

You can
CREATE TEMPORARY TABLE basket_123 [ON COMMIT DROP] AS SELECT ....
If you do not include ON COMMIT DROP, the table will be dropped at the end
of your database session.

To have more than one table and have a unique name, you can
use a sequence to construct the table name. Tha means you will have
to use dynamic SQL.

> Suppose I've a function that return a setof record
>
> I could use that function inside other function as in
>
> select into [vars,...] [cols,...] from AFunction(...) where cols1<7...
>
> Now AFuncion(...) is going to retrieve over and over the same record
> set inside a transaction.
>
> AFuncion will be used inside several other functions.
>
> It would be nice if I could cache the result of AFunction.

Since you are looking for a sample, maybe something like that can get you started:

CREATE SEQUENCE temp_names;

CREATE FUNCTION mkcache(param1 integer, param2 text) RETURNS name
LANGUAGE plpgsql VOLATILE STRICT AS
$$DECLARE
i integer;
BEGIN
SELECT nextval('temp_names') INTO i;
EXECUTE 'CREATE TEMPORARY TABLE basket_' || i || '(col1, col2, ...) AS SELECT .....';
RETURN 'basket_' || i;
END;$$;

CREATE FUNCTION getcache(tabname IN name, col1 OUT integer, col2 OUT text, ...) RETURNS SETOF RECORD
LANGUAGE plpgsql IMMUTABLE STRICT AS
$$BEGIN
FOR col1, col2, ... IN EXECUTE 'SELECT col1, col2, ... FROM ' || tabname LOOP
RETURN NEXT;
END LOOP;
RETURN;
END;$$;

Sample use:

SELECT mkcache(1, 'test');
mkcache
----------
basket_1
(1 row)

SELECT * FROM getcache('basket_1');
col1 | col2 | ...
------+-------+-----
27 | item1 | ...
....
(n rows)

> For me it's not clear if adding some additional caching system (eg.
> create a temp table inside the function) would obtain the same result
> as marking the function STABLE.

No, STABLE doen't help here - that is only a hint for the optimizer.

Yours,
Laurenz Albe

In response to

Responses

Browse pgsql-general by date

  From Date Subject
Next Message korry 2008-04-01 14:11:30 Re: Role attribute for user email?
Previous Message Ivan Sergio Borgonovo 2008-04-01 13:00:41 Re: HOWTO caching data across function calls: temporary tables, cursor?