Skip to main content

datavault4sqlmesh

Each function replaces the full @model decorator, execute function, and manually maintained columns={} dict in a SQLMesh Python model file with a single declarative call.


Installation

pip install datavault4sqlmesh

Requires Python 3.9+ & sqlmesh.


Getting Started

1. Create config.json in your SQLMesh project root

{
  "dialect": "snowflake",
  "ldts_alias": "ldts",
  "rsrc_alias": "rsrc",
  "hash": "MD5"
}

See datavault4sqlglot configuration --> link auf github md for all available keys and their defaults.

2. Load configuration once in models/__init__.py

# models/__init__.py
from datavault4sqlmesh.config import load_dv_config

load_dv_config()  # reads config.json from the SQLMesh project root

All model files in the package automatically inherit these settings.

3. Write model files

# models/stg_customer.py
from datavault4sqlmesh import stage_model

stage_model(
    name="stage.stg_customer",
    source_table="customers",
    source_schema="raw",
    hashed_columns={
        "hk_customer_h": ["customer_id"],
        "hd_customer_s": {
            "is_hashdiff": True,
            "columns": ["customer_name", "email"],
        },
    },
    column_overrides={
        "customer_id":   "VARCHAR",
        "customer_name": "VARCHAR",
        "email":         "VARCHAR",
    },
)
# models/customer_h.py
from datavault4sqlmesh import hub_model

hub_model(
    name="dv.customer_h",
    hashkey="hk_customer_h",
    business_keys=["customer_id"],
    source_schema="stage",
    source_table="stg_customer",
    rsrc_statics=["ERP/customers"],
)
# models/customer_0_s.py
from datavault4sqlmesh import satellite_model

satellite_model(
    name="dv.customer_0_s",
    parent_hash_key="hk_customer_h",
    hash_diff="hd_customer_s",
    payload=["customer_name", "email"],
    source_schema="stage",
    source_table="stg_customer",
)
# models/customer_1_s.py
from datavault4sqlmesh import satellite_v1_model

satellite_v1_model(
    name="dv.customer_1_s",
    parent_hash_key="hk_customer_h",
    hash_diff="hd_customer_s",
    payload=["customer_name", "email"],
    sat_v0_table="customer_0_s",
    sat_v0_schema="dv",
)

Model functions

hub_model

Creates an INCREMENTAL_UNMANAGED Hub model.

from datavault4sqlmesh import hub_model

hub_model(
    name="dv.customer_h",
    hashkey="hk_customer_h",
    business_keys=["customer_id"],
    source_schema="stage",
    source_table="stg_customer",
    rsrc_statics=["ERP/customers"],
    # Optional
    cron="@daily",
    column_overrides={"customer_id": "BIGINT"},
)
Parameter Required Description
name yes Qualified model name, e.g. "dv.customer_h"
hashkey yes Hub hash key column name
business_keys yes Business key column names (at least one)
source_schema no Schema of the staging source table
source_table no Staging source table name; triggers auto-generate mode
sources no List of SourceModel objects for multi-source hubs
rsrc_statics no LIKE-pattern strings for HWM scoping
cron no SQLMesh cron expression
grain no Unique-row columns; defaults to [hashkey]
column_overrides no Override inferred column types

Multi-source hubs pass a list of SourceModel objects via sources. Each source is unioned and deduplicated by earliest ldts per hash key. source_table and sources cannot be combined.


link_model

Creates an INCREMENTAL_UNMANAGED Link model.

from datavault4sqlmesh import link_model

link_model(
    name="dv.order_customer_l",
    link_hash_key="hk_order_customer_l",
    foreign_hash_keys=["hk_order_h", "hk_customer_h"],
    source_schema="stage",
    source_table="stg_orders",
    rsrc_statics=["OMS/orders"],
)
Parameter Required Description
name yes Qualified model name
link_hash_key yes Link hash key column name
foreign_hash_keys yes Foreign hash key columns (at least two)
source_schema no Schema of the staging source table
source_table no Staging source table name; triggers auto-generate mode
sources no List of SourceModel objects for multi-source links
rsrc_statics no LIKE-pattern strings for HWM scoping

