Skip to content

Commit a8b866b

Browse files
committed
fix: clean up comments, add tests, and add changelog for identifier length validation (#1309)
Address review feedback: - Remove verbose comment block from MAX_CHARACTERS_IN_IDENTIFIER constant - Remove redundant inline comments from __post_init__ (implied by the code) - Simplify the error message (no repetition of the limit value) - Add TestIdentifierLengthValidation unit tests covering valid length, too-long raises DbtRuntimeError, no-type skips check, None identifier - Add CHANGELOG entry under 1.11.7 https://claude.ai/code/session_017ZAXMwLSnqz4FqvTt5H7D1
1 parent 6688bce commit a8b866b

3 files changed

Lines changed: 35 additions & 23 deletions

File tree

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
- Fix `workflow_job` Python model submission method failing with dictionary attribute error ([#1360](https://github.com/databricks/dbt-databricks/issues/1360))
1111
- Fix `TestWorkflowJob` functional test that was unreachable on all profiles due to incorrect skip list, wrong model fixture, and invalid `max_retries` parameter ([#1360](https://github.com/databricks/dbt-databricks/issues/1360))
1212
- Fix column order mismatch in microbatch and replace_where incremental strategies by using INSERT BY NAME syntax ([#1338](https://github.com/databricks/dbt-databricks/issues/1338))
13+
- Validate relation identifier length at creation time and raise a clear error when it exceeds Databricks' 255-character limit, preventing confusing runtime failures when `store_failures: true` generates long table names ([#1309](https://github.com/databricks/dbt-databricks/issues/1309))
1314
- Fix `dbt run --empty` failing with inline `ref()` / `source()` aliases ([dbt-labs/dbt-adapters#660](https://github.com/dbt-labs/dbt-adapters/issues/660))
1415

1516
### Under the Hood

dbt/adapters/databricks/relation.py

Lines changed: 8 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -17,12 +17,6 @@
1717
from dbt.adapters.databricks.utils import remove_undefined
1818

1919
KEY_TABLE_PROVIDER = "Provider"
20-
21-
# Databricks (Unity Catalog / Hive Metastore) enforces a 255-character limit
22-
# on table and view names. This constant is used by relation_max_name_length()
23-
# to validate identifier lengths at relation creation time rather than at
24-
# SQL execution time, providing a clear error message instead of a cryptic
25-
# DatabricksExecutionError.
2620
MAX_CHARACTERS_IN_IDENTIFIER = 255
2721

2822

@@ -93,23 +87,14 @@ class DatabricksRelation(BaseRelation):
9387
databricks_table_type: Optional[DatabricksTableType] = None
9488
temporary: Optional[bool] = False
9589

96-
def __post_init__(self):
97-
# Validate identifier length against Databricks' 255-character limit.
98-
# Check self.type to exclude test relation identifiers that may not
99-
# have a type set yet.
100-
if (
101-
self.identifier is not None
102-
and self.type is not None
103-
and len(self.identifier) > self.relation_max_name_length()
104-
):
105-
raise DbtRuntimeError(
106-
f"Relation name '{self.identifier}' "
107-
f"is longer than {self.relation_max_name_length()} characters. "
108-
f"Databricks has a maximum identifier length of "
109-
f"{self.relation_max_name_length()} characters. "
110-
f"If this is a store_failures table, consider using a shorter "
111-
f"test name or setting a custom alias."
112-
)
90+
def __post_init__(self) -> None:
91+
if self.identifier and self.type:
92+
if len(self.identifier) > self.relation_max_name_length():
93+
raise DbtRuntimeError(
94+
f"Relation name '{self.identifier}' is longer than "
95+
f"{self.relation_max_name_length()} characters. "
96+
"Use a shorter test name or configure a custom alias."
97+
)
11398

11499
def relation_max_name_length(self):
115100
return MAX_CHARACTERS_IN_IDENTIFIER

tests/unit/test_relation.py

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import pytest
22
from dbt_common.contracts.constraints import ConstraintType
3+
from dbt_common.exceptions import DbtRuntimeError
34

45
from dbt.adapters.databricks import relation
56
from dbt.adapters.databricks.constraints import (
@@ -8,6 +9,7 @@
89
PrimaryKeyConstraint,
910
)
1011
from dbt.adapters.databricks.relation import (
12+
MAX_CHARACTERS_IN_IDENTIFIER,
1113
DatabricksQuotePolicy,
1214
DatabricksRelation,
1315
DatabricksRelationType,
@@ -370,6 +372,30 @@ def test_render_constraints_for_create__with_constraints(
370372
assert relation.render_constraints_for_create() == "a > 1, PRIMARY KEY (a)"
371373

372374

375+
class TestIdentifierLengthValidation:
376+
def test_relation_max_name_length(self):
377+
assert DatabricksRelation.relation_max_name_length() == MAX_CHARACTERS_IN_IDENTIFIER
378+
379+
def test_valid_identifier_length(self):
380+
identifier = "a" * MAX_CHARACTERS_IN_IDENTIFIER
381+
rel = DatabricksRelation.create(identifier=identifier, type="table")
382+
assert rel.identifier == identifier
383+
384+
def test_identifier_too_long_raises(self):
385+
identifier = "a" * (MAX_CHARACTERS_IN_IDENTIFIER + 1)
386+
with pytest.raises(DbtRuntimeError, match="longer than 255 characters"):
387+
DatabricksRelation.create(identifier=identifier, type="table")
388+
389+
def test_long_identifier_without_type_is_allowed(self):
390+
identifier = "a" * (MAX_CHARACTERS_IN_IDENTIFIER + 1)
391+
rel = DatabricksRelation.create(identifier=identifier)
392+
assert rel.identifier == identifier
393+
394+
def test_none_identifier_is_allowed(self):
395+
rel = DatabricksRelation.create(identifier=None, type="table")
396+
assert rel.identifier is None
397+
398+
373399
class TestDatabricksRenderLimited:
374400
def test_render_limited_with_empty_no_alias(self):
375401
relation = DatabricksRelation.create(

0 commit comments

Comments
 (0)