Skip to content

feat(snowflake): add transient tmp relation type for incremental models - #1894

Merged
colin-k-rogers merged 10 commits into
mainfrom
feat/snowflake-transient-tmp-relation
May 3, 2026
Merged

feat(snowflake): add transient tmp relation type for incremental models#1894
colin-k-rogers merged 10 commits into
mainfrom
feat/snowflake-transient-tmp-relation

Conversation

@b-per

@b-per b-per commented Apr 24, 2026

Copy link
Copy Markdown
Contributor

Summary

  • Adds tmp_relation_type: transient config option for Snowflake incremental models. Unlike session-scoped temporary tables, transient tables persist in the catalog, making them visible to Snowflake's native lineage tracking, while avoiding the 7-day fail-safe storage costs of permanent tables.
  • Adds snowflake__resolve_incremental_tmp_relation dispatch macro, allowing users to override the schema/database of the tmp relation — useful for avoiding name collisions when concurrent runs share the same target schema.
  • Allows transient alongside table for delete+insert and microbatch strategies; both are stable across multi-statement executions.

Note: Iceberg (catalog-linked database) incremental models continue to use a permanent table for the tmp relation — CLD schemas only support Iceberg tables, so neither temporary nor transient tables can be used there.

Closes #1893

Usage

-- Enable lineage tracking via transient tmp table
{{ config(
    materialized='incremental',
    unique_key='id',
    tmp_relation_type='transient',
) }}
-- Redirect tmp relation to a scratch schema to avoid collisions
{% macro snowflake__resolve_incremental_tmp_relation(tmp_relation) %}
  {{ return(tmp_relation.incorporate(schema='scratch')) }}
{% endmacro %}

Test plan

  • Existing unit tests pass (hatch run unit-tests)
  • New functional tests in test_incremental_transient.py pass against a real Snowflake connection (verifies transient DDL is emitted and row counts are correct)

Copilot AI review requested due to automatic review settings April 24, 2026 12:41
@b-per
b-per requested a review from a team as a code owner April 24, 2026 12:41
@cla-bot cla-bot Bot added the cla:yes The PR author has signed the CLA label Apr 24, 2026
@github-actions github-actions Bot added the community A PR, or an issue with a PR, from a community member label Apr 24, 2026

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR extends the Snowflake incremental materialization to support a new tmp_relation_type: transient option for staging relations, aiming to enable Snowflake lineage visibility while avoiding permanent-table fail-safe storage costs, and to improve behavior for Iceberg (catalog-linked) incremental models.

Changes:

  • Add a snowflake__create_table_transient_sql macro to create transient CTAS tables for incremental staging.
  • Update the incremental materialization to (a) select transient tmp relations for catalog-linked databases and (b) allow transient for delete+insert and microbatch strategies.
  • Introduce snowflake__resolve_incremental_tmp_relation to allow overriding where the incremental tmp relation is created, plus new functional coverage and a changelog entry.

Reviewed changes

Copilot reviewed 4 out of 4 changed files in this pull request and generated 5 comments.

File Description
dbt-snowflake/tests/functional/adapter/incremental/test_incremental_transient.py Adds functional tests covering tmp_relation_type='transient' for default and delete+insert incremental strategies.
dbt-snowflake/src/dbt/include/snowflake/macros/relations/table/create.sql Adds a Snowflake macro to create transient tables via CTAS for incremental tmp relations.
dbt-snowflake/src/dbt/include/snowflake/macros/materializations/incremental.sql Updates tmp-relation type selection/creation to support transient tmp relations, uses transient for Iceberg, and adds a tmp-relation resolution hook.
dbt-snowflake/.changes/unreleased/Features-20260424-transient-tmp-relation.yaml Adds a changelog entry describing the new transient tmp relation support and Iceberg behavior change.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread dbt-snowflake/src/dbt/include/snowflake/macros/materializations/incremental.sql Outdated
Comment thread dbt-snowflake/tests/functional/adapter/incremental/test_incremental_transient.py Outdated
Comment thread dbt-snowflake/tests/functional/adapter/incremental/test_incremental_transient.py Outdated

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 5 out of 5 changed files in this pull request and generated 4 comments.

Comments suppressed due to low confidence (1)

