Skip to content

Commit 3b48ab2

Browse files
Merge pull request #267 from microsoft/v1.8.2
Version 1.8.2
2 parents 6b92392 + c08d4d0 commit 3b48ab2

File tree

5 files changed

+143
-5
lines changed

5 files changed

+143
-5
lines changed

dbt/include/synapse/macros/materializations/snapshots/snapshot.sql

Lines changed: 137 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -59,3 +59,140 @@
5959
{{ dropTempTable }}
6060
{%- endcall %}
6161
{% endmacro %}
62+
{% materialization snapshot, adapter='synapse' %}
63+
{#
64+
Synapse-specific snapshot materialization.
65+
66+
Purpose:
67+
This materialization is designed to handle snapshotting in Azure Synapse Analytics.
68+
It manages the creation of temporary tables, the application of snapshot strategies,
69+
and the finalization of the target table.
70+
71+
Configuration Options:
72+
- `strategy`: The snapshot strategy to use (e.g., 'timestamp', 'check').
73+
- `unique_key`: The unique key for identifying records in the snapshot.
74+
- `grants`: Permissions to apply to the target table after creation.
75+
76+
Usage Example:
77+
Configure the snapshot in your model file:
78+
```
79+
{{
80+
config(
81+
materialized='snapshot',
82+
strategy='timestamp',
83+
unique_key='id',
84+
grants=[{'role': 'db_owner', 'privileges': ['select']}]
85+
)
86+
}}
87+
```
88+
#}
89+
{%- set config = model['config'] -%}
90+
{%- set target_table = model.get('alias', model.get('name')) -%}
91+
{%- set strategy_name = config.get('strategy') -%}
92+
{%- set unique_key = config.get('unique_key') %}
93+
-- grab current tables grants config for comparision later on
94+
{%- set grant_config = config.get('grants') -%}
95+
96+
{% set target_relation_exists, target_relation = get_or_create_relation(
97+
database=model.database,
98+
schema=model.schema,
99+
identifier=target_table,
100+
type='table') -%}
101+
102+
{%- if not target_relation.is_table -%}
103+
{% do exceptions.relation_wrong_type(target_relation, 'table') %}
104+
{%- endif -%}
105+
106+
{{ run_hooks(pre_hooks, inside_transaction=False) }}
107+
{{ run_hooks(pre_hooks, inside_transaction=True) }}
108+
109+
{% set strategy_macro = strategy_dispatch(strategy_name) %}
110+
{% set strategy = strategy_macro(model, "snapshotted_data", "source_data", config, target_relation_exists) %}
111+
112+
{% set temp_snapshot_relation_exists, temp_snapshot_relation = get_or_create_relation(
113+
database=model.database,
114+
schema=model.schema,
115+
identifier=target_table+"_snapshot_staging_temp_view",
116+
type='view') -%}
117+
118+
-- Create a temporary view to manage if user SQl uses CTE
119+
{% set temp_snapshot_relation_sql = model['compiled_code'] %}
120+
{{ adapter.drop_relation(temp_snapshot_relation) }}
121+
122+
{% call statement('create temp_snapshot_relation') -%}
123+
{{ get_create_view_as_sql(temp_snapshot_relation, temp_snapshot_relation_sql) }}
124+
{%- endcall %}
125+
126+
{% if not target_relation_exists %}
127+
128+
{% set build_sql = build_snapshot_table(strategy, temp_snapshot_relation) %}
129+
130+
-- naming a temp relation
131+
{% set tmp_relation_view = target_relation.incorporate(path={"identifier": target_relation.identifier ~ '__dbt_tmp_vw'}, type='view')-%}
132+
-- Fabric & Synapse adapters use temp relation because of lack of CTE support for CTE in CTAS, Insert
133+
-- drop temp relation if exists
134+
{{ adapter.drop_relation(tmp_relation_view) }}
135+
{% set final_sql = get_create_table_as_sql(False, target_relation, build_sql) %}
136+
{{ adapter.drop_relation(tmp_relation_view) }}
137+
138+
{% else %}
139+
140+
{{ adapter.valid_snapshot_target(target_relation) }}
141+
{% set staging_table = build_snapshot_staging_table(strategy, temp_snapshot_relation, target_relation) %}
142+
-- this may no-op if the database does not require column expansion
143+
{% do adapter.expand_target_column_types(from_relation=staging_table,
144+
to_relation=target_relation) %}
145+
{% set missing_columns = adapter.get_missing_columns(staging_table, target_relation)
146+
| rejectattr('name', 'equalto', 'dbt_change_type')
147+
| rejectattr('name', 'equalto', 'DBT_CHANGE_TYPE')
148+
| rejectattr('name', 'equalto', 'dbt_unique_key')
149+
| rejectattr('name', 'equalto', 'DBT_UNIQUE_KEY')
150+
| list %}
151+
{% if missing_columns|length > 0 %}
152+
{{log("Missing columns length is: "~ missing_columns|length)}}
153+
{% do create_columns(target_relation, missing_columns) %}
154+
{% endif %}
155+
{% set source_columns = adapter.get_columns_in_relation(staging_table)
156+
| rejectattr('name', 'equalto', 'dbt_change_type')
157+
| rejectattr('name', 'equalto', 'DBT_CHANGE_TYPE')
158+
| rejectattr('name', 'equalto', 'dbt_unique_key')
159+
| rejectattr('name', 'equalto', 'DBT_UNIQUE_KEY')
160+
| list %}
161+
{% set quoted_source_columns = [] %}
162+
{% for column in source_columns %}
163+
{% do quoted_source_columns.append(adapter.quote(column.name)) %}
164+
{% endfor %}
165+
166+
{% set final_sql = snapshot_merge_sql(
167+
target = target_relation,
168+
source = staging_table,
169+
insert_cols = quoted_source_columns
170+
)
171+
%}
172+
{% endif %}
173+
174+
{% call statement('main') %}
175+
{{ final_sql }}
176+
{% endcall %}
177+
178+
{{ adapter.drop_relation(temp_snapshot_relation) }}
179+
{% set should_revoke = should_revoke(target_relation_exists, full_refresh_mode=False) %}
180+
{% do apply_grants(target_relation, grant_config, should_revoke=should_revoke) %}
181+
182+
{% do persist_docs(target_relation, model) %}
183+
184+
{% if not target_relation_exists %}
185+
{% do create_indexes(target_relation) %}
186+
{% endif %}
187+
188+
{{ run_hooks(post_hooks, inside_transaction=True) }}
189+
{{ adapter.commit() }}
190+
191+
{% if staging_table is defined %}
192+
{% do post_snapshot(staging_table) %}
193+
{% endif %}
194+
195+
{{ run_hooks(post_hooks, inside_transaction=False) }}
196+
{{ return({'relations': [target_relation]}) }}
197+
198+
{% endmaterialization %}

dev_requirements.txt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
# install latest changes in dbt-core
22
# TODO: how to automate switching from develop to version branches?
33
git+https://github.com/dbt-labs/dbt-core.git#egg=dbt-core&subdirectory=core
4-
git+https://github.com/dbt-labs/dbt-adapters.git
4+
git+https://github.com/dbt-labs/dbt-adapters.git#egg=dbt-adapters&subdirectory=dbt-adapters
55
git+https://github.com/dbt-labs/dbt-adapters.git#subdirectory=dbt-tests-adapter
66
git+https://github.com/dbt-labs/dbt-common.git
77

setup.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@
1515
"Anders Swanson",
1616
"Sam Debruyn",
1717
]
18-
dbt_fabric_requirement = "dbt-fabric>=1.8.6,<2.0"
18+
dbt_fabric_requirement = "dbt-fabric>=1.8.0,<1.9.0"
1919
description = """An Azure Synapse adapter plugin for dbt"""
2020

