powered by simpleCommunicator - 2.0.49     © 2025 Programmizd 02
Форумы / Firebird, InterBase [игнор отключен] [закрыт для гостей] / Как определить тип триггера?
22 сообщений из 22, страница 1 из 1
Как определить тип триггера?
    #39577870
Polesov
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Привет всем.

Требуется определить наличие триггера определенного типа.

Типы всех триггеров можно получить запросом:
Код: sql
1.
2.
3.
select RDB$TRIGGER_NAME, RDB$TRIGGER_TYPE
  from RDB$TRIGGERS
 where RDB$RELATION_NAME = 'MY_TABLE'


С простыми триггерами вроде все просто:
Код: powershell
1.
2.
3.
4.
5.
6.
before insert  1
after  insert  2
before update  3
after  update  4
before delete  5
after  delete  6


А вот с комбинированными триггерами все сложнее (справа значение RDB$TRIGGER_TYPE в двоичном виде):
Код: powershell
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
before
IU	 17	0001 0001
IUD	113	0111 0001
I D	 25	0001 1001
 UD	 27	0001 1011

after
IU	 18	0001 0010
IUD	114	0111 0010
I D	 26	0001 1010
 UD	 28	0001 1100


Никакой закономерности выявить не смог. Разве что триггера AFTER на единицу больше триггеров BEFORE.

Можно ли по значению RDB$TRIGGER_TYPE определить является ли триггер I или U или D без сравнения с вышеприведенными значениями?

Например, требуется узнать, есть ли для конкретной VIEW хоть один триггер на UPDATE?

С уважением, Polesov.
...
Рейтинг: 0 / 0
Как определить тип триггера?
    #39577888
Dimitry Sibiryakov
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
PolesovМожно ли по значению RDB$TRIGGER_TYPE определить является ли триггер I или U или D без
сравнения с вышеприведенными значениями?

Даже сравнением нельзя. Триггера insert or update и update or insert дадут разное значение.
Код: plaintext
1.
2.
3.
4.
inline int TRIGGER_ACTION_SUFFIX(int value, int slot)
{
         return ((value + 1) >> (slot * 2 - 1)) & 3;
}


Результат этой функции 1 - insert, 2 - update, 3 - delete. Повторять для всех трёх слотов.
Posted via ActualForum NNTP Server 1.5
...
Рейтинг: 0 / 0
Как определить тип триггера?
    #39577897
Polesov
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Dimitry SibiryakovТриггера insert or update и update or insert дадут разное значение.

Фигассе. А есть разница в механизме срабатывания таких триггеров?

Dimitry Sibiryakov
Код: plaintext
1.
2.
3.
4.
inline int TRIGGER_ACTION_SUFFIX(int value, int slot)
{
         return ((value + 1) >> (slot * 2 - 1)) & 3;
}


Результат этой функции 1 - insert, 2 - update, 3 - delete. Повторять для всех трёх слотов.

Спасибо за информацию.
...
Рейтинг: 0 / 0
Как определить тип триггера?
    #39577929
hvlad
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Polesov,

doc\sql.extensions\README.universal_triggers
...
Рейтинг: 0 / 0
Как определить тип триггера?
    #39577934
Polesov
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
hvlad,

Спасибо, все понятно.

А есть разница в механизме срабатывания триггеров insert or update и update or insert ?
...
Рейтинг: 0 / 0
Как определить тип триггера?
    #39577936
hvlad
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
PolesovА есть разница в механизме срабатывания триггеров insert or update и update or insert ?Конечно нет. Откуда бы ей взяться ?
...
Рейтинг: 0 / 0
Как определить тип триггера?
    #39577939
Polesov
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
hvladКонечно нет. Откуда бы ей взяться ?
А зачем тогда такой замороченный алгоритм кодирования типа триггера?
На мой взгляд вполне хватило бы 4 бит.

Или "так исторически сложилось"?
...
Рейтинг: 0 / 0
Как определить тип триггера?
    #39577940
hvlad
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
PolesovА зачем тогда такой замороченный алгоритм кодирования типа триггера?Для обратной совместимости.
...
Рейтинг: 0 / 0
Как определить тип триггера?
    #39580193
Polesov
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Привет всем.

UDF, определяющая соответствие хоть одного из слотов в RDB$TRIGGER_TYPE типу DML.
Возвращает 0 - false, 1 - true

Код: pascal
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.
{
declare external function TRIGGER_IS
    integer,
    integer
    returns integer by value
entry_point 'TriggerIs' module_name 'MyUDF.dll';
}
function TriggerIs( var aType, aKind : integer ) : integer; cdecl; export; assembler;
{
  aType - значение поля RDB$TRIGGERS.RDB$TRIGGER_TYPE
  aKind - тип DML (1 - insert, 2 - update, 3 - delete)
}
asm
     Push    EBX

     Mov     ECX,   [EAX]
     Inc     ECX
     Mov     EDX,   [EDX]

     Xor     EAX,   EAX
     Shr     ECX,   1

