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

adding transient dynamic table capabilities #1210

Open
wants to merge 12 commits into
base: main
Choose a base branch
from
6 changes: 6 additions & 0 deletions .changes/unreleased/Features-20241017-103843.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
kind: Features
body: Adding capability to create transient dynamic tables.
time: 2024-10-17T10:38:43.820283+01:00
custom:
Author: jhsb25
Issue: "1089"
13 changes: 12 additions & 1 deletion dbt/adapters/snowflake/impl.py
Original file line number Diff line number Diff line change
Expand Up @@ -93,7 +93,18 @@ def _behavior_flags(self) -> List[BehaviorFlag]:
"prevent unnecessary latency for other users."
),
"docs_url": "https://docs.getdbt.com/reference/resource-configs/snowflake-configs#iceberg-table-format",
}
},
{
"name": "default_dynamic_tables_to_transient",
"default": False,
"description": (
"Standard Tables are created as transient by default. This can be overridden "
"by setting transient: false in the model config. This saves on storages costs "
"and for most users is the right decision. We are changing the default behavior for "
"dynamic tables to align with this."
"Read more: https://docs.getdbt.com/reference/resource-configs/snowflake-configs#transient-tables"
),
},
]

@classmethod
Expand Down
6 changes: 4 additions & 2 deletions dbt/adapters/snowflake/relation.py
Original file line number Diff line number Diff line change
Expand Up @@ -147,7 +147,9 @@ def can_be_renamed(self) -> bool:
"""
return self.type in self.renameable_relations and not self.is_iceberg_format

def get_ddl_prefix_for_create(self, config: RelationConfig, temporary: bool) -> str:
def get_ddl_prefix_for_create(
self, config: RelationConfig, temporary: bool, transient_default: bool = True
) -> str:
"""
This macro renders the appropriate DDL prefix during the create_table_as
macro. It decides based on mutually exclusive table configuration options:
Expand Down Expand Up @@ -187,7 +189,7 @@ def get_ddl_prefix_for_create(self, config: RelationConfig, temporary: bool) ->

