Skip to main content

A wizard's library for Databricks data tools and data protection — SCD2 merges, upsert, checksum, surrogate keys, schema validations, and guarded Delta writes. You shall not pass... bad data.

Project description

Data Hub Gandalf

Coverage Quality Gate Status

Python library for Databricks data pipelines — SCD Types 0/1/2/3/4/6, upserts, surrogate keys, checksums, and schema validations. You shall not pass... bad data.

Installation

Published on PyPI as data-hub-gandalf (imported as gandalf):

pip install data-hub-gandalf

In a Databricks notebook or cluster:

%pip install data-hub-gandalf

For an offline / air-gapped install, build the wheel with Poetry and install it from a Unity Catalog volume:

poetry build            # -> dist/data_hub_gandalf-<version>-py3-none-any.whl
%pip install /Volumes/<catalog>/<schema>/<volume>/data_hub_gandalf-<version>-py3-none-any.whl

Quickstart

from gandalf import merge_delta_table

merge_delta_table(
    spark=spark,
    df=df,
    path="main.gold.dim_client",
    ids=["id_client"],
    merge_type="scd",       # SCD Type 2, full snapshot — see Capabilities
    sk_type="dim",
    sk_name="sk_client",
)

Capabilities

A scan-map of the merge strategies and helpers gandalf provides. Legend: ✅ supported · ⚙️ automatic · ⚠️ supported with a caveat · not applicable.

Capability merge_type (legacy alias) Status History Deletes Notes
SCD Type 2 — full snapshot scd2 (scd) row versions logical requires all source rows each run; row count validated
SCD Type 2 — incremental scd2_no_delete (scd_no_delete) row versions incremental source; absent keys are not closed
SCD Type 2 — CDC scd2_cdc ⚠️ blocked event-ordering semantics not implemented; raises NotImplementedError
SCD Type 1 — upsert scd1 (upsert) overwrite current value
SCD Type 1 — upsert + delete scd1_delete (upsert-delete) hard also deletes rows absent from source
SCD Type 0 — insert-only scd0 insert new keys only; protected columns cannot change
SCD Type 3 — previous values scd3 previous-value columns requires previous_columns
SCD Type 4 — history table scd4 separate history table configurable requires history_path
SCD Type 6 — hybrid scd6 row versions + prev columns configurable requires previous_columns
Full overwrite overwrite replaces the whole table
Partition overwrite overwrite-partition replaceWhere-scoped replacement
Checksum change detection ⚙️ generate_check_sum over business columns; powers SCD2/4/6
Surrogate keys generate_dim_sk (SHA-256, unique per version) / generate_fact_sk (xxhash64, deterministic)
Schema & duplicate guards ⚙️ column_check, check_duplicates, table_check, row_count run inside merge_delta_table
Auto column-type casting ⚙️ source columns cast to the target schema before merge

SCD history strategies manage four control columns — scd_start_dt, scd_end_dt, scd_is_current, and scd_checksum — automatically. Point gandalf at a table that uses different names by passing scd_columns=SCDColumns(is_current="current_flag", checksum="check_sum").

See COMPARISON.md for how gandalf compares to other SCD libraries (mack, koheesio, hydro, fabricks, dbt, Databricks DLT…) — SCD-type coverage, test rigor (real-engine E2E / Spark / Databricks), and where gandalf is, and isn't, distinctive.


What it does

merge_delta_table

Persists a Spark DataFrame into a Delta table. Internally it:

  1. Validates the target Delta table exists
  2. Filters incoming data incrementally via delta_col_filter (optional)
  3. Detects duplicates in the source
  4. Validates column schema against the target
  5. Generates checksum for change detection
  6. Generates surrogate key (if sk_type is set)
  7. Auto-casts column types to match target schema
  8. Executes the chosen merge strategy
  9. Validates row count after merge
from gandalf import merge_delta_table

merge_delta_table(
    spark=spark,
    df=df,
    path="main.gold.dim_client",
    ids=["id_client"],
    merge_type="scd",       # see strategies below
    sk_type="dim",
    sk_name="sk_client",
)

Merge strategies — canonical names (legacy aliases accepted):

