Skip to content

fix(fabric): support elementary schema in a different DB than target#1009

Open
tderk wants to merge 1 commit into
elementary-data:masterfrom
tderk:fix/fabric-cross-db-elementary-schema
Open

fix(fabric): support elementary schema in a different DB than target#1009
tderk wants to merge 1 commit into
elementary-data:masterfrom
tderk:fix/fabric-cross-db-elementary-schema

Conversation

@tderk
Copy link
Copy Markdown

@tderk tderk commented May 21, 2026

Summary

When the elementary schema lives in a different database than target.database on dbt-fabric / Fabric DW, the CREATE VIEW issued by fabric__query_test_result_rows uses a 2-part name (schema.view) and lands in the connection's current DB (= target.database). If the elementary schema does not exist there, the statement fails with:

('42000', '[42000] [Microsoft][ODBC Driver 18 for SQL Server][SQL Server]
The specified schema name "<elementary_schema>" either does not exist
or you do not have permission to use it. (2760)')

Root cause

The compiled test SQL passed into CREATE VIEW … AS … references the source table via dbt's Relation API, which produces a 3-part qualified name. The target view, however, is only 2-part qualified, so the target side assumes the connection's current DB matches the elementary database. That assumption breaks when the two DBs differ.

Why the obvious fixes don't work on Fabric

  • A 3-part qualified CREATE VIEW is rejected (error 166: 'CREATE/ALTER VIEW' does not allow specifying the database name as a prefix to the object name).
  • USE [db]; CREATE VIEW … in a single batch is rejected (error 111: 'CREATE VIEW' must be the first statement in a query batch).

Fix

Dispatch the CREATE VIEW / DROP VIEW IF EXISTS via EXEC [db]..sp_executesql N'...'. sp_executesql invoked with a database prefix executes in that database's context, so the view is created with a 2-part name inside the elementary database. The SELECT against the helper view stays 3-part qualified (Fabric already accepts that).

No session DB state is mutated, so this is safe under dbt-fabric's threadsafe connection model.

Test plan

  • dbt test on Fabric DW with elementary schema in a separate DB from target.database — passes (was failing with 2760)
  • dbt test on Fabric DW with elementary schema in the same DB as target.database — no regression
  • dbt test on dbt-sqlserver (inherits fabric__ via dispatch) — not verified locally, behaviour identical at SQL level

Summary by CodeRabbit

Bug Fixes

  • Fixed test result sampling to properly handle scenarios where the elementary database differs from the target database, ensuring temporary views are created and executed in the correct database context.

Review Change Stack

@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented May 21, 2026

📝 Walkthrough

Walkthrough

The fabric__query_test_result_rows macro is updated to create and drop temporary sampling views via EXEC...sp_executesql instead of direct DDL, using bracket-quoted fully qualified names to ensure operations execute in the elementary database context rather than the target database when they differ.

Changes

Test Result Sampling View Database Context

Layer / File(s) Summary
Temporary sampling view creation and cleanup with database context
macros/edr/materializations/test/test.sql
Identifiers are built with bracket quotes and fully qualified database/schema naming. View creation and DROP VIEW cleanup are wrapped in EXEC [view_db]..sp_executesql to execute in elementary context. Sampling query selects from the fully qualified bracket-quoted view name. Embedded quotes are escaped in dynamic SQL strings.

🎯 2 (Simple) | ⏱️ ~10 minutes

🐰 A view hops through databases near and far,
With brackets and quotes to mark where they are.
sp_executesql wraps the DDL tight,
So elementary's home is always in sight! ✨

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately describes the main fix: enabling support for elementary schema in a different database than the target database on dbt-fabric, which directly addresses the core problem detailed in the PR objectives.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@github-actions
Copy link
Copy Markdown
Contributor

👋 @tderk
Thank you for raising your pull request.
Please make sure to add tests and document all user-facing changes.
You can do this by editing the docs files in the elementary repository.

@tderk tderk requested a deployment to elementary_test_env May 21, 2026 17:02 — with GitHub Actions Waiting
@tderk tderk closed this May 22, 2026
@tderk tderk reopened this May 22, 2026
@tderk tderk requested a deployment to elementary_test_env May 22, 2026 07:15 — with GitHub Actions Waiting
@tderk tderk marked this pull request as ready for review May 22, 2026 07:16
When the elementary schema lives in a different database than
target.database on dbt-fabric / Fabric DW, the CREATE VIEW issued by
fabric__query_test_result_rows uses a 2-part name (schema.view) and
lands in the connection's current DB (= target.database). If the
elementary schema does not exist there, the statement fails with:

    ('42000', '[42000] [Microsoft][ODBC Driver 18 for SQL Server][SQL Server]
    The specified schema name "<elementary_schema>" either does not exist
    or you do not have permission to use it. (2760)')

Fabric/T-SQL constraints prevent both a 3-part qualified CREATE VIEW
(error 166) and `USE [db]; CREATE VIEW ...` in a single batch (error
111). Dispatching the DDL via `EXEC [db]..sp_executesql N'...'` executes
it in the target database's context with a 2-part name and no
session-DB leak across run_query calls.

The SELECT against the helper view stays 3-part qualified, which Fabric
already accepts.
@tderk tderk force-pushed the fix/fabric-cross-db-elementary-schema branch from 03ee80a to 997c89e Compare May 22, 2026 07:35
@tderk tderk requested a deployment to elementary_test_env May 22, 2026 07:35 — with GitHub Actions Waiting
Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

🧹 Nitpick comments (1)
macros/edr/materializations/test/test.sql (1)

276-290: ⚡ Quick win

Persist the sampling view for deferred cleanup.

If Line 285 fails after the CREATE VIEW on Line 278 succeeds, the DROP VIEW on Line 290 is never reached, so edr_test_sample_* can be left behind in the elementary schema. Please register this helper view in the same Fabric cleanup path used for other temp relations before issuing the sampling query.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@macros/edr/materializations/test/test.sql` around lines 276 - 290, The CREATE
VIEW performed via create_stmt (which builds create_inner) can succeed while the
later sampling query fails, leaving edr_test_sample_* behind; after running
run_query(create_stmt) register the created short_view_name with the same
Fabric/elementary cleanup mechanism used elsewhere (e.g., add the view name to
the temp-relations cleanup list or call the project's register_temp_relation
helper) before executing the sampling query that uses qualified_view_name and
elementary.run_query/elementary.agate_to_dicts; then keep the existing
drop_inner/drop_stmt as a best-effort immediate cleanup so the view is both
registered for deferred cleanup and also dropped if possible.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Nitpick comments:
In `@macros/edr/materializations/test/test.sql`:
- Around line 276-290: The CREATE VIEW performed via create_stmt (which builds
create_inner) can succeed while the later sampling query fails, leaving
edr_test_sample_* behind; after running run_query(create_stmt) register the
created short_view_name with the same Fabric/elementary cleanup mechanism used
elsewhere (e.g., add the view name to the temp-relations cleanup list or call
the project's register_temp_relation helper) before executing the sampling query
that uses qualified_view_name and
elementary.run_query/elementary.agate_to_dicts; then keep the existing
drop_inner/drop_stmt as a best-effort immediate cleanup so the view is both
registered for deferred cleanup and also dropped if possible.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 077a21d3-3694-40c8-802f-b0663fd73e9d

📥 Commits

Reviewing files that changed from the base of the PR and between 03ee80a and 997c89e.

📒 Files selected for processing (1)
  • macros/edr/materializations/test/test.sql

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant