Skip to content

Commit 1edb6b6

Browse files
committed
Added/Updated tests\functional\tabloid\test_aae2ae32.py: Re-implemented in order to check FB 5.x with set 'SubQueryConversion = true' and FB 6.x w/o any changes in its config. Checked on 6.0.0.687-730aa8f, 5.0.3.1647-8993a57
1 parent 93d5f48 commit 1edb6b6

File tree

1 file changed

+51
-57
lines changed

1 file changed

+51
-57
lines changed

tests/functional/tabloid/test_aae2ae32.py

Lines changed: 51 additions & 57 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,10 @@
3434
3535
Checked on 5.0.2.1516-92316F0 -- all ok: two hash joins instead of subquery.
3636
Thanks to dimitr for the advice on implementing the test.
37+
38+
[16.04.2025] pzotov
39+
Re-implemented in order to check FB 5.x with set 'SubQueryConversion = true' and FB 6.x w/o any changes in its config.
40+
Checked on 6.0.0.687-730aa8f, 5.0.3.1647-8993a57
3741
"""
3842

3943
import pytest
@@ -61,7 +65,17 @@
6165

6266
db = db_factory(init=init_script)
6367

64-
act = python_act('db', substitutions = [('record length: \\d+', 'record length')])
68+
# Substitusions are needed here in order to ignore concrete numbers in explained plan parts, e.g.:
69+
# Hash Join (semi) (keys: 1, total key length: 4)
70+
# Sort (record length: 28, key length: 8)
71+
# Record Buffer (record length: 25)
72+
substitutions = [
73+
(r'Hash Join \(semi\) \(keys: \d+, total key length: \d+\)','Hash Join (semi)')
74+
,(r'record length: \d+', 'record length: NN')
75+
,(r'key length: \d+', 'key length: NN')
76+
]
77+
78+
act = python_act('db', substitutions = substitutions)
6579

6680
#-----------------------------------------------------------
6781

@@ -71,7 +85,7 @@ def replace_leading(source, char="."):
7185

7286
#-----------------------------------------------------------
7387

74-
@pytest.mark.version('>=5.0.2,<6')
88+
@pytest.mark.version('>=5.0.2')
7589
def test_1(act: Action, capsys):
7690

7791
test_sql = """
@@ -87,77 +101,57 @@ def test_1(act: Action, capsys):
87101
);
88102
"""
89103

90-
for sq_conv in ('true','false',):
91-
srv_cfg = driver_config.register_server(name = f'srv_cfg_aae2ae32_{sq_conv}', config = '')
92-
db_cfg_name = f'db_cfg_aae2ae32_{sq_conv}'
93-
db_cfg_object = driver_config.register_database(name = db_cfg_name)
94-
db_cfg_object.server.value = srv_cfg.name
95-
db_cfg_object.database.value = str(act.db.db_path)
104+
srv_cfg = driver_config.register_server(name = f'srv_cfg_aae2ae32', config = '')
105+
db_cfg_name = f'db_cfg_aae2ae32'
106+
db_cfg_object = driver_config.register_database(name = db_cfg_name)
107+
db_cfg_object.server.value = srv_cfg.name
108+
db_cfg_object.database.value = str(act.db.db_path)
109+
if act.is_version('<6'):
96110
db_cfg_object.config.value = f"""
97-
SubQueryConversion = {sq_conv}
111+
SubQueryConversion = true
98112
"""
99113

100-
with connect(db_cfg_name, user = act.db.user, password = act.db.password) as con:
101-
ps, rs = None, None
102-
try:
103-
cur = con.cursor()
104-
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'")
105-
for r in cur:
106-
print(r[0],r[1])
107-
108-
ps = cur.prepare(test_sql)
109-
110-
# Print explained plan with padding eash line by dots in order to see indentations:
111-
print( '\n'.join([replace_leading(s) for s in ps.detailed_plan.split('\n')]) )
112-
113-
# ::: NB ::: 'ps' returns data, i.e. this is SELECTABLE expression.
114-
# We have to store result of cur.execute(<psInstance>) in order to
115-
# close it explicitly.
116-
# Otherwise AV can occur during Python garbage collection and this
117-
# causes pytest to hang on its final point.
118-
# Explained by hvlad, email 26.10.24 17:42
119-
rs = cur.execute(ps)
120-
for r in rs:
121-
print(r[0])
122-
except DatabaseError as e:
123-
print(e.__str__())
124-
print(e.gds_codes)
125-
finally:
126-
if rs:
127-
rs.close() # <<< EXPLICITLY CLOSING CURSOR RESULTS
128-
if ps:
129-
ps.free()
114+
with connect(db_cfg_name, user = act.db.user, password = act.db.password) as con:
115+
ps, rs = None, None
116+
try:
117+
cur = con.cursor()
118+
ps = cur.prepare(test_sql)
119+
120+
# Print explained plan with padding eash line by dots in order to see indentations:
121+
print( '\n'.join([replace_leading(s) for s in ps.detailed_plan.split('\n')]) )
122+
123+
# ::: NB ::: 'ps' returns data, i.e. this is SELECTABLE expression.
124+
# We have to store result of cur.execute(<psInstance>) in order to
125+
# close it explicitly.
126+
# Otherwise AV can occur during Python garbage collection and this
127+
# causes pytest to hang on its final point.
128+
# Explained by hvlad, email 26.10.24 17:42
129+
rs = cur.execute(ps)
130+
for r in rs:
131+
print(r[0])
132+
except DatabaseError as e:
133+
print(e.__str__())
134+
print(e.gds_codes)
135+
finally:
136+
if rs:
137+
rs.close() # <<< EXPLICITLY CLOSING CURSOR RESULTS
138+
if ps:
139+
ps.free()
130140

131141
act.expected_stdout = f"""
132-
SubQueryConversion true
133142
Select Expression
134143
....-> Aggregate
135144
........-> Filter
136145
............-> Hash Join (semi)
137146
................-> Table "TEST1" as "A" Full Scan
138-
................-> Record Buffer (record length: 82111)
147+
................-> Record Buffer (record length: 82)
139148
....................-> Filter
140149
........................-> Hash Join (semi)
141150
............................-> Table "TEST2" as "B" Full Scan
142-
............................-> Record Buffer (record length: 57111)
151+
............................-> Record Buffer (record length: 57)
143152
................................-> Filter
144153
....................................-> Table "TEST3" as "C" Full Scan
145154
10
146-
147-
SubQueryConversion false
148-
Sub-query
149-
....-> Filter
150-
........-> Filter
151-
............-> Table "TEST3" as "C" Full Scan
152-
Sub-query
153-
....-> Filter
154-
........-> Filter
155-
............-> Table "TEST2" as "B" Full Scan
156-
Select Expression
157-
....-> Aggregate
158-
........-> Filter
159-
............-> Table "TEST1" as "A" Full Scan
160-
10
161155
"""
162156
act.stdout = capsys.readouterr().out
163157
assert act.clean_stdout == act.clean_expected_stdout

0 commit comments

Comments
 (0)