Skip to content

Commit cc5c590

Browse files
b-percolin-rogers-dbtmikealfare
authored
ADAP-1254: Add row access policy and table_tag config for snowflake (#901)
Co-authored-by: Colin Rogers <[email protected]> Co-authored-by: Colin <[email protected]> Co-authored-by: Mike Alfare <[email protected]>
1 parent f38ece9 commit cc5c590

File tree

8 files changed

+411
-21
lines changed

8 files changed

+411
-21
lines changed
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
kind: Features
2+
body: Add row_access_policy and table_tag config for Snowflake models
3+
time: 2025-03-12T15:10:53.501206+01:00
4+
custom:
5+
Author: b-per
6+
Issue: "697"

dbt-snowflake/src/dbt/adapters/snowflake/impl.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,8 @@ class SnowflakeConfig(AdapterConfig):
5252
tmp_relation_type: Optional[str] = None
5353
merge_update_columns: Optional[str] = None
5454
target_lag: Optional[str] = None
55+
row_access_policy: Optional[str] = None
56+
table_tag: Optional[str] = None
5557

5658
# extended formats
5759
table_format: Optional[str] = None

dbt-snowflake/src/dbt/adapters/snowflake/relation_configs/dynamic_table.py

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,6 @@
99

1010
from dbt.adapters.snowflake.relation_configs.base import SnowflakeRelationConfigBase
1111

12-
1312
if TYPE_CHECKING:
1413
import agate
1514

@@ -58,6 +57,8 @@ class SnowflakeDynamicTableConfig(SnowflakeRelationConfigBase):
5857
snowflake_warehouse: str
5958
refresh_mode: Optional[RefreshMode] = RefreshMode.default()
6059
initialize: Optional[Initialize] = Initialize.default()
60+
row_access_policy: Optional[str] = None
61+
table_tag: Optional[str] = None
6162

6263
@classmethod
6364
def from_dict(cls, config_dict: Dict[str, Any]) -> Self:
@@ -76,6 +77,8 @@ def from_dict(cls, config_dict: Dict[str, Any]) -> Self:
7677
"snowflake_warehouse": config_dict.get("snowflake_warehouse"),
7778
"refresh_mode": config_dict.get("refresh_mode"),
7879
"initialize": config_dict.get("initialize"),
80+
"row_access_policy": config_dict.get("row_access_policy"),
81+
"table_tag": config_dict.get("table_tag"),
7982
}
8083

8184
return super().from_dict(kwargs_dict) # type:ignore
@@ -91,6 +94,10 @@ def parse_relation_config(cls, relation_config: RelationConfig) -> Dict[str, Any
9194
"snowflake_warehouse": relation_config.config.extra.get( # type:ignore
9295
"snowflake_warehouse"
9396
),
97+
"row_access_policy": relation_config.config.extra.get( # type:ignore
98+
"row_access_policy"
99+
),
100+
"table_tag": relation_config.config.extra.get("table_tag"), # type:ignore
94101
}
95102

96103
if refresh_mode := relation_config.config.extra.get("refresh_mode"): # type:ignore
@@ -113,6 +120,8 @@ def parse_relation_results(cls, relation_results: RelationResults) -> Dict[str,
113120
"target_lag": dynamic_table.get("target_lag"),
114121
"snowflake_warehouse": dynamic_table.get("warehouse"),
115122
"refresh_mode": dynamic_table.get("refresh_mode"),
123+
"row_access_policy": dynamic_table.get("row_access_policy"),
124+
"table_tag": dynamic_table.get("table_tag"),
116125
# we don't get initialize since that's a one-time scheduler attribute, not a DT attribute
117126
}
118127

dbt-snowflake/src/dbt/include/snowflake/macros/relations/dynamic_table/create.sql

Lines changed: 23 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -31,14 +31,16 @@
3131
A valid DDL statement which will result in a new dynamic info schema table.
3232
-#}
3333

34-
create dynamic table {{ relation }}
35-
target_lag = '{{ dynamic_table.target_lag }}'
36-
warehouse = {{ dynamic_table.snowflake_warehouse }}
37-
{{ optional('refresh_mode', dynamic_table.refresh_mode) }}
38-
{{ optional('initialize', dynamic_table.initialize) }}
39-
as (
40-
{{ sql }}
41-
)
34+
create dynamic table {{ relation }}
35+
target_lag = '{{ dynamic_table.target_lag }}'
36+
warehouse = {{ dynamic_table.snowflake_warehouse }}
37+
{{ optional('refresh_mode', dynamic_table.refresh_mode) }}
38+
{{ optional('initialize', dynamic_table.initialize) }}
39+
{{ optional('with row access policy', dynamic_table.row_access_policy, equals_char='') }}
40+
{{ optional('with tag', dynamic_table.table_tag, quote_char='(', equals_char='') }}
41+
as (
42+
{{ sql }}
43+
)
4244

4345
{%- endmacro %}
4446

@@ -62,16 +64,18 @@ create dynamic table {{ relation }}
6264

6365
{%- set catalog_relation = adapter.build_catalog_relation(config.model) -%}
6466

