Skip to content

Commit 8fd6f23

Browse files
committed
fix: use catalog name on generated queries
1 parent 604d72c commit 8fd6f23

File tree

3 files changed

+80
-1
lines changed

3 files changed

+80
-1
lines changed

docker/pythonpath_dev/superset_config_docker_light.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919

2020
# Import all settings from the main config first
2121
from flask_caching.backends.filesystemcache import FileSystemCache
22+
2223
from superset_config import * # noqa: F403
2324

2425
# Override caching to use simple in-memory cache instead of Redis

superset/connectors/sqla/models.py

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1369,8 +1369,24 @@ def get_template_processor(self, **kwargs: Any) -> BaseTemplateProcessor:
13691369

13701370
def get_sqla_table(self) -> TableClause:
13711371
tbl = table(self.table_name)
1372-
if self.schema:
1372+
1373+
# For databases that support cross-catalog queries (like BigQuery),
1374+
# include the catalog in the table identifier to generate
1375+
# project.dataset.table format
1376+
if self.catalog and self.database.db_engine_spec.supports_cross_catalog_queries:
1377+
# SQLAlchemy doesn't have built-in catalog support for TableClause,
1378+
# so we need to construct the full identifier manually
1379+
if self.schema:
1380+
full_name = f"{self.catalog}.{self.schema}.{self.table_name}"
1381+
else:
1382+
full_name = f"{self.catalog}.{self.table_name}"
1383+
1384+
tbl = table(full_name)
1385+
1386+
# Otherwise include only the schema, if any
1387+
elif self.schema:
13731388
tbl.schema = self.schema
1389+
13741390
return tbl
13751391

13761392
def get_from_clause(

tests/unit_tests/connectors/sqla/models_test.py

Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -287,3 +287,65 @@ def test_normalize_prequery_result_type_custom_sql() -> None:
287287
sqla_table._normalize_prequery_result_type(row, dimension, columns_by_name)
288288
== "Car"
289289
)
290+
291+
292+
def test_get_sqla_table_with_catalog(mocker: MockerFixture) -> None:
293+
"""Test that get_sqla_table includes catalog in table identifier
294+
for databases with cross-catalog support
295+
"""
296+
# Test case 1: Database supports cross-catalog queries (like BigQuery)
297+
database_with_catalog = mocker.MagicMock()
298+
database_with_catalog.db_engine_spec.supports_cross_catalog_queries = True
299+
300+
table_with_catalog = SqlaTable(
301+
table_name="test_table",
302+
database=database_with_catalog,
303+
schema="test_dataset",
304+
catalog="test_project",
305+
)
306+
307+
sqla_table = table_with_catalog.get_sqla_table()
308+
# Should generate "test_project.test_dataset.test_table"
309+
assert sqla_table.name == "test_project.test_dataset.test_table"
310+
# Schema should not be set as it's now part of the table name
311+
assert sqla_table.schema is None
312+
313+
# Test case 2: Database doesn't support cross-catalog queries
314+
database_no_catalog = mocker.MagicMock()
315+
database_no_catalog.db_engine_spec.supports_cross_catalog_queries = False
316+
317+
table_no_catalog_support = SqlaTable(
318+
table_name="test_table",
319+
database=database_no_catalog,
320+
schema="test_schema",
321+
catalog="test_catalog",
322+
)
323+
324+
sqla_table_no_catalog = table_no_catalog_support.get_sqla_table()
325+
# Should ignore catalog and use traditional schema.table format
326+
assert sqla_table_no_catalog.name == "test_table"
327+
assert sqla_table_no_catalog.schema == "test_schema"
328+
329+
# Test case 3: Table with catalog but no schema (BigQuery style)
330+
table_catalog_only = SqlaTable(
331+
table_name="test_table",
332+
database=database_with_catalog,
333+
catalog="test_project",
334+
)
335+
336+
sqla_table_catalog_only = table_catalog_only.get_sqla_table()
337+
# Should generate "test_project.test_table"
338+
assert sqla_table_catalog_only.name == "test_project.test_table"
339+
assert sqla_table_catalog_only.schema is None
340+
341+
# Test case 4: Table with schema but no catalog (traditional behavior)
342+
table_schema_only = SqlaTable(
343+
table_name="test_table",
344+
database=database_with_catalog,
345+
schema="test_schema",
346+
)
347+
348+
sqla_table_schema_only = table_schema_only.get_sqla_table()
349+
# Should generate just "test_table" with schema set separately
350+
assert sqla_table_schema_only.name == "test_table"
351+
assert sqla_table_schema_only.schema == "test_schema"

0 commit comments

Comments
 (0)