Re: Problema con IF NOT FOUND en función plpgsql

From: "Jaime Casanova" <systemguards(at)gmail(dot)com>
To: Sebastián Villalba <sebastian(at)fcm(dot)unc(dot)edu(dot)ar>
Cc: "Lista Ayuda Pgsql" <pgsql-es-ayuda(at)postgresql(dot)org>
Subject: Re: Problema con IF NOT FOUND en función plpgsql
Date: 2006-04-20 04:54:28
Message-ID: c2d9e70e0604192154s741f9dc9ma886aaba52ed06c8@mail.gmail.com
Views: Raw Message | Whole Thread | Download mbox | Resend email
Thread:
Lists: pgsql-es-ayuda

On 4/19/06, Sebastián Villalba <sebastian(at)fcm(dot)unc(dot)edu(dot)ar> wrote:
> Gracias Rubén, Jaime y Alvaro por responder...
>
> On Tue, 18 Apr 2006 23:36:58 -0500, Jaime Casanova wrote
> > esta funcion no deberia ser declarada IMMUTABLE, porque accesa a la
> > base de datos, algo que no debe hacer *ninguna* funcion que sea
> > IMMUTABLE... (no tiene nada que ver con tu duda, por eso no voy a
> > hacer mucho comentario sobre eso ;)
>
> Es cierto que no es mi duda, no obstante creo que no hay ningún problema en
> ser declarada como IMMUTABLE ya que solamente accede para hacer un SELECT, no
> para modificar datos. Al hacer solamente consulta, entiendo que es mas
> eficiente según lo indica en:
>
> http://www.postgresql.org/docs/8.1/static/xfunc-volatility.html
>

ahi dice:

"An IMMUTABLE function cannot modify the database and is guaranteed to
return the same results given the same arguments forever."

traduccion libre:

"Una funcion IMMUTABLE no puede modificar la base de datos y esta
garantizando que *siempre* retornara los mismo resultados dados los
mismo argumentos."

pregunto: puedes tu garantizar que *nunca* y oigase me bien *nunca*
(no, es poco probable; no, no se deberia; no, no habra necesidad)
nadie actualizara, o eliminara ese registro de la base de datos?
alguna vez se discutio esto en la lista en ingles y la conclusion fue
que todo lo que esta en la base de datos *puede* ser actualizado
(aunque tu *nunca* lo vayas a hacer, *puede* pasar) por lo tanto las
funciones IMMUTABLE no deberian accesar a la base ni siquiera con
selects... para eso quiza prefieras STABLE

el resto:

For best optimization results, you should label your functions with
the strictest volatility category that is valid for them.

Any function with side-effects must be labeled VOLATILE, so that calls
to it cannot be optimized away. Even a function with no side-effects
needs to be labeled VOLATILE if its value can change within a single
query; some examples are random(), currval(), timeofday().

There is relatively little difference between STABLE and IMMUTABLE
categories when considering simple interactive queries that are
planned and immediately executed: it doesn't matter a lot whether a
function is executed once during planning or once during query
execution startup. But there is a big difference if the plan is saved
and reused later. Labeling a function IMMUTABLE when it really isn't
may allow it to be prematurely folded to a constant during planning,
resulting in a stale value being re-used during subsequent uses of the
plan. This is a hazard when using prepared statements or when using
function languages that cache plans (such as PL/pgSQL).

Because of the snapshotting behavior of MVCC (see Chapter 12) a
function containing only SELECT commands can safely be marked STABLE,
even if it selects from tables that might be undergoing modifications
by concurrent queries. PostgreSQL will execute a STABLE function using
the snapshot established for the calling query, and so it will see a
fixed view of the database throughout that query. Also note that the
current_timestamp family of functions qualify as stable, since their
values do not change within a transaction.

The same snapshotting behavior is used for SELECT commands within
IMMUTABLE functions. It is generally unwise to select from database
tables within an IMMUTABLE function at all, since the immutability
will be broken if the table contents ever change. However, PostgreSQL
does not enforce that you do not do that.

de arriba:

It is generally unwise to select from database tables within an
IMMUTABLE function at all

traduccion libre:

Generalmente es poco sabio (inteligente) ejecutar select sobre las
tablas de la base de datos desde una funcion IMMUTABLE

> Ahora... otra cosa que puede pasar es que yo con mi inglés que deja bastante
> que desear, haya entendido cualquier cosa ;).
>

yo creo que eso fue

> > > postgres$# IF NOT FOUND THEN
> > > postgres$# RETURN valor;
> > > postgres$# END IF;
> > >
> > > Aquí debería devolverme el valor 33 o yo estoy haciendo muy mal?.
> >
> > No, porque estas haciendo "SELECT INTO valor id" al hacer eso cuando
> > no regreso ninguna fila le asigno NULL valor...
>
> Es cierto... hice ese ejemplo para "simplificarlo" y no fué bueno. En realidad
> lo que necesito es que si no encuentra, haga una nueva consulta en una nueva
> tabla. La función original es la siguiente:
>
> CREATE OR REPLACE FUNCTION "selectCupoActividadPerfil"(integer,integer)
> RETURNS int4 AS $$
> DECLARE
> cupoGral INTEGER;
> cupoPart INTEGER;
> BEGIN
> SELECT INTO cupoGral cupo FROM actividad WHERE id = $1;
> IF NOT FOUND THEN
> SELECT INTO cupoPart cupo FROM "cupoActividadPerfil" WHERE actividad_id =
> $1 AND perfil_id = $2;
> RETURN cupoPart;
> END IF;
> RETURN cupoGral;
> END;
> $$ LANGUAGE plpgsql IMMUTABLE SECURITY DEFINER;
>
> La ejecuto en psql:
>
> text=# SELECT * FROM "selectCupoActividadPerfil"(4,7);
> selectCupoActividadPerfil
> ---------------------------
>
> (1 row)
>
> test=# SELECT cupo FROM "cupoActividadPerfil" WHERE actividad_id = 4 AND
> perfil_id = 7;
> cupo
> ------
> 0
> (1 row)
>
> Osea, yo espero que la función me devuelva cero, no nulo. Perdón si lo estoy
> haciendo muy largo. Un gran saludo a todos...

que pasa si ejecutas? no sera que si esta regresando un registro? y lo
que ocurre es que el valor de cupo efectivamente es NULL?

SELECT cupo FROM actividad WHERE id = 4;

--
Atentamente,
Jaime Casanova

"What they (MySQL) lose in usability, they gain back in benchmarks, and that's
all that matters: getting the wrong answer really fast."
Randal L. Schwartz

In response to

Responses

Browse pgsql-es-ayuda by date

  From Date Subject
Next Message Jaime Casanova 2006-04-20 05:04:59 Re: Debo usar Transacciones?
Previous Message Alvaro Herrera 2006-04-19 22:07:11 Re: Debo usar Transacciones?