@@10:
     Jcxz    @@90
     Mov     EBX,   ECX
     Shr     ECX,   2
     And     EBX,   0003h
     Cmp     EBX,   EDX
     Jne     @@10

     Inc     EAX

@@90:
     Pop     EBX
end;



С уважением, Polesov.
...
Рейтинг: 0 / 0
Как определить тип триггера?
    #39580200
Гаджимурадов Рустам
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Я бы для этого UDF не цеплял, проще RDB$TRIGGER_TYPE case-ом распарсить.
Posted via ActualForum NNTP Server 1.5
...
Рейтинг: 0 / 0
Как определить тип триггера?
    #39580207
Polesov
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Гаджимурадов Рустампроще RDB$TRIGGER_TYPE case-ом распарсить.

С учетом алгоритма кодирования типа триггера 21072831 , case получится уж очень ветвистым.
Тогда уж проще использовать битовые функции bin_and, bin_shl и т.п.

Если баз данных, использующих данную функцию, несколько, то при изменении алгоритма,
в случае pSQL-реализации, правки потребуется вносить в каждую БД.
При UDF-реализации достаточно подменить файл библиотеки на сервере.
Ну и UDF - одной больше, одной меньше :-)

Впрочем, оба варианта имеют свои плюсы и свои минусы.
...
Рейтинг: 0 / 0
Как определить тип триггера?
    #39580213
Polesov
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Polesov,

Реализация вышеприведенной UDF на pSQL:
Код: plsql
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.
set term ^ ;

create procedure TRIIGER_IS (
    TRIGGER_TYPE integer,
    KIND  smallint )
returns (
    IS_TRUE smallint )
as
begin
  IS_TRUE = 0;
  TRIGGER_TYPE = :TRIGGER_TYPE + 1;
  bin_shr( :TRIGGER_TYPE, 1 );

  while ( :TRIGGER_TYPE > 0 ) do
  begin
    if ( bin_and( :TRIGGER_TYPE, 3 ) = :KIND ) then
    begin
      IS_TRUE = 1;
      break;
    end
    bin_shr( :TRIGGER_TYPE, 2 );
  end

  suspend;
end ^

set term ; ^
...
Рейтинг: 0 / 0
Как определить тип триггера?
    #39580216
Гаджимурадов Рустам
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
На SQL/PSQL гораздо лучше, ИМХО. Впрочем, не настаиваю.
Posted via ActualForum NNTP Server 1.5
...
Рейтинг: 0 / 0
Как определить тип триггера?
    #39580226
чччД
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Э... а разве bin_shr() модифицирует входные аргументы?
...
Рейтинг: 0 / 0
Как определить тип триггера?
    #39580230
Polesov
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
чччДЭ... а разве bin_shr() модифицирует входные аргументы?
Нет, не модифицирует - ашипка.

Правильно так:
TRIGGER_TYPE = bin_shr( :TRIGGER_TYPE, 2 );
Иначе бесконечный цикл.

Код: plsql
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.
set term ^ ;

create procedure TRIGGER_IS (
    TRIGGER_TYPE integer,
    KIND  smallint )
returns (
    IS_TRUE smallint )
as
begin
  IS_TRUE = 0;
  TRIGGER_TYPE = :TRIGGER_TYPE + 1;
  bin_shr( :TRIGGER_TYPE, 1 );

  while ( :TRIGGER_TYPE > 0 ) do
  begin
    if ( bin_and( :TRIGGER_TYPE, 3 ) = :KIND ) then
    begin
      IS_TRUE = 1;
      break;
    end
    TRIGGER_TYPE = bin_shr( :TRIGGER_TYPE, 2 );
  end

  suspend;
end ^

set term ; ^



Кстати, замеры показали, что UDF примерно в 12 раз быстрее SP
Код: plsql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
execute block
as
  declare variable CNT integer;
  declare variable TMP integer;
begin
  CNT = 1000000;
  while ( :CNT > 0 ) do
  begin
--    TMP = TRIGGER_IS( 27, 1 );
    TMP = ( select IS_TRUE from TRIGGER_IS( 27, 1 ) );
    CNT = :CNT - 1;
  end
end
...
Рейтинг: 0 / 0
Как определить тип триггера?
    #39580287
чччД
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Тогда бы уж сразу в виде функции оформлял, а не процедуры.
Код: sql
1.
2.
3.
4.
create or alter function IS_TRIIGER_TYPE(
    TRIGGER_TYPE integer,
    KIND  integer )
returns boolean


... и т.д.
...
Рейтинг: 0 / 0
Как определить тип триггера?
    #39580292
