Создание подпрограммы для генерации кода CREATE TRIGGER в Postgres - PullRequest
1 голос
/ 11 февраля 2020

Я не нашел простого способа получить код определения триггера. Я имею в виду объявление триггера / привязки, а не функцию триггера. Я решил использовать некоторые системные каталоги для создания сценария. Следующая, неполная, версия дает разумный вывод:

CREATE OR REPLACE FUNCTION dba.ddl_get_build_trigger_code(trigger_id oid) -- I starting from having the OID.
    RETURNS text

AS $BODY$

DECLARE

trigger_name_in text;
code text;

BEGIN
/*
What the original declaration looks like:

CREATE TRIGGER trigger_hsys_after_delete
    AFTER DELETE
    ON data.hsys
    REFERENCING OLD TABLE AS deleted_rows
    FOR EACH STATEMENT
    EXECUTE PROCEDURE data.trigger_function_log_deletion_count();
*/

SELECT tgname FROM pg_trigger WHERE oid = trigger_id INTO trigger_name_in; -- information_schema tables don't use PG OIDs.

RETURN 
'CREATE TRIGGER ' || trigger_name || chr(10) ||
 chr(9) || action_timing || ' ' || event_manipulation || chr(10) ||
 chr(9) || 'ON ' || event_object_schema || '.' || event_object_table ||

 CASE WHEN action_reference_old_table IS NOT NULL THEN
 chr(10) || chr(9) || 'REFERENCING OLD TABLE AS ' || action_reference_old_table || chr(10) END ||

--  CASE WHEN action_reference_new_table IS NOT NULL THEN
--  chr(10) || chr(9) || 'REFERENCING NEW TABLE AS ' || action_reference_new_table || chr(10) END ||

 chr(9) || 'FOR EACH ' || action_orientation || chr(10) ||
 chr(9) || action_statement || ';' as create_trigger_code

  FROM information_schema.triggers 
 WHERE trigger_name = trigger_name_in;

END;
 $BODY$
LANGUAGE plpgsql;

Вот пример, соответствующий моему реальному случаю:

CREATE TRIGGER trigger_hsys_after_delete
    AFTER DELETE
    ON data.hsys
    REFERENCING OLD TABLE AS deleted_rows
    FOR EACH STATEMENT
    EXECUTE PROCEDURE trigger_function_log_deletion_count();

В information_schema.triggers есть еще несколько атрибутов, которые могут иметь значения такой как action_reference_new_table. Когда я включаю строки ниже и action_reference_new_table равен NULL, скрипт возвращает NULL:

CASE WHEN action_reference_new_table IS NOT NULL THEN
chr(10) || chr(9) || 'REFERENCING NEW TABLE AS ' || action_reference_new_table || chr(10) END ||

Я не понимаю, почему значение NULL для action_reference_new_table взрывает мой код конкатенации и дает полный результат NULL.

Помимо справки по этому конкретному c вопросу, не стесняйтесь указывать на все, что я должен сделать, чтобы написать более разумный код PL / Pg SQL. Мне сложнее освоить, чем я мог бы предположить.

1 Ответ

1 голос
/ 11 февраля 2020

Просто используйте

SELECT pg_get_triggerdef(oid)
FROM pg_trigger
WHERE tgname = trigger_name_in;

Кроме того, никогда не использует конкатенацию строк при создании кода SQL. Опасность инъекции SQL слишком велика. Используйте функцию format() с заполнителем %I.

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