ondatrasql

module
v0.40.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Sep 6, 2026 License: AGPL-3.0

README

OndatraSQL

OndatraSQL

A data pipeline runtime for DuckDB and DuckLake
Ingestion, transformation, and validation in a single binary.

Documentation · Discord · Blueprints


OndatraSQL runs data pipelines using SQL models, DuckDB for query execution, and DuckLake for catalog management, snapshots, and time-travel.

The runtime handles:

  • Dependency resolution — extracted from SQL references
  • Change detection — via DuckLake snapshots and table_changes()
  • Schema evolution — columns added, renamed, or type-promoted automatically
  • Validation — constraints, audits, and warnings as part of execution
  • Incremental processing — Smart CDC rewrites queries to process only changed data, falling back to a full query where it cannot be applied

Install

curl -fsSL https://ondatra.sh/install.sh | sh

Supports Linux, macOS, and Windows via WSL2.

Quick Start

mkdir my-pipeline && cd my-pipeline
ondatrasql init

Ingest data from an API (create a blueprint in lib/):

# lib/countries_fetch.star
API = {
    "base_url": "https://restcountries.com",
    "fetch": {
        "args": [],
    },
}

def fetch(page):
    resp = http.get("/v3.1/region/europe")
    rows = [{"name": c["name"]["common"], "capital": c["capital"][0], "population": c["population"]} for c in resp.json]
    return {"rows": rows, "next": None}
-- models/raw/countries.sql
-- @kind: table
SELECT name::VARCHAR AS name, capital::VARCHAR AS capital, population::BIGINT AS population
FROM countries_fetch()

Transform with SQL:

ondatrasql new staging.countries.sql
ondatrasql edit staging.countries.sql
-- @kind: table
-- @constraint: not_null(name)

SELECT
    name, capital, population,
    CASE
        WHEN population > 50000000 THEN 'large'
        WHEN population > 10000000 THEN 'medium'
        ELSE 'small'
    END AS size
FROM raw.countries

Run the pipeline:

ondatrasql run
Running 2 models...
[OK] raw.countries      (table, backfill, 53 rows, 1.1s)
[OK] staging.countries  (table, backfill, 53 rows, 250ms — first run)

Done: 2 ran, 0 skipped, 0 failed (106 rows, 1.4s)

Model Types

SQL — transformations:

-- @kind: table

SELECT date, SUM(total) AS revenue
FROM staging.orders GROUP BY date

Lib functions — API ingestion and outbound sync via Starlark in lib/:

-- models/raw/users.sql
-- @kind: table
SELECT id::BIGINT AS id, email::VARCHAR AS email, name::VARCHAR AS name FROM my_api('users')
# lib/my_api.star — fetch function called by the SQL model
API = {"base_url": "https://api.example.com", "auth": {"env": "API_KEY"},
       "fetch": {"args": ["resource"], "page_size": 100}}

def fetch(resource, page):
    resp = http.get("/v1/" + resource, params={"limit": page.size, "cursor": page.cursor})
    return {"rows": resp.json["items"], "next": resp.json.get("next")}

Models are SQL files. Starlark is used in lib/ for API transport (HTTP, auth, pagination).

All models execute in the same pipeline and share the same dependency graph.

Key Capabilities

Capability How it works
SQL transformation SQL models with automatic materialization and CDC
API ingestion Built-in HTTP, OAuth, pagination via Starlark
Outbound sync Push to APIs via @push with raw DuckLake change types
Validation 30 constraint macros, 18 audit macros, 14 warning macros
Schema evolution Automatic via ALTER TABLE (metadata-only in DuckLake)
Sandbox preview Full DAG simulation before committing
Column lineage Extracted from SQL AST

Design

OndatraSQL executes on a single machine using DuckDB. It is not a distributed system. For workloads that fit on one machine — batch ETL, reporting, analytics, internal tooling — this approach provides the full pipeline lifecycle with minimal operational overhead.

Commands

run [model]          Execute pipeline or specific model
sandbox [model]      Preview changes before committing
auth [provider]      Authenticate with OAuth2 providers
new <model>          Create a model file
edit <target>        Open file in $EDITOR
sql "SELECT ..."     Query DuckLake catalog
stats                Project overview
describe <model>     Model details and schema
describe blueprint   Blueprint API contract introspection
validate             Static validation of models and blueprints
history [model]      Run history
lineage overview     View dependencies and column lineage
flush                Flush inlined data to Parquet
checkpoint           Run all maintenance

Full CLI reference →

Documentation

ondatra.sh

License

GNU AGPL v3

Directories

