отладка триггера postgresql - PullRequest
23 голосов
/ 20 ноября 2008

У меня есть этот триггер в Postgresql, который я не могу просто заставить работать (ничего не делает). Для понимания, вот как я это определил:

CREATE TABLE documents (
    ...
    modification_time timestamp with time zone DEFAULT now()
);

CREATE FUNCTION documents_update_mod_time() RETURNS trigger
AS $$
    begin
    new.modification_time := now();
    return new;
    end
$$
    LANGUAGE plpgsql;

CREATE TRIGGER documents_modification_time
    BEFORE INSERT OR UPDATE ON documents
    FOR EACH ROW
    EXECUTE PROCEDURE documents_update_mod_time();

Теперь, чтобы сделать его немного интереснее .. Как вы отлаживаете триггеры?

Ответы [ 3 ]

48 голосов
/ 10 января 2009
  1. Используйте следующий код в функции триггера, затем просмотрите вкладку 'messages' в pgAdmin3 или вывод в psql:

    RAISE NOTICE 'myplpgsqlval is currently %', myplpgsqlval;       -- either this
    RAISE EXCEPTION 'failed';  -- or that
    
  2. Чтобы увидеть, какие триггеры на самом деле вызывались, сколько раз и т. Д., Следующее спасение может быть выбрано:

    EXPLAIN ANALYZE UPDATE table SET foo='bar'; -- shows the called triggers
    

    Обратите внимание, что если ваш триггер не вызывается и вы используете наследование, возможно, вы определили только триггер для родительской таблицы, тогда как триггеры не наследуются дочерними таблицами автоматически.

  3. Чтобы пройти через функцию, вы можете использовать отладчик, встроенный в pgAdmin3, который в Windows включен по умолчанию; все, что вам нужно сделать, это выполнить код, найденный в ... \ 8.3 \ share \ contrib \ pldbgapi.sql для базы данных, которую вы отлаживаете, перезапустите pgAdmin3, щелкните правой кнопкой мыши по своей функции триггера и нажмите Установите точку останова ', а затем выполните инструкцию, которая вызовет срабатывание триггера, например, приведенную выше инструкцию UPDATE.

3 голосов
/ 23 ноября 2008

Оказывается, я использовал наследование в вышеуказанной проблеме и забыл упомянуть об этом. Теперь для всех, кто может столкнуться с этим, вот несколько советов по отладке:

Используйте следующий код для отладки того, что делает триггер:

RAISE NOTICE 'test';       -- either this
RAISE EXCEPTION 'failed';  -- or that

Чтобы узнать, какие триггеры на самом деле вызывались, сколько раз и т. Д., Следующее утверждение является жизненно важным выбором:

EXPLAIN ANALYZE UPDATE table SET foo='bar'; -- shows the called triggers

Тогда есть одна вещь, которую я не знал раньше: триггеры срабатывают только при обновлении точной таблицы, для которой они определены. Если вы используете наследование, вы ДОЛЖНЫ определить их и в дочерних таблицах!

3 голосов
/ 20 ноября 2008

Вы можете использовать операторы «повысить уведомление» внутри функции триггера для его отладки. Отладка триггера, который вообще не вызывается, - другая история.

Если вы добавите «исключение повышения» внутри функции триггера, сможете ли вы по-прежнему делать вставки / обновления?

Кроме того, если ваш тест обновления происходит в той же транзакции, что и тест вставки, now () будет таким же (поскольку он рассчитывается только один раз для транзакции), и, следовательно, обновление, похоже, ничего не даст. Если это так, либо выполните их в отдельных транзакциях, либо, если это модульный тест, и вы не можете этого сделать, используйте clock_timestamp ().

У меня есть модульный тест, который зависит от времени между транзакциями, поэтому в начале модульного теста у меня есть что-то вроде:

ALTER TABLE documents
   ALTER COLUMN modification_time SET DEFAULT clock_timestamp();

Затем в триггере используйте "set mod_time = default".

Так что обычно он не выполняет дополнительных вычислений, но во время модульного теста это позволяет мне делать вставки с pg_sleep между ними, чтобы имитировать переход времени и фактически отражать это в данных.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...