6
0
mirror of https://github.com/FirebirdSQL/firebird-qa.git synced 2025-01-22 13:33:07 +01:00
firebird-qa/tests/bugs/gh_7208_test.py

317 lines
11 KiB
Python

#coding:utf-8
"""
ID: issue-7208
ISSUE: 7208
TITLE: Trace: provide performance statistics for DDL statements
DESCRIPTION:
Test creates all kinds of DDL object, makes altering some of them and then drops all these objects.
Every DDL statement is supplied with two special tags: "/* DDL_BEG */" and "/* DDL_END */" at the start and end of it.
These tags allow to filter only start and final line of DDL, thus simplifying further parsing.
We launch trace session and run these DDLs. After that, we search in the trace log DDL statements (first and line lines)
and also we check that after /* DDL_END */ trace log contains two mandatory lines:
"0 records fetched"
"Table ... Natural ... Purge Expunge"
After these lines trace log must have at least one line with some RDB$ table and non-zero statistics.
Only one line with statistics is taken in account for one DDL (because their quantity can differ between FB versions).
Concrete values of NR, IR, Inserts are ignored because they can change, so each line from statistics looks just like
short prefix: 'RDB' (in expected output).
NOTES:
[24.02.2023] pzotov
Checked on 5.0.0.958, 4.0.3.2903 -- all fine.
"""
import locale
import re
import pytest
from firebird.qa import *
test_sql = '''
create sequence g_common /* DDL_BEG */ /* DDL_END */;
create collation name_coll for utf8 from unicode case insensitive /* DDL_BEG */ /* DDL_END */;
create exception ex_invalid_value 'Invalid value detected' /* DDL_BEG */ /* DDL_END */;
create domain dm_idb as bigint /* DDL_BEG */ /* DDL_END */;
create table test(id dm_idb not null, x dm_idb) /* DDL_BEG */ /* DDL_END */;
alter table test add constraint test_pk primary key(id) /* DDL_BEG */ /* DDL_END */;
create index test_x on test(x) /* DDL_BEG */ /* DDL_END */;
alter index test_x inactive /* DDL_BEG */ /* DDL_END */;
alter index test_x active /* DDL_BEG */ /* DDL_END */;
create view v_test as select * from test /* DDL_BEG */ /* DDL_END */;
set term ^;
create trigger trg_test_bi before insert on test /* DDL_BEG */ as
begin
new.id = coalesce(new.id, gen_id(g_common,1));
end /* DDL_END */
^
create procedure standalone_proc(a_id dm_idb, a_x dm_idb) /* DDL_BEG */ as
begin
update test set x =:a_x where id = :a_id;
end /* DDL_END */
^
create function standalone_func returns int /* DDL_BEG */ as
begin
update test set id = rand()*10000000;
return (select max(id) from test);
end /* DDL_END */
^
create package pg_test /* DDL_BEG */ as
begin
procedure packaged_selectable_sp returns(id int);
function packaged_func returns int;
procedure packaged_nonselected_sp;
end /* DDL_END */
^
create package body pg_test /* DDL_BEG */ as
begin
procedure packaged_selectable_sp returns(id int) as
begin
for select id from test as cursor c
do begin
update test set id = -id * (select count(*) from rdb$database)
where current of c;
suspend;
end
end
procedure packaged_nonselected_sp as
begin
for select id from test as cursor c
do begin
update test set id = -id * (select count(*) from rdb$database)
where current of c;
end
end
function packaged_func returns int as
begin
update test set id = rand()*10000000;
return (select min(id) from test);
end
end /* DDL_END */
^
set term ;^
commit;
drop package pg_test /* DDL_BEG */ /* DDL_END */;
drop function standalone_func /* DDL_BEG */ /* DDL_END */;
drop procedure standalone_proc /* DDL_BEG */ /* DDL_END */;
drop trigger trg_test_bi /* DDL_BEG */ /* DDL_END */;
drop view v_test /* DDL_BEG */ /* DDL_END */;
drop index test_x /* DDL_BEG */ /* DDL_END */;
commit;
drop table test /* DDL_BEG */ /* DDL_END */;
drop domain dm_idb /* DDL_BEG */ /* DDL_END */;
drop exception ex_invalid_value /* DDL_BEG */ /* DDL_END */;
drop collation name_coll /* DDL_BEG */ /* DDL_END */;
drop sequence g_common /* DDL_BEG */ /* DDL_END */;
commit;
'''
db = db_factory()
act = python_act('db', substitutions = [(r'RDB\$\S+\s+\d+(\s+\d+)*', 'RDB')])
expected_stdout_trace = """
SET TRANSACTION
0 records fetched
create sequence g_common /* DDL_BEG */ /* DDL_END */
0 records fetched
Table Natural Index Update Insert Delete Backout Purge Expunge
RDB
create collation name_coll for utf8 from unicode case insensitive /* DDL_BEG */ /* DDL_END */
0 records fetched
Table Natural Index Update Insert Delete Backout Purge Expunge
RDB
create exception ex_invalid_value 'Invalid value detected' /* DDL_BEG */ /* DDL_END */
0 records fetched
Table Natural Index Update Insert Delete Backout Purge Expunge
RDB
create domain dm_idb as bigint /* DDL_BEG */ /* DDL_END */
0 records fetched
Table Natural Index Update Insert Delete Backout Purge Expunge
RDB
create table test(id dm_idb not null, x dm_idb) /* DDL_BEG */ /* DDL_END */
0 records fetched
Table Natural Index Update Insert Delete Backout Purge Expunge
RDB
alter table test add constraint test_pk primary key(id) /* DDL_BEG */ /* DDL_END */
0 records fetched
Table Natural Index Update Insert Delete Backout Purge Expunge
RDB
create index test_x on test(x) /* DDL_BEG */ /* DDL_END */
0 records fetched
Table Natural Index Update Insert Delete Backout Purge Expunge
RDB
alter index test_x inactive /* DDL_BEG */ /* DDL_END */
0 records fetched
Table Natural Index Update Insert Delete Backout Purge Expunge
RDB
alter index test_x active /* DDL_BEG */ /* DDL_END */
0 records fetched
Table Natural Index Update Insert Delete Backout Purge Expunge
RDB
create view v_test as select * from test /* DDL_BEG */ /* DDL_END */
0 records fetched
Table Natural Index Update Insert Delete Backout Purge Expunge
RDB
create trigger trg_test_bi before insert on test /* DDL_BEG */ as
end /* DDL_END */
0 records fetched
Table Natural Index Update Insert Delete Backout Purge Expunge
RDB
create procedure standalone_proc(a_id dm_idb, a_x dm_idb) /* DDL_BEG */ as
end /* DDL_END */
0 records fetched
Table Natural Index Update Insert Delete Backout Purge Expunge
RDB
create function standalone_func returns int /* DDL_BEG */ as
end /* DDL_END */
0 records fetched
Table Natural Index Update Insert Delete Backout Purge Expunge
RDB
create package pg_test /* DDL_BEG */ as
end /* DDL_END */
0 records fetched
Table Natural Index Update Insert Delete Backout Purge Expunge
RDB
create package body pg_test /* DDL_BEG */ as
end /* DDL_END */
0 records fetched
Table Natural Index Update Insert Delete Backout Purge Expunge
RDB
commit
0 records fetched
SET TRANSACTION
0 records fetched
drop package pg_test /* DDL_BEG */ /* DDL_END */
0 records fetched
Table Natural Index Update Insert Delete Backout Purge Expunge
RDB
drop function standalone_func /* DDL_BEG */ /* DDL_END */
0 records fetched
Table Natural Index Update Insert Delete Backout Purge Expunge
RDB
drop procedure standalone_proc /* DDL_BEG */ /* DDL_END */
0 records fetched
Table Natural Index Update Insert Delete Backout Purge Expunge
RDB
drop trigger trg_test_bi /* DDL_BEG */ /* DDL_END */
0 records fetched
Table Natural Index Update Insert Delete Backout Purge Expunge
RDB
drop view v_test /* DDL_BEG */ /* DDL_END */
0 records fetched
Table Natural Index Update Insert Delete Backout Purge Expunge
RDB
drop index test_x /* DDL_BEG */ /* DDL_END */
0 records fetched
Table Natural Index Update Insert Delete Backout Purge Expunge
RDB
commit
0 records fetched
SET TRANSACTION
0 records fetched
drop table test /* DDL_BEG */ /* DDL_END */
0 records fetched
Table Natural Index Update Insert Delete Backout Purge Expunge
RDB
drop domain dm_idb /* DDL_BEG */ /* DDL_END */
0 records fetched
Table Natural Index Update Insert Delete Backout Purge Expunge
RDB
drop exception ex_invalid_value /* DDL_BEG */ /* DDL_END */
0 records fetched
Table Natural Index Update Insert Delete Backout Purge Expunge
RDB
drop collation name_coll /* DDL_BEG */ /* DDL_END */
0 records fetched
Table Natural Index Update Insert Delete Backout Purge Expunge
RDB
drop sequence g_common /* DDL_BEG */ /* DDL_END */
0 records fetched
Table Natural Index Update Insert Delete Backout Purge Expunge
RDB
commit
0 records fetched
"""
@pytest.mark.trace
@pytest.mark.version('>=4.0.2')
def test_1(act: Action, capsys):
trace_cfg_items = [
'time_threshold = 0',
'log_errors = true',
'log_statement_finish = true',
'print_perf = true',
'max_sql_length = 32768',
]
with act.trace(db_events = trace_cfg_items, encoding=locale.getpreferredencoding()):
act.isql(input = test_sql, combine_output = True)
allowed_patterns = \
(
'(SET TRANSACTION)'
,'DDL_(BEG|END)'
,'0 records fetched'
,r'\s+\d+\s+ms(,)?'
,r'Table\s+Natural\s+Index\s+Update\s+Insert\s+Delete\s+Backout\s+Purge\s+Expunge'
,r'^RDB\$\S+\s+\d+'
,'^commit$'
)
allowed_patterns = [ re.compile(p, re.IGNORECASE) for p in allowed_patterns ]
rdb_tables_found_for_this_ddl = False
for line in act.trace_log:
if line.strip():
#print(line.strip())
if act.match_any(line.strip(), allowed_patterns):
if line.startswith('RDB$'):
if not rdb_tables_found_for_this_ddl:
print(line.strip())
rdb_tables_found_for_this_ddl = True
else:
rdb_tables_found_for_this_ddl = False
print(line.strip())
act.expected_stdout = expected_stdout_trace
act.stdout = capsys.readouterr().out
assert act.clean_stdout == act.clean_expected_stdout