Контроль целостности типов документов

Материал из GedeminWiki
Перейти к: навигация, поиск

Приведенный ниже код создает для каждой таблицы документа триггер, который проверяет соответствие этой таблицы типу документа из поля GD_DOCUMENT.DOCUMENTTYPEKEY:

EXECUTE BLOCK
AS
  DECLARE VARIABLE id INTEGER;
  DECLARE VARIABLE relname VARCHAR(1024);
  DECLARE VARIABLE dtkeys VARCHAR(1024);
BEGIN
  FOR
    SELECT
      hr.id,
      hr.relationname,
      LIST(dt.id)
    FROM
      gd_documenttype dt
      JOIN at_relations hr ON hr.id = dt.HEADERRELKEY
    WHERE
      hr.relationname STARTING WITH 'USR$'
    GROUP BY
      1, 2
    INTO
      :id, :relname, :dtkeys
  DO BEGIN
    EXECUTE STATEMENT 
      'CREATE OR ALTER TRIGGER gd_check_dt_' || :id || ' FOR ' || :relname ||
      '  ACTIVE ' ||
      '  AFTER INSERT OR UPDATE ' ||
      '  POSITION 32000 ' ||
      'AS ' ||
      '  DECLARE VARIABLE dtkey INTEGER = NULL; ' ||
      'BEGIN ' ||
      '  SELECT documenttypekey FROM gd_document WHERE id = NEW.documentkey INTO :dtkey;' ||
      '  IF (NOT (:dtkey IN (' || :dtkeys || '))) THEN ' ||
      '    EXCEPTION gd_e_exception ''Document type doesn`t match table ' || :relname || ''';' ||
      'END'
      WITH AUTONOMOUS TRANSACTION;
  END
END

Впоследствии удалить созданные триггеры можно с помощью кода:

EXECUTE BLOCK
AS
  DECLARE VARIABLE tn VARCHAR(256);
BEGIN
  FOR
    SELECT
      rdb$trigger_name
    FROM
      rdb$triggers
    WHERE
      rdb$trigger_name STARTING WITH 'GD_CHECK_DT_'
    INTO
      :tn
  DO BEGIN
    EXECUTE STATEMENT
      'DROP TRIGGER ' || :tn
      WITH AUTONOMOUS TRANSACTION;
  END
END

Приведенная ниже хранимая процедура выводит список всех записей в таблицах документов, для которых в GD_DOCUMENT содержится неверный тип в поле DOCUMENTTYPEKEY.

CREATE OR ALTER PROCEDURE gd_p_detect_corrupted_docs
  RETURNS(
    relname VARCHAR(64),
    documentkey INTEGER,
    dtkey INTEGER,
    expecteddtkey VARCHAR(256)
  )
AS
BEGIN
  FOR
    SELECT
      hr.relationname,
      LIST(dt.id)
    FROM
      gd_documenttype dt
      JOIN at_relations hr ON hr.id = dt.HEADERRELKEY
    WHERE
      hr.relationname STARTING WITH 'USR$'
    GROUP BY
      1
    INTO
      :relname, :expecteddtkey
  DO BEGIN
    FOR
      EXECUTE STATEMENT
        'SELECT t.documentkey, d.documenttypekey ' ||
        'FROM ' || :relname || ' t ' ||
        '  JOIN gd_document d ON d.id = t.documentkey ' ||
        'WHERE ' ||
        '  NOT d.documenttypekey IN (' || :expecteddtkey || ')'
      INTO :documentkey, :dtkey
    DO
      SUSPEND;
  END
END

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

Персональные инструменты
Пространства имён

Варианты
Действия
Навигация
Инструменты