Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Change table materialization logic when on_table_exists = 'rename' #425

Merged
merged 2 commits into from
Aug 2, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions .changes/unreleased/Fixes-20240729-101114.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
kind: Fixes
body: Change table materialization logic when on_table_exists = 'rename'
time: 2024-07-29T10:11:14.451171+02:00
custom:
Author: hovaesco
Issue: "423"
PR: "425"
29 changes: 18 additions & 11 deletions dbt/include/trino/macros/materializations/table.sql
Original file line number Diff line number Diff line change
Expand Up @@ -48,20 +48,27 @@
{% macro on_table_exists_logic(on_table_exists, existing_relation, intermediate_relation, backup_relation, target_relation) -%}
{#-- Create table with given `on_table_exists` mode #}
{% if on_table_exists == 'rename' %}
{#-- build modeldock #}
{% call statement('main') -%}
{{ create_table_as(False, intermediate_relation, sql) }}
{%- endcall %}

{#-- cleanup #}
{% if existing_relation is not none %}
{{ adapter.rename_relation(existing_relation, backup_relation) }}
{% endif %}
{#-- table does not exists #}
{% if existing_relation is none %}
{% call statement('main') -%}
{{ create_table_as(False, target_relation, sql) }}
{%- endcall %}

{#-- table does exists #}
{% else %}
{#-- build modeldock #}
{% call statement('main') -%}
{{ create_table_as(False, intermediate_relation, sql) }}
{%- endcall %}

{{ adapter.rename_relation(intermediate_relation, target_relation) }}
{#-- cleanup #}
{{ adapter.rename_relation(existing_relation, backup_relation) }}
{{ adapter.rename_relation(intermediate_relation, target_relation) }}

{#-- finally, drop the existing/backup relation after the commit #}
{{ drop_relation_if_exists(backup_relation) }}
{#-- finally, drop the existing/backup relation after the commit #}
{{ drop_relation_if_exists(backup_relation) }}
{% endif %}

{% elif on_table_exists == 'drop' %}
{#-- cleanup #}
Expand Down
1 change: 1 addition & 0 deletions docker/starburst/catalog/tpch.properties
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
connector.name=tpch
1 change: 1 addition & 0 deletions docker/trino/catalog/tpch.properties
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
connector.name=tpch
110 changes: 110 additions & 0 deletions tests/functional/adapter/materialization/test_on_table_exists.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,116 @@ def models(self):
}


class TestOnTableExistsRename(BaseOnTableExists):
"""
Testing on_table_exists = `rename` configuration for table materialization,
using dbt seed, run and tests commands and validate data load correctness.
"""

@pytest.fixture(scope="class")
def project_config_update(self):
return {
"name": "table_rename",
"models": {"+materialized": "table", "+on_table_exists": "rename"},
"seeds": {
"+column_types": {"some_date": "timestamp(6)"},
},
}

# The actual sequence of dbt commands and assertions
# pytest will take care of all "setup" + "teardown"
def test_run_seed_test(self, project):
# seed seeds
results = run_dbt(["seed"], expect_pass=True)
assert len(results) == 1
# run models two times to check on_table_exists = 'rename'
results, logs = run_dbt_and_capture(["--debug", "run"], expect_pass=True)
assert len(results) == 1
assert (
f'create table "{project.database}"."{project.test_schema}"."materialization"' in logs
)
assert "alter table" not in logs
results, logs = run_dbt_and_capture(["--debug", "run"], expect_pass=True)
assert len(results) == 1
assert (
f'create table "{project.database}"."{project.test_schema}"."materialization__dbt_tmp"'
in logs
)
assert (
f'alter table "{project.database}"."{project.test_schema}"."materialization" rename to "{project.database}"."{project.test_schema}"."materialization__dbt_backup"'
in logs
)
assert (
f'alter table "{project.database}"."{project.test_schema}"."materialization__dbt_tmp" rename to "{project.database}"."{project.test_schema}"."materialization"'
in logs
)
assert (
f'drop table if exists "{project.database}"."{project.test_schema}"."materialization__dbt_backup"'
in logs
)
# test tests
results = run_dbt(["test"], expect_pass=True)
assert len(results) == 3

# check if the data was loaded correctly
check_relations_equal(project.adapter, ["seed", "materialization"])


class TestOnTableExistsRenameIncrementalFullRefresh(BaseOnTableExists):
"""
Testing on_table_exists = `rename` configuration for incremental materialization and full refresh flag,
using dbt seed, run and tests commands and validate data load correctness.
"""

@pytest.fixture(scope="class")
def project_config_update(self):
return {
"name": "table_rename",
"models": {"+materialized": "incremental", "+on_table_exists": "rename"},
"seeds": {
"+column_types": {"some_date": "timestamp(6)"},
},
}

# The actual sequence of dbt commands and assertions
# pytest will take care of all "setup" + "teardown"
def test_run_seed_test(self, project):
# seed seeds
results = run_dbt(["seed"], expect_pass=True)
assert len(results) == 1
# run models two times to check on_table_exists = 'rename'
results, logs = run_dbt_and_capture(["--debug", "run"], expect_pass=True)
assert (
f'create table "{project.database}"."{project.test_schema}"."materialization"' in logs
)
assert "alter table" not in logs
results, logs = run_dbt_and_capture(["--debug", "run", "--full-refresh"], expect_pass=True)
assert len(results) == 1
assert (
f'create table "{project.database}"."{project.test_schema}"."materialization__dbt_tmp"'
in logs
)
assert (
f'alter table "{project.database}"."{project.test_schema}"."materialization" rename to "{project.database}"."{project.test_schema}"."materialization__dbt_backup"'
in logs
)
assert (
f'alter table "{project.database}"."{project.test_schema}"."materialization__dbt_tmp" rename to "{project.database}"."{project.test_schema}"."materialization"'
in logs
)
assert (
f'drop table if exists "{project.database}"."{project.test_schema}"."materialization__dbt_backup"'
in logs
)
assert "create or replace view" not in logs
# test tests
results = run_dbt(["test"], expect_pass=True)
assert len(results) == 3

# check if the data was loaded correctly
check_relations_equal(project.adapter, ["seed", "materialization"])


class TestOnTableExistsDrop(BaseOnTableExists):
"""
Testing on_table_exists = `drop` configuration for table materialization,
Expand Down
Loading