Skip to content
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
8 changes: 8 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,14 @@
# Data Engineers Snowflake DataOps Utils Project Changelog
This file contains the changelog for the Data Engineers Snowflake DataOps Utils project, detailing updates, fixes, and enhancements made to the project over time.

## v1.0.6 - 2026-06-23 - Database Clone Grant Ownership

### Added
- Added `database_clone_grant_ownership` macro to grant ownership of a cloned database and all its schemas, tables, and views to a specified role. Iterates over all schemas in the destination database (excluding INFORMATION_SCHEMA) and grants ownership on the schema, all tables, and all views to the target role with `COPY CURRENT GRANTS`.

### Changed
- Bumped version from 1.0.5 to 1.0.6

## v1.0.5 - 2026-06-16 - Grant OPERATE on Tasks to Applications

### Added
Expand Down
3 changes: 2 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

A macro-only [dbt](https://github.com/dbt-labs/dbt) package for Snowflake DataOps. Provides utilities for object lifecycle management, RBAC grant orchestration, dimensional modelling helpers, tagging, shares, and more.

- **Version**: 1.0.5
- **Version**: 1.0.6
- **dbt**: `>=1.3.0, <3.0.0`
- **Dependencies**: None (zero external package dependencies)
- **dbt Fusion**: Compatible
Expand Down Expand Up @@ -72,6 +72,7 @@ The following `vars` can be set in your `dbt_project.yml` or via `--vars` on the
| Macro | Description |
|---|---|
| `database_clone(source_database, destination_database, new_owner_role, comment, include_internal_stages)` | Zero-copy clone a database with optional ownership transfer and internal stage cloning |
| `database_clone_grant_ownership(destination_database, new_owner_role)` | Grant ownership of a cloned database and all its schemas, tables, and views to a role |
| `database_destroy(database_name)` | Drop the supplied database |
| `schema_clone(source_schema, destination_schema, source_database, destination_database, new_owner_role)` | Zero-copy clone a schema with optional ownership transfer |

Expand Down
2 changes: 1 addition & 1 deletion dbt_project.yml
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
name: 'dbt_dataengineers_utils'
version: '1.0.5'
version: '1.0.6'
config-version: 2

require-dbt-version: [">=1.9.4", "<3.0.0"]
Expand Down
8 changes: 8 additions & 0 deletions macros/database/database.yml
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,14 @@ macros:
- name: new_owner_role
description: "[Optional] The new owner role of the newly created object"

- name: database_clone_grant_ownership
description: Grant ownership of a cloned database and all its schemas, tables, and views to a specified role.
arguments:
- name: destination_database
description: The database to transfer ownership of
- name: new_owner_role
description: The role to grant ownership to

- name: database_destroy
description: Drop the supplied database (destructive operation).
arguments:
Expand Down
79 changes: 79 additions & 0 deletions macros/database/database_clone_grant_ownership.sql
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
{% macro database_clone_grant_ownership(destination_database, new_owner_role) %}

{% if not destination_database or not new_owner_role %}
{{ exceptions.raise_compiler_error("Invalid arguments. Missing destination_database and/or new_owner_role") }}
{% endif %}

{{ log("Granting ownership on " ~ destination_database ~ " to " ~ new_owner_role, info=True) }}

{% call statement('grant_db_ownership', fetch_result=True, auto_begin=False) -%}
GRANT OWNERSHIP ON DATABASE {{ destination_database }} TO ROLE {{ new_owner_role }} REVOKE CURRENT GRANTS;
{%- endcall %}

{% set list_schemas_query %}
SELECT schema_name
FROM {{ destination_database }}.information_schema.schemata
WHERE schema_name != 'INFORMATION_SCHEMA'
{% endset %}

{% if execute %}
{% set results = run_query(list_schemas_query) %}
{% set schemata_list = results.columns[0].values() %}
{% else %}
{% set schemata_list = [] %}
{% endif %}

{% for schema_name in schemata_list %}
{{ log("Granting ownership on schema " ~ destination_database ~ "." ~ schema_name ~ " to " ~ new_owner_role, info=True) }}

{% call statement('grant_schema_' ~ loop.index, auto_begin=False) -%}
GRANT OWNERSHIP ON SCHEMA {{ destination_database }}.{{ schema_name }} TO ROLE {{ new_owner_role }} REVOKE CURRENT GRANTS;
{%- endcall %}

{% call statement('grant_views_' ~ loop.index, auto_begin=False) -%}
GRANT OWNERSHIP ON ALL VIEWS IN SCHEMA {{ destination_database }}.{{ schema_name }} TO ROLE {{ new_owner_role }} REVOKE CURRENT GRANTS;
{%- endcall %}

{% call statement('grant_mat_views_' ~ loop.index, auto_begin=False) -%}
GRANT OWNERSHIP ON ALL MATERIALIZED VIEWS IN SCHEMA {{ destination_database }}.{{ schema_name }} TO ROLE {{ new_owner_role }} REVOKE CURRENT GRANTS;
{%- endcall %}

{% call statement('grant_tables_' ~ loop.index, auto_begin=False) -%}
GRANT OWNERSHIP ON ALL TABLES IN SCHEMA {{ destination_database }}.{{ schema_name }} TO ROLE {{ new_owner_role }} REVOKE CURRENT GRANTS;
{%- endcall %}

{% call statement('grant_ext_tables_' ~ loop.index, auto_begin=False) -%}
GRANT OWNERSHIP ON ALL EXTERNAL TABLES IN SCHEMA {{ destination_database }}.{{ schema_name }} TO ROLE {{ new_owner_role }} REVOKE CURRENT GRANTS;
{%- endcall %}

{% call statement('grant_dyn_tables_' ~ loop.index, auto_begin=False) -%}
GRANT OWNERSHIP ON ALL DYNAMIC TABLES IN SCHEMA {{ destination_database }}.{{ schema_name }} TO ROLE {{ new_owner_role }} REVOKE CURRENT GRANTS;
{%- endcall %}

{% call statement('grant_stages_' ~ loop.index, auto_begin=False) -%}
GRANT OWNERSHIP ON ALL STAGES IN SCHEMA {{ destination_database }}.{{ schema_name }} TO ROLE {{ new_owner_role }} REVOKE CURRENT GRANTS;
{%- endcall %}

{% call statement('grant_file_formats_' ~ loop.index, auto_begin=False) -%}
GRANT OWNERSHIP ON ALL FILE FORMATS IN SCHEMA {{ destination_database }}.{{ schema_name }} TO ROLE {{ new_owner_role }} REVOKE CURRENT GRANTS;
{%- endcall %}

{% call statement('grant_functions_' ~ loop.index, auto_begin=False) -%}
GRANT OWNERSHIP ON ALL FUNCTIONS IN SCHEMA {{ destination_database }}.{{ schema_name }} TO ROLE {{ new_owner_role }} REVOKE CURRENT GRANTS;
{%- endcall %}

{% call statement('grant_procedures_' ~ loop.index, auto_begin=False) -%}
GRANT OWNERSHIP ON ALL PROCEDURES IN SCHEMA {{ destination_database }}.{{ schema_name }} TO ROLE {{ new_owner_role }} REVOKE CURRENT GRANTS;
{%- endcall %}

{% call statement('grant_streams_' ~ loop.index, auto_begin=False) -%}
GRANT OWNERSHIP ON ALL STREAMS IN SCHEMA {{ destination_database }}.{{ schema_name }} TO ROLE {{ new_owner_role }} REVOKE CURRENT GRANTS;
{%- endcall %}

{% call statement('grant_tasks_' ~ loop.index, auto_begin=False) -%}
GRANT OWNERSHIP ON ALL TASKS IN SCHEMA {{ destination_database }}.{{ schema_name }} TO ROLE {{ new_owner_role }} REVOKE CURRENT GRANTS;
{%- endcall %}

{% endfor %}

{% endmacro %}
Loading