|
7 | 7 |
|
8 | 8 | from sqlmesh import Context |
9 | 9 | from sqlmesh.core.config import ModelDefaultsConfig |
| 10 | +from sqlmesh.core.engine_adapter import DuckDBEngineAdapter |
10 | 11 | from sqlmesh.core.model.kind import DbtCustomKind |
11 | 12 | from sqlmesh.dbt.context import DbtContext |
12 | 13 | from sqlmesh.dbt.manifest import ManifestHelper |
@@ -719,3 +720,58 @@ def test_custom_materialization_lineage_tracking(copy_to_temp_path: t.Callable): |
719 | 720 | # Dev and prod should have the same data as they share physical data |
720 | 721 | assert dev_analytics_result["count"][0] == prod_analytics_result["count"][0] |
721 | 722 | assert dev_analytics_result["unique_waiters"][0] == prod_analytics_result["unique_waiters"][0] |
| 723 | + |
| 724 | + |
| 725 | +@pytest.mark.xdist_group("dbt_manifest") |
| 726 | +def test_custom_materialization_grants(copy_to_temp_path: t.Callable, mocker): |
| 727 | + path = copy_to_temp_path("tests/fixtures/dbt/sushi_test") |
| 728 | + temp_project = path[0] |
| 729 | + |
| 730 | + models_dir = temp_project / "models" |
| 731 | + models_dir.mkdir(parents=True, exist_ok=True) |
| 732 | + |
| 733 | + grants_model_content = """ |
| 734 | +{{ config( |
| 735 | + materialized='custom_incremental', |
| 736 | + grants={ |
| 737 | + 'select': ['user1', 'user2'], |
| 738 | + 'insert': ['writer'] |
| 739 | + } |
| 740 | +) }} |
| 741 | +
|
| 742 | +SELECT |
| 743 | + CURRENT_TIMESTAMP as created_at, |
| 744 | + 1 as id, |
| 745 | + 'grants_test' as test_type |
| 746 | +""".strip() |
| 747 | + |
| 748 | + (models_dir / "test_grants_model.sql").write_text(grants_model_content) |
| 749 | + |
| 750 | + mocker.patch.object(DuckDBEngineAdapter, "SUPPORTS_GRANTS", True) |
| 751 | + mocker.patch.object(DuckDBEngineAdapter, "_get_current_grants_config", return_value={}) |
| 752 | + |
| 753 | + sync_grants_calls = [] |
| 754 | + |
| 755 | + def mock_sync_grants(*args, **kwargs): |
| 756 | + sync_grants_calls.append((args, kwargs)) |
| 757 | + |
| 758 | + mocker.patch.object(DuckDBEngineAdapter, "sync_grants_config", side_effect=mock_sync_grants) |
| 759 | + |
| 760 | + context = Context(paths=path) |
| 761 | + |
| 762 | + model = context.get_model("sushi.test_grants_model") |
| 763 | + assert isinstance(model.kind, DbtCustomKind) |
| 764 | + plan = context.plan(select_models=["sushi.test_grants_model"]) |
| 765 | + context.apply(plan) |
| 766 | + |
| 767 | + assert len(sync_grants_calls) == 1 |
| 768 | + args = sync_grants_calls[0][0] |
| 769 | + assert args |
| 770 | + |
| 771 | + table = args[0] |
| 772 | + grants_config = args[1] |
| 773 | + assert table.sql(dialect="duckdb") == "memory.sushi.test_grants_model" |
| 774 | + assert grants_config == { |
| 775 | + "select": ["user1", "user2"], |
| 776 | + "insert": ["writer"], |
| 777 | + } |
0 commit comments