satellite_model

Creates an INCREMENTAL_UNMANAGED Satellite v0 (current-record) model.

Single source only — pass one SourceModel to source_model.

from datavault4sqlmesh import satellite_model

satellite_model(
    name="dv.customer_0_s",
    parent_hash_key="hk_customer_h",
    hash_diff="hd_customer_s",
    payload=["customer_name", "email"],
    source_schema="stage",
    source_table="stg_customer",
)
Parameter Required Description
name yes Qualified model name
parent_hash_key yes Hash key of the parent Hub or Link
hash_diff yes Hash diff column name
payload no Attribute column names
source_schema no Schema of the staging source table
source_table no Staging source table name; triggers auto-generate mode

satellite_v1_model

Creates a FULL Satellite v1 (end-dated) model derived from a v0 satellite.

from datavault4sqlmesh import satellite_v1_model

satellite_v1_model(
    name="dv.customer_1_s",
    parent_hash_key="hk_customer_h",
    hash_diff="hd_customer_s",
    payload=["customer_name", "email"],
    sat_v0_table="customer_0_s",
    sat_v0_schema="dv",
)
Parameter Required Description
name yes Qualified model name
parent_hash_key yes Hash key of the parent Hub or Link
hash_diff yes Hash diff column name
payload no Attribute column names
sat_v0_table no Table name of the v0 source satellite; omit to use decorator mode
sat_v0_schema no Schema of the v0 source; defaults to the same schema as the v1 target
add_is_current no Append an is_current boolean column (default True)

stage_model

Creates a FULL (complete refresh) Stage model.

from datavault4sqlmesh import stage_model

stage_model(
    name="stage.stg_customer",
    source_table="customers",
    source_schema="raw",
    hashed_columns={
        "hk_customer_h": ["customer_id"],
        "hd_customer_s": {
            "is_hashdiff": True,
            "columns": ["customer_name", "email"],
        },
    },
    column_overrides={
        "customer_id":   "VARCHAR",
        "customer_name": "VARCHAR",
        "email":         "VARCHAR",
    },
)

Use derived_columns for expressions not present in the raw source (e.g. a constant record source):

stage_model(
    name="stage.stg_orders",
    source_table="orders",
    source_schema="raw",
    derived_columns={"rsrc": "'OMS/orders'"},
    hashed_columns={"hk_order_h": ["order_id"]},
)

Column type inference

All model functions automatically build the columns={} dict required by SQLMesh. Default types:

Column category Inferred type
Hash key / hash diff VARCHAR
Business keys / payload VARCHAR
Foreign hash keys VARCHAR
ldts_alias (load date) TIMESTAMP
rsrc_alias (record source) VARCHAR
ledts_alias (load end date, sat v1 only) TIMESTAMP
is_current (sat v1 only) BOOLEAN

Override specific columns with column_overrides:

hub_model(..., column_overrides={"customer_id": "BIGINT"})

SQLMesh model kind mapping

DV entity SQLMesh kind Notes
Stage FULL Complete refresh every run
Hub INCREMENTAL_UNMANAGED HWM-based incremental load
Link INCREMENTAL_UNMANAGED HWM-based incremental load
Satellite v0 INCREMENTAL_UNMANAGED HWM-based incremental load
Satellite v1 FULL Complete refresh; see Limitations

Override the kind via kind={"name": "FULL"} if needed.


Limitations

Satellite v1 materializes as a table, not a view

Data Vault 2 specifies that a v1 (end-dated) satellite is a derived view over the v0 base satellite. In SQLMesh, Python execute models can only produce tables — the VIEW model kind is only available for SQL models. For this reason, satellite_v1_model uses FULL (complete refresh table).

The semantic result is the same: every run reconstructs the full end-dated history from the v0 source. The cost is a full table rewrite on each run rather than a no-op view.

