-
Notifications
You must be signed in to change notification settings - Fork 288
Description
Summary
Add a profile credentials option (drop_without_cascade or similar) to omit CASCADE from DROP TABLE/VIEW/MATERIALIZED VIEW statements in dbt-redshift.
Background
All three dbt-redshift drop macros unconditionally append CASCADE:
macros/relations/table/drop.sql (line 2):
drop table if exists {{ relation }} cascademacros/relations/view/drop.sql (line 2):
drop view if exists {{ relation }} cascademacros/relations/materialized_view/drop.sql (line 2):
drop materialized view if exists {{ relation }} cascadeCASCADE instructs Redshift to automatically drop all dependent objects (views, etc.). On clusters with many objects, Redshift must walk the full dependency graph to resolve each DROP ... CASCADE, which is expensive. For users who exclusively use unbound views (or have no downstream views at all), there are no dependents to cascade to — the overhead is pure waste.
Additionally, CASCADE is the root cause of the concurrent-transaction race condition that requires the global thread lock (see related issue). Removing CASCADE also opens the door to removing the lock.
Proposed Change
Add a boolean profile credential field drop_without_cascade (default False) that, when True, emits DROP ... RESTRICT (or simply omits CASCADE) instead.
Files to change
dbt-redshift/src/dbt/adapters/redshift/connections.py
Add to RedshiftCredentials dataclass (~line 190):
# Drop behavior
drop_without_cascade: bool = FalseAdd to _connection_keys() (~line 228):
"drop_without_cascade",macros/relations/table/drop.sql:
{%- macro redshift__drop_table(relation) -%}
drop table if exists {{ relation }} {% if not adapter.config.credentials.drop_without_cascade %}cascade{% endif %}
{%- endmacro -%}macros/relations/view/drop.sql:
{%- macro redshift__drop_view(relation) -%}
drop view if exists {{ relation }} {% if not adapter.config.credentials.drop_without_cascade %}cascade{% endif %}
{%- endmacro -%}macros/relations/materialized_view/drop.sql:
{% macro redshift__drop_materialized_view(relation) -%}
drop materialized view if exists {{ relation }} {% if not adapter.config.credentials.drop_without_cascade %}cascade{% endif %}
{%- endmacro %}Note: The exact mechanism for passing credentials into Jinja macros should follow the existing pattern used by
redshift__use_show_apis()inmacros/metadata/helpers.sql. Alternatively this could be implemented as a Python-level override of the drop macros usingexecute()directly inimpl.py.
Safety
- Default is
False— no change in behavior for existing users. - Safe only for projects that don't have dependent views downstream of dropped relations (e.g., projects using only unbound views, or where dbt manages all dependencies).
- Must be documented with a clear warning: if a dependent object exists and
CASCADEis omitted, Redshift will raise an error rather than silently dropping it. - Pairs naturally with
drop_without_lock(see related issue): users who set both get maximum DROP performance with minimal risk when their project has no downstream view dependencies.
Related
- Related to the
drop_without_lockfeature request — the thread lock exists specifically because ofCASCADErace conditions.