Автоматически DROP FUNCTION, когда DROP TABLE на POSTGRESQL 11,7 - PullRequest
1 голос
/ 16 апреля 2020

Я пытаюсь каким-то образом вызвать автоматическое удаление функции c при удалении таблицы, и я не могу понять, как это сделать.

TL; DR : Есть ли способ вызвать удаление функции при удалении указанной таблицы c? (POSTGRESQL 11.7)


Подробное объяснение

Я попытаюсь объяснить мою проблему, используя упрощенный вариант использования с фиктивными именами.

  1. У меня есть три таблицы: sensor1, sensor2 и sumSensors ;

  2. A FUNCTION ( sumdata ) создано для INSERT данных sumSensors таблицы. Внутри этой функции я получу данные из таблиц sensor1 и sensor2 и вставлю их сумму в таблицу sumSensors;

  3. Триггер был создан для каждая таблица датчиков, которая выглядит так:

    CREATE TRIGGER trig1 ПОСЛЕ ВСТАВКИ НА Sensor1 ДЛЯ КАЖДОЙ СТРОКИ ВЫПОЛНИТЬ ФУНКЦИЮ sumdata ();

  4. Теперь, когда новая строка вставлена ​​ в таблицы датчик1 ИЛИ датчик2 , функция сумма данных будет выполнен и вставит сумму последних значений из обоих в таблицу sumSensors

Если я хотел DROP FUNTION sumdata CASCADE;, триггеры будут автоматически удалены из таблиц sensor1 и sensor2 . До сих пор это все хорошо! Но это не то, что я хочу.


Моя проблема:

В: А если я просто DROP TABLE sumSensors CASCADE;? Что произойдет с функцией, которая должна была быть вставлена ​​в эту таблицу?

A: Как и ожидалось, поскольку нет связи между таблицей sumSensors и функцией sumdata, функция не будет удалена (все-еще существует)! То же самое происходит с триггерами , которые его используют (все еще существуют). Это означает, что при вставке новой строки в таблицы датчиков функция sumdata будет исполнена и повреждена, что приведет к ошибке (даже вставка, вызвавшая выполнение функции, фактически не будет вставлена).

Есть ли способ вызвать сброс функции при удалении определенной таблицы c?

Заранее спасибо

1 Ответ

2 голосов
/ 16 апреля 2020

Для функций в PostgreSQL (начиная с версии 12) отслеживание зависимостей отсутствует.

Вы можете использовать триггеры событий , чтобы самостоятельно поддерживать зависимости.

Полный пример приведен ниже.

Дополнительная информация: документация о функции триггеров событий , функции поддержки .

BEGIN;

CREATE TABLE _testtable ( id serial primary key, payload text );

INSERT INTO _testtable (payload) VALUES ('Test data');

CREATE FUNCTION _testfunc(integer) RETURNS integer
LANGUAGE SQL AS $$ SELECT $1 + count(*)::integer FROM _testtable; $$;

SELECT _testfunc(100);

CREATE FUNCTION trg_drop_dependent_functions()
RETURNS event_trigger 
LANGUAGE plpgsql AS $$
DECLARE
    _dropped record;
BEGIN
    FOR _dropped IN
        SELECT schema_name, object_name
        FROM pg_catalog.pg_event_trigger_dropped_objects()
        WHERE object_type = 'table'
    LOOP
        IF _dropped.schema_name = 'public' AND _dropped.object_name = '_testtable' THEN
            EXECUTE 'DROP FUNCTION IF EXISTS _testfunc(integer)';
        END IF;
    END LOOP;
END;
$$;

CREATE EVENT TRIGGER trg_drop_dependent_functions ON sql_drop
EXECUTE FUNCTION trg_drop_dependent_functions();

DROP TABLE _testtable;

ROLLBACK;
...