PostgreSQL vs Oracle: comprobación de PL/pgSQL en "tiempo de compilación"
plsql plpgsql (2)
El lenguaje Plpgsql está diseñado sin verificación semántica en tiempo de compilación. No estoy seguro de cómo esta característica fue una intención o efecto secundario de la antigua implementación de plpgsql, pero con el tiempo encontramos algunas ventajas (pero con usted mencionó la desventaja).
más:
- hay menos problemas con la dependencia entre funciones y otros objetos de base de datos. Es una solución simple de dependencia cíclica. El despliegue de las funciones de plpgsql es más simple, porque no necesita respetar la dependencia.
- Algunos patrones con tablas temporales son posibles debido a la dependencia diferida. Es necesario, porque Postgres no admite tablas temporales globales.
Ejemplo:
BEGIN
CREATE TEMP TABLE xx(a int);
INSERT INTO xx VALUES(10); -- isn''t possible with compile time dependency
END;
Menos:
- No es posible una verificación profunda en tiempo de compilación (verificación de identificadores), aunque a veces es posible.
Para algunos proyectos más grandes, se debe usar una combinación de soluciones:
- pruebas de regresión y unidad: es la base, porque algunas situaciones no se pueden verificar estáticamente, por ejemplo, SQL dinámico.
-
plpgsql_check
- es externo, pero el proyecto admitido usó algunas compañías más grandes y usuarios más grandes de plpgsql. Puede aplicar una comprobación estática de la validez de los identificadores de SQL. Puede aplicar esta verificación mediante activadores DDL.
Resumen ejecutivo: PostgreSQL es increíble, pero enfrentamos muchos problemas en el trabajo debido al hecho de que pospone muchos controles en el código PL / pgSQL hasta el tiempo de ejecución. ¿Hay alguna manera de hacerlo más parecido a PL / SQL de Oracle a este respecto ?
Por ejemplo...
Intente ejecutar esto en cualquier Oracle DB:
create function foo return number as
begin
select a from dual;
return a;
end;
Oracle responderá de inmediato (es decir, en tiempo de compilación ) con:
[Error] ORA-00904: invalid identifier
Ahora prueba lo semánticamente equivalente en PostgreSQL:
CREATE OR REPLACE FUNCTION public.foo ()
RETURNS integer AS
$body$
BEGIN
select a;
return a;
END;
$body$
LANGUAGE plpgsql;
Lo verás, desafortunadamente - ejecutar bien ... No se informa ningún error.
Pero cuando intente llamar a esta función (es decir, en tiempo de ejecución ) obtendrá:
ERROR: column "a" does not exist
LINE 1: select a
¿Hay alguna manera de obligar a PostgreSQL a realizar análisis de sintaxis y verificar el tiempo de definición de la función, no en tiempo de ejecución? Tenemos toneladas de código PL / SQL en funcionamiento, que estamos migrando a PostgreSQL, pero la falta de comprobaciones en tiempo de compilación es muy dolorosa, obligándonos a realizar trabajos manuales, es decir, escribir código para probar todas las rutas de código en todas las funciones / procedimientos, que de otro modo estaban automatizados en Oracle.
Sí, este es un problema conocido.
PL / pgSQL (como cualquier otra función, excepto en SQL
) es una "caja negra" para PostgreSQL, por lo tanto, no es posible detectar errores, excepto en tiempo de ejecución.
Puedes hacer varias cosas:
- envuelva su función llamando a
SQL
consultasSQL
en las instruccionesBEGIN
/COMMIT
para tener un mejor control sobre los errores; - agregue bloques
EXCEPTION
a su código para capturar y rastrear errores. Sin embargo, tenga en cuenta que esto afectará el rendimiento de la función; - utilice la extensión
plpgsql_check
, desarrollada por Pavel Stěhule, quien es uno de los principales contribuyentes al desarrollo PL / pgSQL. Supongo que eventualmente esta extensión llegará al núcleo de PostgreSQL, pero llevará algo de tiempo (ahora estamos en estado 9.4beta3); - También puede consultar esta pregunta relacionada: comprobación de sintaxis postgresql sin ejecutar la consulta
Y realmente parece que tienes una gran necesidad de un marco de prueba de unidades.