Skip to content
Merged
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
9 changes: 5 additions & 4 deletions src/sqlbuild/compiler/compile/_helpers/config/retention.py
Original file line number Diff line number Diff line change
Expand Up @@ -29,15 +29,16 @@ def resolve_time_travel_retention(
) -> ResolvedTimeTravelRetention:
"""Resolve target, materialization, and model retention precedence."""

table_backed: bool = isinstance(materialized, str) and MaterializationType.is_table_backed(
materialized=materialized
)
policy: AuthoredTimeTravelRetention | None = (
target_config.time_travel_retention if target_config is not None else None
target_config.time_travel_retention if table_backed and target_config is not None else None
)
source: TimeTravelRetentionSource | None = (
TimeTravelRetentionSource.TARGET if policy is not None else None
)
if isinstance(materialized, str) and MaterializationType.is_table_backed(
materialized=materialized
):
if table_backed and isinstance(materialized, str):
materialization_policy: AuthoredTimeTravelRetention | None = getattr(
materialization_defaults, materialized
).time_travel_retention
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -569,3 +569,11 @@ class DenseCompileFixtureTestCase:
model_count: int
expected_rule_misses: int
expected_tail_lineage_edges: int


@dataclass(frozen=True)
class TargetRetentionViewsTestCase:
description: str
view_header: str
expected_exit_code: int
expected_fragment: str
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
"""Integration coverage for target-level retention defaults with views."""

from __future__ import annotations

from pathlib import Path

import pytest

from sqlbuild.cli.commands.main.entrypoint.entry import main
from tests.integration.src.sqlbuild.cli.commands.main._test_types import (
TargetRetentionViewsTestCase,
)

_PROJECT_TOML: str = (
'name = "demo"\nadapter = "duckdb"\ndefault_target = "prod"\n\n'
'[connection]\ndatabase = "demo.duckdb"\n\n'
'[targets.prod]\ntime_travel_retention = "90d"\n'
)


@pytest.mark.parametrize(
"test_case",
[
TargetRetentionViewsTestCase(
description="view skips inherited target retention",
view_header="MODEL (materialized view);",
expected_exit_code=0,
expected_fragment="Project compiled",
),
TargetRetentionViewsTestCase(
description="explicit view retention is still rejected",
view_header="MODEL (materialized view, time_travel_retention 7d);",
expected_exit_code=1,
expected_fragment="managed time_travel_retention is not valid for views",
),
],
ids=lambda case: case.description,
)
def test_given_target_retention_default_when_compiling_views_then_only_explicit_retention_fails(
test_case: TargetRetentionViewsTestCase,
tmp_path: Path,
capsys: pytest.CaptureFixture[str],
) -> None:
(tmp_path / "models").mkdir()
(tmp_path / "sqlbuild_project.toml").write_text(_PROJECT_TOML, encoding="utf-8")
(tmp_path / "models" / "orders.sql").write_text(
"MODEL (materialized table);\n\nSELECT 1 AS order_id\n", encoding="utf-8"
)
(tmp_path / "models" / "order_view.sql").write_text(
f'{test_case.view_header}\n\nSELECT order_id FROM __ref("orders")\n', encoding="utf-8"
)

exit_code: int = main(["--project-dir", str(tmp_path), "--no-color", "compile"])
captured: str = "".join(capsys.readouterr())

assert exit_code == test_case.expected_exit_code, captured
assert test_case.expected_fragment in captured


if __name__ == "__main__":
pytest.main([__file__, "-vv"])
2 changes: 1 addition & 1 deletion tests/unit/src/sqlbuild/compiler/compile/_test_types.py
Original file line number Diff line number Diff line change
Expand Up @@ -92,7 +92,7 @@ class BuildModelRetentionConfigTestCase:
materialization_defaults: MaterializationDefaultsConfig
expected_desired_days: int | None
expected_unmanaged: bool
expected_source: TimeTravelRetentionSource
expected_source: TimeTravelRetentionSource | None


@dataclass(frozen=True)
Expand Down
24 changes: 24 additions & 0 deletions tests/unit/src/sqlbuild/compiler/compile/test_main.py
Original file line number Diff line number Diff line change
Expand Up @@ -4596,6 +4596,30 @@ def test_given_typed_hook_defaults_when_building_config_then_layers_values(
expected_unmanaged=True,
expected_source=TimeTravelRetentionSource.MODEL,
),
BuildModelRetentionConfigTestCase(
description="incremental model inherits target retention",
defaults=DefaultsConfig(materialized="incremental"),
model_header_values={},
target_config=TargetConfig(
time_travel_retention=AuthoredTimeTravelRetention(desired_days=90)
),
materialization_defaults=MaterializationDefaultsConfig(),
expected_desired_days=90,
expected_unmanaged=False,
expected_source=TimeTravelRetentionSource.TARGET,
),
BuildModelRetentionConfigTestCase(
description="view does not inherit target retention",
defaults=DefaultsConfig(materialized="view"),
model_header_values={},
target_config=TargetConfig(
time_travel_retention=AuthoredTimeTravelRetention(desired_days=90)
),
materialization_defaults=MaterializationDefaultsConfig(),
expected_desired_days=None,
expected_unmanaged=True,
expected_source=None,
),
],
ids=lambda case: case.description,
)
Expand Down
Loading