предел глубины стека превышен при срабатывании триггера - PullRequest
0 голосов
/ 20 июня 2019

Я пытаюсь построить медленно меняющуюся таблицу размеров, она отслеживает всю историю записей. Схема таблицы выглядит следующим образом:

CREATE TABLE test.dim
(id text,
 column1 text,
 column2 text,
 begin_date timestamp without time zone,
 is_current boolean,
 end_date timestamp without time zone)

Я определил функцию триггера и запускаю ее перед каждым действием вставки:

CREATE OR REPLACE FUNCTION test.slow_change_func()
  RETURNS trigger AS
$BODY$
  DECLARE
    BEGIN
        IF ( NOT EXISTS ( SELECT 1 FROM yang_test.dim
                          WHERE id= NEW.id  
                                AND(column1 = NEW.column1 OR (column1 is null AND NEW.column1 is null))
                                AND (column2 = NEW.column2 OR (column2 is null AND NEW.column2 is null))
                                AND is_current
                          )
            )
        THEN  UPDATE yang_test.dim
               SET (end_date, is_current) = (now(), FALSE)
               WHERE id = NEW.id
                        AND is_current;
               INSERT INTO test.dim (id, column1, column2, begin_date, is_current, end_date)
               VALUES ( NEW.id, NEW.column1, NEW.column2, now(), TRUE, 'infinity'::timestamp );

         END IF;
      RETURN NULL;
    END;
$BODY$
  LANGUAGE plpgsql VOLATILE
  COST 100;





CREATE TRIGGER slow_change_trigger
  BEFORE INSERT
  ON test.dim
  FOR EACH ROW
  EXECUTE PROCEDURE test.slow_change_func();

Когда я пытаюсь это проверить,

INSERT INTO test.dim (id, column1, column2, begin_date, is_current, end_date)
               VALUES ( 1, 'hello', 'world', now(), TRUE, 'infinity'::timestamp )

будет выдано сообщение об ошибке: превышен предел глубины стека. похоже, что функция выполняет цикл. Любое предложение с?

1 Ответ

0 голосов
/ 20 июня 2019

Я думаю, что понял это, это будет соответствовать моему требованию:

CREATE OR REPLACE FUNCTION yang_test.slow_change_func()
  RETURNS trigger AS
$BODY$
  DECLARE
    BEGIN
        IF ( NOT EXISTS ( SELECT 1 FROM yang_test.dim
                          WHERE id= NEW.id  
                                AND(column1 = NEW.column1 OR (column1 is null AND NEW.column1 is null))
                                AND (column2 = NEW.column2 OR (column2 is null AND NEW.column2 is null))
                                AND is_current
                          )
            )
        THEN  UPDATE yang_test.dim
               SET (end_date, is_current) = (now(), FALSE)
               WHERE id = NEW.id
                        AND is_current;
        ELSE RETURN null;


         END IF;
        RETURN NEW;
    END;
$BODY$
  LANGUAGE plpgsql VOLATILE
  COST 100;
...