Skip to content

Commit 9a900af

Browse files
committed
fix: ignore grants for model kinds that don't support it
1 parent 78bcf8d commit 9a900af

5 files changed

Lines changed: 54 additions & 7 deletions

File tree

sqlmesh/core/model/kind.py

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -150,6 +150,11 @@ def full_history_restatement_only(self) -> bool:
150150
def supports_python_models(self) -> bool:
151151
return True
152152

153+
@property
154+
def supports_grants(self) -> bool:
155+
"""Whether this model kind supports grants configuration."""
156+
return self.is_materialized or self.is_view
157+
153158

154159
class ModelKindName(str, ModelKindMixin, Enum):
155160
"""The kind of model, determining how this data is computed and stored in the warehouse."""

sqlmesh/core/model/meta.py

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -442,11 +442,8 @@ def _root_validator(self) -> Self:
442442
)
443443

444444
# Validate grants configuration for model kind support
445-
if self.grants is not None:
446-
if kind.is_symbolic:
447-
raise ValueError(f"grants cannot be set for {kind.name} models")
448-
elif not (kind.is_materialized or kind.is_view):
449-
raise ValueError(f"grants field is not supported for {kind.name} models")
445+
if self.grants is not None and not kind.supports_grants:
446+
raise ValueError(f"grants cannot be set for {kind.name} models")
450447

451448
return self
452449

sqlmesh/dbt/model.py

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -644,11 +644,12 @@ def to_sqlmesh(
644644
if physical_properties:
645645
model_kwargs["physical_properties"] = physical_properties
646646

647+
kind = self.model_kind(context)
648+
647649
# A falsy grants config (None or {}) is considered as unmanaged per dbt semantics
648-
if self.grants:
650+
if self.grants and kind.supports_grants:
649651
model_kwargs["grants"] = self.grants
650652

651-
kind = self.model_kind(context)
652653
allow_partials = model_kwargs.pop("allow_partials", None)
653654
if allow_partials is None:
654655
# Set allow_partials to True for dbt models to preserve the original semantics.

tests/core/test_model.py

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,8 @@
5353
TimeColumn,
5454
ExternalKind,
5555
ViewKind,
56+
EmbeddedKind,
57+
SCDType2ByTimeKind,
5658
create_external_model,
5759
create_seed_model,
5860
create_sql_model,
@@ -11808,6 +11810,17 @@ def test_grants_invalid_model_kind_errors(kind: str):
1180811810
)
1180911811

1181011812

11813+
def test_model_kind_supports_grants():
11814+
assert FullKind().supports_grants is True
11815+
assert ViewKind().supports_grants is True
11816+
assert IncrementalByTimeRangeKind(time_column="ds").supports_grants is True
11817+
assert IncrementalByUniqueKeyKind(unique_key=["id"]).supports_grants is True
11818+
assert SCDType2ByTimeKind(unique_key=["id"]).supports_grants is True
11819+
11820+
assert EmbeddedKind().supports_grants is False
11821+
assert ExternalKind().supports_grants is False
11822+
11823+
1181111824
def test_grants_validation_no_grants():
1181211825
model = create_sql_model("db.table", parse_one("SELECT 1 AS id"), kind="FULL")
1181311826
assert model.grants is None

tests/dbt/test_model.py

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -870,3 +870,34 @@ def test_model_grants_engine_specific_bigquery() -> None:
870870
assert grants_config is not None
871871
assert grants_config["bigquery.dataviewer"] == ["user@domain.com"]
872872
assert grants_config["select"] == ["analyst@company.com"]
873+
874+
875+
def test_ephemeral_model_with_global_grants(create_empty_project):
876+
dbt_project_dir, dbt_model_dir = create_empty_project()
877+
878+
yaml = YAML()
879+
dbt_project_config = {
880+
"name": "test_project",
881+
"version": "1.0.0",
882+
"config-version": 2,
883+
"profile": "test",
884+
"model-paths": ["models"],
885+
"models": {"test_project": {"grants": {"select": ["reporter", "analyst"]}}},
886+
}
887+
dbt_project_file = dbt_project_dir / "dbt_project.yml"
888+
with open(dbt_project_file, "w", encoding="utf-8") as f:
889+
yaml.dump(dbt_project_config, f)
890+
891+
ephemeral_model_sql = """
892+
{{ config(materialized='ephemeral') }}
893+
SELECT 1 as id
894+
"""
895+
ephemeral_model_file = dbt_model_dir / "ephemeral_model.sql"
896+
with open(ephemeral_model_file, "w", encoding="utf-8") as f:
897+
f.write(ephemeral_model_sql)
898+
899+
context = Context(paths=dbt_project_dir)
900+
model = context.get_model('"local"."main"."ephemeral_model"')
901+
902+
assert model.kind.is_embedded
903+
assert model.grants is None # grants config is skipped for ephemeral / embedded models

0 commit comments

Comments
 (0)