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

Материал из GedeminWiki
(Различия между версиями)
Перейти к: навигация, поиск
(Новая страница: «Приведенный ниже код создает для каждой таблицы документа триггер, который проверяет со…»)
 
 
(не показаны 5 промежуточных версий 1 участника)
Строка 4: Строка 4:
 
EXECUTE BLOCK
 
EXECUTE BLOCK
 
AS
 
AS
  DECLARE VARIABLE stmt VARCHAR(2048);
 
 
   DECLARE VARIABLE id INTEGER;
 
   DECLARE VARIABLE id INTEGER;
 
   DECLARE VARIABLE relname VARCHAR(1024);
 
   DECLARE VARIABLE relname VARCHAR(1024);
   DECLARE VARIABLE keys VARCHAR(1024);
+
   DECLARE VARIABLE dtkeys VARCHAR(1024);
 
BEGIN
 
BEGIN
 
   FOR
 
   FOR
Строка 17: Строка 16:
 
       gd_documenttype dt
 
       gd_documenttype dt
 
       JOIN at_relations hr ON hr.id = dt.HEADERRELKEY
 
       JOIN at_relations hr ON hr.id = dt.HEADERRELKEY
 +
    WHERE
 +
      hr.relationname STARTING WITH 'USR$'
 
     GROUP BY
 
     GROUP BY
 
       1, 2
 
       1, 2
 
     INTO
 
     INTO
       :id, :relname, :keys
+
       :id, :relname, :dtkeys
 
   DO BEGIN
 
   DO BEGIN
     stmt =
+
     EXECUTE STATEMENT
 
       'CREATE OR ALTER TRIGGER gd_check_dt_' || :id || ' FOR ' || :relname ||
 
       'CREATE OR ALTER TRIGGER gd_check_dt_' || :id || ' FOR ' || :relname ||
 
       '  ACTIVE ' ||
 
       '  ACTIVE ' ||
Строка 31: Строка 32:
 
       'BEGIN ' ||
 
       'BEGIN ' ||
 
       '  SELECT documenttypekey FROM gd_document WHERE id = NEW.documentkey INTO :dtkey;' ||
 
       '  SELECT documenttypekey FROM gd_document WHERE id = NEW.documentkey INTO :dtkey;' ||
       '  IF (NOT (:dtkey IN (' || :keys || '))) THEN ' ||
+
       '  IF (NOT (:dtkey IN (' || :dtkeys || '))) THEN ' ||
 
       '    EXCEPTION gd_e_exception ''Document type doesn`t match table ' || :relname || ''';' ||
 
       '    EXCEPTION gd_e_exception ''Document type doesn`t match table ' || :relname || ''';' ||
       'END';
+
       'END'
    EXECUTE STATEMENT :stmt WITH AUTONOMOUS TRANSACTION;
+
      WITH AUTONOMOUS TRANSACTION;
 
   END
 
   END
 
END
 
END
 
</syntaxhighlight>
 
</syntaxhighlight>
 +
 +
Впоследствии удалить созданные триггеры можно с помощью кода:
 +
 +
<syntaxhighlight lang="SQL">
 +
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
 +
</syntaxhighlight>
 +
 +
Приведенная ниже хранимая процедура выводит список всех записей в таблицах документов, для которых в GD_DOCUMENT содержится неверный тип в поле DOCUMENTTYPEKEY.
 +
 +
<syntaxhighlight lang="SQL">
 +
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
 +
</syntaxhighlight>
 +
 +
Вывод данной процедуры можно записать в промежуточную таблицу для анализа и обработки.
 +
  
 
[[Category:База данных]]
 
[[Category:База данных]]

Текущая версия на 13:09, 12 января 2018

Приведенный ниже код создает для каждой таблицы документа триггер, который проверяет соответствие этой таблицы типу документа из поля 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

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

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

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