Skip to content

Commit be0ab62

Browse files
Fix Snapshot behavior in new_record mode for records already marked as deleted (reopened) (#1174)
Co-authored-by: Colin Rogers <[email protected]>
1 parent 5348b5d commit be0ab62

File tree

4 files changed

+46
-1
lines changed

4 files changed

+46
-1
lines changed
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
kind: Fixes
2+
body: Fix Snapshot to avoid inserting redundant entries for records already marked as deleted
3+
time: 2025-06-26T11:26:59.01969873+02:00
4+
custom:
5+
Author: lpillmann
6+
Issue: "654"

dbt-adapters/src/dbt/include/global_project/macros/materializations/snapshots/helpers.sql

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -153,6 +153,14 @@
153153
left join deletes_source_data as source_data
154154
on {{ unique_key_join_on(strategy.unique_key, "snapshotted_data", "source_data") }}
155155
where {{ unique_key_is_null(strategy.unique_key, "source_data") }}
156+
157+
{%- if strategy.hard_deletes == 'new_record' %}
158+
and not (
159+
--avoid updating the record's valid_to if the latest entry is marked as deleted
160+
snapshotted_data.{{ columns.dbt_is_deleted }} = 'True'
161+
and snapshotted_data.{{ columns.dbt_valid_to }} is null
162+
)
163+
{%- endif %}
156164
)
157165
{%- endif %}
158166

@@ -182,6 +190,11 @@
182190
left join deletes_source_data as source_data
183191
on {{ unique_key_join_on(strategy.unique_key, "snapshotted_data", "source_data") }}
184192
where {{ unique_key_is_null(strategy.unique_key, "source_data") }}
193+
and not (
194+
--avoid inserting a new record if the latest one is marked as deleted
195+
snapshotted_data.{{ columns.dbt_is_deleted }} = 'True'
196+
and snapshotted_data.{{ columns.dbt_valid_to }} is null
197+
)
185198

186199
)
187200
{%- endif %}
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
kind: Under the Hood
2+
body: Improve test coverage for snapshots with new record mode
3+
time: 2025-06-27T09:22:11.280507585+02:00
4+
custom:
5+
Author: lpillmann
6+
Issue: "654"

dbt-tests-adapter/src/dbt/tests/adapter/simple_snapshot/new_record_timestamp_mode.py

Lines changed: 21 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -248,7 +248,7 @@ def test_snapshot_new_record_mode(
248248

249249
check_relations_equal(project.adapter, ["snapshot_actual", "snapshot_expected"])
250250

251-
project.run_sql(_delete_sql)
251+
project.run_sql(delete_sql)
252252

253253
results = run_dbt(["snapshot"])
254254
assert len(results) == 1
@@ -282,8 +282,28 @@ def test_snapshot_new_record_mode(
282282
)
283283
assert check_result[0][scd_id] != check_result[1][scd_id]
284284

285+
# run snapshot with the same source data; neither insert nor update should happen
286+
run_dbt(["snapshot"])
287+
assert len(results) == 1
288+
check_result = project.run_sql(_delete_check_sql, fetch="all")
289+
assert len(check_result) == 2
290+
291+
# insert the record back and run the snapshot again; update and insert expected
285292
project.run_sql(reinsert_sql)
286293
results = run_dbt(["snapshot"])
287294
assert len(results) == 1
288295
check_result = project.run_sql(reinsert_check_sql, fetch="all")
289296
assert len(check_result) == 3
297+
298+
# delete it once again and run the snapshot; update and insert expected
299+
project.run_sql(delete_sql)
300+
results = run_dbt(["snapshot"])
301+
assert len(results) == 1
302+
check_result = project.run_sql(_delete_check_sql, fetch="all")
303+
assert len(check_result) == 4
304+
305+
# run snapshot with the same source data; neither insert nor update should happen
306+
results = run_dbt(["snapshot"])
307+
assert len(results) == 1
308+
check_result = project.run_sql(_delete_check_sql, fetch="all")
309+
assert len(check_result) == 4

0 commit comments

Comments
 (0)