Гость
Форумы / Firebird, InterBase [игнор отключен] [закрыт для гостей] / Логирование изменений / 13 сообщений из 13, страница 1 из 1
12.09.2019, 15:42
    #39861031
romero111
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Логирование изменений
Добрый день.
Опишу задачу: необходимо логировать данные в БД, пока только удаление. Знаю, что в IBExpert есть своя штука для этого. Но хочется под себя. Чтобы написанный один единственный триггер / процедуру можно было размножить на все таблицы с минимальными изменениями самого триггера / процедуры. Созданы две таблицы LOG_TABLES, LOG_FIELDS.
Алгоритм решения: из системных таблиц нахожу все поля конкретной таблицы, для которой хочу после удаления из нее записи сделать лог в таблицах логирования. Значение old для каждого поля пишем в таблицу логирования. Все.
Проблема: хочу к контекстной переменной Old добавить названия полей и именно это значение писать в лог-таблицу. Т.е. неким образом превратить ее опять в контекстную после конкатенации и выполнить запись. Возможно это?

:context_old_value = 'old.'||lower(:field_name);
:deleted_value = :context_old_value;
s = 'insert into LOG_FIELDS (LOG_TABLE_ID,FIELD_NAME, FIELD_TYPE, OLD_VALUE) values (?,?,?,?)';
execute statement (:s) (:sequence_id,:field_name,:type_data,:deleted_value)

Записывает он здесь, конечно, как текст.
...
Рейтинг: 0 / 0
12.09.2019, 15:59
    #39861046
Симонов Денис
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Логирование изменений
romero111,

создай себе процедуру которая автоматически будет генерировать текст логирующего триггера для произвольной таблицы.
Потом выполни эту ХП для всех нужных таблиц из результатов собери скрипт. Это не сложно.
...
Рейтинг: 0 / 0
12.09.2019, 16:03
    #39861051
Мимопроходящий
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Логирование изменений
1. нужно учитывать NULL-ы
2. вещественные числа
Posted via ActualForum NNTP Server 1.5
...
Рейтинг: 0 / 0
12.09.2019, 16:12
    #39861062
romero111
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Логирование изменений
я и собираюсь составить некий текст триггера. Но пробела в том, что я соберу все названия полей таблицы: пусть 'field1', 'field2', 'field3'. Присобачу к OLD это имя - и это уже будет текст, а не контекстная переменная.
В переменной ins_field_value = названия поля таблицы = 'field1'.
insert into log_table (field_name,flield_value) values ('field1','old.'||ins_field_value )
Он вставить запись в flield_value как текст = 'old.field1'. Мне же надо, что он взял как контекстную переменную этот параметр и вставил туда значение поля field1.
...
Рейтинг: 0 / 0
12.09.2019, 16:16
    #39861063
Dimitry Sibiryakov
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Логирование изменений
romero111я и собираюсь составить некий текст триггера.

Обломись. Не может быть "универсального протоколирующего триггера".
Posted via ActualForum NNTP Server 1.5
...
Рейтинг: 0 / 0
12.09.2019, 16:33
    #39861077
Симонов Денис
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Логирование изменений
romero111,

тебе говорят собирай текст триггера целиком как строку и скармливай её выполнителю скрипта
...
Рейтинг: 0 / 0
12.09.2019, 21:05
    #39861178
YuRock
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Логирование изменений
Dimitry Sibiryakovromero111я и собираюсь составить некий текст триггера.

Обломись. Не может быть "универсального протоколирующего триггера".Ну почему же.
Такая задача, и многие другие, уже решены здесь:
http://button.dekel.ru/
...
Рейтинг: 0 / 0
13.09.2019, 10:06
    #39861335
romero111
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Логирование изменений
Симонов Денис, процка создана (где входящие параметры Таблица и Операция). Создается длиннющая строка текста триггера. Но проблема то этим не решилась: я ее (строку) вставляю в выполнитель скриптов, но последняя моя операция в этом скрипте, как и описано в самом первом сообщении, никак не преобразилась. Т.е. она осталась текстовым полем, а мне ее надо скормить как old.field_name, а не как 'old.field_name'.
Задача: я беру все поля таблицы и хочу записать их значения при удалении из таблицы в таблицу лога. Делать хочу это в триггере на before_delete. Где есть контекстная переменная OLD. Хочу к ней в цикле (или как хотите называйте) присобачивать по очереди названия полей и получать значение, которые записывать в лог. С присобавчиванием (конкатенацией) проблем нет, есть проблема, что эта переменная уже не является контекстной и не выполняет свои "функции", а просто превратилась в текст.
...
Рейтинг: 0 / 0
13.09.2019, 10:40
    #39861358
KreatorXXI
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Логирование изменений
romero111,

"execute statement" не выполняет скрипт? Или что?
...
Рейтинг: 0 / 0
13.09.2019, 10:43
    #39861363