Satellite v0 is single-source only

satellite_model accepts a single SourceModel. Multi-source satellites are not supported. If your source data comes from multiple staging tables, load them into a single staging model first.

Stage source columns are not inferred automatically

StageGenerator produces a SELECT * from the raw source, so the source table columns are not known at model-definition time. Any column that needs to appear in the SQLMesh columns={} schema — including all business key and payload columns — must be declared explicitly via column_overrides.


Running tests

cd datavault4sqlmesh
pip install -e ".[test]"
pytest tests/

📄 License

This project is licensed under the GNU Affero General Public License v3 (AGPL-3.0) - see the LICENSE file for details.


🤝 Contributing

We welcome and appreciate community contributions! To keep the project sustainable while ensuring the software remains open and accessible, we follow a Dual-Licensing model.

📜 Licensing & Open Source

This project is licensed under the GNU Affero General Public License v3 (AGPL-3.0).

The AGPL is a "strong copyleft" license. If you modify this software and provide it as a service over a network (SaaS), you must make your modified source code available to your users under the same license.

✍️ Contributor License Agreement (CLA)

To contribute code, all contributors are required to sign our Contributor License Agreement (CLA).

  • Why? This ensures that you have the right to contribute the code and grants us the necessary rights to include your work in future versions of the project, including potential commercial or non-AGPL distributions.
  • How? FIXME

💼 Commercial Usage & Licensing

We understand that the AGPL-3.0 may not be suitable for every organization's internal policies or proprietary products.

If you wish to use this project in a commercial or proprietary setting without the "copyleft" requirements of the AGPL, we offer alternative commercial licenses. This allows you to:

  • Use the software without disclosing your own source code.
  • Receive dedicated support and enterprise-grade warranties.
  • Support the development team.

Please contact us at contact@scalefree.com to discuss a commercial license tailored to your needs.


Built by Scalefree

Metadata

Release files for datavault4sqlmesh 0.1.1

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for datavault4sqlmesh 0.1.1
File Size Uploaded Provenance Actions
datavault4sqlmesh-0.1.1.tar.gz 58.4 kB Without provenance Details for datavault4sqlmesh-0.1.1.tar.gz

Built distribution (wheel)

Table of built distributions (wheels) for datavault4sqlmesh 0.1.1
File Interpreter ABI Platform Actions
datavault4sqlmesh-0.1.1-py3-none-any.whl Python 3 none any Details for datavault4sqlmesh-0.1.1-py3-none-any.whl

Total release size: 105.1 kB

Release files / datavault4sqlmesh-0.1.1.tar.gz

Download URL datavault4sqlmesh-0.1.1.tar.gz
Size 58.4 kB
Tags Source
SHA-256 checksum
How to use checksums
5f2ab970668ce053d4a14751c868ae24607a2ce68068361192930b11a9baa02b
BLAKE2b-256 checksum
How to use checksums
b66fdd887d5c1348a3fcb0ad45e544cfed54cc1ea3a639aa7c3815923c179168
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/6.2.0 CPython/3.13.6

Release files / datavault4sqlmesh-0.1.1-py3-none-any.whl

Download URL datavault4sqlmesh-0.1.1-py3-none-any.whl
Size 46.6 kB
Tags Python 3
SHA-256 checksum
How to use checksums
11e4bcbcab9fb685635bf3db22cc6f5fef5d20d3a97dc437bfd0d39451ed724e
BLAKE2b-256 checksum
How to use checksums
c5105912aa27423836554e0ffe8af0e79d551135d6e0be6b6e0cd9dc135c8e62
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/6.2.0 CPython/3.13.6

Security for datavault4sqlmesh 0.1.1

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

No provenance found

None of the files in this release were uploaded with provenance metadata.

A note on package security

PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.

To learn more about protecting yourself from malicious actors, visit our package security documentation.

Release history Release notifications | RSS feed

This release

0.1.1 This release

2 release files No provenance

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page