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_4369_test.py

271 lines
7.6 KiB
Python

#coding:utf-8
#
# id: bugs.core_4369
# title: BUGCHECK(177) for MERGE with multiple matches
# decription:
# Checked (again, 07.06.2020) on 3.0.6.33296.
#
# 07.06.2020. NOTE: separate section for FB 4.x was added since fix for core-2274 issued:
# MERGE can not change the same record multiple times.
# For this reason we have to check only presense of ERROR in 4.x and that result is the same after merge and rollback.
# Checked on 4.0.0.2022
#
# tracker_id: CORE-4369
# min_versions: ['3.0']
# versions: 3.0, 4.0
# qmid: None
import pytest
from firebird.qa import db_factory, isql_act, Action
# version: 3.0
# resources: None
substitutions_1 = []
init_script_1 = """"""
db_1 = db_factory(sql_dialect=3, init=init_script_1)
test_script_1 = """
recreate sequence g;
recreate table t1 (
id int,
val int
);
recreate table t2 (
id int,
val int,
seq_inside_merge int
);
commit;
insert into t1 (id, val) select row_number() over(), 1000 from rdb$types rows 17; -- '17' ==> 'N', see below formula for seq_inside_merge
insert into t2(id, val, seq_inside_merge) select id, val, 0 from t1;
commit;
alter sequence g restart with 0;
commit;
merge into t2 as t
using t1 as s
on 1 = 1
when matched then update set t.val = t.val + s.val, t.seq_inside_merge = next value for g
;
set list on;
select * from t2 order by id;
-- 1st value of `SEQ_INSIDE_MERGE` = N * (N-1) + 1
-- All subsequent values are incremented by 1.
-- Confirmed result in WI-T3.0.0.31374 Beta-1:
-- "internal Firebird consistency check (applied differences will not fit in record (177), file: sqz.cpp line: 147)"
"""
act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1)
expected_stdout_1 = """
ID 1
VAL 2000
SEQ_INSIDE_MERGE 273
ID 2
VAL 2000
SEQ_INSIDE_MERGE 274
ID 3
VAL 2000
SEQ_INSIDE_MERGE 275
ID 4
VAL 2000
SEQ_INSIDE_MERGE 276
ID 5
VAL 2000
SEQ_INSIDE_MERGE 277
ID 6
VAL 2000
SEQ_INSIDE_MERGE 278
ID 7
VAL 2000
SEQ_INSIDE_MERGE 279
ID 8
VAL 2000
SEQ_INSIDE_MERGE 280
ID 9
VAL 2000
SEQ_INSIDE_MERGE 281
ID 10
VAL 2000
SEQ_INSIDE_MERGE 282
ID 11
VAL 2000
SEQ_INSIDE_MERGE 283
ID 12
VAL 2000
SEQ_INSIDE_MERGE 284
ID 13
VAL 2000
SEQ_INSIDE_MERGE 285
ID 14
VAL 2000
SEQ_INSIDE_MERGE 286
ID 15
VAL 2000
SEQ_INSIDE_MERGE 287
ID 16
VAL 2000
SEQ_INSIDE_MERGE 288
ID 17
VAL 2000
SEQ_INSIDE_MERGE 289
"""
@pytest.mark.version('>=3.0,<4.0')
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
# version: 4.0
# resources: None
substitutions_2 = []
init_script_2 = """"""
db_2 = db_factory(sql_dialect=3, init=init_script_2)
test_script_2 = """
recreate sequence g;
recreate table t1 (
id int,
val int
);
recreate table t2 (
id int,
val int,
seq_inside_merge int
);
commit;
insert into t1 (id, val) select row_number() over(), 1000 from rdb$types rows 17; -- '17' ==> 'N', see below formula for seq_inside_merge
insert into t2(id, val, seq_inside_merge) select id, val, 0 from t1;
commit;
alter sequence g restart with 0;
commit;
merge into t2 as t
using t1 as s
on 1 = 1
when matched then update set t.val = t.val + s.val, t.seq_inside_merge = next value for g
;
-- all values should remain unchanged:
set list on;
select * from t2 order by id;
"""
act_2 = isql_act('db_2', test_script_2, substitutions=substitutions_2)
expected_stdout_2 = """
ID 1
VAL 1000
SEQ_INSIDE_MERGE 0
ID 2
VAL 1000
SEQ_INSIDE_MERGE 0
ID 3
VAL 1000
SEQ_INSIDE_MERGE 0
ID 4
VAL 1000
SEQ_INSIDE_MERGE 0
ID 5
VAL 1000
SEQ_INSIDE_MERGE 0
ID 6
VAL 1000
SEQ_INSIDE_MERGE 0
ID 7
VAL 1000
SEQ_INSIDE_MERGE 0
ID 8
VAL 1000
SEQ_INSIDE_MERGE 0
ID 9
VAL 1000
SEQ_INSIDE_MERGE 0
ID 10
VAL 1000
SEQ_INSIDE_MERGE 0
ID 11
VAL 1000
SEQ_INSIDE_MERGE 0
ID 12
VAL 1000
SEQ_INSIDE_MERGE 0
ID 13
VAL 1000
SEQ_INSIDE_MERGE 0
ID 14
VAL 1000
SEQ_INSIDE_MERGE 0
ID 15
VAL 1000
SEQ_INSIDE_MERGE 0
ID 16
VAL 1000
SEQ_INSIDE_MERGE 0
ID 17
VAL 1000
SEQ_INSIDE_MERGE 0
"""
expected_stderr_2 = """
Statement failed, SQLSTATE = 21000
Multiple source records cannot match the same target during MERGE
"""
@pytest.mark.version('>=4.0')
def test_2(act_2: Action):
act_2.expected_stdout = expected_stdout_2
act_2.expected_stderr = expected_stderr_2
act_2.execute()
assert act_2.clean_expected_stderr == act_2.clean_stderr
assert act_2.clean_expected_stdout == act_2.clean_stdout