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

143 lines
5.3 KiB
Python

#coding:utf-8
#
# id: bugs.core_1606
# title: Ability to insert child record if parent record is locked but foreign key target unchanged
# decription:
# Master table has two record, both are updated but without changing PK field.
# Than we check that we CAN add rows in detail table with references to existed PK from main,
# and even can change FK-values in these added rows, but can do it only with maintenance that
# MAIN table's PK exists for new values in FK
# Checked on:
# 4.0.0.1635 SS: 1.598s.
# 4.0.0.1633 CS: 1.883s.
# 3.0.5.33180 SS: 1.077s.
# 3.0.5.33178 CS: 1.391s.
# 2.5.9.27119 SS: 0.347s.
# 2.5.9.27146 SC: 0.352s.
#
# tracker_id: CORE-1606
# min_versions: ['2.5.0']
# versions: 2.5
# qmid: None
import pytest
from firebird.qa import db_factory, isql_act, Action
# version: 2.5
# resources: None
substitutions_1 = []
init_script_1 = """"""
db_1 = db_factory(sql_dialect=3, init=init_script_1)
test_script_1 = """
set term ^;
execute block as
begin
execute statement 'drop sequence g';
when any do begin end
end
^
set term ;^
commit;
create sequence g;
commit;
recreate table tdetl(id int constraint tdetl_pk primary key, pid int);
commit;
recreate table tmain(id int constraint tmain_pk primary key, x int);
commit;
alter table tdetl add constraint tdetl_fk foreign key(pid) references tmain(id);
commit;
insert into tmain(id, x) values(1, 100);
insert into tmain(id, x) values(2, 200);
commit;
set list on;
set transaction no wait;
--set count on;
update tmain set id = id, x = -x*10 where id=1;
update tmain set id = id, x = -x*20 where id=2;
set term ^;
execute block returns(id int, pid int) as
declare s varchar(1024);
begin
s = 'insert into tdetl(id, pid) select gen_id(g,1), cast( ? as int) from rdb$types rows 3';
/*
-- todo later, after fix CORE-4796
'merge into tdetl t '
|| 'using ( select 5 as id, 1 as pid from rdb$types rows 2 ) s '
|| 'on t.id=s.id '
|| 'when matched then update set t.pid = s.pid '
|| 'when not matched then insert values( s.id, s.pid)';
*/
execute statement ( s ) ( 1 ) -------------------------------------- [1]: add rows with pid=1
on external 'localhost:' || rdb$get_context('SYSTEM','DB_NAME')
as user 'sysdba' password 'masterkey' role 'RCHILD';
execute statement ( s ) ( 2 ) -------------------------------------- [2]: add rows with pid=2
on external 'localhost:' || rdb$get_context('SYSTEM','DB_NAME')
as user 'sysdba' password 'masterkey' role 'RCHILD';
execute statement ('update tdetl set pid = 3 - pid') -- rows with pid=1 that were inserted on [1] will have pid=2 and vice versa
on external 'localhost:' || rdb$get_context('SYSTEM','DB_NAME')
as user 'sysdba' password 'masterkey' role 'RCHILD';
for
execute statement 'select id,pid from tdetl order by id'
on external 'localhost:' || rdb$get_context('SYSTEM','DB_NAME')
as user 'sysdba' password 'masterkey' role 'RCHILD'
into id,pid
do
suspend;
end
^
set term ;^
commit;
-- ||||||||||||||||||||||||||||
-- ###################################||| FB 4.0+, SS and SC |||##############################
-- ||||||||||||||||||||||||||||
-- If we check SS or SC and ExtConnPoolLifeTime > 0 (config parameter FB 4.0+) then current
-- DB (bugs.core_NNNN.fdb) will be 'captured' by firebird.exe process and fbt_run utility
-- will not able to drop this database at the final point of test.
-- Moreover, DB file will be hold until all activity in firebird.exe completed and AFTER this
-- we have to wait for <ExtConnPoolLifeTime> seconds after it (discussion and small test see
-- in the letter to hvlad and dimitr 13.10.2019 11:10).
-- This means that one need to kill all connections to prevent from exception on cleanup phase:
-- SQLCODE: -901 / lock time-out on wait transaction / object <this_test_DB> is in use
-- #############################################################################################
delete from mon$attachments where mon$attachment_id != current_connection;
commit;
"""
act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1)
expected_stdout_1 = """
ID 1
PID 2
ID 2
PID 2
ID 3
PID 2
ID 4
PID 1
ID 5
PID 1
ID 6
PID 1
"""
@pytest.mark.version('>=2.5')
def test_1(act_1: Action):
act_1.expected_stdout = expected_stdout_1
act_1.execute()
assert act_1.clean_expected_stdout == act_1.clean_stdout