Path Synopsis
cmd
ondatrachecks command
ondatrachecks is the project's custom go/analysis multichecker.
ondatrachecks is the project's custom go/analysis multichecker.
ondatrasql command
internal
backfill
Package backfill handles SQL hash calculation and backfill detection.
Package backfill handles SQL hash calculation and backfill detection.
config
Package config handles configuration and paths.
Package config handles configuration and paths.
dag
Package dag builds and sorts a directed acyclic graph of model dependencies.
Package dag builds and sorts a directed acyclic graph of model dependencies.
duckast
Package duckast wraps DuckDB's json_serialize_sql output as a typed view over a raw map.
Package duckast wraps DuckDB's json_serialize_sql output as a typed view over a raw map.
duckdb
Package duckdb provides an embedded DuckDB session using go-duckdb.
Package duckdb provides an embedded DuckDB session using go-duckdb.
execute
Package execute provides batch query capabilities for run_type decisions.
Package execute provides batch query capabilities for run_type decisions.
git
Package git provides utilities for extracting Git repository metadata.
Package git provides utilities for extracting Git repository metadata.
libcall
Package libcall detects blueprint (lib function) references in SQL ASTs.
Package libcall detects blueprint (lib function) references in SQL ASTs.
lineage
Package lineage provides column-level lineage tracking and visualization.
Package lineage provides column-level lineage tracking and visualization.
lintcheck/committhreadcheck
Package committhreadcheck enforces that every materialize write transaction in internal/execute/materialize.go is built through the commitTxnSQL helper rather than a direct sql.MustFormat("execute/commit.sql", ...) call.
Package committhreadcheck enforces that every materialize write transaction in internal/execute/materialize.go is built through the commitTxnSQL helper rather than a direct sql.MustFormat("execute/commit.sql", ...) call.
lintcheck/escapesqlcheck
Package escapesqlcheck enforces that values interpolated into quoted-string SQL contexts (ATTACH '<conn>', SET search_path = '<v>', and similar) are wrapped in EscapeSQL — never raw.
Package escapesqlcheck enforces that values interpolated into quoted-string SQL contexts (ATTACH '<conn>', SET search_path = '<v>', and similar) are wrapped in EscapeSQL — never raw.
lintcheck/listenandservecheck
Package listenandservecheck flags net/http Server.Serve and Server.ListenAndServe call sites whose returned error isn't matched against http.ErrServerClosed.
Package listenandservecheck flags net/http Server.Serve and Server.ListenAndServe call sites whose returned error isn't matched against http.ErrServerClosed.
lintcheck/pushauthcheck
Package pushauthcheck enforces that every call to a RunPush* method (RunPush, RunPushFinalize, RunPushPoll, ...) includes a call to httpConfigFromLib(...) among its arguments.
Package pushauthcheck enforces that every call to a RunPush* method (RunPush, RunPushFinalize, RunPushPoll, ...) includes a call to httpConfigFromLib(...) among its arguments.
lintcheck/pushdeltacheck
Package pushdeltacheck enforces that internal/execute/push_delta.go is kind-agnostic — every supported kind goes through the same table_changes() query path.
Package pushdeltacheck enforces that internal/execute/push_delta.go is kind-agnostic — every supported kind goes through the same table_changes() query path.
lintcheck/removedlibdictscheck
Package removedlibdictscheck flags top-level `TABLE = ...` or `SINK = ...` variable declarations in `internal/parser` and `internal/libregistry`.
Package removedlibdictscheck flags top-level `TABLE = ...` or `SINK = ...` variable declarations in `internal/parser` and `internal/libregistry`.
lintcheck/schemaversioncheck
Package schemaversioncheck enforces the v0.31 contract that every machine-readable output type emitted by the CLI carries a schema_version field.
Package schemaversioncheck enforces the v0.31 contract that every machine-readable output type emitted by the CLI carries a schema_version field.
lintcheck/sqlfmtcheck
Package sqlfmtcheck flags fmt.Sprintf calls that build SQL strings using the %v or %s verb on values of unknown provenance.
Package sqlfmtcheck flags fmt.Sprintf calls that build SQL strings using the %v or %s verb on values of unknown provenance.
lintcheck/sscanfcheck
Package sscanfcheck flags fmt.Sscanf calls that parse integers or floats.
Package sscanfcheck flags fmt.Sscanf calls that parse integers or floats.
lintcheck/strconvcheck
Package strconvcheck flags strconv parse calls (Atoi, ParseInt, ParseUint, ParseFloat, ParseBool) whose error return is discarded via the blank identifier.
Package strconvcheck flags strconv parse calls (Atoi, ParseInt, ParseUint, ParseFloat, ParseBool) whose error return is discarded via the blank identifier.
lintcheck/syntheticcolcheck
Package syntheticcolcheck enforces the kind-conversion contract in internal/execute/materialize.go: any materialize function that issues an INSERT … BY NAME while also dealing with a kind's persisted *synthetic* columns must first ensure those columns exist on the target.
Package syntheticcolcheck enforces the kind-conversion contract in internal/execute/materialize.go: any materialize function that issues an INSERT … BY NAME while also dealing with a kind's persisted *synthetic* columns must first ensure those columns exist on the target.
oauth2host
Package oauth2host implements the self-contained ("local") OAuth flow: browser consent and token refresh run directly against the provider using the user's own client_id/client_secret (from env), with the refresh token stored in the encrypted state catalog.
Package oauth2host implements the self-contained ("local") OAuth flow: browser consent and token refresh run directly against the provider using the user's own client_id/client_secret (from env), with the refresh token stored in the encrypted state catalog.
output
Package output provides structured JSON output support.
Package output provides structured JSON output support.
parser
Package parser handles SQL model file parsing.
Package parser handles SQL model file parsing.
script
Package script provides a Starlark-based scripting runtime for data pipelines.
Package script provides a Starlark-based scripting runtime for data pipelines.
sql
Package sql provides embedded SQL files for OndatraSQL operations.
Package sql provides embedded SQL files for OndatraSQL operations.
state
Package state provides a local DuckDB-backed store for operational state — push queue, fetch staging buffer, OAuth tokens.
Package state provides a local DuckDB-backed store for operational state — push queue, fetch staging buffer, OAuth tokens.
testutil
Package testutil provides shared test helpers.
Package testutil provides shared test helpers.
validate
Package validate is the static validation engine behind the `validate` CLI command.
Package validate is the static validation engine behind the `validate` CLI command.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL