diff --git a/tests/functional/tabloid/test_aae2ae32.py b/tests/functional/tabloid/test_aae2ae32.py index 1fed532d..afde4a68 100644 --- a/tests/functional/tabloid/test_aae2ae32.py +++ b/tests/functional/tabloid/test_aae2ae32.py @@ -25,6 +25,13 @@ NOTES: Because of that, testing version are limited only for 5.0.2. FB 6.x currently is NOT tested. 4. Custom driver config objects are created here, one with SubQueryConversion = true and second with false. + [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"). + Checked on 5.0.2.1516-92316F0 -- all ok: two hash joins instead of subquery. Thanks to dimitr for the advice on implementing the test. """ @@ -33,6 +40,7 @@ import pytest from firebird.qa import * from firebird.driver import driver_config, connect, DatabaseError + init_script = """ create table test1(id int not null); create table test2(id int not null, pid int not null); @@ -90,6 +98,7 @@ def test_1(act: Action, capsys): """ with connect(db_cfg_name, user = act.db.user, password = act.db.password) as con: + ps, rs = None, None try: cur = con.cursor() cur.execute("select g.rdb$config_name, g.rdb$config_value from rdb$database r left join rdb$config g on g.rdb$config_name = 'SubQueryConversion'") @@ -101,12 +110,23 @@ def test_1(act: Action, capsys): # Print explained plan with padding eash line by dots in order to see indentations: print( '\n'.join([replace_leading(s) for s in ps.detailed_plan.split('\n')]) ) - # Print data: - for r in cur.execute(ps): + # ::: 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) + 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() act.expected_stdout = f""" SubQueryConversion true