Migrate Legacy SQL codebase to dbt : automaticaly generate Lineage.
Project description
dbt-migrator
Migrate legacy SQL scripts to dbt models with safe, lineage‑aware {{ ref(...) }} replacement.
Why dbt_migrator ?
In modern data platforms, lineage is the foundation of trust. dbt excels at providing column‑level and table‑level lineage – but only if all references are expressed via {{ ref(...) }}. Legacy SQL scripts often contain hard‑coded database/schema/table names, breaking lineage and making impact analysis, testing, and CI/CD impossible.
dbt_migrator bridges that gap:
- Parses legacy SQL using a full SQL parser (
sqlparser‑rs), not fragile regex. - Matches table references against your actual dbt model files (respecting schema, database, and tags inheritance from
dbt_project.yml). - Rewrites them to
{{ ref('model_name') }}only when an unambiguous match exists – conflicts are flagged, never silently resolved. - Works with any dialect – Snowflake, BigQuery, Redshift, SQL Server, DuckDB, and more (via
sqlparser). - Delivers reports (JSON/CSV) of all replacements, warnings, and conflicts, so you can review changes before committing.
The result: clean, dbt‑native SQL with full lineage, enabling:
- Reliable impact analysis (“Which dashboards break if I change this model?”)
- Automated testing (data tests, freshness, etc.) with full dependency resolution.
- CI/CD pipelines that only run models affected by a pull request.
- Improved data quality through visibility and governance.
Key Features
- 🧠 Smart resolution – three‑level priority (full
db.schema.table→schema.table→ baretable) with explicit conflict detection. - 🔍 Parses real SQL – uses
sqlparser‑rsAST visitor, no fragile regex. - 📦 dbt‑aware – reads
dbt_project.yml, traversesmodels:hierarchy, accumulatesschema/database/tagsper model directory. - ⚙️ Configurable – per‑table rules, output modes (overwrite or
.migratedcopy), thread control. - 📊 Rich reports – JSON for automation, CSV for human review.
- 🐍 Python bindings – use it as a library in your dbt orchestration scripts (via PyO3/Maturin).
- 🔀 Multithreaded – processes thousands of files in parallel (Rayon), with optional single‑thread mode for debugging.
Quick Start
Command‑line Interface
# Install from source (requires Rust)
cargo install dbt_migrator
# Or run directly
cargo run -- \
--project-dir /path/to/dbt_project \
--sql-path /path/to/legacy_sql \
--config migrate_config.yml \
--report-dir ./reports
Python Package (via PyO3)
pip install dbt-migrator
from dbt_migrator import migrate_project
report = migrate_project(
project_dir="path/to/dbt_project",
sql_path="path/to/legacy_sql",
config_path="migrate_config.yml"
)
print(report.summary())
The Python API returns the same report data (replacements, warnings, conflicts) as the CLI, ready for integration into your CI/CD workflows.
Configuration
migrate_config.yml (example):
dialect: "snowflake" # or "bigquery", "mssql", "duckdb", …
multithreading: true
output_mode: "overwrite" # or "copy" (saves as .migrated)
conflicts:
- script: "report_orders.sql"
table: "dim_customers"
target: "dim_customers_master" # explicit override
normalization:
# Optional regex for non‑standard table names (e.g., Dremio paths)
regex: "(?P<schema>[^/]+)/(?P<table>[^/]+)"
All settings are optional; defaults are documented in the example config.
How It Works
- Parse
dbt_project.yml– extract model paths and themodels:tree. - Build resolution index – walk every
.sqlfile undermodel-paths, accumulate schema/database/tags from themodels:hierarchy (exact dbt inheritance logic: deepest schema wins, tags union). - Parse each legacy SQL file – using the chosen dialect.
- Visit every table reference – with
sqlparser’sVisitorMut:- Try explicit rules from config.
- Query the index (full → schema.table → table, with conflict detection).
- If unambiguous, replace
ObjectNamewith{{ ref('model') }}(AST‑level rewrite). - Otherwise, log a warning/conflict and keep the original.
- Write back (overwrite or side‑by‑side) and generate report.
⚠️ Important: The tool uses the
dbt_project.ymlalone (notmanifest.json), so it’s a reasonable approximation of dbt’s final model names. If you have amanifest.jsonavailable, you can plug it into the index as a more accurate source.
Demo
A demo project is included. Four legacy SQL references are tested:
| Legacy Reference | Result |
|---|---|
[analytics].[marts_finance].[fct_orders] |
{{ ref('fct_orders') }} |
marts.dim_customers |
{{ ref('dim_customers') }} |
dbo.legacy_unmapped_table |
kept (unmapped, warning) |
dim_customers (ambiguous) |
kept (conflict reported) |
Run the tests:
cargo test
Or using Python:
pytest tests/
Build from Source
Rust (CLI)
cargo build --release
target/release/dbt_migrator --help
Python Wheel
pip install maturin
maturin build --release --features python
# Wheel is in target/wheels/
For development:
maturin develop --features python
Limitations & Future Plans
- No
manifest.jsonsupport yet – usingdbt_project.ymlonly. A future version will optionally readmanifest.jsonfor 100% accuracy. - Tree‑based fallback – disabled by default (spec’s “last resort”); can be enabled via config flag, but we recommend resolving conflicts manually.
Contributing
Issues and pull requests are welcome !
License
GPL-3.0-or-later
Give your dbt project the lineage it deserves. Try dbt_migrator today.
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distributions
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file dbt_migrator-0.2.0.tar.gz.
File metadata
- Download URL: dbt_migrator-0.2.0.tar.gz
- Upload date:
- Size: 37.1 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
0921d421f4a869e182a94a52dbf495ac2f892c6225ca4b4204151664c20b9111
|
|
| MD5 |
d1bc5695cd8d53506936d808602ef7f8
|
|
| BLAKE2b-256 |
3f77e0d9e34d5daee79306f287be899938134163000133c5274158e3e14854b0
|
File details
Details for the file dbt_migrator-0.2.0-cp38-abi3-win_amd64.whl.
File metadata
- Download URL: dbt_migrator-0.2.0-cp38-abi3-win_amd64.whl
- Upload date:
- Size: 1.9 MB
- Tags: CPython 3.8+, Windows x86-64
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
f8a33a2b3e6103224b00c7d566d9e1c305dc054ebdf31a969af0e583b6f29071
|
|
| MD5 |
a8bc90cef4ddceac5b8ca28c780b7c66
|
|
| BLAKE2b-256 |
3e10f248432abf39b24f8d469ea6ea13704670a9079a3e83f1142b3c00dc2093
|
File details
Details for the file dbt_migrator-0.2.0-cp38-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl.
File metadata
- Download URL: dbt_migrator-0.2.0-cp38-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
- Upload date:
- Size: 2.0 MB
- Tags: CPython 3.8+, manylinux: glibc 2.17+ x86-64
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
585eda0f8400ab551905c725c2d99b31ad74deeffeb88cb56e5b1d292ce0571d
|
|
| MD5 |
84811cf520b7f85f464d0c35920b3576
|
|
| BLAKE2b-256 |
f8b05989eac0ee1b88ad4ae1602fe18cd54e181acba7dc0e804fe6f5403fde6c
|
File details
Details for the file dbt_migrator-0.2.0-cp38-abi3-macosx_11_0_arm64.whl.
File metadata
- Download URL: dbt_migrator-0.2.0-cp38-abi3-macosx_11_0_arm64.whl
- Upload date:
- Size: 1.8 MB
- Tags: CPython 3.8+, macOS 11.0+ ARM64
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
330784b71c46c2717f675ed16a3f7bd45ad98cdbab7385ecb593aaa928c10567
|
|
| MD5 |
d1f759a15b5f7734e5d871c4e0785d0a
|
|
| BLAKE2b-256 |
5922e35d9ea5c22c4789a2ba5bad9c76f62526fc501ec178cae99b93862bde3a
|