чччД
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
...
Код: sql
1.
2.
3.
4.
5.
6.
7.
8.
9.
as
begin
  TRIGGER_TYPE =  bin_shr(:TRIGGER_TYPE + 1, 1);
  while((:TRIGGER_TYPE > 0)
     and (bin_and(:TRIGGER_TYPE, 3) <> :KIND)) do
    TRIGGER_TYPE = bin_shr(:TRIGGER_TYPE, 2);
 
  return bin_and(:TRIGGER_TYPE, 3) = :KIND;
end


? /* Без проверки, ибо мобильник */
...
Рейтинг: 0 / 0
Как определить тип триггера?
    #39580294
Фотография Симонов Денис
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
двоеточие вне SQL команд можно и не использовать
...
Рейтинг: 0 / 0
Как определить тип триггера?
    #39580297
Гаджимурадов Рустам
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
C двоеточием нагляднее. Да и привычка, автоматом уже набираешь.
Posted via ActualForum NNTP Server 1.5
...
Рейтинг: 0 / 0
Период между сообщениями больше года.
Как определить тип триггера?
    #40108530
atronah
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Я в своей хранимой процедуре aux_get_create_statement
(формирует SQL-запрос создания объекта БД по его имени)
использовал такую вот конструкцию:

Код: plsql
1.
2.
3.
4.
5.
6.
select
    decode(bin_and(rdb$trigger_type + 1, 1), 0, 'before', 'after')
            || ' ' || decode(bin_and(bin_shr(rdb$trigger_type + 1, 1), 3), 1, 'insert', 2, 'update', 3, 'delete')
            || coalesce(' or ' || decode(bin_and(bin_shr(rdb$trigger_type + 1, 3), 3), 1, 'insert', 2, 'update', 3, 'delete'), '')
            || coalesce(' or ' || decode(bin_and(bin_shr(rdb$trigger_type + 1, 5), 3), 1, 'insert', 2, 'update', 3, 'delete'), '')
from rdb$triggers



полученную на основе описания логики определения типа триггера из исходников Firebird :
исходники Firebird на GitHub// that's how trigger action types are encoded
/*
bit 0 = TRIGGER_BEFORE/TRIGGER_AFTER flag,
bits 1-2 = TRIGGER_INSERT/TRIGGER_UPDATE/TRIGGER_DELETE (slot #1),
bits 3-4 = TRIGGER_INSERT/TRIGGER_UPDATE/TRIGGER_DELETE (slot #2),
bits 5-6 = TRIGGER_INSERT/TRIGGER_UPDATE/TRIGGER_DELETE (slot #3),
and finally the above calculated value is decremented

example #1:
TRIGGER_AFTER_DELETE =
= ((TRIGGER_DELETE << 1) | TRIGGER_AFTER) - 1 =
= ((3 << 1) | 1) - 1 =
= 0x00000110 (6)

example #2:
TRIGGER_BEFORE_INSERT_UPDATE =
= ((TRIGGER_UPDATE << 3) | (TRIGGER_INSERT << 1) | TRIGGER_BEFORE) - 1 =
= ((2 << 3) | (1 << 1) | 0) - 1 =
= 0x00010001 (17)

example #3:
TRIGGER_AFTER_UPDATE_DELETE_INSERT =
= ((TRIGGER_INSERT << 5) | (TRIGGER_DELETE << 3) | (TRIGGER_UPDATE << 1) | TRIGGER_AFTER) - 1 =
= ((1 << 5) | (3 << 3) | (2 << 1) | 1) - 1 =
= 0x00111100 (60)
*/
...
Рейтинг: 0 / 0
Как определить тип триггера?
    #40108535
Softologic
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
atronah
Я в своей хранимой процедуре использовал такую вот конструкцию:

Код: plsql
1.
2.
3.
4.
5.
6.
select
    decode(bin_and(rdb$trigger_type + 1, 1), 0, 'before', 'after')
            || ' ' || decode(bin_and(bin_shr(rdb$trigger_type + 1, 1), 3), 1, 'insert', 2, 'update', 3, 'delete')
            || coalesce(' or ' || decode(bin_and(bin_shr(rdb$trigger_type + 1, 3), 3), 1, 'insert', 2, 'update', 3, 'delete'), '')
            || coalesce(' or ' || decode(bin_and(bin_shr(rdb$trigger_type + 1, 5), 3), 1, 'insert', 2, 'update', 3, 'delete'), '')
from rdb$triggers




А неплохо, однако. Респект. Пригодится в случае автоматизации создания триггеров!
...
Рейтинг: 0 / 0
Как определить тип триггера?
    #40108536
Softologic
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость

Отдельная благодарность за ссылку на fb-утилитки. Есть что поизучать на досуге.
...
Рейтинг: 0 / 0
22 сообщений из 22, страница 1 из 1
Форумы / Firebird, InterBase [игнор отключен] [закрыт для гостей] / Как определить тип триггера?
Целевая тема:
Создать новую тему:
Автор:
Закрыть
Цитировать
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


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