Dependency Graph
Your queries define the graph
Dependencies are automatic. Write queries. OndatraSQL figures out the order.
Mental Model
- Files are nodes
- SQL references create edges
- Execution is automatic
You never define the DAG.
How Dependencies Are Detected
- SQL models → table references from
FROM,JOIN, CTEs, subqueries - Starlark models →
query("...")calls (followed throughload()imports) - YAML models → same as Starlark via source functions
Only references to other models create dependencies.
Limitation
Only static SQL is detected:
query("SELECT * FROM staging.orders") # tracked
query("SELECT * FROM " + table) # not tracked
Dynamic queries are silently skipped.
Execution Order
If a model reads another model, it runs after it.
raw.orders → staging.orders
raw.customers → staging.customers
staging.* → mart.revenue
Run Types
Each model gets a run type before execution:
| Run Type | Meaning |
|---|---|
skip | Nothing changed |
backfill | First run or definition changed |
incremental | New/changed data |
full | Upstream changed |
These decisions propagate through the graph.
Propagation
When a model runs, downstream models are re-evaluated. Changes flow through the DAG.
If a model fails, downstream models do not run.
Traditional Approach
@task
def staging_orders():
...
@task
def mart_revenue():
staging_orders()
Manual DAG. Maintained by hand.
OndatraSQL:
SELECT * FROM staging.orders
DAG inferred automatically.
Commands
Run:
ondatrasql run # All models in DAG order
ondatrasql run staging.orders # Single model
Preview:
ondatrasql sandbox
Inspect:
ondatrasql lineage overview # All dependencies
ondatrasql lineage staging.orders # One model
Circular dependencies are detected at build time.
Why This Matters
Most tools require defining dependencies manually, maintaining DAGs, and debugging execution order.
OndatraSQL builds the graph from your code. Your queries define the graph.
Ondatra Labs