Skip to content

Commit 63e2dbd

Browse files
authored
Feat: include dropped column name in destructive change message (#3367)
1 parent 1bd152a commit 63e2dbd

6 files changed

Lines changed: 34 additions & 10 deletions

File tree

sqlmesh/core/plan/builder.py

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@
1717
from sqlmesh.core.context_diff import ContextDiff
1818
from sqlmesh.core.environment import EnvironmentNamingInfo
1919
from sqlmesh.core.plan.definition import Plan, SnapshotMapping, earliest_interval_start
20-
from sqlmesh.core.schema_diff import SchemaDiffer, has_drop_alteration
20+
from sqlmesh.core.schema_diff import SchemaDiffer, has_drop_alteration, get_dropped_column_names
2121
from sqlmesh.core.snapshot import (
2222
DeployabilityIndex,
2323
Snapshot,
@@ -464,12 +464,21 @@ def _check_destructive_changes(self, directly_modified: t.Set[SnapshotId]) -> No
464464
)
465465

466466
if has_drop_alteration(schema_diff):
467-
warning_msg = f"Plan results in a destructive change to forward-only model '{snapshot.name}'s schema"
467+
dropped_column_names = get_dropped_column_names(schema_diff)
468+
dropped_column_str = (
469+
"', '".join(dropped_column_names) if dropped_column_names else None
470+
)
471+
dropped_column_msg = (
472+
f" that drops column{'s' if dropped_column_names and len(dropped_column_names) > 1 else ''} '{dropped_column_str}'"
473+
if dropped_column_str
474+
else ""
475+
)
476+
warning_msg = f"Plan results in a destructive change to forward-only model '{snapshot.name}'s schema{dropped_column_msg}."
468477
if snapshot.model.on_destructive_change.is_warn:
469478
logger.warning(warning_msg)
470479
else:
471480
raise PlanError(
472-
f"{warning_msg}. To allow this, change the model's `on_destructive_change` setting to `warn` or `allow` or include it in the plan's `--allow-destructive-model` option."
481+
f"{warning_msg} To allow this, change the model's `on_destructive_change` setting to `warn` or `allow` or include it in the plan's `--allow-destructive-model` option."
473482
)
474483

475484
def _categorize_snapshots(

sqlmesh/core/schema_diff.py

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -687,5 +687,15 @@ def has_drop_alteration(alter_expressions: t.List[exp.Alter]) -> bool:
687687
)
688688

689689

690+
def get_dropped_column_names(alter_expressions: t.List[exp.Alter]) -> t.List[str]:
691+
dropped_columns = []
692+
for actions in alter_expressions:
693+
for action in actions.args.get("actions", []):
694+
if isinstance(action, exp.Drop):
695+
if action.kind == "COLUMN":
696+
dropped_columns.append(action.alias_or_name)
697+
return dropped_columns
698+
699+
690700
def _get_name_and_type(struct: exp.ColumnDef) -> t.Tuple[exp.Identifier, exp.DataType]:
691701
return struct.this, struct.args["kind"]

sqlmesh/core/snapshot/evaluator.py

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,7 @@
4949
SCDType2ByTimeKind,
5050
ViewKind,
5151
)
52-
from sqlmesh.core.schema_diff import has_drop_alteration
52+
from sqlmesh.core.schema_diff import has_drop_alteration, get_dropped_column_names
5353
from sqlmesh.core.snapshot import (
5454
DeployabilityIndex,
5555
Intervals,
@@ -1855,9 +1855,14 @@ def _check_destructive_schema_change(
18551855
if snapshot.needs_destructive_check(allow_destructive_snapshots) and has_drop_alteration(
18561856
alter_expressions
18571857
):
1858-
warning_msg = (
1859-
f"Plan results in a destructive change to forward-only table '{snapshot.name}'s schema."
1858+
dropped_column_names = get_dropped_column_names(alter_expressions)
1859+
dropped_column_str = "', '".join(dropped_column_names) if dropped_column_names else None
1860+
dropped_column_msg = (
1861+
f" that drops column{'s' if dropped_column_names and len(dropped_column_names) > 1 else ''} '{dropped_column_str}'"
1862+
if dropped_column_str
1863+
else ""
18601864
)
1865+
warning_msg = f"Plan results in a destructive change to forward-only table '{snapshot.name}'s schema{dropped_column_msg}."
18611866
if snapshot.model.on_destructive_change.is_warn:
18621867
logger.warning(warning_msg)
18631868
return

tests/conftest.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -366,8 +366,8 @@ def _make_function(node: Node, version: t.Optional[str] = None, **kwargs) -> Sna
366366
def make_snapshot_on_destructive_change(make_snapshot: t.Callable) -> t.Callable:
367367
def _make_function(
368368
name: str = "a",
369-
old_query: str = "select '1' as one, '2022-01-01' ds",
370-
new_query: str = "select 1 as one, '2022-01-01' ds",
369+
old_query: str = "select '1' as one, '2' as two, '2022-01-01' ds",
370+
new_query: str = "select 1 as one, 2 as two, '2022-01-01' ds",
371371
on_destructive_change: OnDestructiveChange = OnDestructiveChange.ERROR,
372372
) -> t.Tuple[Snapshot, Snapshot]:
373373
snapshot_old = make_snapshot(

tests/core/test_plan.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -484,7 +484,7 @@ def test_forward_only_model_on_destructive_change(
484484

485485
with pytest.raises(
486486
PlanError,
487-
match="""Plan results in a destructive change to forward-only model '"a"'s schema.""",
487+
match="""Plan results in a destructive change to forward-only model '"a"'s schema that drops columns 'one', 'two'.""",
488488
):
489489
PlanBuilder(context_diff_1, schema_differ).build()
490490

tests/core/test_snapshot_evaluator.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1550,7 +1550,7 @@ def columns(table_name):
15501550
evaluator.migrate([snapshot], {})
15511551
assert (
15521552
mock_logger.call_args[0][0]
1553-
== """Plan results in a destructive change to forward-only table '"test_schema"."test_model"'s schema."""
1553+
== """Plan results in a destructive change to forward-only table '"test_schema"."test_model"'s schema that drops column 'b'."""
15541554
)
15551555

15561556
# allow destructive

0 commit comments

Comments
 (0)