mirror of
https://github.com/FirebirdSQL/firebird-qa.git
synced 2025-01-22 13:33:07 +01:00
148 lines
4.9 KiB
Python
148 lines
4.9 KiB
Python
|
#coding:utf-8
|
||
|
|
||
|
"""
|
||
|
ID: issue-8168
|
||
|
ISSUE: https://github.com/FirebirdSQL/firebird/issues/8168
|
||
|
TITLE: MAKE_DBKEY bug after backup/restore
|
||
|
DESCRIPTION:
|
||
|
Test creates two tables (tab_1, tab_2) and stores their relation_id in appropriate context variables.
|
||
|
Then we drop these tables and create them again but in 'reverse' order: tab_2, tab_1.
|
||
|
At this point we have to check that values of relation_id must differ for both tables and raise error
|
||
|
(see 'exc_rel_id_not_changed') if this is not so. Test logic must be changed if this error raises.
|
||
|
Then we add one row into each table and create SP (sp_chk) that uses make_dbkey() for returning these
|
||
|
rows. Key note: this SP *must* find appropriate record for each table.
|
||
|
Otherwise (if record not found) we raise exception exc_invalid_make_dbkey.
|
||
|
Finally, we do backup / restore and repeat call of sp_chk. It must return same ID values as before b/r.
|
||
|
NOTES:
|
||
|
[16.07.2024] pzotov
|
||
|
Confirmed bug on 6.0.0.386, 5.0.1.1425.
|
||
|
Checked on 6.0.0.387, 5.0.1.1428.
|
||
|
|
||
|
Thanks to Vlad for suggestion about test implementation.
|
||
|
"""
|
||
|
import pytest
|
||
|
from firebird.qa import *
|
||
|
from io import BytesIO
|
||
|
from firebird.driver import SrvRestoreFlag
|
||
|
import locale
|
||
|
|
||
|
db = db_factory()
|
||
|
act = python_act('db', substitutions=[('[ \t]+', ' ')])
|
||
|
|
||
|
@pytest.mark.version('>=5.0.1')
|
||
|
def test_1(act: Action, capsys):
|
||
|
|
||
|
init_sql = f"""
|
||
|
set bail on;
|
||
|
set list on;
|
||
|
create exception exc_rel_id_not_changed 'RELATION_ID not changed table(s): @1. One need to change test logic!';
|
||
|
create exception exc_invalid_make_dbkey 'Invalid make_dbkey() detected for table(s): @1';
|
||
|
|
||
|
create view v_get_rel_id as
|
||
|
select
|
||
|
max( iif( upper(rdb$relation_name) = 'TAB_1', rdb$relation_id, null ) ) as t1_rel_id
|
||
|
,max( iif( upper(rdb$relation_name) = 'TAB_2', rdb$relation_id, null ) ) as t2_rel_id
|
||
|
from rdb$relations
|
||
|
where rdb$relation_name starting with upper('tab_')
|
||
|
;
|
||
|
create table tab_1(id int);
|
||
|
create table tab_2(id int);
|
||
|
commit;
|
||
|
|
||
|
set term ^;
|
||
|
execute block as
|
||
|
begin
|
||
|
for
|
||
|
select t1_rel_id, t2_rel_id
|
||
|
from v_get_rel_id
|
||
|
as cursor c
|
||
|
do begin
|
||
|
rdb$set_context('USER_SESSION', 'TAB1_REL_ID', c.t1_rel_id);
|
||
|
rdb$set_context('USER_SESSION', 'TAB2_REL_ID', c.t2_rel_id);
|
||
|
end
|
||
|
end
|
||
|
^
|
||
|
set term ;^
|
||
|
|
||
|
drop table tab_1;
|
||
|
drop table tab_2;
|
||
|
|
||
|
recreate table tab_2(id int);
|
||
|
recreate table tab_1(id int);
|
||
|
commit;
|
||
|
|
||
|
set term ^;
|
||
|
execute block as
|
||
|
declare v_list varchar(100) = '';
|
||
|
begin
|
||
|
for
|
||
|
select t1_rel_id, t2_rel_id
|
||
|
from v_get_rel_id
|
||
|
as cursor c
|
||
|
do begin
|
||
|
if (c.t1_rel_id = rdb$get_context('USER_SESSION', 'TAB1_REL_ID')) then
|
||
|
v_list = v_list || 'TAB_1; ';
|
||
|
if (c.t2_rel_id = rdb$get_context('USER_SESSION', 'TAB2_REL_ID')) then
|
||
|
v_list = v_list || 'TAB_2';
|
||
|
|
||
|
if (v_list > '') then
|
||
|
exception exc_rel_id_not_changed using(v_list);
|
||
|
end
|
||
|
end
|
||
|
^
|
||
|
set term ;^
|
||
|
|
||
|
-----------------------------------------
|
||
|
|
||
|
insert into tab_1(id) values(1);
|
||
|
insert into tab_2(id) values(2);
|
||
|
commit;
|
||
|
|
||
|
set term ^;
|
||
|
create or alter procedure sp_chk returns (id1 int, id2 int) as
|
||
|
declare v_list varchar(100) = '';
|
||
|
begin
|
||
|
select id from tab_1 where rdb$db_key = make_dbkey('TAB_1', 0) into id1;
|
||
|
if (row_count = 0) then v_list = v_list || 'TAB_1; ';
|
||
|
|
||
|
select id from tab_2 where rdb$db_key = make_dbkey('TAB_2', 0) into id2;
|
||
|
if (row_count = 0) then v_list = v_list || 'TAB_2';
|
||
|
|
||
|
if (v_list > '') then
|
||
|
exception exc_invalid_make_dbkey using(v_list);
|
||
|
|
||
|
suspend;
|
||
|
end
|
||
|
^
|
||
|
set term ;^
|
||
|
commit;
|
||
|
select * from sp_chk;
|
||
|
|
||
|
"""
|
||
|
|
||
|
expected_stdout = """
|
||
|
ID1 1
|
||
|
ID2 2
|
||
|
"""
|
||
|
act.expected_stdout = expected_stdout
|
||
|
act.isql(input = init_sql, combine_output = True)
|
||
|
assert act.clean_stdout == act.clean_expected_stdout
|
||
|
act.reset()
|
||
|
|
||
|
#---------------------------------------------------
|
||
|
|
||
|
backup = BytesIO()
|
||
|
|
||
|
with act.connect_server() as srv:
|
||
|
srv.database.local_backup(database=act.db.db_path, backup_stream=backup)
|
||
|
backup.seek(0)
|
||
|
srv.database.local_restore(backup_stream=backup, database=act.db.db_path, flags = SrvRestoreFlag.REPLACE)
|
||
|
|
||
|
act.expected_stdout = """
|
||
|
ID1 1
|
||
|
ID2 2
|
||
|
"""
|
||
|
act.isql(input = "set list on; select * from sp_chk;", combine_output = True)
|
||
|
assert act.clean_stdout == act.clean_expected_stdout
|
||
|
act.reset()
|