Симонов Денис
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Логирование изменений
romero111,

ещё раз объясняю. Так сделать нельзя. Поля после OLD надо указывать в явном виде. Т.е. создать универсальный триггер не получится, но можно сделать процедуру которая облегчит написание таких триггеров.
Вот кусок моего пакета для записи логов. Тебе он не подойдёт, но ты можешь уловить мысль

Код: sql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
  PROCEDURE CREATE_UPDATE_TRIGGER(ATable VARCHAR(31)) RETURNS (SQL_TEXT BLOB SUB_TYPE TEXT)
  AS
    DECLARE EOL CHAR(2);
    DECLARE PK_FIELDNAME VARCHAR(31);
  BEGIN
    ATable = TRIM(ATable);
    SELECT
      TRIM(IND.RDB$FIELD_NAME) AS FIELD_NAME
    FROM RDB$RELATION_CONSTRAINTS RC
      JOIN RDB$INDEX_SEGMENTS IND ON IND.RDB$INDEX_NAME = RC.RDB$INDEX_NAME
    WHERE RC.RDB$RELATION_NAME = :ATable AND RC.RDB$CONSTRAINT_TYPE = 'PRIMARY KEY'
    INTO PK_FIELDNAME;

    EOL = ASCII_CHAR(13) || ASCII_CHAR(10);
    SQL_TEXT = 'CREATE OR ALTER TRIGGER TR_' || ATable || '_REPL_AU FOR ' || ATable || EOL;
    SQL_TEXT = SQL_TEXT || 'ACTIVE AFTER UPDATE POSITION 0' || EOL;
    SQL_TEXT = SQL_TEXT || 'AS' || EOL;
    SQL_TEXT = SQL_TEXT || '  DECLARE LOG_ID INT;' || EOL;
    SQL_TEXT = SQL_TEXT || 'BEGIN' || EOL;

    SQL_TEXT = SQL_TEXT || '  EXECUTE PROCEDURE REPL_WRITE_LOG.BEGIN_OPERATION(' || '''' || ATable || ''', ''U'', ''' || PK_FIELDNAME || ''', OLD.' || PK_FIELDNAME || ') RETURNING_VALUES LOG_ID;' || EOL;
    FOR
      SELECT
           F.FIELD_SOURCE AS FIELD_NAME,
           F.FIELD_TYPE,
           F.FIELD_SCALE,
           F.FIELD_POS
      FROM
          TABLE_MAP T
          JOIN FIELD_MAP F ON F.CODE_TABLE_MAP = T.CODE_TABLE_MAP
      WHERE T.CODE_SENDER = 1 AND T.TABLE_SOURCE = :ATable
      ORDER BY F.FIELD_POS
      AS CURSOR C
    DO
    BEGIN
      SQL_TEXT = SQL_TEXT || '  IF (NEW.' || C.FIELD_NAME || ' IS DISTINCT FROM OLD.' || C.FIELD_NAME || ') THEN' || EOL;
      SQL_TEXT = SQL_TEXT || '    EXECUTE PROCEDURE REPL_WRITE_LOG.WRITE_' || C.FIELD_TYPE ||'_VALUE(LOG_ID, ''' || C.FIELD_NAME || ''', NEW.' || C.FIELD_NAME || ');' || EOL;
    END
    SQL_TEXT = SQL_TEXT || 'END' || EOL;
    SUSPEND;
  END
...
Рейтинг: 0 / 0
13.09.2019, 10:57
    #39861375
romero111
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Логирование изменений
KreatorXXI, выполняется, но не хочет понимать old.tag_id, например. Сейчас :field_name = tag_id.

:field_value = 'old.' || lower(:field_name);

execute statement 'insert into LOG_FIELDS (LOG_TABLE_ID,FIELD_NAME, FIELD_TYPE, INT_VALUE) values (' || :sequence_id || ',''' || :field_name || ''',''' || :type_data || ''',' || :field_value || ')'
on external :setting_value
as user :user_login password :user_pass;

Пишет, что не знает такое поле....
...
Рейтинг: 0 / 0
13.09.2019, 10:58
    #39861377
romero111
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Логирование изменений
Симонов Денис,

красиво. Спасибо, что поделились творчеством. Полезная идея.
...
Рейтинг: 0 / 0
13.09.2019, 13:16
    #39861476
kdv
kdv
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Логирование изменений
romero111,

оператор, выполняемый execute statement не имеет доступа к "внешнему" контексту. Допустим, когда оно вызывается из триггера, оператор ES ни про какой триггер понятия не имеет. Он выполняется точно так же, как любой клиентский запрос.
...
Рейтинг: 0 / 0
Форумы / Firebird, InterBase [игнор отключен] [закрыт для гостей] / Логирование изменений / 13 сообщений из 13, страница 1 из 1
Целевая тема:
Создать новую тему:
Автор:
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


Просмотр
0 / 0
Close
Debug Console [Select Text]