|
26 | 26 | SqlModel, |
27 | 27 | ModelKindName, |
28 | 28 | ) |
29 | | -from sqlmesh.core.model.kind import OnDestructiveChange, OnAdditiveChange |
| 29 | +from sqlmesh.core.model.kind import OnDestructiveChange, OnAdditiveChange, ViewKind |
30 | 30 | from sqlmesh.core.model.seed import Seed |
31 | 31 | from sqlmesh.core.plan import Plan, PlanBuilder, SnapshotIntervals |
32 | 32 | from sqlmesh.core.snapshot import ( |
@@ -4162,3 +4162,143 @@ def test_plan_ignore_cron_flag(make_snapshot): |
4162 | 4162 | ], |
4163 | 4163 | ) |
4164 | 4164 | ] |
| 4165 | + |
| 4166 | + |
| 4167 | +def test_indirect_change_to_materialized_view_is_breaking(make_snapshot): |
| 4168 | + snapshot_a_old = make_snapshot( |
| 4169 | + SqlModel( |
| 4170 | + name="a", |
| 4171 | + query=parse_one("select 1 as col_a"), |
| 4172 | + kind=ViewKind(materialized=True), |
| 4173 | + ) |
| 4174 | + ) |
| 4175 | + snapshot_a_old.categorize_as(SnapshotChangeCategory.BREAKING) |
| 4176 | + |
| 4177 | + snapshot_b_old = make_snapshot( |
| 4178 | + SqlModel( |
| 4179 | + name="b", |
| 4180 | + query=parse_one("select col_a from a"), |
| 4181 | + kind=ViewKind(materialized=True), |
| 4182 | + ), |
| 4183 | + nodes={'"a"': snapshot_a_old.model}, |
| 4184 | + ) |
| 4185 | + snapshot_b_old.categorize_as(SnapshotChangeCategory.BREAKING) |
| 4186 | + |
| 4187 | + snapshot_a_new = make_snapshot( |
| 4188 | + SqlModel( |
| 4189 | + name="a", |
| 4190 | + query=parse_one("select 1 as col_a, 2 as col_b"), |
| 4191 | + kind=ViewKind(materialized=True), |
| 4192 | + ) |
| 4193 | + ) |
| 4194 | + |
| 4195 | + snapshot_a_new.previous_versions = snapshot_a_old.all_versions |
| 4196 | + |
| 4197 | + snapshot_b_new = make_snapshot( |
| 4198 | + snapshot_b_old.model, |
| 4199 | + nodes={'"a"': snapshot_a_new.model}, |
| 4200 | + ) |
| 4201 | + snapshot_b_new.previous_versions = snapshot_b_old.all_versions |
| 4202 | + |
| 4203 | + context_diff = ContextDiff( |
| 4204 | + environment="test_environment", |
| 4205 | + is_new_environment=True, |
| 4206 | + is_unfinalized_environment=False, |
| 4207 | + normalize_environment_name=True, |
| 4208 | + create_from="prod", |
| 4209 | + create_from_env_exists=True, |
| 4210 | + added=set(), |
| 4211 | + removed_snapshots={}, |
| 4212 | + modified_snapshots={ |
| 4213 | + snapshot_a_new.name: (snapshot_a_new, snapshot_a_old), |
| 4214 | + snapshot_b_new.name: (snapshot_b_new, snapshot_b_old), |
| 4215 | + }, |
| 4216 | + snapshots={ |
| 4217 | + snapshot_a_new.snapshot_id: snapshot_a_new, |
| 4218 | + snapshot_b_new.snapshot_id: snapshot_b_new, |
| 4219 | + }, |
| 4220 | + new_snapshots={ |
| 4221 | + snapshot_a_new.snapshot_id: snapshot_a_new, |
| 4222 | + snapshot_b_new.snapshot_id: snapshot_b_new, |
| 4223 | + }, |
| 4224 | + previous_plan_id=None, |
| 4225 | + previously_promoted_snapshot_ids=set(), |
| 4226 | + previous_finalized_snapshots=None, |
| 4227 | + previous_gateway_managed_virtual_layer=False, |
| 4228 | + gateway_managed_virtual_layer=False, |
| 4229 | + environment_statements=[], |
| 4230 | + ) |
| 4231 | + |
| 4232 | + PlanBuilder(context_diff, forward_only=False).build() |
| 4233 | + |
| 4234 | + assert snapshot_b_new.change_category == SnapshotChangeCategory.INDIRECT_BREAKING |
| 4235 | + |
| 4236 | + |
| 4237 | +def test_forward_only_indirect_change_to_materialized_view(make_snapshot): |
| 4238 | + snapshot_a_old = make_snapshot( |
| 4239 | + SqlModel( |
| 4240 | + name="a", |
| 4241 | + query=parse_one("select 1 as col_a"), |
| 4242 | + ) |
| 4243 | + ) |
| 4244 | + snapshot_a_old.categorize_as(SnapshotChangeCategory.BREAKING) |
| 4245 | + |
| 4246 | + snapshot_b_old = make_snapshot( |
| 4247 | + SqlModel( |
| 4248 | + name="b", |
| 4249 | + query=parse_one("select col_a from a"), |
| 4250 | + kind=ViewKind(materialized=True), |
| 4251 | + ), |
| 4252 | + nodes={'"a"': snapshot_a_old.model}, |
| 4253 | + ) |
| 4254 | + snapshot_b_old.categorize_as(SnapshotChangeCategory.BREAKING) |
| 4255 | + |
| 4256 | + snapshot_a_new = make_snapshot( |
| 4257 | + SqlModel( |
| 4258 | + name="a", |
| 4259 | + query=parse_one("select 1 as col_a, 2 as col_b"), |
| 4260 | + ) |
| 4261 | + ) |
| 4262 | + |
| 4263 | + snapshot_a_new.previous_versions = snapshot_a_old.all_versions |
| 4264 | + |
| 4265 | + snapshot_b_new = make_snapshot( |
| 4266 | + snapshot_b_old.model, |
| 4267 | + nodes={'"a"': snapshot_a_new.model}, |
| 4268 | + ) |
| 4269 | + snapshot_b_new.previous_versions = snapshot_b_old.all_versions |
| 4270 | + |
| 4271 | + context_diff = ContextDiff( |
| 4272 | + environment="test_environment", |
| 4273 | + is_new_environment=True, |
| 4274 | + is_unfinalized_environment=False, |
| 4275 | + normalize_environment_name=True, |
| 4276 | + create_from="prod", |
| 4277 | + create_from_env_exists=True, |
| 4278 | + added=set(), |
| 4279 | + removed_snapshots={}, |
| 4280 | + modified_snapshots={ |
| 4281 | + snapshot_a_new.name: (snapshot_a_new, snapshot_a_old), |
| 4282 | + snapshot_b_new.name: (snapshot_b_new, snapshot_b_old), |
| 4283 | + }, |
| 4284 | + snapshots={ |
| 4285 | + snapshot_a_new.snapshot_id: snapshot_a_new, |
| 4286 | + snapshot_b_new.snapshot_id: snapshot_b_new, |
| 4287 | + }, |
| 4288 | + new_snapshots={ |
| 4289 | + snapshot_a_new.snapshot_id: snapshot_a_new, |
| 4290 | + snapshot_b_new.snapshot_id: snapshot_b_new, |
| 4291 | + }, |
| 4292 | + previous_plan_id=None, |
| 4293 | + previously_promoted_snapshot_ids=set(), |
| 4294 | + previous_finalized_snapshots=None, |
| 4295 | + previous_gateway_managed_virtual_layer=False, |
| 4296 | + gateway_managed_virtual_layer=False, |
| 4297 | + environment_statements=[], |
| 4298 | + ) |
| 4299 | + |
| 4300 | + PlanBuilder(context_diff, forward_only=True).build() |
| 4301 | + |
| 4302 | + # Forward-only indirect changes to MVs should not always be classified as indirect breaking. |
| 4303 | + # Instead, we want to preserve the standard categorization. |
| 4304 | + assert snapshot_b_new.change_category == SnapshotChangeCategory.INDIRECT_NON_BREAKING |
0 commit comments