6
0
mirror of https://github.com/FirebirdSQL/firebird-qa.git synced 2025-01-22 21:43:06 +01:00
firebird-qa/tests/bugs/gh_7426_test.py

145 lines
5.3 KiB
Python

#coding:utf-8
"""
ID: issue-7426
ISSUE: https://github.com/FirebirdSQL/firebird/issues/7426
TITLE: Ensure the DDL trigger requests are cached
DESCRIPTION:
Test prepares trace config with requrement to see TRIGGERS compilation.
We create two DDL triggers for logging any DDL statement, before and after it occurs.
Then we create table with two constraints and one index, and make several alter statements.
Finally, we parse trace log and filter only lines containing name of DDL triggers.
Only ONE occurence must be for each of DDL trigger (totally 2).
Before this ticked was fixed, every time we did some DDL appropriate trigger was compiled
and this could be seen in a trace log (checked on 5.0.0.1182).
No errors must present in the trace log.
NOTES:
[07-sep-2023] pzotov
::: NB :::
1. It must be noted that the term 'COMPILE' means parsing of BLR code into an execution tree, i.e. this action
occurs when unit code is loaded into metadata cache.
2. Currently there is no way to specify in the trace what EXACT type of DDL trigger fired. It is shown as "AFTER DDL".
Checked on 5.0.0.1190.
"""
import locale
import re
import pytest
from firebird.qa import *
db = db_factory()
act = python_act('db')
trace = ['log_initfini = false',
'log_errors = true',
'log_trigger_compile = true',
]
allowed_patterns = [ ' ERROR AT ', 'Trigger TRG_ANY_DDL_STATEMENT_', ]
allowed_patterns = [ re.compile(r, re.IGNORECASE) for r in allowed_patterns]
@pytest.mark.version('>=5.0')
def test_1(act: Action, capsys):
test_script = f"""
recreate table log_ddl_triggers_activity (
id int generated by default as identity constraint pk_log_ddl_triggers_activity primary key
,ddl_trigger_name varchar(64)
,event_type varchar(25) not null
,object_type varchar(25) not null
,ddl_event varchar(25) not null
,object_name varchar(64) not null
,dts timestamp default 'now'
);
set autoddl off;
set term ^;
execute block as
begin
rdb$set_context('USER_SESSION', 'SKIP_DDL_TRG', '1');
end
^
create or alter trigger trg_any_ddl_statement_alter active after any ddl statement as
begin
if (rdb$get_context('USER_SESSION', 'SKIP_DDL_TRG') is null) then
execute statement
('insert into log_ddl_triggers_activity(ddl_trigger_name, event_type, object_type, ddl_event, object_name) values( ?, ?, ?, ?, ? )' )
( 'ANY_DDL_STATEMENT_AFTER'
,rdb$get_context('DDL_TRIGGER', 'EVENT_TYPE')
,rdb$get_context('DDL_TRIGGER', 'OBJECT_TYPE')
,rdb$get_context('DDL_TRIGGER', 'DDL_EVENT')
,rdb$get_context('DDL_TRIGGER', 'OBJECT_NAME')
);
end
^
create or alter trigger trg_any_ddl_statement_before active before any ddl statement as
begin
if (rdb$get_context('USER_SESSION', 'SKIP_DDL_TRG') is null) then
execute statement
('insert into log_ddl_triggers_activity(ddl_trigger_name, event_type, object_type, ddl_event, object_name) values( ?, ?, ?, ?, ? )' )
( 'ANY_DDL_STATEMENT_BEFORE'
,rdb$get_context('DDL_TRIGGER', 'EVENT_TYPE')
,rdb$get_context('DDL_TRIGGER', 'OBJECT_TYPE')
,rdb$get_context('DDL_TRIGGER', 'DDL_EVENT')
,rdb$get_context('DDL_TRIGGER', 'OBJECT_NAME')
);
end
^
execute block as
begin
rdb$set_context('USER_SESSION', 'SKIP_DDL_TRG', null);
end
^
commit
^
----------
create table test(id int not null, x smallint, y int, z int, name varchar(10))
^
--/*
alter table test add constraint test_pk primary key(id) using descending index test_id_desc
^
alter table test add constraint test_unq unique(x,y) using descending index test_x_y_unq_desc
^
create index test_name on test(name)
^
alter index test_name inactive
^
alter index test_name active
^
drop index test_name
^
alter table test drop constraint test_pk, drop constraint test_unq
^
alter table test alter x type int, alter y type bigint, alter name type varchar(20), drop z, add u varchar(10)
^
--*/
commit
^
set term ;^
"""
with act.trace(db_events=trace, encoding = locale.getpreferredencoding(), encoding_errors='utf8'):
act.isql(switches = ['-q'], input = test_script, combine_output = True, io_enc = locale.getpreferredencoding())
# Process trace
for line in act.trace_log:
if line.rstrip().split():
for p in allowed_patterns:
if p.search(line):
print(line.strip())
expected_stdout = f"""
Trigger TRG_ANY_DDL_STATEMENT_BEFORE (BEFORE DDL):
Trigger TRG_ANY_DDL_STATEMENT_ALTER (AFTER DDL):
"""
act.expected_stdout = expected_stdout
act.stdout = capsys.readouterr().out
assert act.clean_stdout == act.clean_expected_stdout