> ## Documentation Index
> Fetch the complete documentation index at: https://docs.paradime.io/llms.txt
> Use this file to discover all available pages before exploring further.

# Turbo CI with Snowflake shared databases

> Configure dbt™ clone to fall back to views for models in Snowflake shared databases, which cannot be zero-copy cloned during Turbo CI runs.

## Overview

Some dbt™ projects build on top of data that arrives through [Snowflake Secure Data Sharing](https://docs.snowflake.com/en/user-guide/data-sharing-intro), for example when an upstream team shares its models from a separate Snowflake account. If your Turbo CI commands use `dbt clone` to copy production relations into the temporary CI schema, any relation that lives in a shared database fails to clone:

```text theme={"system"}
003029 (0A000): SQL compilation error:
Cannot clone from a table that was imported from a share.
```

## Why a macro override is needed

Three things combine to cause this failure, and only the last one is fixable in your project:

1. **Snowflake cannot clone shared objects.** Zero-copy cloning works by referencing a table's underlying storage metadata, which stays in the provider's account. A shared database is a read-only window into that account, so there is nothing to clone from. This is a platform limit with no workaround, and no `GRANT` changes it.
2. **dbt™ has the right fallback, but never uses it on Snowflake.** The clone materialization already knows how to create a view over the production relation instead of a clone. It picks between the two up front by asking the adapter `can_clone_table()`, and the Snowflake adapter answers `true` unconditionally. The check means "does this warehouse support CLONE at all", not "can this specific relation be cloned", and dbt™ does not catch the error and retry as a view. The result is that the fallback exists but the routing to it never fires.
3. **The routing is overridable.** `dbt clone` builds its SQL through dispatched macros, so a project-level `snowflake__create_or_replace_clone` can make the clone-or-view decision per relation instead of per adapter.

The macro override below does exactly that: models that resolve to a shared database are created as views pointing at the shared table, and every other model keeps the regular zero-copy clone. A view is free, is created instantly, and reads live data through the share, which is what a CI run needs from unchanged upstream models.

## Configure the macro override

### 1. Add the macro

In your dbt™ project's *macros* folder, create `create_or_replace_clone.sql`:

```sql title="create_or_replace_clone.sql" lineNumbers theme={"system"}
{% macro snowflake__create_or_replace_clone(this_relation, defer_relation) %}

    {% set shared_dbs = var('shared_databases', []) | map('upper') | list %}

    {% if defer_relation.database | upper in shared_dbs %}
        {# Share-backed relation: CLONE is not possible, create a pointer view instead #}
        create or replace view {{ this_relation }} as
            select * from {{ defer_relation }}
    {% else %}
        {# Normal path: identical to the dbt-snowflake default implementation #}
        create or replace
          {{ "transient" if config.get("transient", true) }}
          table {{ this_relation }}
          clone {{ defer_relation }}
    {% endif %}

{% endmacro %}
```

### 2. Register the override

In `dbt_project.yml`, add a `dispatch` config so dbt™ finds your macro before its built-in one. Replace `my_project` with the `name` defined at the top of your `dbt_project.yml`:

```yaml title="dbt_project.yml" theme={"system"}
dispatch:
  - macro_namespace: dbt
    search_order: ['my_project', 'dbt']
```

<Info>
  If your project already has a `dispatch` block, for example for `dbt_utils`, add the `macro_namespace: dbt` entry to it instead of creating a second block.
</Info>

### 3. List your shared databases

Also in `dbt_project.yml`, list every database that is imported through a share. Matching is case-insensitive:

```yaml title="dbt_project.yml" theme={"system"}
vars:
  shared_databases: ['RAW_SHARED', 'PROD_ANALYTICS']
```

Only relations whose production database is in this list get the view treatment. Everything else is unaffected.

## Usage

The macro only changes what `dbt clone` executes, not how you configure Turbo CI. Make sure your Turbo CI schedule has [deferral enabled](/products/bolt/ci-cd/index#deferral-and-state-comparison) by setting `deferred_schedule_slug` to your production schedule. Paradime supplies the production manifest to every command in the schedule, so you do not pass `--state` or `--defer` flags yourself:

```bash theme={"system"}
dbt clone --select state:modified+ --target ci
dbt build --select state:modified+ --target ci
```

During the clone step, models that resolve to a shared database are created in the Turbo CI schema as views over the shared tables. All other models are cloned as usual.

To verify, check the temporary schema after a run:

```sql theme={"system"}
show views in schema <ci_database>.<turbo_ci_schema>;
```

Share-backed models appear as views, and querying one returns live data from the share.

## Requirements and limitations

* **Permissions**: the warehouse user in your `ci` environment needs `IMPORTED PRIVILEGES` on each shared database. If it can already `select` from the share, no extra grant is needed.
* **Views read live data, not a snapshot**: a clone freezes data at the moment it is created, while a view always shows the share's current state. If the provider refreshes the shared data during or between CI runs, queries against the view reflect the new data. This is usually fine for CI, but results are not point-in-time reproducible the way clones are.
* **Upstream schema changes**: Snowflake expands `select *` when the view is created. If the provider adds, removes, or renames columns in a shared table, existing views can fail or return an outdated column set. Re-run `dbt clone` with `--full-refresh` to recreate them.
* **Re-runs**: `dbt clone` skips relations that already exist in the target schema. Pass `--full-refresh` when you want them recreated, for example while testing this setup.
* **Changed incremental models**: a view is not a writable base. An incremental model that is itself modified in a pull request and whose production relation lives in a shared database builds from scratch in the CI schema. For very large models, add a row-limit filter for the `ci` target.
* **dbt™ versions**: requires dbt™ 1.6 or later, when `dbt clone` was introduced. The macro shadows the adapter's default implementation, so compare it against the default again after major `dbt-snowflake` upgrades.


## Related topics

- [Turbo CI on GitHub pull requests](/products/bolt/ci-cd/turbo-ci/github.md)
- [Turbo CI for dbt™ pull requests](/products/bolt/ci-cd/turbo-ci/index.md)
- [Turbo CI on BitBucket pull requests](/products/bolt/ci-cd/turbo-ci/bitbucket.md)
- [Turbo CI on Azure DevOps pull requests](/products/bolt/ci-cd/turbo-ci/azure-devops.md)
- [Turbo CI on GitLab merge requests](/products/bolt/ci-cd/turbo-ci/gitlab.md)
