diff --git a/tests/bugs/core_5062_test.py b/tests/bugs/core_5062_test.py index e91ab20a..353d4357 100644 --- a/tests/bugs/core_5062_test.py +++ b/tests/bugs/core_5062_test.py @@ -3,26 +3,31 @@ """ ID: issue-5349 ISSUE: 5349 -TITLE: CHAR_TO_UUID on column with index throws expression evaluation not supported - Human readable UUID argument for CHAR_TO_UUID must be of exact length 36 +TITLE: CHAR_TO_UUID on column with index throws expression evaluation not supported. Human readable UUID argument for CHAR_TO_UUID must be of exact length 36 DESCRIPTION: JIRA: CORE-5062 -FBTEST: bugs.core_5062 +NOTES: + [18.01.2025] pzotov + Resultset of cursor that executes using instance of selectable PreparedStatement must be stored + in some variable in order to have ability close it EXPLICITLY (before PS will be freed). + Otherwise access violation raises during Python GC and pytest hangs at final point (does not return control to OS). + This occurs at least for: Python 3.11.2 / pytest: 7.4.4 / firebird.driver: 1.10.6 / Firebird.Qa: 0.19.3 + The reason of that was explained by Vlad, 26.10.24 17:42 ("oddities when use instances of selective statements"). """ import pytest from firebird.qa import * +from firebird.driver import DatabaseError init_script = """ -recreate table test_uuid( - datavalue int, - uuid char(16) character set octets, - constraint test_uuid_unq unique(uuid) -); -commit; -insert into test_uuid(datavalue, uuid) values( 1, char_to_uuid('57F2B8C7-E1D8-4B61-9086-C66D1794F2D9') ); ---insert into test_uuid(datavalue, uuid) values( 2, char_to_uuid('37F2B8C3-E1D8-4B31-9083-C33D1794F2D3') ); -commit; + recreate table test_uuid( + datavalue int, + uuid char(16) character set octets, + constraint test_uuid_unq unique(uuid) + ); + commit; + insert into test_uuid(datavalue, uuid) values( 1, char_to_uuid('57F2B8C7-E1D8-4B61-9086-C66D1794F2D9') ); + commit; """ db = db_factory(init=init_script) @@ -30,11 +35,38 @@ db = db_factory(init=init_script) act = python_act('db') @pytest.mark.version('>=3.0') -def test_1(act: Action): +def test_1(act: Action, capsys): with act.db.connect() as con: - c = con.cursor() - stmt = c.prepare("select datavalue from test_uuid where uuid = char_to_uuid(?)") - assert stmt.plan == 'PLAN (TEST_UUID INDEX (TEST_UUID_UNQ))' - result = c.execute(stmt, ['57F2B8C7-E1D8-4B61-9086-C66D1794F2D9']).fetchall() - assert result == [(1, )] + ps, rs = None, None + cur = con.cursor() + try: + ps = cur.prepare("select datavalue from test_uuid where uuid = char_to_uuid(?)") + print(ps.plan) + # ::: NB ::: 'ps' returns data, i.e. this is SELECTABLE expression. + # We have to store result of cur.execute() in order to + # close it explicitly. + # Otherwise AV can occur during Python garbage collection and this + # causes pytest to hang on its final point. + # Explained by hvlad, email 26.10.24 17:42 + rs = cur.execute(ps, ['57F2B8C7-E1D8-4B61-9086-C66D1794F2D9']) + for r in rs: + print(r[0]) + except DatabaseError as e: + print( e.__str__() ) + print(e.gds_codes) + finally: + if rs: + rs.close() # <<< EXPLICITLY CLOSING CURSOR RESULTS + if ps: + ps.free() + + expected_stdout = f""" + PLAN (TEST_UUID INDEX (TEST_UUID_UNQ)) + 1 + """ + + act.expected_stdout = expected_stdout + act.stdout = capsys.readouterr().out + assert act.clean_stdout == act.clean_expected_stdout + act.reset()