Skip to content

Commit cf4cac9

Browse files
committed
Warn when documented columns are missing from the relation in persist_docs
When persist_docs.columns is enabled, columns documented in a model's schema.yml but absent from the materialized relation were silently skipped by get_persist_doc_columns. Emit a warning naming those columns so users can catch typos and stale documentation. The columns are still filtered out (no behavior change to the comments that get applied). Ports the behavior added upstream in dbt-adapters#1684 (issue #1690).
1 parent ae37b8a commit cf4cac9

3 files changed

Lines changed: 48 additions & 0 deletions

File tree

CHANGELOG.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,8 @@
55
- Support `catalog_database` in v2 catalogs.yml to route Unity catalog models to a physical catalog independent of the dbt catalog name (requires `dbt-core>=1.12` and `dbt-adapters>=1.24.4`). ([#1590](https://github.com/databricks/dbt-databricks/pull/1590))
66

77
### Fixes
8+
9+
- Warn when a column documented in a model's `schema.yml` is absent from the relation while applying column comments, instead of silently skipping it — surfaces typos and stale column documentation. Covers the column-comment comparison paths (V1 `get_persist_doc_columns` and V2 `ColumnCommentsConfig.get_diff`); create-time inline comments are not yet covered. Ports the behavior added in dbt-adapters ([dbt-adapters#1684](https://github.com/dbt-labs/dbt-adapters/pull/1684) closes [dbt-adapters#1690](https://github.com/dbt-labs/dbt-adapters/issues/1690)) ([#1563](https://github.com/databricks/dbt-databricks/pull/1563)).
810
- Support `dbt clone` and rebuilds over an existing shallow clone ([#1592](https://github.com/databricks/dbt-databricks/pull/1592) resolves [#1165](https://github.com/databricks/dbt-databricks/issues/1165))
911
- Fix managed Iceberg Python models failing with `MANAGED_TABLE_FORMAT` by emitting `.format("iceberg")` instead of the `parquet` sentinel from `resolve_file_format` (thanks @Divya-Kovvuru-0802!) ([#1593](https://github.com/databricks/dbt-databricks/pull/1593) resolves [#1591](https://github.com/databricks/dbt-databricks/issues/1591))
1012
- Quote generated column identifiers in incremental strategies so non-ASCII column names no longer fail on subsequent runs ([#1595](https://github.com/databricks/dbt-databricks/pull/1595) resolves [#1594](https://github.com/databricks/dbt-databricks/issues/1594))

dbt/adapters/databricks/impl.py

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
from dbt.adapters.catalogs import CatalogRelation
2121
from dbt.adapters.contracts.connection import AdapterResponse, Connection
2222
from dbt.adapters.contracts.relation import RelationConfig, RelationType
23+
from dbt.adapters.events.types import AdapterEventWarning
2324
from dbt.adapters.relation_configs import RelationResults
2425
from dbt.adapters.spark.impl import (
2526
DESCRIBE_TABLE_EXTENDED_MACRO_NAME,
@@ -31,6 +32,7 @@
3132
)
3233
from dbt_common.behavior_flags import BehaviorFlag
3334
from dbt_common.contracts.config.base import BaseConfig, MergeBehavior
35+
from dbt_common.events.functions import warn_or_error
3436
from dbt_common.exceptions import DbtConfigError, DbtInternalError, DbtRuntimeError
3537
from dbt_common.record import auto_record_function, record_function
3638
from dbt_common.utils import executor
@@ -1008,6 +1010,25 @@ def get_persist_doc_columns(
10081010
# Create a case-insensitive lookup for column names
10091011
columns_lower = {k.lower(): k for k in columns.keys()}
10101012

1013+
# Warn about columns that are documented in the model's schema but are not present in the
1014+
# relation. These are silently skipped below (rather than erroring on the alter), so surface
1015+
# them to the user to catch typos and stale documentation.
1016+
existing_lower = {column.column.lower() for column in existing_columns}
1017+
missing = [
1018+
original_name
1019+
for name_lower, original_name in columns_lower.items()
1020+
if name_lower not in existing_lower
1021+
]
1022+
if missing:
1023+
warn_or_error(
1024+
AdapterEventWarning(
1025+
base_msg=(
1026+
"The following columns are specified in the schema but are not present "
1027+
"in the database and will be skipped: " + ", ".join(missing)
1028+
)
1029+
)
1030+
)
1031+
10111032
for column in existing_columns:
10121033
name = column.column
10131034
# Use case-insensitive comparison for column names

tests/unit/test_adapter.py

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1182,6 +1182,31 @@ def test_get_persist_doc_columns_case_mismatch_no_update_needed(self, adapter):
11821182
# No update needed since comments match
11831183
assert result == {}
11841184

1185+
@patch("dbt.adapters.databricks.impl.warn_or_error")
1186+
def test_get_persist_doc_columns_warns_on_missing_column(self, mock_warn, adapter):
1187+
"""Documented columns absent from the relation are warned about and skipped."""
1188+
existing = [self.create_column("col1", "comment1")]
1189+
column_dict = {
1190+
"col1": {"name": "col1", "description": "new comment"},
1191+
"col2": {"name": "col2", "description": "comment for missing column"},
1192+
}
1193+
result = adapter.get_persist_doc_columns(existing, column_dict)
1194+
# The missing column is filtered out; only the existing column is returned.
1195+
assert result == {"col1": {"name": "col1", "description": "new comment"}}
1196+
# A warning is emitted naming the missing column.
1197+
mock_warn.assert_called_once()
1198+
warned_event = mock_warn.call_args.args[0]
1199+
assert "col2" in warned_event.base_msg
1200+
assert "col1" not in warned_event.base_msg
1201+
1202+
@patch("dbt.adapters.databricks.impl.warn_or_error")
1203+
def test_get_persist_doc_columns_no_warning_when_all_present(self, mock_warn, adapter):
1204+
"""No warning is emitted when every documented column exists (case-insensitively)."""
1205+
existing = [self.create_column("Account_ID", "")]
1206+
column_dict = {"account_id": {"name": "account_id", "description": "Account ID column"}}
1207+
adapter.get_persist_doc_columns(existing, column_dict)
1208+
mock_warn.assert_not_called()
1209+
11851210

11861211
class TestGetColumnsByDbrVersion(DatabricksAdapterBase):
11871212
@pytest.fixture

0 commit comments

Comments
 (0)