mirror of
https://github.com/FirebirdSQL/firebird-qa.git
synced 2025-01-22 13:33:07 +01:00
285 lines
10 KiB
Python
285 lines
10 KiB
Python
#coding:utf-8
|
|
|
|
"""
|
|
ID: issue-4803
|
|
ISSUE: 4803
|
|
TITLE: Changed data not visible in WHEN-section if exception occured inside SP that has been called from this code
|
|
DESCRIPTION:
|
|
JIRA: CORE-4483
|
|
FBTEST: bugs.core_4483
|
|
NOTES:
|
|
[25.11.2023] pzotov
|
|
Writing code requires more care since 6.0.0.150: ISQL does not allow specifying duplicate delimiters without any statements between them (two semicolon, two carets etc).
|
|
"""
|
|
|
|
import pytest
|
|
from firebird.qa import *
|
|
|
|
db = db_factory()
|
|
|
|
test_script = """
|
|
-- ISSUE-1: if procedure_A calls procedure_B and the latter makes some DML changes but then fails
|
|
-- then proc_A does NOT see any changes that were made by proc_B.
|
|
-- See letter to dimitr, 02-feb-2015 23:47, attachment: 'core-4483_test1.sql'.
|
|
|
|
set term ^;
|
|
create or alter procedure P1 as begin end^
|
|
create or alter procedure P2 as begin end^
|
|
create or alter procedure P3 as begin end^
|
|
create or alter procedure P4 as begin end^
|
|
create or alter procedure P5 as begin end^
|
|
create or alter procedure P6 as begin end^
|
|
commit^
|
|
|
|
recreate table t(id int primary key)^
|
|
commit^
|
|
|
|
-- P1...P4 -- procedures WITHOUT when blocks and correct code:
|
|
create or alter procedure P1 as begin insert into t values(1); end^
|
|
create or alter procedure P2 as begin insert into t values(2); end^
|
|
create or alter procedure P3 as begin insert into t values(3); end^
|
|
create or alter procedure P4 as begin insert into t values(4); end^
|
|
|
|
|
|
-- P5 -- single proc WITH when block (but with correct code);
|
|
create or alter procedure P5 as
|
|
begin
|
|
insert into t values(5);
|
|
rdb$set_context('USER_SESSION','PROC_P5_BEFORE_P6_CALL', (select list(id) from t)); --- [ 2 ]
|
|
execute procedure P6;
|
|
when any do
|
|
begin
|
|
rdb$set_context('USER_SESSION','PROC_P5_WHEN_BLK_AFTER_P6_CALL', (select list(id) from t)); --- [ 4 ]
|
|
exception;
|
|
end
|
|
end^
|
|
|
|
-- P6 -- deepest procedure with INCORRECT code (where exception occurs):
|
|
create or alter procedure P6 as
|
|
declare i int;
|
|
begin
|
|
insert into t values(6);
|
|
-- ### ERRONEOUS CODE ###
|
|
i = rdb$set_context('USER_SESSION','PROC_P6_ERROR_LINE', (select list(id) from t)) / 0; --- [ 3a ]
|
|
when any do
|
|
begin
|
|
rdb$set_context('USER_SESSION','PROC_P6_WHEN_BLK_CATCHING_ERR', (select list(id) from t)); --- [ 3b ]
|
|
exception;
|
|
end
|
|
end^
|
|
commit^
|
|
set term ;^
|
|
commit;
|
|
|
|
set transaction no wait;
|
|
set term ^;
|
|
execute block
|
|
as
|
|
declare i int;
|
|
begin
|
|
delete from t;
|
|
execute procedure P1;
|
|
execute procedure P2;
|
|
execute procedure P3;
|
|
execute procedure P4;
|
|
rdb$set_context('USER_SESSION','MAIN_EB_AFTER_CALL_P1_P4', (select list(id) from t)); --- [ 1 ]
|
|
|
|
execute procedure P5; -- ==> update context vars 'PROC_P5_BEFORE_P6_CALL' and 'PROC_P5_WHEN_BLK_AFTER_P6_CALL'
|
|
|
|
when any do
|
|
begin
|
|
rdb$set_context('USER_SESSION','MAIN_EB_WHEN_BLK_AFTER_P5_EXC', (select list(id) from t)); --- [ 4 ]
|
|
--exception;
|
|
end
|
|
end
|
|
^ set term ;^
|
|
|
|
SET LIST ON;
|
|
select
|
|
rdb$get_context('USER_SESSION','MAIN_EB_AFTER_CALL_P1_P4') "main EB after P1,P2,P3,P4" -- [ 1 ]
|
|
,rdb$get_context('USER_SESSION','PROC_P5_BEFORE_P6_CALL') "proc P5 before call P6" -- [ 2 ]
|
|
,rdb$get_context('USER_SESSION','PROC_P6_ERROR_LINE') "proc P6 error source line" -- [ 3a ]
|
|
,rdb$get_context('USER_SESSION','PROC_P6_WHEN_BLK_CATCHING_ERR') "proc P6 WHEN blk: catch exceptn" -- [ 3b ]
|
|
,rdb$get_context('USER_SESSION','PROC_P5_WHEN_BLK_AFTER_P6_CALL') "proc P5 WHEN blk: catch exceptn" -- [ 4 ]
|
|
,rdb$get_context('USER_SESSION','MAIN_EB_WHEN_BLK_AFTER_P5_EXC') "main EB WHEN blk: catch exceptn" -- [ 5 ]
|
|
from rdb$database;
|
|
|
|
select count(*) t_count from t;
|
|
commit;
|
|
|
|
-- #############################################################################################
|
|
|
|
-- ISSUE-2: if some procedure performs several DML statements (s1, s2, s3, ..., sN) and N-th DML
|
|
-- fails and control falls into WHEN-block of this SP then we can not see any changes that we
|
|
-- have done inside THIS procedure.
|
|
-- See letter to dimitr, 02-feb-2015 23:47, attachment: 'core-4483_test2.sql'.
|
|
|
|
set term ^;
|
|
create or alter procedure p1 as begin end^
|
|
create or alter procedure p2 as begin end^
|
|
create or alter procedure p3 as begin end^
|
|
create or alter procedure p4 as begin end^
|
|
create or alter procedure p5 as begin end^
|
|
create or alter procedure p6 as begin end^
|
|
commit^
|
|
|
|
recreate table t(id int)^
|
|
|
|
create or alter procedure p1 as
|
|
begin
|
|
insert into t values(1);
|
|
insert into t values(12);
|
|
insert into t values(133);
|
|
rdb$set_context('USER_SESSION','P1_CODE_BEFO_CALL_P2',(select list(id) from t));
|
|
execute procedure p2;
|
|
when any do
|
|
begin
|
|
-- here we must be able to see ALL changes that current procedure has done, i.e.
|
|
-- records with ID = 1, 12 and 133 must be visible for us at this point.
|
|
rdb$set_context('USER_SESSION','P1_CATCH_BLK_SEES',(select list(id) from t));
|
|
--exception;
|
|
end
|
|
end^
|
|
|
|
create or alter procedure p2 as
|
|
begin
|
|
insert into t values(2);
|
|
insert into t values(22);
|
|
insert into t values(233);
|
|
rdb$set_context('USER_SESSION','P2_CODE_BEFO_CALL_P3',(select list(id) from t));
|
|
execute procedure p3;
|
|
when any do
|
|
begin
|
|
-- here we must be able to see ALL changes that current procedure has done, i.e.
|
|
-- records with ID = 2, 22 and 233 must be visible for us at this point.
|
|
rdb$set_context('USER_SESSION','P2_CATCH_BLK_SEES',(select list(id) from t));
|
|
exception;
|
|
end
|
|
end^
|
|
|
|
create or alter procedure p3 as
|
|
begin
|
|
insert into t values(3);
|
|
insert into t values(32);
|
|
insert into t values(333);
|
|
rdb$set_context('USER_SESSION','P3_CODE_BEFO_CALL_P4',(select list(id) from t));
|
|
execute procedure p4;
|
|
when any do
|
|
begin
|
|
-- here we must be able to see ALL changes that current procedure has done, i.e.
|
|
-- records with ID = 3, 32 and 333 must be visible for us at this point.
|
|
rdb$set_context('USER_SESSION','P3_CATCH_BLK_SEES',(select list(id) from t));
|
|
exception;
|
|
end
|
|
end^
|
|
|
|
create or alter procedure p4 as
|
|
begin
|
|
insert into t values(4);
|
|
insert into t values(42);
|
|
insert into t values(433);
|
|
rdb$set_context('USER_SESSION','P4_CODE_BEFO_CALL_P5',(select list(id) from t));
|
|
execute procedure p5;
|
|
when any do
|
|
begin
|
|
-- here we must be able to see ALL changes that current procedure has done, i.e.
|
|
-- records with ID = 4, 42 and 433 must be visible for us at this point.
|
|
rdb$set_context('USER_SESSION','P4_CATCH_BLK_SEES',(select list(id) from t));
|
|
exception;
|
|
end
|
|
end^
|
|
|
|
create or alter procedure p5 as
|
|
begin
|
|
insert into t values(5);
|
|
insert into t values(52);
|
|
insert into t values(533);
|
|
rdb$set_context('USER_SESSION','P5_CODE_BEFO_CALL_P6',(select list(id) from t));
|
|
execute procedure p6;
|
|
when any do
|
|
begin
|
|
-- here we must be able to see ALL changes that current procedure has done, i.e.
|
|
-- records with ID = 5, 52 and 533 must be visible for us at this point.
|
|
rdb$set_context('USER_SESSION','P5_CATCH_BLK_SEES',(select list(id) from t));
|
|
exception;
|
|
end
|
|
end^
|
|
|
|
create or alter procedure p6 as
|
|
declare i int;
|
|
begin
|
|
insert into t values(6);
|
|
insert into t values(62);
|
|
insert into t values(633);
|
|
rdb$set_context('USER_SESSION','P6_CODE_BEFO_ZERO_DIV',(select list(id) from t));
|
|
i = 1/0;
|
|
when any do
|
|
begin
|
|
-- here we must be able to see ALL changes that current procedure has done, i.e.
|
|
-- records with ID = 6, 62 and 633 must be visible for us at this point.
|
|
rdb$set_context('USER_SESSION','P6_CATCH_BLK_SEES',(select list(id) from t));
|
|
exception;
|
|
end
|
|
end^
|
|
|
|
commit^
|
|
set term ;^
|
|
|
|
execute procedure p1;
|
|
|
|
set list on;
|
|
select
|
|
rdb$get_context('USER_SESSION', 'P6_CODE_BEFO_ZERO_DIV') as "IDs in p6 before zero div"
|
|
,rdb$get_context('USER_SESSION', 'P6_CATCH_BLK_SEES') as "IDs in p6 catch blk"
|
|
|
|
,rdb$get_context('USER_SESSION', 'P5_CODE_BEFO_CALL_P6') as "IDs in p5 before p6 call"
|
|
,rdb$get_context('USER_SESSION', 'P5_CATCH_BLK_SEES') as "IDs in p5 catch blk"
|
|
|
|
,rdb$get_context('USER_SESSION', 'P4_CODE_BEFO_CALL_P5') as "IDs in p4 before p5 call"
|
|
,rdb$get_context('USER_SESSION', 'P4_CATCH_BLK_SEES') as "IDs in p4 catch blk"
|
|
|
|
,rdb$get_context('USER_SESSION', 'P3_CODE_BEFO_CALL_P4') as "IDs in p3 before p4 call"
|
|
,rdb$get_context('USER_SESSION', 'P3_CATCH_BLK_SEES') as "IDs in p3 catch blk"
|
|
|
|
,rdb$get_context('USER_SESSION', 'P2_CODE_BEFO_CALL_P3') as "IDs in p2 before p3 call"
|
|
,rdb$get_context('USER_SESSION', 'P2_CATCH_BLK_SEES') as "IDs in p2 catch blk"
|
|
|
|
,rdb$get_context('USER_SESSION', 'P1_CODE_BEFO_CALL_P2') as "IDs in p1 before p2 call"
|
|
,rdb$get_context('USER_SESSION', 'P1_CATCH_BLK_SEES') as "IDs in p1 catch blk"
|
|
|
|
from rdb$database;
|
|
set list off;
|
|
"""
|
|
|
|
act = isql_act('db', test_script)
|
|
|
|
expected_stdout = """
|
|
main EB after P1,P2,P3,P4 1,2,3,4
|
|
proc P5 before call P6 1,2,3,4,5
|
|
proc P6 error source line 1,2,3,4,5,6
|
|
proc P6 WHEN blk: catch exceptn 1,2,3,4,5,6
|
|
proc P5 WHEN blk: catch exceptn 1,2,3,4,5
|
|
main EB WHEN blk: catch exceptn 1,2,3,4
|
|
T_COUNT 4
|
|
|
|
IDs in p6 before zero div 1,12,133,2,22,233,3,32,333,4,42,433,5,52,533,6,62,633
|
|
IDs in p6 catch blk 1,12,133,2,22,233,3,32,333,4,42,433,5,52,533,6,62,633
|
|
IDs in p5 before p6 call 1,12,133,2,22,233,3,32,333,4,42,433,5,52,533
|
|
IDs in p5 catch blk 1,12,133,2,22,233,3,32,333,4,42,433,5,52,533
|
|
IDs in p4 before p5 call 1,12,133,2,22,233,3,32,333,4,42,433
|
|
IDs in p4 catch blk 1,12,133,2,22,233,3,32,333,4,42,433
|
|
IDs in p3 before p4 call 1,12,133,2,22,233,3,32,333
|
|
IDs in p3 catch blk 1,12,133,2,22,233,3,32,333
|
|
IDs in p2 before p3 call 1,12,133,2,22,233
|
|
IDs in p2 catch blk 1,12,133,2,22,233
|
|
IDs in p1 before p2 call 1,12,133
|
|
IDs in p1 catch blk 1,12,133
|
|
"""
|
|
|
|
@pytest.mark.version('>=4.0')
|
|
def test_1(act: Action):
|
|
act.expected_stdout = expected_stdout
|
|
act.execute()
|
|
assert act.clean_stdout == act.clean_expected_stdout
|
|
|