return query sobre esquemas cambiantes
- From: "Fernando Moreno" <azazel(dot)7(at)gmail(dot)com>
- To: pgsql-es-ayuda(at)postgresql(dot)org
- Subject: return query sobre esquemas cambiantes
- Date: Wed, 30 Apr 2008 15:27:51 -0500
- Message-id: <b1c45530804301327x42eb613em5a588fc5c02e0c81(at)mail(dot)gmail(dot)com>
Qué tal, hasta apenas un rato que comencé a utilizar la opción RETURN QUERY en las funciones pl/pgsql. Estoy recibiendo datos incorrectos y no sé si lo esté usando mal, les describiré la situación lo mejor posible:
* Manejamos múltiples sucursales, por medio de esquemas. Tenemos una tabla public.sucursales donde almacenamos estos registros, además del nombre del esquema.
* Dentro de cada esquema existen las tablas asientos y partidas, y una vista llamada diario_gral, que combina las primeras dos tablas mas unos dos ubicadas en public.
* El objetivo es desplazarse en los esquemas (modificando el search_path en cada ciclo), consultar la vista (agregando dos campos), ir acumulando esos resultados y enviarlos a la aplicación cliente.
La función es la siguiente:
CREATE OR REPLACE FUNCTION diario_gral_empresa(ej int,mes int) RETURNS setof record AS $$
declare
rec record;
begin
for rec in select * from sucursales loop
execute 'set search_path to '||rec.esquema||',public';
return query select rec.idsuc,rec.nombre,d.* from diario_gral d where d.id_ejercicio=ej and d.cns_mes=mes;
end loop;
return;
end;
$$ LANGUAGE 'plpgsql';
Al ejecutar la función, el ciclo se ejecuta tres veces, pero en los últimos dos tenemos datos repetidos que pertenecen al primer ciclo de ejecución, lo que si va cambiando son los dos valores que agregamos directamente y que provienen de la variable record (idsuc y nombre) .
Reemplacé RETURN QUERY con un FOR record IN SELECT ... sobre la vista (el método antiguo) y los mostré en pantalla con RAISE NOTICE. El resultado es el mismo, cada ciclo interior se suponía que mostrara un registro distinto generado por la vista, pero muestra los mismos datos generados por el primer ciclo FOR exterior (el que cambia entre esquemas). Al final probé algo como esto:
execute 'set search_path to '||'sucursal008'||',public';
return query select 8,'sucursal8'::text,d.* from diario_gral d where d.id_ejercicio=ej and d.cns_mes=mes;
Esta vez no usé ciclos, solo para verificar el funcionamiento de RETURN QUERY (ejecutado una sola vez) y todo bien, regresó los datos completos de un esquema.
Después recordé que hace poco tuve un problema al insertar datos en tablas temporales creadas con la opción ON COMMIT DROP (para eliminarse al terminar la transacción), y encontré que era una falla de postgres al guardar referencias a esas tablas temporales eliminadas y no "replanificar" las consultas en ejecuciones posteriores de la misma función. En su momento lo solucioné tal como señalaban los diversos comentarios en foros y listas de correo: con EXECUTE. El problema parece ser el mismo, pues el cambio dinámico de search_path parece no afectar como debe ser a la consulta realizada por RETURN QUERY SELECT..., quizás la única forma de señalar el esquema explícitamente en esta consulta, sea con una estructura dinámica como la usada en FOR record in EXECUTE cadena, pero no está disponible para RETURN QUERY.
¿Alguien más ha usado RETURN QUERY con los mismos problemas? ¿Podría ser un error en postgres?
---Agrego:
He probado dos bloques que modificaban el search_path, seguido de un RETURN QUERY y los resultados son correctos. Algo así:
execute 'set search_path to '||'sucursal008'||',public';
return query select 8,'sucursal8'::text,d.* from diario_gral d where d.id_ejercicio=ej and d.cns_mes=mes;
execute 'set search_path to '||'sucursal002'||',public';
return query select 2,'sucursal2'::text,d.* from diario_gral d where d.id_ejercicio=ej and d.cns_mes=mes;
Lo que hace parecerse aún más al problema de las tablas temporales, pues en esa ocasión pude hacer funcionar los INSERT literalmente uno tras otro, pero el ejecutarlos dentro de un ciclo no.
Home |
Main Index |
Thread Index