Обсуждение: when to use "execute" in plpgsql?

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

when to use "execute" in plpgsql?

От
Enrico Sirola
Дата:
Hello,

I'm having some troubles with the correct use of the execute plpgsql
statement. Where I work, we have a postgresql db hosting a set of
schemas all with the same tables and, from time to time, we upgrade
the schemas to a new version coding a stored procedure like the
following (pseudocode):

-------> example use case <--------

-- upgrade function, gets a schema name as input and upgrades it
create function upgrade_to_new_version(schema_name name)
returns void as $$
begin

    -- become the schema owner
    execute 'set role to ' || schema_name;

    /* perform DDL and data transformations work here */
    /* body here */
end;
language plpgsql volatile strict;

-- schemas_to_upgrade contains a column sname with the names of
-- the schemas needing an upgrade
select upgrade_to_new_version(sname) from schemas_to_upgrade;

--------->example end<-------------

the strange thing is that from time to time the function doesn't work.
Or, even worst, It works for a database but doesn't on another. The
issue usually goes away if we substitute the statement into /* body
here */ prepending those with an execute and submitting those via
execute; apparently the behaviour is reproducibile given a database
instance (i.e. it is not random), but it is impossible (at least for
us) to tell in advance if it will happen on another database (with the
same schemas and postgresql version number which, by the way, is the
official 8.3.5 on centos5/x86_64). The "safe" way to do things (it
never breaks) is to pass every statement via executes but we would
like to dig on this.

What are we missing?
Thanks in advance for your help,
enrico

Re: when to use "execute" in plpgsql?

От
Fernando Moreno
Дата:
Hi, check this out:
http://archives.postgresql.org/pgsql-general/2008-05/msg00938.php

I would say that execute is the only way to achieve some things
related to schemas and temp tables.

Re: when to use "execute" in plpgsql?

От
Merlin Moncure
Дата:
On Fri, Feb 27, 2009 at 12:00 PM, Enrico Sirola <enrico.sirola@gmail.com> wrote:
> Hello,
>
> I'm having some troubles with the correct use of the execute plpgsql
> statement. Where I work, we have a postgresql db hosting a set of schemas
> all with the same tables and, from time to time, we upgrade the schemas to a
> new version coding a stored procedure like the following (pseudocode):
>
> -------> example use case <--------
>
> -- upgrade function, gets a schema name as input and upgrades it
> create function upgrade_to_new_version(schema_name name)
> returns void as $$
> begin

I'm not completely sure what the problem is because this is light on
detail, but here's a what I bet the problem is. static (that is, not
EXECUTE-ed) queries in pl/pgsql functions convert table references in
the function body to fixed 'pointers' to actual tables that are always
schema qualified.  Once the function is run the first time and the
plan generated, changing the schema will have no bearing on which
tables are used.  Thus, the function will not 'float' with the current
schema search path setting.

dynamic sql functions however will always re-look up the tables based
on the search path because the plan is not saved off for the query.

If this is your problem, you have a couple of options:

*) always use dynamic sql in functions that are meant to apply to
multiple schemas in the same session
*) duplicate your function for each schema and make your tables fully
schema qualified
*) DISCARD your plans before running your function

merlin

Re: when to use "execute" in plpgsql?

От
Sim Zacks
Дата:
-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1

Merlin Moncure wrote:
> I'm not completely sure what the problem is because this is light on
> detail, but here's a what I bet the problem is. static (that is, not
> EXECUTE-ed) queries in pl/pgsql functions convert table references in
> the function body to fixed 'pointers' to actual tables that are always
> schema qualified.  Once the function is run the first time and the
> plan generated, changing the schema will have no bearing on which
> tables are used.  Thus, the function will not 'float' with the current
> schema search path setting.

We had similar problems to this when using temp tables in a function.
Because the temp tables disappear and pg stores the oid, the second time
it is run we were getting an error message. I posted about it on Oct 10.
2005, subject: strange error.

My experience in this is just from 8.0 so I don't know if anything has
changed. In general, if tables are created or deleted within the
function then you want to use execute, as well as if the tables are
recreated in the course of a normal workflow. For example, if you have a
table that you regenerate once a day (by drop and create) you will not
want to reference that table in a view or function.

Obviously if you want to run dynamic code you also need to use execute.

Sim
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.4.9 (MingW32)
Comment: Using GnuPG with Mozilla - http://enigmail.mozdev.org

iEYEARECAAYFAkmqnSkACgkQjDX6szCBa+o77gCgjB7W+4tIYZVPtEvaF1Uj3QBC
fPcAoOubAAC9dr5opTRyFsyUfLq6ojQF
=q5NU
-----END PGP SIGNATURE-----

Re: when to use "execute" in plpgsql?

От
Pavel Stehule
Дата:
Hello

>
> My experience in this is just from 8.0 so I don't know if anything has
> changed. In general, if tables are created or deleted within the
> function then you want to use execute, as well as if the tables are
> recreated in the course of a normal workflow. For example, if you have a
> table that you regenerate once a day (by drop and create) you will not
> want to reference that table in a view or function.

this bug is solved in 8.3

regards
Pavel Stehule
>
> Obviously if you want to run dynamic code you also need to use execute.
>
> Sim
> -----BEGIN PGP SIGNATURE-----
> Version: GnuPG v1.4.9 (MingW32)
> Comment: Using GnuPG with Mozilla - http://enigmail.mozdev.org
>
> iEYEARECAAYFAkmqnSkACgkQjDX6szCBa+o77gCgjB7W+4tIYZVPtEvaF1Uj3QBC
> fPcAoOubAAC9dr5opTRyFsyUfLq6ojQF
> =q5NU
> -----END PGP SIGNATURE-----
>
> --
> Sent via pgsql-general mailing list (pgsql-general@postgresql.org)
> To make changes to your subscription:
> http://www.postgresql.org/mailpref/pgsql-general
>