dbt-snowflake/src/dbt/include/snowflake/macros/materializations/incremental.sql:186

  • The tmp-relation creation path no longer treats catalog-linked (Iceberg/CLD) models specially. For CLD, tmp_relation_type resolves to table, which will hit this create_table_as(True, ...) branch and emit CREATE OR REPLACE TEMPORARY TABLE ... via snowflake__create_table_as, but Iceberg/CLD explicitly does not support temporary tables. Reintroduce an is_catalog_linked_db branch here (as previously) to create a non-temporary staging relation for CLD (or otherwise ensure the DDL is not temporary).
    {% else %}
        {%- call statement('create_tmp_relation', language=language) -%}
          {{ create_table_as(True, tmp_relation, compiled_code, language) }}
        {%- endcall -%}

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread dbt-snowflake/src/dbt/include/snowflake/macros/materializations/incremental.sql Outdated
Comment thread dbt-snowflake/src/dbt/adapters/snowflake/relation_configs/policies.py Outdated
Comment thread dbt-snowflake/.changes/unreleased/Features-20260424-transient-tmp-relation.yaml Outdated

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 4 out of 4 changed files in this pull request and generated 3 comments.

Comments suppressed due to low confidence (1)

dbt-snowflake/src/dbt/include/snowflake/macros/materializations/incremental.sql:186

  • For catalog-linked database (Iceberg/CLD) incremental models, tmp_relation_type is forced to table, which means this branch will call create_table_as(True, ...) and attempt CREATE OR REPLACE TEMPORARY TABLE. Temporary tables are not supported for Iceberg/CLD (and the comment above says CLD should use a permanent table), so this will break CLD incremental runs. Consider restoring a CLD-specific branch here (or basing the decision on whether tmp_relation is catalog-linked after resolve_incremental_tmp_relation) to create a non-temporary table for CLD tmp relations.
    {% else %}
        {%- call statement('create_tmp_relation', language=language) -%}
          {{ create_table_as(True, tmp_relation, compiled_code, language) }}
        {%- endcall -%}

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread dbt-snowflake/tests/functional/adapter/incremental/test_incremental_transient.py Outdated

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 4 out of 4 changed files in this pull request and generated no new comments.

Comments suppressed due to low confidence (1)

dbt-snowflake/src/dbt/include/snowflake/macros/materializations/incremental.sql:186

  • The tmp-relation creation logic no longer special-cases catalog-linked databases (Iceberg/CLD). When is_catalog_linked_db is true, tmp_relation_type is forced to table, so this branch calls create_table_as(True, ...) which emits CREATE OR REPLACE TEMPORARY TABLE (via snowflake__create_table_temporary_sql). CLD schemas do not support temporary relations, so incremental runs against Iceberg tables will fail. Reintroduce the CLD branch here (create the tmp relation as a non-temporary table/Iceberg table) before checking tmp_relation_type for view/transient.
    {% else %}
        {%- call statement('create_tmp_relation', language=language) -%}
          {{ create_table_as(True, tmp_relation, compiled_code, language) }}
        {%- endcall -%}

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

b-per added 7 commits April 27, 2026 09:33
- Add `tmp_relation_type: transient` config option, which creates a
  non-session-scoped staging table visible to Snowflake's lineage
  tracking while avoiding permanent-table fail-safe storage costs
- Add `snowflake__resolve_incremental_tmp_relation` dispatch macro,
  letting users override the schema/database of the tmp relation to
  avoid name collisions when concurrent runs share the same schema
- Fix Iceberg (catalog-linked) incremental models to use transient
  instead of permanent tmp tables, reducing fail-safe storage costs
- Allow `transient` alongside `table` for delete+insert and microbatch
  strategies, since both are stable across multi-statement executions

Closes #1893
Adds the generic wrapper macro `resolve_incremental_tmp_relation` that
calls adapter.dispatch(), following the standard dbt pattern (same as
`set_query_tag`). The materialization calls the wrapper instead of
dispatch directly.
…type

Python models must return "table" before the Iceberg CLD check, otherwise
a Python incremental model on a catalog-linked database would receive
"transient" and have its compiled Python code passed to
snowflake__create_table_transient_sql.
CLD schemas only support Iceberg tables — transient tables are not
allowed, so creating a transient tmp relation would fail. Revert to
the original permanent table behavior for CLD incremental models.
incorporate(type='transient') failed validation because 'transient'
was not a recognized value in the enum.
- Use type='table' when building the transient tmp relation object so
  DROP TABLE is emitted correctly (DROP TRANSIENT is invalid SQL)
- Add contract enforcement to snowflake__create_table_transient_sql,
  matching the behavior of the temporary table path
- Consolidate three separate test methods into one to reduce CI runtime
- Remove unused relation_from_name import from test file
- Fix docstring: CLD schemas only support Iceberg tables, so the tmp
  relation remains a permanent table (not transient)
