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, поэтому на самом деле невозможно обнаружить ошибки, кроме как во время выполнения.

вы можете сделать несколько вещей:

  1. обернуть вызов функции SQL запросы в BEGIN / COMMIT заявления для того, чтобы иметь лучший контроль над ошибками;
  2. добавить EXCEPTION блоки к вашему коду, чтобы поймать и отслеживать ошибки. Заметим, однако, что это повлияет на производительность функции;
  3. использовать plpgsql_check расширение, разработанный Павлом Штехуле, который является одним из основных участников разработки PL/pgSQL. Я предполагаю, что в конечном итоге это расширение попадет в ядро PostgreSQL, но это займет некоторое время (теперь мы в 9.4beta3 state);
  4. вы также можете посмотреть на этот связанный вопрос:проверка синтаксиса 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.