PostgreSQL vs Oracle: проверка PL/pgSQL во время компиляции
резюме: PostgreSQL удивительно, но мы сталкиваемся со многими проблемами на работе из-за того, что он откладывает многие проверки кода PL/pgSQL до времени выполнения. есть ли способ сделать его более похожим на PL/SQL Oracle в этом отношении?
например...
попробуйте выполнить это в любой Oracle DB:
create function foo return number as
begin
select a from dual;
return a;
end;
Oracle будет немедленно (т. е. в времени компиляции!) ответить:
[Error] ORA-00904: invalid identifier
теперь попробовать семантически эквивалентная вещь в PostgreSQL:
CREATE OR REPLACE FUNCTION public.foo ()
RETURNS integer AS
$body$
BEGIN
select a;
return a;
END;
$body$
LANGUAGE plpgsql;
вы увидите это-к сожалению! - выполнить нормально ... Об ошибке не сообщается.
но когда вы затем пытаетесь вызвать эту функцию (т. е. at время работы) вы получите:
ERROR: column "a" does not exist
LINE 1: select a
есть ли способ заставить PostgreSQL выполнять синтаксический анализ и проверку во время определения функции, а не во время выполнения? У нас есть тонны устаревшего кода PL / SQL на работе , который мы портируем на PostgreSQL-но отсутствие времени компиляции проверки очень болезненны, заставляя нас выполнять ручную работу, то есть писать код для тестирования всех путей кода во всех функциях/процедурах, которые в противном случае были автоматизированы в Oracle.
2 ответов
Да, это известная проблема.
PL / pgSQL (как и любая другая функция, кроме SQL
) является "черным ящиком" для PostgreSQL, поэтому на самом деле невозможно обнаружить ошибки, кроме как во время выполнения.
вы можете сделать несколько вещей:
- обернуть вызов функции
SQL
запросы вBEGIN
/COMMIT
заявления для того, чтобы иметь лучший контроль над ошибками; - добавить
EXCEPTION
блоки к вашему коду, чтобы поймать и отслеживать ошибки. Заметим, однако, что это повлияет на производительность функции; - использовать
plpgsql_check
расширение, разработанный Павлом Штехуле, который является одним из основных участников разработки PL/pgSQL. Я предполагаю, что в конечном итоге это расширение попадет в ядро PostgreSQL, но это займет некоторое время (теперь мы в 9.4beta3 state); - вы также можете посмотреть на этот связанный вопрос:проверка синтаксиса postgresql без запуска запрос
и это действительно похоже на то, что вам очень нужна структура модульного тестирования.
язык Plpgsql разработан без проверки семантики во время компиляции. Я не уверен, как эта функция была намерением или побочным эффектом старой реализации plpgsql, но со временем мы нашли некоторые преимущества (но с упомянутым вами недостатком).
плюсы:
- меньше проблем с зависимостей между функциями и другими объектами базы данных. Это простое решение циклической зависимости. Развертывание функции plpgsql проще, потому что вы не нужно уважать зависимость.
- некоторые шаблоны с временными таблицами возможны из-за ленивой зависимости. Это необходимо, потому что Postgres не поддерживает глобальные временные таблицы.
пример:
BEGIN
CREATE TEMP TABLE xx(a int);
INSERT INTO xx VALUES(10); -- isn't possible with compile time dependency
END;
минус:
- нет возможности глубокой проверки времени компиляции (проверка идентификаторов), хотя иногда это возможно.
для некоторых более больших проектов смешивание решений должно быть используется:
- регресс и модульные тесты-это база, потому что некоторая ситуация не может быть проверена статически-динамический SQL, например.
-
plpgsql_check
- это внешний, но поддерживаемый проект используется некоторыми крупными компаниями и большими пользователями plpgsql. Он может применять статическую проверку достоверности идентификаторов SQL. Вы можете применить эту проверку триггерами DDL.