Skip to content

Commit c89dd18

Browse files
committed
Added/Updated tests\bugs\gh_8628_test.py: Checked on 6.0.0.1020, 5.0.3.1683
1 parent 86b6fd1 commit c89dd18

File tree

1 file changed

+99
-0
lines changed

1 file changed

+99
-0
lines changed

tests/bugs/gh_8628_test.py

Lines changed: 99 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,99 @@
1+
#coding:utf-8
2+
3+
"""
4+
ID: n/a
5+
ISSUE: https://github.com/FirebirdSQL/firebird/issues/8628
6+
TITLE: Incorrect join order for JOIN LATERAL with UNION referencing the outer stream(s) via its select list
7+
DESCRIPTION:
8+
NOTES:
9+
[17.07.2025] pzotov
10+
SQL schema name (introduced since 6.0.0.834), single and double quotes are suppressed in the output.
11+
See $QA_HOME/README.substitutions.md or https://github.com/FirebirdSQL/firebird-qa/blob/master/README.substitutions.md
12+
Confirmed problem on 6.0.0.877, 5.0.3.1622
13+
Checked on 6.0.0.1020, 5.0.3.1683
14+
"""
15+
16+
import pytest
17+
from firebird.qa import *
18+
from firebird.driver import DatabaseError
19+
20+
db = db_factory()
21+
22+
substitutions = []
23+
# QA_GLOBALS -- dict, is defined in qa/plugin.py, obtain settings
24+
# from act.files_dir/'test_config.ini':
25+
#
26+
addi_subst_settings = QA_GLOBALS['schema_n_quotes_suppress']
27+
addi_subst_tokens = addi_subst_settings['addi_subst']
28+
29+
for p in addi_subst_tokens.split(' '):
30+
substitutions.append( (p, '') )
31+
32+
act = python_act('db', substitutions = substitutions)
33+
34+
#-----------------------------------------------------------
35+
36+
def replace_leading(source, char="."):
37+
stripped = source.lstrip()
38+
return char * (len(source) - len(stripped)) + stripped
39+
40+
#-----------------------------------------------------------
41+
42+
@pytest.mark.version('>=5.0.3')
43+
def test_1(act: Action, capsys):
44+
45+
qry_list = (
46+
"""
47+
select t.name
48+
from rdb$relations r
49+
cross join lateral (
50+
select r.rdb$relation_name as name from rdb$database
51+
union all
52+
select r.rdb$owner_name as name from rdb$database
53+
) t
54+
""",
55+
)
56+
57+
with act.db.connect() as con:
58+
cur = con.cursor()
59+
for test_sql in qry_list:
60+
ps, rs = None, None
61+
try:
62+
cur = con.cursor()
63+
ps = cur.prepare(test_sql)
64+
print(test_sql)
65+
# Print explained plan with padding eash line by dots in order to see indentations:
66+
print( '\n'.join([replace_leading(s) for s in ps.detailed_plan.split('\n')]) )
67+
68+
# ::: NB ::: 'ps' returns data, i.e. this is SELECTABLE expression.
69+
# We have to store result of cur.execute(<psInstance>) in order to
70+
# close it explicitly.
71+
# Otherwise AV can occur during Python garbage collection and this
72+
# causes pytest to hang on its final point.
73+
# Explained by hvlad, email 26.10.24 17:42
74+
rs = cur.execute(ps)
75+
for r in rs:
76+
pass
77+
print('Fetching completed.')
78+
except DatabaseError as e:
79+
print(e.__str__())
80+
print(e.gds_codes)
81+
finally:
82+
if rs:
83+
rs.close() # <<< EXPLICITLY CLOSING CURSOR RESULTS
84+
if ps:
85+
ps.free()
86+
87+
act.expected_stdout = f"""
88+
{qry_list[0]}
89+
Select Expression
90+
....-> Nested Loop Join (inner)
91+
........-> Table RDB$RELATIONS as R Full Scan
92+
........-> Union
93+
............-> Table RDB$DATABASE as T RDB$DATABASE Full Scan
94+
............-> Table RDB$DATABASE as T RDB$DATABASE Full Scan
95+
Fetching completed.
96+
"""
97+
98+
act.stdout = capsys.readouterr().out
99+
assert act.clean_stdout == act.clean_expected_stdout

0 commit comments

Comments
 (0)