# Always supply transient on table create DDL unless user specifically sets
# transient to false or unset. Might as well update the object attribute too!
elif transient_explicitly_set_true or config.get("transient", True):
elif transient_explicitly_set_true or config.get("transient", transient_default):
return "transient"
else:
return ""
Expand Down
1 change: 0 additions & 1 deletion dbt/adapters/snowflake/relation_configs/dynamic_table.py
Original file line number Diff line number Diff line change
Expand Up @@ -105,7 +105,6 @@ def parse_relation_config(cls, relation_config: RelationConfig) -> Dict[str, Any
@classmethod
def parse_relation_results(cls, relation_results: RelationResults) -> Dict[str, Any]:
dynamic_table: "agate.Row" = relation_results["dynamic_table"].rows[0]

config_dict = {
"name": dynamic_table.get("name"),
"schema_name": dynamic_table.get("schema_name"),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -40,8 +40,15 @@
-- Returns:
-- A valid DDL statement which will result in a new dynamic standard table.
-#}
{%- if adapter.behavior.default_dynamic_tables_to_transient -%}
{%- set transient = True -%}
{%- else -%}
{%- set transient = False -%}
{%- endif -%}

{%- set materialization_prefix = relation.get_ddl_prefix_for_create(config.model.config, False, transient) -%}

create dynamic table {{ relation }}
create {{ materialization_prefix }} dynamic table {{ relation }}
target_lag = '{{ dynamic_table.target_lag }}'
warehouse = {{ dynamic_table.snowflake_warehouse }}
{{ optional('refresh_mode', dynamic_table.refresh_mode) }}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,15 @@
-- A valid DDL statement which will result in a new dynamic standard table.
-#}

create or replace dynamic table {{ relation }}
{%- if adapter.behavior.default_dynamic_tables_to_transient -%}
{%- set transient = True -%}
{%- else -%}
{%- set transient = False -%}
{%- endif -%}

{%- set materialization_prefix = relation.get_ddl_prefix_for_create(config.model.config, False, transient) -%}

create or replace {{ materialization_prefix }} dynamic table {{ relation }}
target_lag = '{{ dynamic_table.target_lag }}'
warehouse = {{ dynamic_table.snowflake_warehouse }}
{{ optional('refresh_mode', dynamic_table.refresh_mode) }}
Expand Down
13 changes: 13 additions & 0 deletions tests/functional/relation_tests/dynamic_table_tests/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,12 +17,25 @@
"""


DYNAMIC_TRANSIENT_TABLE = """
{{ config(
materialized='dynamic_table',
snowflake_warehouse='DBT_TESTING',
target_lag='2 minutes',
refresh_mode='INCREMENTAL',
transient=True,
) }}
select * from {{ ref('my_seed') }}
"""


DYNAMIC_TABLE_DOWNSTREAM = """
{{ config(
materialized='dynamic_table',
snowflake_warehouse='DBT_TESTING',
target_lag='DOWNSTREAM',
refresh_mode='INCREMENTAL',
transient=False,
) }}
select * from {{ ref('my_seed') }}
"""
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ def models(self):
my_models = {
"my_dynamic_table.sql": models.DYNAMIC_TABLE,
"my_dynamic_table_downstream.sql": models.DYNAMIC_TABLE_DOWNSTREAM,
"my_dynamic_transient_table.sql": models.DYNAMIC_TRANSIENT_TABLE,
}
if self.iceberg:
my_models.update(
Expand All @@ -36,6 +37,9 @@ def test_dynamic_table_full_refresh(self, project):
run_dbt(["run", "--full-refresh"])
assert query_relation_type(project, "my_dynamic_table") == "dynamic_table"
assert query_relation_type(project, "my_dynamic_table_downstream") == "dynamic_table"
assert (
query_relation_type(project, "my_dynamic_transient_table") == "dynamic_table_transient"
)
if self.iceberg:
assert query_relation_type(project, "my_dynamic_iceberg_table") == "dynamic_table"

Expand All @@ -46,3 +50,18 @@ class TestBasicIcebergOn(TestBasic):
@pytest.fixture(scope="class")
def project_config_update(self):
return {"flags": {"enable_iceberg_materializations": True}}


class TestDefaultTransient(TestBasic):

@pytest.fixture(scope="class")
def project_config_update(self):
return {"flags": {"default_dynamic_tables_to_transient": True}}

def test_dynamic_table_full_refresh(self, project):
run_dbt(["run", "--full-refresh"])
assert (
query_relation_type(project, "my_dynamic_transient_table") == "dynamic_table_transient"
)
assert query_relation_type(project, "my_dynamic_table_downstream") == "dynamic_table"
assert query_relation_type(project, "my_dynamic_table") == "dynamic_table_transient"
Original file line number Diff line number Diff line change
Expand Up @@ -53,8 +53,8 @@ def uses_iceberg(self) -> bool:

relations = [
Model(models.VIEW, "view"),
Model(models.TABLE, "table", "default"),
Model(models.INCREMENTAL_TABLE, "table", "default", is_incremental=True),
Model(models.TABLE, "table_transient", "default"),
Model(models.INCREMENTAL_TABLE, "table_transient", "default", is_incremental=True),
Model(models.DYNAMIC_TABLE, "dynamic_table", "default"),
Model(models.ICEBERG_TABLE, "table", "iceberg"),
Model(models.INCREMENTAL_ICEBERG_TABLE, "table", "iceberg", is_incremental=True),
Expand Down
2 changes: 1 addition & 1 deletion tests/functional/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ def query_relation_type(project, name: str) -> Optional[str]:
select
case table_type
when 'BASE TABLE' then iff(is_dynamic = 'YES', 'dynamic_table', 'table')
|| iff(is_transient = 'YES', '_transient', '')
when 'VIEW' then 'view'
when 'EXTERNAL TABLE' then 'external_table'
end as relation_type
Expand All @@ -25,7 +26,6 @@ def query_relation_type(project, name: str) -> Optional[str]:
and table_catalog like '{relation.database.upper()}'
"""
results = project.run_sql(sql, fetch="all")

assert len(results) > 0, f"Relation {relation} not found"
assert len(results) == 1, f"Multiple relations found"

Expand Down
Loading