6
0
mirror of https://github.com/FirebirdSQL/firebird-qa.git synced 2025-01-22 13:33:07 +01:00
firebird-qa/tests/bugs/gh_7057_test.py

153 lines
4.4 KiB
Python

#coding:utf-8
"""
ID: issue-7057
ISSUE: https://github.com/FirebirdSQL/firebird/issues/7057
TITLE: Client-side positioned updates work wrongly with scrollable cursors
DESCRIPTION:
Fetching from a scrollable cursor may overwrite user-specified buffer and corrupt memory.
Engine did overwrite the user-specified buffer with four more bytes than expected that could corrupt the caller memory.
Discussed between dimitr, pcisar and pzotov, see letters of 29-30 NOV 2021,
subj: "firebird-driver & scrollable cursors // misc. tests, requested by dimitr"
NOTES:
[29.07.2024] pzotov
1. ### ACHTUNG ###
Old snapshots (before 5.0.0.890-aa847a7) must be checked with usage "--disable-db-cache" command switch for pytest!
Otherwise one may FALSE failure (bugcheck) with:
"internal Firebird consistency check (decompression overran buffer (179), file: sqz.cpp line: 293)"
2. Test caused crash of server on snapshots before 6.0.0.401-a7d10a4.
Problem related to MaxStatementCacheSize which default value > 0
(explained by dimitr, letter 19-JUL-2024 12:52).
It seems that bug was fixed in:
FB 5.x: https://github.com/FirebirdSQL/firebird/commit/08dc25f8c45342a73c786bc60571c8a5f2c8c6e3 (27.07.2024 14:55)
FB 6.x: https://github.com/FirebirdSQL/firebird/commit/a7d10a40147d326e56540498b50e40b2da0e5850 (29.07.2024 03:53)
("Fix #8185 - SIGSEGV with WHERE CURRENT OF statement with statement cache turned on.")
3. Attempt to run this test on FB 4.0.5.3127 (10-JUL-2024) raises:
"E firebird.driver.types.DatabaseError: feature is not supported"
(scollable cursors are not supported in network protocol in FB-4.x)
Checked on 6.0.0.401-a7d10a4, 5.0.1.1453-62ee5f1.
"""
import pytest
from firebird.qa import *
from firebird.driver import driver_config, connect, NetProtocol, DatabaseError
import re
db = db_factory()
act = python_act('db', substitutions=[('[ \t]+', ' ')])
#------------------------------------------------------
def print_row(row, cur = None):
if row:
print(f"{row[0]}")
if cur and (cur.is_bof() or cur.is_eof()):
print('### STRANGE BOF/EOR WHILE SOME DATA CAN BE SEEN ###')
else:
msg = '*** NO_DATA***'
if cur:
msg += ' BOF=%r EOF=%r' % ( cur.is_bof(), cur.is_eof() )
print(msg)
#------------------------------------------------------
@pytest.mark.scroll_cur
@pytest.mark.version('>=5.0.1')
def test_1(act: Action, capsys):
with act.db.connect() as con:
con.execute_immediate('recreate table ts(id int)')
con.commit()
con.execute_immediate('insert into ts (id) select row_number() over() from rdb$types rows 10')
con.commit()
cur = con.cursor()
cur.open('select id from ts for update')
cur.set_cursor_name('X')
for row in cur:
print_row(row)
cur.fetch_first()
print('Updating first record')
con.execute_immediate('update ts set id = -id where current of X')
con.commit()
cur = con.cursor()
cur.open('select id from ts for update')
cur.set_cursor_name('X')
for row in cur:
print_row(row)
cur.fetch_last()
print('Updating last record')
con.execute_immediate('update ts set id = -id where current of X')
con.commit()
cur = con.cursor()
cur.open('select id from ts for update')
cur.set_cursor_name('X')
for row in cur:
print_row(row)
cur.fetch_absolute(5)
print('Updating 5th record')
con.execute_immediate('update ts set id = -id where current of X')
con.commit()
cur = con.cursor()
cur.open('select id from ts')
for row in cur:
print_row(row)
act.stdout = capsys.readouterr().out
act.expected_stdout = """
1
2
3
4
5
6
7
8
9
10
Updating first record
-1
2
3
4
5
6
7
8
9
10
Updating last record
-1
2
3
4
5
6
7
8
9
-10
Updating 5th record
-1
2
3
4
-5
6
7
8
9
-10
"""
assert act.clean_stdout == act.clean_expected_stdout