Getting started¶
duckrun gives you a DuckDB SQL engine that reads and writes Delta Lake — locally or on
OneLake / S3 / GCS / ADLS. Everything below is plain conn.sql(...): if you know SQL, you're
already productive.
1. Connect¶
import duckrun
# Read-only by default — safe to explore, no accidental writes.
conn = duckrun.connect("./lakehouse/Tables")
# OneLake: duckrun.connect("abfss://<ws>@onelake.dfs.fabric.microsoft.com/<lakehouse>/Tables/dbo")
# OneLake shorthand for the same thing: duckrun.connect("<ws>/<lakehouse>.Lakehouse/dbo")
# — also takes GUIDs: duckrun.connect("<ws-guid>/<lakehouse-guid>")
# — a suffix-less "ws/lh" stays a local relative path
# Opt into writes:
conn = duckrun.connect("./lakehouse/Tables", read_only=False)
2. Explore and query¶
conn.sql("SHOW TABLES").show()
conn.sql("SELECT status, count(*) FROM orders GROUP BY status").show()
reader = conn.sql("SELECT * FROM orders").fetch_arrow_reader() # streaming pyarrow.RecordBatchReader
# conn.sql(...) returns DuckDB's native relation — .df() / .arrow() / .pl() / .fetchall() all work
3. Write a table — plain SQL¶
# create (or replace) a Delta table from a query
conn.sql("CREATE OR REPLACE TABLE clean_orders AS SELECT * FROM orders WHERE amount > 0")
# append more rows
conn.sql("INSERT INTO clean_orders SELECT * FROM new_orders")
# update / delete in place
conn.sql("UPDATE clean_orders SET status = 'closed' WHERE amount = 0")
conn.sql("DELETE FROM clean_orders WHERE status = 'void'")
4. Upsert with MERGE¶
conn.sql("""
MERGE INTO clean_orders USING updates ON target.id = source.id
WHEN MATCHED THEN UPDATE SET *
WHEN NOT MATCHED THEN INSERT *
""")
Every write commits snapshot-pinned: if another writer changed the table since you read it,
the commit fails loud (CommitFailedError) instead of silently overwriting — so concurrent jobs
never lose each other's updates.
5. Use more than one catalog¶
Attach another lakehouse — or a Fabric Warehouse read-only — and join across them by
three-part catalog.schema.table name:
conn.attach(
"abfss://<ws>@onelake.dfs.fabric.microsoft.com/<warehouse>.Warehouse/Tables",
name="wh", read_only=True,
)
conn.sql("""
CREATE OR REPLACE TABLE daily_revenue AS
SELECT d.order_date, sum(f.amount) AS revenue
FROM wh.dbo.fact_sales f JOIN dim_date d ON d.date_id = f.date_id
GROUP BY d.order_date
""")
The read-only fence refuses any write to wh. Works the same against a local path, s3://,
gs://, or az://.
Next: building multi-model pipelines with dbt · runnable Examples · the full Connection API reference.