65-
create dynamic iceberg table {{ relation }}
66-
target_lag = '{{ dynamic_table.target_lag }}'
67-
warehouse = {{ dynamic_table.snowflake_warehouse }}
68-
{{ optional('external_volume', catalog_relation.external_volume, "'") }}
69-
catalog = 'SNOWFLAKE' -- required, and always SNOWFLAKE for built-in Iceberg tables
70-
base_location = '{{ catalog_relation.base_location }}'
71-
{{ optional('refresh_mode', dynamic_table.refresh_mode) }}
72-
{{ optional('initialize', dynamic_table.initialize) }}
73-
as (
74-
{{ sql }}
75-
)
67+
create dynamic iceberg table {{ relation }}
68+
target_lag = '{{ dynamic_table.target_lag }}'
69+
warehouse = {{ dynamic_table.snowflake_warehouse }}
70+
{{ optional('external_volume', catalog_relation.external_volume, "'") }}
71+
catalog = 'SNOWFLAKE' -- required, and always SNOWFLAKE for built-in Iceberg tables
72+
base_location = '{{ catalog_relation.base_location }}'
73+
{{ optional('refresh_mode', dynamic_table.refresh_mode) }}
74+
{{ optional('initialize', dynamic_table.initialize) }}
75+
{{ optional('row_access_policy', dynamic_table.row_access_policy) }}
76+
{{ optional('table_tag', dynamic_table.table_tag) }}
77+
as (
78+
{{ sql }}
79+
)
7680

7781
{%- endmacro %}

dbt-snowflake/src/dbt/include/snowflake/macros/relations/dynamic_table/replace.sql

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,8 @@ create or replace dynamic table {{ relation }}
4949
warehouse = {{ dynamic_table.snowflake_warehouse }}
5050
{{ optional('refresh_mode', dynamic_table.refresh_mode) }}
5151
{{ optional('initialize', dynamic_table.initialize) }}
52+
{{ optional('with row access policy', dynamic_table.row_access_policy, equals_char='') }}
53+
{{ optional('with tag', dynamic_table.table_tag, quote_char='(', equals_char='') }}
5254
as (
5355
{{ sql }}
5456
)
@@ -83,6 +85,8 @@ create or replace dynamic iceberg table {{ relation }}
8385
base_location = '{{ catalog_relation.base_location }}'
8486
{{ optional('refresh_mode', dynamic_table.refresh_mode) }}
8587
{{ optional('initialize', dynamic_table.initialize) }}
88+
{{ optional('row_access_policy', dynamic_table.row_access_policy) }}
89+
{{ optional('table_tag', dynamic_table.table_tag) }}
8690
as (
8791
{{ sql }}
8892
)

dbt-snowflake/src/dbt/include/snowflake/macros/relations/table/create.sql

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,9 @@ as (
7373

7474
{%- set copy_grants = config.get('copy_grants', default=false) -%}
7575

76+
{%- set row_access_policy = config.get('row_access_policy', default=none) -%}
77+
{%- set table_tag = config.get('table_tag', default=none) -%}
78+
7679
{%- set contract_config = config.get('contract') -%}
7780
{%- if contract_config.enforced -%}
7881
{{- get_assert_columns_equivalent(compiled_code) -}}
@@ -88,6 +91,8 @@ create or replace {{ transient }}table {{ relation }}
8891
{{ get_table_columns_and_constraints() }}
8992
{%- endif %}
9093
{% if copy_grants -%} copy grants {%- endif %}
94+
{% if row_access_policy -%} with row access policy {{ row_access_policy }} {%- endif %}
95+
{% if table_tag -%} with tag ({{ table_tag }}) {%- endif %}
9196
as (
9297
{%- if catalog_relation.cluster_by is not none -%}
9398
select * from (
@@ -126,6 +131,9 @@ alter table {{ relation }} resume recluster;
126131

127132
{%- set copy_grants = config.get('copy_grants', default=false) -%}
128133

134+
{%- set row_access_policy = config.get('row_access_policy', default=none) -%}
135+
{%- set table_tag = config.get('table_tag', default=none) -%}
136+
129137
{%- set contract_config = config.get('contract') -%}
130138
{%- if contract_config.enforced -%}
131139
{{- get_assert_columns_equivalent(compiled_code) -}}
@@ -142,6 +150,8 @@ create or replace iceberg table {{ relation }}
142150
{{ optional('external_volume', catalog_relation.external_volume, "'") }}
143151
catalog = 'SNOWFLAKE' -- required, and always SNOWFLAKE for built-in Iceberg tables
144152
base_location = '{{ catalog_relation.base_location }}'
153+
{% if row_access_policy -%} with row access policy {{ row_access_policy }} {%- endif %}
154+
{% if table_tag -%} with tag ({{ table_tag }}) {%- endif %}
145155
{% if copy_grants -%} copy grants {%- endif %}
146156
as (
147157
{%- if catalog_relation.cluster_by is not none -%}

dbt-snowflake/src/dbt/include/snowflake/macros/relations/view/create.sql

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
{% macro snowflake__create_view_as_with_temp_flag(relation, sql, is_temporary=False) -%}
22
{%- set secure = config.get('secure', default=false) -%}
33
{%- set copy_grants = config.get('copy_grants', default=false) -%}
4+
{%- set row_access_policy = config.get('row_access_policy', default=none) -%}
5+
{%- set table_tag = config.get('table_tag', default=none) -%}
46
{%- set sql_header = config.get('sql_header', none) -%}
57

68
{{ sql_header if sql_header is not none }}
@@ -19,7 +21,10 @@
1921
{%- if contract_config.enforced -%}
2022
{{ get_assert_columns_equivalent(sql) }}
2123
{%- endif %}
22-
{% if copy_grants -%} copy grants {%- endif %} as (
24+
{% if copy_grants -%} copy grants {%- endif %}
25+
{% if row_access_policy -%} with row access policy {{ row_access_policy }} {%- endif %}
26+
{% if table_tag -%} with tag ({{ table_tag }}) {%- endif %}
27+
as (
2328
{{ sql }}
2429
);
2530
{% endmacro %}

0 commit comments

Comments
 (0)