Skip to content

Commit 1570b34

Browse files
benc-dbclaude
andauthored
fix: Forward port fix for schema checking (#1262)
Forward-ported fix from 1.10.15 to 1.11.1. The previous implementation relied on list_schemas which could be unreliable. This change introduces a dedicated check_schema_exists macro that uses SHOW SCHEMAS ... LIKE for precise matching. Changes: - Modified check_schema_exists in impl.py to use execute_macro - Added databricks__check_schema_exists and check_schema_exists_sql macros - Added databricks__list_schemas and list_schemas_sql macros - Added functional test for schema existence checking 🤖 Generated with [Claude Code](https://claude.com/claude-code) --------- Co-authored-by: Claude <noreply@anthropic.com>
1 parent abbfa59 commit 1570b34

4 files changed

Lines changed: 83 additions & 2 deletions

File tree

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
### Fixes
44

55
- Fix bug that was applying UniForm tblproperties on managed Iceberg tables causing materializations to fail
6+
- Switch to a more reliable mechanism for checking schema existence (forward-ported from 1.10.15) ([1261](https://github.com/databricks/dbt-databricks/pull/1261))
67

78
### Under the hood
89

dbt/adapters/databricks/impl.py

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -387,9 +387,11 @@ def list_schemas(self, database: Optional[str]) -> list[str]:
387387

388388
def check_schema_exists(self, database: Optional[str], schema: str) -> bool:
389389
"""Check if a schema exists."""
390-
return schema.lower() in set(
391-
s.lower() for s in self.connections.list_schemas(database or "hive_metastore", schema)
390+
results = self.execute_macro(
391+
"databricks__check_schema_exists",
392+
kwargs={"database": database or "hive_metastore", "schema": schema},
392393
)
394+
return len(results) > 0
393395

394396
def execute(
395397
self,

dbt/include/databricks/macros/adapters/metadata.sql

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,9 +23,30 @@ SHOW TABLE EXTENDED IN {{ schema_relation.without_identifier()|lower }} LIKE '{{
2323
{% endmacro %}
2424

2525
{% macro show_tables_sql(relation) %}
26+
2627
SHOW TABLES IN {{ relation.render() }}
2728
{% endmacro %}
2829

30+
{% macro databricks__list_schemas(database) -%}
31+
{{ return(run_query_as(list_schemas_sql(database), 'list_schemas')) }}
32+
{% endmacro %}
33+
34+
{% macro list_schemas_sql(database) %}
35+
{% if database %}
36+
SHOW SCHEMAS IN {{ database }}
37+
{% else %}
38+
SHOW SCHEMAS
39+
{% endif %}
40+
{% endmacro %}
41+
42+
{% macro databricks__check_schema_exists(database, schema) %}
43+
{{ return(run_query_as(check_schema_exists_sql(database, schema), 'check_schema_exists')) }}
44+
{% endmacro %}
45+
46+
{% macro check_schema_exists_sql(database, schema) %}
47+
SHOW SCHEMAS IN {{ database }} LIKE '{{ schema }}'
48+
{% endmacro %}
49+
2950
{% macro show_views(relation) %}
3051
{{ return(adapter.dispatch('show_views', 'dbt')(relation)) }}
3152
{% endmacro %}
Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
import pytest
2+
3+
4+
class TestCheckSchemaExists:
5+
"""Test the check_schema_exists adapter method."""
6+
7+
@pytest.fixture(scope="class", autouse=True)
8+
def setUp(self, project):
9+
"""Create a test schema and clean it up after tests."""
10+
test_schema = f"{project.test_schema}_check_exists"
11+
12+
with project.adapter.connection_named("__test"):
13+
relation = project.adapter.Relation.create(
14+
database=project.database,
15+
schema=test_schema,
16+
)
17+
# Drop if exists from previous run
18+
project.adapter.drop_schema(relation)
19+
# Create the test schema
20+
project.adapter.create_schema(relation)
21+
22+
yield test_schema
23+
24+
# Cleanup
25+
with project.adapter.connection_named("__test"):
26+
project.adapter.drop_schema(relation)
27+
28+
def test_check_schema_exists(self, project, setUp):
29+
"""Test that check_schema_exists correctly identifies existing and non-existing schemas."""
30+
test_schema = setUp
31+
32+
with project.adapter.connection_named("__test"):
33+
# Test 1: Verify existing schema returns True
34+
exists = project.adapter.check_schema_exists(
35+
database=project.database, schema=test_schema
36+
)
37+
assert exists is True, (
38+
f"Expected schema '{test_schema}' to exist but check returned False"
39+
)
40+
41+
# Test 2: Verify non-existing schema returns False
42+
non_existent_schema = "this_schema_definitely_does_not_exist_12345"
43+
exists = project.adapter.check_schema_exists(
44+
database=project.database, schema=non_existent_schema
45+
)
46+
assert exists is False, (
47+
f"Expected schema '{non_existent_schema}' to not exist but check returned True"
48+
)
49+
50+
# Test 3: Verify existing default schema returns True (should always exist)
51+
exists = project.adapter.check_schema_exists(
52+
database=project.database, schema=project.test_schema
53+
)
54+
assert exists is True, (
55+
f"Expected default test schema '{project.test_schema}' "
56+
"to exist but check returned False"
57+
)

0 commit comments

Comments
 (0)