Skip to content
This repository was archived by the owner on Mar 16, 2026. It is now read-only.

Commit da9f228

Browse files
committed
modified tests for join order variation in 1.4 vs 2.0
1 parent 455dbeb commit da9f228

4 files changed

Lines changed: 36 additions & 20 deletions

File tree

noxfile.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -213,6 +213,8 @@ def default(session, install_extras=True):
213213
install_target = "."
214214
session.install("-e", install_target, "-c", constraints_path)
215215

216+
session.run("python", "-m", "pip", "freeze")
217+
216218
# Run py.test against the unit tests.
217219
session.run(
218220
"py.test",
@@ -550,6 +552,7 @@ def prerelease_deps(session):
550552
"requests",
551553
]
552554
session.install(*other_deps)
555+
session.run("python", "-m", "pip", "freeze")
553556

554557
# Print out prerelease package versions
555558
session.run(

sqlalchemy_bigquery/base.py

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -275,8 +275,7 @@ def _known_tables(self):
275275
asfrom_froms = self.stack[-1].get("asfrom_froms", [])
276276
for from_ in asfrom_froms:
277277
if isinstance(from_, Table):
278-
if from_.name not in known_tables:
279-
known_tables.add(from_.name)
278+
known_tables.add(from_.name)
280279

281280
return known_tables
282281

tests/unit/conftest.py

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,14 @@
4040
sqlalchemy_version >= packaging.version.parse("1.4"),
4141
reason="requires sqlalchemy 1.3 or lower",
4242
)
43-
43+
sqlalchemy_before_2_0 = pytest.mark.skipif(
44+
sqlalchemy_version >= packaging.version.parse("2.0"),
45+
reason="requires sqlalchemy 1.3 or lower",
46+
)
47+
sqlalchemy_2_0_or_higher = pytest.mark.skipif(
48+
sqlalchemy_version < packaging.version.parse("2.0"),
49+
reason="requires sqlalchemy 1.4 or higher",
50+
)
4451

4552
@pytest.fixture()
4653
def faux_conn():

tests/unit/test_compiler.py

Lines changed: 24 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,12 @@
2121
import sqlalchemy.exc
2222

2323
from .conftest import setup_table
24-
from .conftest import sqlalchemy_1_4_or_higher, sqlalchemy_before_1_4
24+
from .conftest import (
25+
sqlalchemy_1_4_or_higher,
26+
sqlalchemy_before_1_4,
27+
sqlalchemy_2_0_or_higher,
28+
sqlalchemy_before_2_0,
29+
)
2530

2631

