Description
Добрый день!
Мне необходимо использовать триггеры для заполнения некоторых полей перед вставкой / обновлением партиционной таблицы. Обычные триггеры, например, типа BEFORE INSERT FOR EACH ROW, похоже, не работают (ERROR: partitioned column's value should not be NULL) .
Для решения этой проблемы, создаю, представление и вешаю на нее триггер INSTEAD OF INSERT OR UPDATE OR DELETE, в котором генерирую скрипт вставки / обновления / удаления записи из базовой таблицы.
Однако, если таблица партицирована pg_pathman триггер работает только для INSERT. Пример, см. ниже.
Создаю базовую таблицу:
CREATE TABLE public._items (
id SERIAL PRIMARY KEY,
name TEXT,
code BIGINT);
INSERT INTO public._items (id, name, code)
SELECT g, md5(g::text), random() * 100000
FROM generate_series(1, 100000) as g;
Создаю представление:
CREATE VIEW public.items as SELECT * FROM public._items;
Создаю триггер:
CREATE OR REPLACE FUNCTION public.test_items_tr ()
RETURNS trigger AS
$$
BEGIN
RAISE EXCEPTION '%', TG_OP;
RETURN NULL;
END;
$$
LANGUAGE 'plpgsql';
CREATE TRIGGER items_tr
INSTEAD OF INSERT OR UPDATE OR DELETE
ON public.items FOR EACH ROW
EXECUTE PROCEDURE public.test_items_tr();
Пробую выполнить операции вставки / обновления / удаления:
INSERT INTO public.items values(1, md5(1::text), random() * 100000); // ERROR: INSERT
UPDATE public.items SET name = '' WHERE id = 1; // ERROR: UPDATE
DELETE FROM public.items where id = 1; // ERROR: DELETE
пока все ОК, триггер работает для все операций.
Теперь создаю партиции:
SELECT public.create_range_partitions('public._items', 'id', 1, 100000, NULL ,true);
Пробую снова выполнить операции вставки / обновления / удаления:
INSERT INTO public.items values(1, md5(1::text), random() * 100000); // ERROR: INSERT
UPDATE public.items SET name = '' WHERE id = 1; // Query OK, 0 rows affected (execution time: 0 ms; total time: 0 ms)
DELETE FROM public.items where id = 1; // Query OK, 0 rows affected (execution time: 0 ms; total time: 0 ms)
Триггер теперь срабатывает только для INSERT.