merge_type Legacy alias SCD type History Deletes Notes
scd2 scd Type 2 Row versions Logical Full snapshot; requires all source rows
scd2_no_delete scd_no_delete Type 2 Row versions No Incremental source
scd2_cdc Type 2 Row versions Yes CDC event ordering — explicitly blocked, raises NotImplementedError
scd1 upsert Type 1 No No Overwrite current value
scd1_delete upsert-delete Type 1 No Hard Overwrite + delete absent rows
scd0 Type 0 No No Insert new keys only; protected columns cannot change
scd3 Type 3 Previous value columns No Requires previous_columns config
scd4 Type 4 Separate history table Configurable Requires history_path config
scd6 Type 6 Row versions + prev columns Configurable Requires previous_columns config
overwrite No N/A Full table replacement
overwrite-partition No N/A Partition-scoped replacement

Advanced strategies (scd0/scd3/scd4/scd6) are configured through SCDConfig:

from gandalf import SCDColumns, SCDConfig, merge_delta_table

# SCD Type 3 — previous-value columns
merge_delta_table(
    spark, df, "catalog.schema.dim_client", ["id_client"],
    scd_config=SCDConfig(scd_type="scd3", ids=["id_client"],
                         previous_columns={"address": "previous_address"}),
)

# SCD Type 4 — current table + history table
merge_delta_table(
    spark, df, "catalog.schema.current_client", ["id_client"],
    scd_config=SCDConfig(scd_type="scd4", ids=["id_client"],
                         history_path="catalog.schema.hist_client"),
)

# SCD Type 6 — Type 2 rows + previous-value columns
merge_delta_table(
    spark, df, "catalog.schema.dim_client", ["id_client"],
    scd_config=SCDConfig(scd_type="scd6", ids=["id_client"],
                         previous_columns={"address": "previous_address"}),
)

SCDConfig also carries the control-column names (columns=SCDColumns(...)), return_metrics, and tracked_columns. Pass either scd_columns or scd_config — not both.


Utilities

from gandalf import generate_check_sum, generate_dim_sk, generate_fact_sk, hash_columns

hash_columns(*cols)                    # SHA-256 Column expr for withColumn/select/when
generate_check_sum(df, control_cols)   # adds scd_checksum over all business columns
generate_dim_sk(df, ids, sk_name)      # SHA-256 surrogate key (unique per SCD version)
generate_fact_sk(df, ids, sk_name)     # xxhash64 surrogate key (deterministic)
Function Description
hash_columns(*cols) SHA-256 Column expression — use inside withColumn, select, when
generate_check_sum(df, control_cols) Adds the scd_checksum column over all business columns
generate_dim_sk(df, ids, sk_name) SHA-256 surrogate key — unique per SCD version
generate_fact_sk(df, ids, sk_name) xxhash64 surrogate key — deterministic across runs

Data protection guidance

  • Prefer checksum comparisons over blind updates so reruns remain idempotent.
  • Validate source-vs-target schemas before Delta MERGE.
  • Use deterministic surrogate keys for dimensions and facts.
  • Keep partition overwrites constrained by explicit predicates.
  • Avoid embedding notebook-only globals inside core library logic; pass dependencies as function arguments.

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

data_hub_gandalf-0.1.1.tar.gz (31.6 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

data_hub_gandalf-0.1.1-py3-none-any.whl (34.9 kB view details)

Uploaded Python 3

File details

Details for the file data_hub_gandalf-0.1.1.tar.gz.

File metadata

  • Download URL: data_hub_gandalf-0.1.1.tar.gz
  • Upload date:
  • Size: 31.6 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: poetry/2.4.1 CPython/3.12.13 Linux/6.17.0-1018-azure

File hashes

Hashes for data_hub_gandalf-0.1.1.tar.gz
Algorithm Hash digest
SHA256 c1661252d633105f09fd28fac016940779269263fb0cac75c97a0dae55b8b8c9
MD5 d5fb14a69d9866bfdd1e005e0e674a00
BLAKE2b-256 e1c6252ea2e3d181fd95d7093f949c7a81e7b5b2da5683d66097464a5c99f9f6

See more details on using hashes here.

File details

Details for the file data_hub_gandalf-0.1.1-py3-none-any.whl.

File metadata

  • Download URL: data_hub_gandalf-0.1.1-py3-none-any.whl
  • Upload date:
  • Size: 34.9 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: poetry/2.4.1 CPython/3.12.13 Linux/6.17.0-1018-azure

File hashes

Hashes for data_hub_gandalf-0.1.1-py3-none-any.whl
Algorithm Hash digest
SHA256 0d95ce378a5b9c7c5c1471c189ce84a3223ca9b31642c748b6a29624fc33d328
MD5 c089796d6ce0b5506dd1550186037735
BLAKE2b-256 91548f750c6a41c1da490d191d68ddd816c2d50586bb50fb2a9b829feefb8c4f

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page