2732
def test_constraints_are_ignored(faux_conn, metadata):
@@ -142,35 +147,36 @@ def prepare_implicit_join_base_query(
142147
return q
143148

144149

145-
@sqlalchemy_before_1_4
146-
def test_no_implicit_join_asterix_for_inner_unnest_before_1_4(faux_conn, metadata):
150+
@sqlalchemy_before_2_0
151+
def test_no_implicit_join_asterix_for_inner_unnest_before_2_0(faux_conn, metadata):
147152
# See: https://github.com/googleapis/python-bigquery-sqlalchemy/issues/368
148-
q = prepare_implicit_join_base_query(faux_conn, metadata, True, True)
153+
q = prepare_implicit_join_base_query(faux_conn, metadata, True, False)
149154
expected_initial_sql = (
150155
"SELECT `table1`.`foo`, `table2`.`bar` \n"
151156
"FROM `table2`, unnest(`table2`.`foos`) AS `unnested_foos` JOIN `table1` ON `table1`.`foo` = `unnested_foos`"
152157
)
153158
found_initial_sql = q.compile(faux_conn).string
154159
assert found_initial_sql == expected_initial_sql
155160

156-
q = sqlalchemy.select(["*"]).select_from(q)
161+
q = q.subquery()
162+
q = sqlalchemy.select("*").select_from(q)
157163

158164
expected_outer_sql = (
159165
"SELECT * \n"
160166
"FROM (SELECT `table1`.`foo` AS `foo`, `table2`.`bar` AS `bar` \n"
161-
"FROM `table2`, unnest(`table2`.`foos`) AS `unnested_foos` JOIN `table1` ON `table1`.`foo` = `unnested_foos`)"
167+
"FROM `table2`, unnest(`table2`.`foos`) AS `unnested_foos` JOIN `table1` ON `table1`.`foo` = `unnested_foos`) AS `anon_1`"
162168
)
163169
found_outer_sql = q.compile(faux_conn).string
164170
assert found_outer_sql == expected_outer_sql
165171

166172

167-
@sqlalchemy_1_4_or_higher
173+
@sqlalchemy_2_0_or_higher
168174
def test_no_implicit_join_asterix_for_inner_unnest(faux_conn, metadata):
169175
# See: https://github.com/googleapis/python-bigquery-sqlalchemy/issues/368
170176
q = prepare_implicit_join_base_query(faux_conn, metadata, True, False)
171177
expected_initial_sql = (
172178
"SELECT `table1`.`foo`, `table2`.`bar` \n"
173-
"FROM `table2`, unnest(`table2`.`foos`) AS `unnested_foos` JOIN `table1` ON `table1`.`foo` = `unnested_foos`"
179+
"FROM unnest(`table2`.`foos`) AS `unnested_foos` JOIN `table1` ON `table1`.`foo` = `unnested_foos`, `table2`"
174180
)
175181
found_initial_sql = q.compile(faux_conn).string
176182
assert found_initial_sql == expected_initial_sql
@@ -181,41 +187,42 @@ def test_no_implicit_join_asterix_for_inner_unnest(faux_conn, metadata):
181187
expected_outer_sql = (
182188
"SELECT * \n"
183189
"FROM (SELECT `table1`.`foo` AS `foo`, `table2`.`bar` AS `bar` \n"
184-
"FROM `table2`, unnest(`table2`.`foos`) AS `unnested_foos` JOIN `table1` ON `table1`.`foo` = `unnested_foos`) AS `anon_1`"
190+
"FROM unnest(`table2`.`foos`) AS `unnested_foos` JOIN `table1` ON `table1`.`foo` = `unnested_foos`, `table2`) AS `anon_1`"
185191
)
186192
found_outer_sql = q.compile(faux_conn).string
187193
assert found_outer_sql == expected_outer_sql
188194

189195

190-
@sqlalchemy_before_1_4
196+
@sqlalchemy_before_2_0
191197
def test_no_implicit_join_for_inner_unnest_before_1_4(faux_conn, metadata):
192198
# See: https://github.com/googleapis/python-bigquery-sqlalchemy/issues/368
193-
q = prepare_implicit_join_base_query(faux_conn, metadata, True, True)
199+
q = prepare_implicit_join_base_query(faux_conn, metadata, True, False)
194200
expected_initial_sql = (
195201
"SELECT `table1`.`foo`, `table2`.`bar` \n"
196202
"FROM `table2`, unnest(`table2`.`foos`) AS `unnested_foos` JOIN `table1` ON `table1`.`foo` = `unnested_foos`"
197203
)
198204
found_initial_sql = q.compile(faux_conn).string
199205
assert found_initial_sql == expected_initial_sql
200206

201-
q = sqlalchemy.select([q.c.foo]).select_from(q)
207+
q = q.subquery()
208+
q = sqlalchemy.select(q.c.foo).select_from(q)
202209

203210
expected_outer_sql = (
204-
"SELECT `foo` \n"
211+
"SELECT `anon_1`.`foo` \n"
205212
"FROM (SELECT `table1`.`foo` AS `foo`, `table2`.`bar` AS `bar` \n"
206-
"FROM `table2`, unnest(`table2`.`foos`) AS `unnested_foos` JOIN `table1` ON `table1`.`foo` = `unnested_foos`)"
213+
"FROM `table2`, unnest(`table2`.`foos`) AS `unnested_foos` JOIN `table1` ON `table1`.`foo` = `unnested_foos`) AS `anon_1`"
207214
)
208215
found_outer_sql = q.compile(faux_conn).string
209216
assert found_outer_sql == expected_outer_sql
210217

211218

212-
@sqlalchemy_1_4_or_higher
219+
@sqlalchemy_2_0_or_higher
213220
def test_no_implicit_join_for_inner_unnest(faux_conn, metadata):
214221
# See: https://github.com/googleapis/python-bigquery-sqlalchemy/issues/368
215222
q = prepare_implicit_join_base_query(faux_conn, metadata, True, False)
216223
expected_initial_sql = (
217224
"SELECT `table1`.`foo`, `table2`.`bar` \n"
218-
"FROM `table2`, unnest(`table2`.`foos`) AS `unnested_foos` JOIN `table1` ON `table1`.`foo` = `unnested_foos`"
225+
"FROM unnest(`table2`.`foos`) AS `unnested_foos` JOIN `table1` ON `table1`.`foo` = `unnested_foos`, `table2`"
219226
)
220227
found_initial_sql = q.compile(faux_conn).string
221228
assert found_initial_sql == expected_initial_sql
@@ -226,7 +233,7 @@ def test_no_implicit_join_for_inner_unnest(faux_conn, metadata):
226233
expected_outer_sql = (
227234
"SELECT `anon_1`.`foo` \n"
228235
"FROM (SELECT `table1`.`foo` AS `foo`, `table2`.`bar` AS `bar` \n"
229-
"FROM `table2`, unnest(`table2`.`foos`) AS `unnested_foos` JOIN `table1` ON `table1`.`foo` = `unnested_foos`) AS `anon_1`"
236+
"FROM unnest(`table2`.`foos`) AS `unnested_foos` JOIN `table1` ON `table1`.`foo` = `unnested_foos`, `table2`) AS `anon_1`"
230237
)
231238
found_outer_sql = q.compile(faux_conn).string
232239
assert found_outer_sql == expected_outer_sql

0 commit comments

Comments
 (0)