Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
- Validate relation identifier length at creation time and raise a clear error when it exceeds Databricks' 255-character limit ([#1309](https://github.com/databricks/dbt-databricks/issues/1309))
- Fix spurious `MicrobatchConcurrency` behavior-change warning firing on every run regardless of whether the project contained microbatch models ([#1406](https://github.com/databricks/dbt-databricks/issues/1406))
- Fix DBR capability cache being permanently poisoned by a transient version-query failure ([#1398](https://github.com/databricks/dbt-databricks/issues/1398))
- Fix spurious `use_managed_iceberg` behavior-change warning firing on every run for projects that don't use Iceberg ([#1266](https://github.com/databricks/dbt-databricks/issues/1266))

## dbt-databricks 1.11.7 (Apr 17, 2026)

Expand Down
21 changes: 16 additions & 5 deletions dbt/adapters/databricks/impl.py
Original file line number Diff line number Diff line change
Expand Up @@ -248,7 +248,9 @@ def __init__(self, config: Any, mp_context: SpawnContext) -> None:
self.add_catalog_integration(constants.DEFAULT_HIVE_METASTORE_CATALOG)

# Store the use_managed_iceberg flag in GlobalState for the session
GlobalState.set_use_managed_iceberg(bool(self.behavior.use_managed_iceberg))
GlobalState.set_use_managed_iceberg(
self.get_behavior_flag_no_warn(USE_MANAGED_ICEBERG["name"])
)

@property
def _behavior_flags(self) -> list[BehaviorFlag]:
Expand All @@ -262,8 +264,7 @@ def _behavior_flags(self) -> list[BehaviorFlag]:

def supports(self, capability: Capability) -> bool:
if capability == Capability.MicrobatchConcurrency:
# `.no_warn` avoids a BehaviorChangeEvent on dbt-core's per-parse probe.
return self.behavior.use_concurrent_microbatch.no_warn
return self.get_behavior_flag_no_warn(USE_CONCURRENT_MICROBATCH["name"])
return super().supports(capability)

def quote(self, identifier): # type: ignore[override,no-untyped-def]
Expand All @@ -281,7 +282,7 @@ def is_uniform(self, config: BaseConfig) -> bool:
", 'table', or 'snapshot'."
)
if (
self.behavior.use_managed_iceberg
self.get_behavior_flag_no_warn(USE_MANAGED_ICEBERG["name"])
Comment thread
sd-db marked this conversation as resolved.
and catalog_relation.catalog_type != constants.UNITY_CATALOG_TYPE
):
raise DbtConfigError(
Expand All @@ -290,7 +291,7 @@ def is_uniform(self, config: BaseConfig) -> bool:
)
# UniForm refers to Delta tables with Iceberg compatibility.
# Native managed Iceberg tables don't need Delta properties.
return not self.behavior.use_managed_iceberg
return not self.get_behavior_flag_no_warn(USE_MANAGED_ICEBERG["name"])
else:
return False

Expand Down Expand Up @@ -770,6 +771,16 @@ def _get_columns_for_catalog( # type: ignore[override]
as_dict["column_type"] = as_dict.pop("dtype")
yield as_dict

def get_behavior_flag_no_warn(self, behavior_flag_name: str) -> bool:
"""Get the value of a behavior flag without triggering a warning.

dbt logs a warning the first time a behavior flag with a False value is accessed. Use
this method to access the value of a behavior flag without triggering a warning.
"""
# As intended - This method will error out if the behavior flag is missing.
behavior_flag = getattr(self.behavior, behavior_flag_name)
return behavior_flag.no_warn

def add_query(
self,
sql: str,
Expand Down
2 changes: 1 addition & 1 deletion dbt/include/databricks/macros/relations/file_format.sql
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@
{% endif %}

{#-- Use managed Iceberg if behavior flag is enabled and table_format is iceberg --#}
{% if adapter.behavior.use_managed_iceberg and table_format == 'iceberg' %}
{% if table_format == 'iceberg' and adapter.behavior.use_managed_iceberg %}
using iceberg
{% else %}
using {{ file_format }}
Expand Down
36 changes: 36 additions & 0 deletions tests/unit/macros/relations/test_table_macros.py
Original file line number Diff line number Diff line change
Expand Up @@ -339,3 +339,39 @@ def test_macros_create_table_as_uniform_iceberg(self, config, template_bundle):
"'delta.universalFormat.enabledFormats' = 'iceberg') as select 1"
)
assert sql == expected


class TestFileFormatClause(MacroTestBase):
"""Regression tests for `file_format_clause` short-circuit behavior.

For non-Iceberg models, the macro must not read `adapter.behavior.use_managed_iceberg`,
since that access fires a BehaviorChangeEvent deprecation warning on every run.
"""

@pytest.fixture(scope="class")
def template_name(self) -> str:
return "file_format.sql"

@pytest.fixture(scope="class")
def macro_folders_to_load(self) -> list:
return ["macros/relations", "macros"]

def test_file_format_clause_does_not_access_flag_for_non_iceberg(self, template_bundle):
"""Non-Iceberg relations must short-circuit before reading the behavior flag."""

class ErrorOnUseManagedIcebergAccess:
@property
def use_managed_iceberg(self):
raise AssertionError(
"use_managed_iceberg must not be accessed when table_format != 'iceberg'"
)

template_bundle.context["adapter"].behavior = ErrorOnUseManagedIcebergAccess()
catalog_relation = unity_relation(
table_format=constants.DEFAULT_TABLE_FORMAT,
file_format=constants.DELTA_FILE_FORMAT,
)

sql = self.run_macro(template_bundle.template, "file_format_clause", catalog_relation)

assert sql == "using delta"
10 changes: 5 additions & 5 deletions tests/unit/test_adapter.py
Original file line number Diff line number Diff line change
Expand Up @@ -1282,7 +1282,7 @@ def test_is_uniform_with_managed_iceberg_returns_false(

Native managed Iceberg tables don't use UniForm (Delta with Iceberg compatibility),
so they shouldn't get Delta table properties added."""
adapter.behavior.use_managed_iceberg = True
adapter.behavior.use_managed_iceberg.setting = True
adapter.build_catalog_relation = Mock(
return_value=unity_catalog_relation_managed_iceberg_relation
)
Expand All @@ -1295,7 +1295,7 @@ def test_is_uniform_with_uniform_iceberg_returns_true(
self, adapter, mock_config, unity_catalog_relation
):
"""Test that is_uniform returns True for UniForm Iceberg tables"""
adapter.behavior.use_managed_iceberg = False # Default
adapter.behavior.use_managed_iceberg.setting = False # Default
adapter.build_catalog_relation = Mock(return_value=unity_catalog_relation)
adapter.has_capability = Mock(return_value=True) # Has iceberg capability

Expand All @@ -1318,7 +1318,7 @@ def test_is_uniform_with_managed_iceberg_hive_metastore_error(
self, adapter, mock_config, hive_catalog_relation
):
"""Test that is_uniform raises error for managed Iceberg with Hive Metastore"""
adapter.behavior.use_managed_iceberg = True
adapter.behavior.use_managed_iceberg.setting = True
adapter.build_catalog_relation = Mock(return_value=hive_catalog_relation)
adapter.has_capability = Mock(return_value=True) # Has iceberg capability

Expand All @@ -1331,7 +1331,7 @@ def test_is_uniform_with_old_dbr_version_error(
self, adapter, mock_config, unity_catalog_relation
):
"""Test that is_uniform raises error for insufficient DBR version"""
adapter.behavior.use_managed_iceberg = False
adapter.behavior.use_managed_iceberg.setting = False
adapter.build_catalog_relation = Mock(return_value=unity_catalog_relation)
adapter.has_capability = Mock(return_value=False) # No ICEBERG capability

Expand All @@ -1342,7 +1342,7 @@ def test_is_uniform_with_invalid_materialization_error(
self, adapter, mock_config, unity_catalog_relation
):
"""Test that is_uniform raises error for invalid materialization"""
adapter.behavior.use_managed_iceberg = False
adapter.behavior.use_managed_iceberg.setting = False
adapter.build_catalog_relation = Mock(return_value=unity_catalog_relation)
adapter.has_capability = Mock(return_value=True) # Has iceberg capability
mock_config.get.side_effect = lambda key: "view" if key == "materialized" else None
Expand Down
Loading