- Remove unused SnowflakeRelationType.Transient enum value — transient
  tmp relations use type='table' for the relation object
- Remove incorrect Iceberg claim from changelog entry
Use run_dbt_and_capture with --debug to verify the tmp relation is
actually created as a transient table, not just that the run succeeds.
@b-per
b-per force-pushed the feat/snowflake-transient-tmp-relation branch from c2ea309 to 12320ac Compare April 27, 2026 07:33
@b-per

b-per commented Apr 27, 2026

Copy link
Copy Markdown
Contributor Author

CI failure analysis

The integration test suite shows 1 failed, 400 passed — our new tests both passed:

  • TestIncrementalTransientTmpRelation::test_incremental_transient
  • TestIncrementalTransientTmpRelationDeleteInsert::test_incremental_transient_delete_insert_runs

The sole failure is TestSnowflakeIcebergRestCatalogIntegration::test_basic_iceberg_rest_catalog_integration.

After further investigation, this failure was caused by our PR: we accidentally removed the is_catalog_linked_db branch from the tmp relation creation section, causing CLD incremental models to use create_table_as(True, ...) (temporary table) instead of create_table_as(False, ...) (non-temporary Iceberg-compatible table). This broke the second run_dbt(["run"]) call (the incremental run) with SQL Compilation Error: This operation is not supported in a catalog-linked database.

The fix has been pushed in commit 569e000, which restores the original CLD creation path.

…l models

CLD (catalog-linked database) models require a non-temporary Iceberg
table as the tmp relation; use create_table_as(False, ...) for CLD so
the DDL follows the Iceberg path rather than the temporary-table path.
@b-per
b-per temporarily deployed to dbt-snowflake April 27, 2026 09:04 — with GitHub Actions Inactive
@colin-k-rogers
colin-k-rogers enabled auto-merge (squash) April 29, 2026 19:04
@colin-k-rogers
colin-k-rogers merged commit 2ca2a96 into main May 3, 2026
20 checks passed
@colin-k-rogers
colin-k-rogers deleted the feat/snowflake-transient-tmp-relation branch May 3, 2026 21:48
@b-per

b-per commented May 5, 2026

Copy link
Copy Markdown
Contributor Author

I am creating a draft doc PR for it.

Is anyone working on porting it to Fusion as well?

b-per added a commit to dbt-labs/docs.getdbt.com that referenced this pull request May 5, 2026
Adds `transient` as a valid value for `tmp_relation_type` in Snowflake
incremental models, explains lineage tracking benefits and fail-safe
trade-offs, adds a warning about concurrent-run conflicts, and documents
the `snowflake__resolve_incremental_tmp_relation` dispatch macro as the
recommended fix.

Tracks: dbt-labs/dbt-adapters#1894
runleonarun added a commit to dbt-labs/docs.getdbt.com that referenced this pull request May 13, 2026
…ro (#9098)

## What are you changing in this pull request and why?

Documents the new `transient` option for `tmp_relation_type` in
Snowflake incremental models, added in
[dbt-labs/dbt-adapters#1894](dbt-labs/dbt-adapters#1894).

Changes to
`website/docs/reference/resource-configs/snowflake-configs.md`
(Temporary tables section):

- Adds `transient` as a valid value for `tmp_relation_type` alongside
`table` and `view`
- Adds a bullet-point comparison of all three options (default behavior,
catalog visibility, lineage tracking, fail-safe trade-offs)
- Adds a `:::warning` admonition about concurrent-run conflicts when
using `transient` (since the tmp table persists in the catalog under a
deterministic name)
- Adds a new `### Avoiding tmp relation conflicts` subsection
documenting the `snowflake__resolve_incremental_tmp_relation` dispatch
macro with two usage examples (simple scratch schema and CI-job-aware
schema)

## Checklist

- [x] I have reviewed the [Content style
guide](https://github.com/dbt-labs/docs.getdbt.com/blob/current/contributing/content-style-guide.md)
so my content adheres to these guidelines.
- [ ] The changes in this PR are related to the adapter docs and I have
[pinged the relevant
maintainer](https://github.com/dbt-labs/docs.getdbt.com/blob/current/contributing/adapter-doc-guide.md).
- [x] The PR is draft because the underlying feature
(dbt-labs/dbt-adapters#1894) is not yet released.

---------

Co-authored-by: Leona B. Campbell <3880403+runleonarun@users.noreply.github.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

cla:yes The PR author has signed the CLA community A PR, or an issue with a PR, from a community member needs:docs

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Bug] Iceberg incremental tmp relations can collide when sharing the same schema

3 participants