Skip to content

Commit c735831

Browse files
committed
support on_table_exists=skip
implement table materialization option on_table_exists=skip to allow user to skip a model if the target relation already exists.
1 parent 34dd3ab commit c735831

File tree

4 files changed

+71
-11
lines changed

4 files changed

+71
-11
lines changed
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
kind: Features
2+
body: table materialization on_table_exists=skip option
3+
time: 2025-06-02T21:22:47.837474-04:00
4+
custom:
5+
Author: choyrim
6+
Issue: "479"
7+
PR: "481"

dbt/include/trino/macros/adapters.sql

Lines changed: 6 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -145,18 +145,15 @@
145145
{%- endif -%}
146146
{%- endmacro -%}
147147
148-
{% macro trino__create_table_as(temporary, relation, sql, replace=False) -%}
148+
{% macro trino__create_table_as(temporary, relation, sql, on_exists=None) -%}
149149
150-
{%- if replace -%}
151-
{%- set or_replace = ' or replace' -%}
152-
{%- else -%}
153-
{%- set or_replace = '' -%}
154-
{%- endif -%}
150+
{%- set or_replace = ' or replace' if on_exists == 'replace' else '' -%}
151+
{%- set if_not_exists = ' if not exists' if on_exists == 'skip' else '' -%}
155152
156153
{%- set contract_config = config.get('contract') -%}
157154
{%- if contract_config.enforced -%}
158155
159-
create{{ or_replace }} table
156+
create{{ or_replace }} table{{ if_not_exists }}
160157
{{ relation }}
161158
{{ get_table_columns_and_constraints() }}
162159
{{ get_assert_columns_equivalent(sql) }}
@@ -173,14 +170,14 @@
173170
174171
{%- else %}
175172
176-
create{{ or_replace }} table {{ relation }}
173+
create{{ or_replace }} table{{ if_not_exists }} {{ relation }}
177174
{{ comment(model.get('description')) }}
178175
{{ properties(temporary) }}
179176
as (
180177
{{ sql }}
181178
);
182179
183-
{%- endif %}
180+
{%- endif %}
184181
{% endmacro %}
185182
186183

dbt/include/trino/macros/materializations/table.sql

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{% materialization table, adapter = 'trino' %}
22
{%- set on_table_exists = config.get('on_table_exists', 'rename') -%}
3-
{% if on_table_exists not in ['rename', 'drop', 'replace'] %}
3+
{% if on_table_exists not in ['rename', 'drop', 'replace', 'skip'] %}
44
{%- set log_message = 'Invalid value for on_table_exists (%s) specified. Setting default value (%s).' % (on_table_exists, 'rename') -%}
55
{% do log(log_message) %}
66
{%- set on_table_exists = 'rename' -%}
@@ -84,7 +84,14 @@
8484
{% elif on_table_exists == 'replace' %}
8585
{#-- build model #}
8686
{% call statement('main') -%}
87-
{{ create_table_as(False, target_relation, sql, True) }}
87+
{{ create_table_as(False, target_relation, sql, 'replace') }}
8888
{%- endcall %}
89+
90+
{% elif on_table_exists == 'skip' %}
91+
{#-- build model #}
92+
{% call statement('main') -%}
93+
{{ create_table_as(False, target_relation, sql, 'skip') }}
94+
{%- endcall %}
95+
8996
{% endif %}
9097
{% endmacro %}

tests/functional/adapter/materialization/test_on_table_exists.py

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -309,3 +309,52 @@ class TestOnTableExistsReplaceDeltaIncrementalFullRefresh(
309309
BaseOnTableExistsReplaceIncrementalFullRefresh
310310
):
311311
pass
312+
313+
314+
class TestOnTableExistsSkip(BaseOnTableExists):
315+
"""
316+
Testing on_table_exists = `skip` configuration for table materialization,
317+
using dbt seed, run and tests commands and validate data load correctness.
318+
"""
319+
320+
@pytest.fixture(scope="class")
321+
def project_config_update(self):
322+
return {
323+
"name": "table_rename",
324+
"models": {"+materialized": "table", "+on_table_exists": "skip"},
325+
"seeds": {
326+
"+column_types": {"some_date": "timestamp(6)"},
327+
},
328+
}
329+
330+
# The actual sequence of dbt commands and assertions
331+
# pytest will take care of all "setup" + "teardown"
332+
def test_run_seed_test(self, project):
333+
# seed seeds
334+
results = run_dbt(["seed"], expect_pass=True)
335+
assert len(results) == 1
336+
# run models two times to check on_table_exists = 'skip'
337+
results, logs = run_dbt_and_capture(["--debug", "run"], expect_pass=True)
338+
assert len(results) == 1
339+
assert (
340+
f'create table if not exists "{project.database}"."{project.test_schema}"."materialization"'
341+
in logs
342+
)
343+
assert "alter table" not in logs
344+
assert "drop table" not in logs
345+
assert "or replace" not in logs
346+
results, logs = run_dbt_and_capture(["--debug", "run"], expect_pass=True)
347+
assert len(results) == 1
348+
assert (
349+
f'create table if not exists "{project.database}"."{project.test_schema}"."materialization"'
350+
in logs
351+
)
352+
assert "alter table" not in logs
353+
assert "drop table" not in logs
354+
assert "or replace" not in logs
355+
# test tests
356+
results = run_dbt(["test"], expect_pass=True)
357+
assert len(results) == 3
358+
359+
# check if the data was loaded correctly
360+
check_relations_equal(project.adapter, ["seed", "materialization"])

0 commit comments

Comments
 (0)