|
64 | 64 | table_name, |
65 | 65 | TableNamingConvention, |
66 | 66 | ) |
| 67 | +from sqlmesh.core.config.common import VirtualEnvironmentMode |
67 | 68 | from sqlmesh.utils import AttributeDict |
68 | 69 | from sqlmesh.utils.date import DatetimeRanges, to_date, to_datetime, to_timestamp |
69 | 70 | from sqlmesh.utils.errors import SQLMeshError, SignalEvalError |
@@ -3339,3 +3340,161 @@ def test_partitioned_by_roundtrip(make_snapshot: t.Callable): |
3339 | 3340 |
|
3340 | 3341 | assert isinstance(deserialized.node, SqlModel) |
3341 | 3342 | assert deserialized.node.partitioned_by == snapshot.node.partitioned_by |
| 3343 | + |
| 3344 | + |
| 3345 | +def test_merge_intervals_virtual_environment_mode_full(make_snapshot): |
| 3346 | + model = SqlModel( |
| 3347 | + name="test_model", |
| 3348 | + kind=IncrementalByTimeRangeKind(time_column="ds"), |
| 3349 | + query=parse_one("SELECT 1, ds FROM parent_tbl"), |
| 3350 | + ) |
| 3351 | + |
| 3352 | + # Create source snapshot with intervals |
| 3353 | + source_snapshot = make_snapshot(model, virtual_environment_mode=VirtualEnvironmentMode.FULL) |
| 3354 | + source_snapshot.add_interval("2020-01-01", "2020-01-03") |
| 3355 | + source_snapshot.add_interval("2020-01-05", "2020-01-07") |
| 3356 | + |
| 3357 | + # Create target snapshot with different fingerprint and virtual_environment_mode FULL |
| 3358 | + target_snapshot = make_snapshot(model, virtual_environment_mode=VirtualEnvironmentMode.FULL) |
| 3359 | + target_snapshot.fingerprint = SnapshotFingerprint( |
| 3360 | + data_hash="different", metadata_hash="different", parent_data_hash="different" |
| 3361 | + ) |
| 3362 | + target_snapshot.categorize_as(SnapshotChangeCategory.BREAKING) |
| 3363 | + |
| 3364 | + # When virtual_environment_mode is FULL, intervals should be merged |
| 3365 | + target_snapshot.merge_intervals(source_snapshot) |
| 3366 | + |
| 3367 | + assert target_snapshot.intervals == [ |
| 3368 | + (to_timestamp("2020-01-01"), to_timestamp("2020-01-04")), |
| 3369 | + (to_timestamp("2020-01-05"), to_timestamp("2020-01-08")), |
| 3370 | + ] |
| 3371 | + |
| 3372 | + |
| 3373 | +def test_merge_intervals_virtual_environment_mode_dev_only_paused_breaking(make_snapshot): |
| 3374 | + model = SqlModel( |
| 3375 | + name="test_model", |
| 3376 | + kind=IncrementalByTimeRangeKind(time_column="ds"), |
| 3377 | + query=parse_one("SELECT 1, ds FROM parent_tbl"), |
| 3378 | + ) |
| 3379 | + |
| 3380 | + # Create source snapshot with intervals |
| 3381 | + source_snapshot = make_snapshot(model, virtual_environment_mode=VirtualEnvironmentMode.DEV_ONLY) |
| 3382 | + source_snapshot.add_interval("2020-01-01", "2020-01-03") |
| 3383 | + source_snapshot.add_interval("2020-01-05", "2020-01-07") |
| 3384 | + |
| 3385 | + # Create target snapshot with different fingerprint and virtual_environment_mode DEV_ONLY |
| 3386 | + target_snapshot = make_snapshot(model, virtual_environment_mode=VirtualEnvironmentMode.DEV_ONLY) |
| 3387 | + target_snapshot.fingerprint = SnapshotFingerprint( |
| 3388 | + data_hash="different", metadata_hash="different", parent_data_hash="different" |
| 3389 | + ) |
| 3390 | + target_snapshot.categorize_as(SnapshotChangeCategory.BREAKING) |
| 3391 | + |
| 3392 | + # Ensure snapshot is paused (unpaused_ts is None) |
| 3393 | + target_snapshot.unpaused_ts = None |
| 3394 | + |
| 3395 | + # When virtual_environment_mode is DEV_ONLY and snapshot is paused and breaking, intervals should NOT be merged |
| 3396 | + target_snapshot.merge_intervals(source_snapshot) |
| 3397 | + |
| 3398 | + assert target_snapshot.intervals == [] |
| 3399 | + |
| 3400 | + |
| 3401 | +def test_merge_intervals_virtual_environment_mode_dev_only_unpaused(make_snapshot): |
| 3402 | + model = SqlModel( |
| 3403 | + name="test_model", |
| 3404 | + kind=IncrementalByTimeRangeKind(time_column="ds"), |
| 3405 | + query=parse_one("SELECT 1, ds FROM parent_tbl"), |
| 3406 | + ) |
| 3407 | + |
| 3408 | + # Create source snapshot with intervals |
| 3409 | + source_snapshot = make_snapshot(model, virtual_environment_mode=VirtualEnvironmentMode.DEV_ONLY) |
| 3410 | + source_snapshot.add_interval("2020-01-01", "2020-01-03") |
| 3411 | + source_snapshot.add_interval("2020-01-05", "2020-01-07") |
| 3412 | + |
| 3413 | + # Create target snapshot with different fingerprint and virtual_environment_mode DEV_ONLY |
| 3414 | + target_snapshot = make_snapshot(model, virtual_environment_mode=VirtualEnvironmentMode.DEV_ONLY) |
| 3415 | + target_snapshot.fingerprint = SnapshotFingerprint( |
| 3416 | + data_hash="different", metadata_hash="different", parent_data_hash="different" |
| 3417 | + ) |
| 3418 | + target_snapshot.categorize_as(SnapshotChangeCategory.BREAKING) |
| 3419 | + |
| 3420 | + # Ensure snapshot is unpaused |
| 3421 | + target_snapshot.unpaused_ts = to_timestamp("2020-01-01") |
| 3422 | + |
| 3423 | + # When snapshot is unpaused, intervals should be merged regardless of virtual_environment_mode |
| 3424 | + target_snapshot.merge_intervals(source_snapshot) |
| 3425 | + |
| 3426 | + assert target_snapshot.intervals == [ |
| 3427 | + (to_timestamp("2020-01-01"), to_timestamp("2020-01-04")), |
| 3428 | + (to_timestamp("2020-01-05"), to_timestamp("2020-01-08")), |
| 3429 | + ] |
| 3430 | + |
| 3431 | + |
| 3432 | +def test_merge_intervals_virtual_environment_mode_dev_only_no_rebuild(make_snapshot): |
| 3433 | + model = SqlModel( |
| 3434 | + name="test_model", |
| 3435 | + kind=IncrementalByTimeRangeKind(time_column="ds"), |
| 3436 | + query=parse_one("SELECT 1, ds FROM parent_tbl"), |
| 3437 | + ) |
| 3438 | + |
| 3439 | + # Create source snapshot with intervals |
| 3440 | + source_snapshot = make_snapshot(model, virtual_environment_mode=VirtualEnvironmentMode.DEV_ONLY) |
| 3441 | + source_snapshot.add_interval("2020-01-01", "2020-01-03") |
| 3442 | + source_snapshot.add_interval("2020-01-05", "2020-01-07") |
| 3443 | + |
| 3444 | + # Create target snapshot with different fingerprint and virtual_environment_mode DEV_ONLY |
| 3445 | + target_snapshot = make_snapshot(model, virtual_environment_mode=VirtualEnvironmentMode.DEV_ONLY) |
| 3446 | + target_snapshot.fingerprint = SnapshotFingerprint( |
| 3447 | + data_hash="different", metadata_hash="different", parent_data_hash="different" |
| 3448 | + ) |
| 3449 | + target_snapshot.categorize_as( |
| 3450 | + SnapshotChangeCategory.FORWARD_ONLY |
| 3451 | + ) # This is a no-rebuild category |
| 3452 | + |
| 3453 | + # Ensure snapshot is paused |
| 3454 | + target_snapshot.unpaused_ts = None |
| 3455 | + |
| 3456 | + # When change category is no-rebuild, intervals should be merged regardless of virtual_environment_mode |
| 3457 | + target_snapshot.merge_intervals(source_snapshot) |
| 3458 | + |
| 3459 | + assert target_snapshot.intervals == [ |
| 3460 | + (to_timestamp("2020-01-01"), to_timestamp("2020-01-04")), |
| 3461 | + (to_timestamp("2020-01-05"), to_timestamp("2020-01-08")), |
| 3462 | + ] |
| 3463 | + |
| 3464 | + |
| 3465 | +@pytest.mark.parametrize( |
| 3466 | + "virtual_env_mode,is_deployable,expected_uses_name_as_is", |
| 3467 | + [ |
| 3468 | + (VirtualEnvironmentMode.DEV_ONLY, True, True), |
| 3469 | + (VirtualEnvironmentMode.DEV_ONLY, False, False), |
| 3470 | + (VirtualEnvironmentMode.FULL, True, False), |
| 3471 | + (VirtualEnvironmentMode.FULL, False, False), |
| 3472 | + ], |
| 3473 | +) |
| 3474 | +def test_table_name_virtual_environment_mode( |
| 3475 | + make_snapshot, |
| 3476 | + virtual_env_mode: VirtualEnvironmentMode, |
| 3477 | + is_deployable: bool, |
| 3478 | + expected_uses_name_as_is: bool, |
| 3479 | +): |
| 3480 | + model = SqlModel( |
| 3481 | + name="my_schema.my_model", |
| 3482 | + kind=IncrementalByTimeRangeKind(time_column="ds"), |
| 3483 | + query=parse_one("SELECT 1, ds"), |
| 3484 | + ) |
| 3485 | + |
| 3486 | + snapshot = make_snapshot(model, virtual_environment_mode=virtual_env_mode) |
| 3487 | + snapshot.categorize_as(SnapshotChangeCategory.BREAKING) |
| 3488 | + |
| 3489 | + table_name_result = snapshot.table_name(is_deployable=is_deployable) |
| 3490 | + |
| 3491 | + if expected_uses_name_as_is: |
| 3492 | + assert table_name_result == '"my_schema"."my_model"' |
| 3493 | + else: |
| 3494 | + # Should contain the versioned table name with schema prefix |
| 3495 | + assert "sqlmesh__my_schema" in table_name_result |
| 3496 | + assert "my_schema__my_model" in table_name_result |
| 3497 | + if is_deployable: |
| 3498 | + assert table_name_result.endswith(snapshot.version) |
| 3499 | + else: |
| 3500 | + assert table_name_result.endswith(f"{snapshot.dev_version}__dev") |
0 commit comments