2121
this_directory = os.path.abspath(os.path.dirname(__file__))
@@ -36,6 +36,7 @@ def _dbt_synapse_version():
3636

3737
package_version = _dbt_synapse_version()
3838

39+
3940
class VerifyVersionCommand(install):
4041
"""Custom command to verify that the git tag matches our version"""
4142

tests/functional/adapter/test_concurrency.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,4 +33,4 @@ def test_concurrency(self, project):
3333
check_table_does_not_exist(project.adapter, "invalid")
3434
check_table_does_not_exist(project.adapter, "skip")
3535

36-
assert "PASS=5 WARN=0 ERROR=1 SKIP=1 TOTAL=7" in output
36+
assert "PASS=5 WARN=0 ERROR=1 SKIP=1 NO-OP=0 TOTAL=7" in output

tests/functional/adapter/test_docs.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ class TestDocsGenerateSynapse(BaseDocsGenerate):
1919
def expected_catalog(self, project):
2020
return base_expected_catalog(
2121
project,
22-
role="dbt-synapse-ci",
22+
role="dbo",
2323
id_type="int",
2424
text_type="varchar",
2525
time_type="datetime2",
@@ -34,7 +34,7 @@ class TestDocsGenReferencesSynapse(BaseDocsGenReferences):
3434
def expected_catalog(self, project):
3535
return expected_references_catalog(
3636
project,
37-
role="dbt-synapse-ci",
37+
role="dbo",
3838
id_type="int",
3939
text_type="varchar",
4040
time_type="datetime2",

0 commit comments

Comments
 (0)