mirror of
https://github.com/FirebirdSQL/firebird-qa.git
synced 2025-01-22 21:43:06 +01:00
145 lines
6.2 KiB
Python
145 lines
6.2 KiB
Python
#coding:utf-8
|
|
|
|
"""
|
|
ID: issue-6278
|
|
ISSUE: 6278
|
|
TITLE: Trigger on system table restored in FB3 database and can't be deleted
|
|
DESCRIPTION:
|
|
We restore here database that was created in FB 2.5.9 and contained triggers for tables RDB$RELATION_FIELDS, MON$STATEMENTS and MON$ATTACHMENTS.
|
|
Table RDB$RELATION_FIELDS had triggers BEFORE INSERT and AFTER INSERT. Monitoring tabled had triggers BEFORE DELETE and AFTER DELETE.
|
|
Also, table 'TLOG' is in this database, and this table serves as log for actions: create/drop table; delete from mon$statements and delete from mon$attachments.
|
|
For DDL like 'create table test(x int)' and 'drop table test' table TLOG will contain two records which are added there by triggers on RDB$RELATION_FIELDS.
|
|
Further, if we create addition connection and run statement which returns at least one record (like 'select ... from rdb$database') then in 2.5 two recors
|
|
had been added into TLOG for each of: 'DELETE FROM MON$STATEMENTS' and 'DELETE FROM MON$ATTACHMENTS'.
|
|
|
|
Finally, BEFORE fix of this ticket issue (e.g. in WI-V3.0.5.33109):
|
|
1) restored database contained following triggers: TRG_MON_ATTACHMENTS*, TRG_MON_STATEMENTS* and TRG_RDB_REL_FIELDS*
|
|
2) statements 'create table' and 'drop table' led to logging following records in TLOG:
|
|
rdb$relation_fields: record is to be created
|
|
rdb$relation_fields: record has been created
|
|
rdb$relation_fields: record is to be removed
|
|
rdb$relation_fields: record has been removed
|
|
3) command 'delete from mon$statement' (when there was another non-system connection with one running or completed statement)
|
|
led to logging these records in TLOG:
|
|
mon$statements: record is to be removed
|
|
mon$statements: record has been removed
|
|
4) command 'delete from mon$attachments' (when there was another non-system connection) led to logging these records in TLOG:
|
|
mon$attachments: record is to be removed
|
|
mon$attachments: record has been removed
|
|
|
|
All of above mentioned should NOT appear in a database that is restored AFTER this ticket was fixed.
|
|
Finally, we try to create three new triggers for tables rdb$relation-fields, mon$statements and mon$attachments.
|
|
All of these attempts must FAIL with:
|
|
========
|
|
- no permission for ALTER access to TABLE RDB$RELATION_FIELDS
|
|
-607
|
|
335544351
|
|
========
|
|
JIRA: CORE-6028
|
|
FBTEST: bugs.core_6028
|
|
"""
|
|
|
|
import pytest
|
|
import zipfile
|
|
from pathlib import Path
|
|
from firebird.qa import *
|
|
from firebird.driver import SrvRestoreFlag, DatabaseError
|
|
|
|
db = db_factory()
|
|
db_tmp = db_factory(filename='tmp_core_602.fdb', do_not_create=True)
|
|
|
|
act = python_act('db')
|
|
|
|
expected_stdout = """
|
|
NO USER-DEFINED TRIGGERS IN JUST RESTORED DATABASE.
|
|
NO ACTIONS WAS LOGGED IN THE TABLE TLOG.
|
|
unsuccessful metadata update
|
|
-CREATE OR ALTER TRIGGER NEW_TRG_RDB_REL_FLDS_BI failed
|
|
-no permission for ALTER access to TABLE RDB$RELATION_FIELDS
|
|
-607
|
|
(335544351, 336397272, 335544352)
|
|
unsuccessful metadata update
|
|
-CREATE OR ALTER TRIGGER NEW_TRG_MON_STM_BD failed
|
|
-no permission for ALTER access to TABLE MON$STATEMENTS
|
|
-607
|
|
(335544351, 336397272, 335544352)
|
|
unsuccessful metadata update
|
|
-CREATE OR ALTER TRIGGER NEW_TRG_MON_ATT_BD failed
|
|
-no permission for ALTER access to TABLE MON$ATTACHMENTS
|
|
-607
|
|
(335544351, 336397272, 335544352)
|
|
"""
|
|
|
|
fbk_file = temp_file('core_6028_25.fbk')
|
|
|
|
ddl_probes = ["""
|
|
create or alter trigger new_trg_rdb_rel_flds_bi for rdb$relation_fields active before insert position 0 as
|
|
begin
|
|
insert into tlog(id, action) values( gen_id(g, 111), 'rdb$relation_fields: record is to be created' );
|
|
end
|
|
""", """
|
|
create or alter trigger new_trg_mon_stm_bd for mon$statements active before delete position 0 as
|
|
begin
|
|
insert into tlog(id, action) values( gen_id(g, 222), 'mon$statements: record is to be removed' );
|
|
end
|
|
""", """
|
|
create or alter trigger new_trg_mon_att_bd for mon$attachments active before delete position 0 as
|
|
begin
|
|
insert into tlog(id, action) values( gen_id(g, 333), 'mon$attachments: record is to be removed' );
|
|
end
|
|
"""]
|
|
|
|
@pytest.mark.version('>=3.0.5')
|
|
def test_1(act: Action, fbk_file: Path, db_tmp: Database, capsys):
|
|
zipped_fbk_file = zipfile.Path(act.files_dir / 'core_6028_25.zip', at='core_6028_25.fbk')
|
|
fbk_file.write_bytes(zipped_fbk_file.read_bytes())
|
|
#
|
|
with act.connect_server() as srv:
|
|
srv.database.restore(backup=fbk_file, database=db_tmp.db_path,
|
|
flags=SrvRestoreFlag.REPLACE)
|
|
srv.wait()
|
|
#
|
|
con_worker = db_tmp.connect()
|
|
con_worker_attachment_id = con_worker.info.id
|
|
con_worker.execute_immediate('create table test(id int)')
|
|
con_worker.commit()
|
|
con_worker.execute_immediate('drop table test')
|
|
con_worker.commit()
|
|
#
|
|
cur_worker=con_worker.cursor()
|
|
cur_worker.execute("select coalesce(rt.rdb$trigger_name, 'NO USER-DEFINED TRIGGERS IN JUST RESTORED DATABASE.') from rdb$database rd left join rdb$triggers rt on rt.rdb$system_flag is distinct from 1 order by 1")
|
|
for r in cur_worker:
|
|
print(r[0])
|
|
#
|
|
with db_tmp.connect() as con_killer:
|
|
cur_killer = con_killer.cursor()
|
|
cur_killer.execute(f'delete from mon$statements s where s.mon$attachment_id = {con_worker_attachment_id}')
|
|
con_killer.commit()
|
|
cur_killer.execute(f'delete from mon$attachments a where a.mon$attachment_id = {con_worker_attachment_id}')
|
|
con_killer.commit()
|
|
cur_killer.execute("select coalesce(t.action, 'NO ACTIONS WAS LOGGED IN THE TABLE TLOG.') as sys_tabs_action from rdb$database rd left join tlog t on 1=1")
|
|
for r in cur_killer:
|
|
print(r[0])
|
|
#
|
|
try:
|
|
cur_worker.close()
|
|
except Exception:
|
|
pass
|
|
try:
|
|
con_worker.close()
|
|
except Exception:
|
|
pass
|
|
#
|
|
for cmd in ddl_probes:
|
|
try:
|
|
con_killer.execute_immediate(cmd)
|
|
except DatabaseError as e:
|
|
print(e)
|
|
print(e.sqlcode)
|
|
print(e.gds_codes)
|
|
# Check
|
|
act.reset()
|
|
act.expected_stdout = expected_stdout
|
|
act.stdout = capsys.readouterr().out
|
|
assert act.clean_stdout == act.clean_expected_stdout
|