Skip to main content

An Apache Arrow ADBC driver for DuckDB's Quack remote protocol.

Project description

adbc-driver-quack

An Apache Arrow ADBC driver for DuckDB's Quack remote protocol.

PyPI PyPI downloads Python versions Go module CI GitHub Repo License: MIT

Returns Apache Arrow RecordBatches directly from a remote DuckDB server speaking Quack. Supports the standard ADBC bulk-ingest path (Statement.BindStreamAPPEND_REQUEST) for fast column-oriented loads.

Distributed as:

  • a Go module — github.com/gizmodata/adbc-driver-quack
  • a pip install adbc-driver-quack wheel for Python (macOS / Linux / Windows × x64 / arm64)

Status: Alpha — v0.1.0-alpha.1 is the first release. The companion gizmodata/quack-jdbc JDBC driver is the same protocol from the JVM and is at v0.1.0-alpha.1 on Maven Central.

Quickstart

1. Start a Quack server (any DuckDB v1.5.2+)

-- in any DuckDB session, with the unsigned extensions flag enabled (`duckdb -unsigned`)
INSTALL quack FROM core_nightly;
LOAD quack;
CALL quack_serve('quack:127.0.0.1:9494', token=>'my-secret-token');

The server stays running until the DuckDB session exits. Press Ctrl-C in the DuckDB REPL to stop it.

2. Install the driver

Python:

pip install adbc-driver-quack

Go:

go get github.com/gizmodata/adbc-driver-quack@latest

3. Connect and query

import adbc_driver_quack.dbapi as quack
import pyarrow

with quack.connect(
    uri="quack://127.0.0.1:9494",
    db_kwargs={"adbc.quack.token": "my-secret-token"},
) as conn, conn.cursor() as cur:
    cur.execute("SELECT 42 AS answer, 'hello duckdb' AS greeting")
    table: pyarrow.Table = cur.fetch_arrow_table()
    print(table)

The result is a real pyarrow.Table — pass it straight to Polars, Pandas, DuckDB-in-process, ibis, or anything else that consumes Arrow:

import polars as pl
df = pl.from_arrow(table)

Alternative: drive adbc_driver_manager directly

If you prefer the adbc-quickstarts idiom — passing the driver to adbc_driver_manager.dbapi.connect rather than going through our wrapper — point at the bundled shared library via _driver_path():

from adbc_driver_manager import dbapi
import adbc_driver_quack

with dbapi.connect(
    driver=adbc_driver_quack._driver_path(),
    entrypoint="QuackDriverInit",
    db_kwargs={
        "uri": "quack://127.0.0.1:9494",
        "adbc.quack.token": "my-secret-token",
    },
) as conn, conn.cursor() as cur:
    cur.execute("SELECT 42 AS answer")
    table = cur.fetch_arrow_table()

Both styles work the same on the wire — pick whichever reads better for your codebase.

Streaming large result sets

Cursor.fetch_record_batch() returns a pyarrow.RecordBatchReader that pulls one server-side DataChunk per read_next_batch() call. Memory stays bounded by the server's chunk size (~2k rows) even when the result is millions of rows:

with conn.cursor() as cur:
    cur.execute("SELECT * FROM lineitem")  # arbitrary size
    reader = cur.fetch_record_batch()
    for batch in reader:
        process(batch)  # one ~2k-row Arrow batch at a time

Bulk ingest (Arrow → DuckDB)

import pyarrow as pa
import adbc_driver_quack.dbapi as quack

table = pa.table({"id": [1, 2, 3], "name": ["alice", "bob", "carol"]})
with quack.connect(uri="quack://127.0.0.1:9494", db_kwargs={"adbc.quack.token": "..."}) as conn, conn.cursor() as cur:
    cur.adbc_ingest(table_name="customers", data=table, mode="append")  # one APPEND_REQUEST per RecordBatch

Transactions (autocommit off)

import adbc_driver_quack.dbapi as quack

with quack.connect(
    uri="quack://127.0.0.1:9494",
    db_kwargs={"adbc.quack.token": "..."},
    autocommit=False,
) as conn, conn.cursor() as cur:
    cur.execute("INSERT INTO orders VALUES (1, 'pending')")
    cur.execute("INSERT INTO order_items VALUES (1, 'widget', 2)")
    conn.commit()  # both inserts persist atomically

Connection URL

quack://host[:port]
Option Default Notes
adbc.uri Required. Pass as the uri= kwarg to quack.connect.
adbc.quack.token (none) Authentication token. Server-side token=> argument to quack_serve().
adbc.quack.tls false true → use https:// for the underlying HTTP transport.

The URI is its own kwarg; everything else goes through db_kwargs:

import adbc_driver_quack.dbapi as quack

quack.connect(
    uri="quack://127.0.0.1:9494",
    db_kwargs={
        "adbc.quack.token": "my-secret-token",
        "adbc.quack.tls": "false",
    },
)

Why ADBC and not JDBC?

Both drivers speak the same protocol to the same kind of server. Pick the one that fits your runtime:

You're using Reach for
A JVM tool (DBeaver, IntelliJ, Spark, dbt-jdbc, plain java.sql) quack-jdbc
Python (pip install), Go, Rust, R, anything via ADBC C ABI this driver
You want zero-copy Arrow data end-to-end this driver

Repo layout

adbc-driver-quack/
├── go.mod, go.sum
├── internal/
│   ├── codec/       — BinaryReader/Writer for DuckDB BinarySerializer
│   ├── quacktype/   — Logical / physical / extra type system + codec
│   ├── message/     — DataChunk, DecodedVector, MessageCodec, VectorCodec
│   └── transport/   — QuackURI parser + net/http transport (IPv4/IPv6 fallback)
├── driver/quack/    — pure-Go ADBC Driver/Database/Connection/Statement impl
├── pkg/quack/       — cgo c-shared wrapper (produces libadbc_driver_quack.{so,dylib,dll})
├── python/          — Python wheel sources (adbc_driver_quack)
└── .github/         — CI: go test, python tests, cibuildwheel matrix, PyPI publish

The internal/ layer is a clean-room Go port of the matching Java packages in quack-jdbc.

Credits

License

MIT — see LICENSE for full attribution.

Project details


Download files

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

Source Distributions

No source distribution files available for this release.See tutorial on generating distribution archives.

Built Distributions

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

adbc_driver_quack-0.1.0a3-py3-none-win_amd64.whl (8.5 MB view details)

Uploaded Python 3Windows x86-64

adbc_driver_quack-0.1.0a3-py3-none-macosx_15_0_universal2.whl (4.2 MB view details)

Uploaded Python 3macOS 15.0+ universal2 (ARM64, x86-64)

File details

Details for the file adbc_driver_quack-0.1.0a3-py3-none-win_amd64.whl.

File metadata

File hashes

Hashes for adbc_driver_quack-0.1.0a3-py3-none-win_amd64.whl
Algorithm Hash digest
SHA256 9c08ee2053f2b22d908753bcf8c2dabcc4fe52ecee503594aa0d4ad8a1e344c9
MD5 66a5ace2dc550e27f6f6b0dad58c67f4
BLAKE2b-256 6ec0b99a5ed2697f9e5af997bdd038c691dd9ed09176f212d3835fc065c46b8b

See more details on using hashes here.

Provenance

The following attestation bundles were made for adbc_driver_quack-0.1.0a3-py3-none-win_amd64.whl:

Publisher: python.yml on gizmodata/adbc-driver-quack

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file adbc_driver_quack-0.1.0a3-py3-none-manylinux2014_x86_64.whl.

File metadata

File hashes

Hashes for adbc_driver_quack-0.1.0a3-py3-none-manylinux2014_x86_64.whl
Algorithm Hash digest
SHA256 2116f0884feebc3edf393b1a9afea454b294a8e59f485780c2ab0377af1fa1b7
MD5 b020553cafab5a0f5dcaff3b2212af16
BLAKE2b-256 039a96229cf2ae79a3777b88ccf6363dd44af348cafcdbba29a063391c0b466a

See more details on using hashes here.

Provenance

The following attestation bundles were made for adbc_driver_quack-0.1.0a3-py3-none-manylinux2014_x86_64.whl:

Publisher: python.yml on gizmodata/adbc-driver-quack

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file adbc_driver_quack-0.1.0a3-py3-none-manylinux2014_aarch64.whl.

File metadata

File hashes

Hashes for adbc_driver_quack-0.1.0a3-py3-none-manylinux2014_aarch64.whl
Algorithm Hash digest
SHA256 98b1feba89d13ff8979b1ffe63e80c7b8d52c2c505cd45006116e8a8266d4a76
MD5 40c9408ad78ff661af2a0502d670cdeb
BLAKE2b-256 207622df1149e6c0c5f0293c97ae921e68d112739d97f61c628e2d55edadbf6c

See more details on using hashes here.

Provenance

The following attestation bundles were made for adbc_driver_quack-0.1.0a3-py3-none-manylinux2014_aarch64.whl:

Publisher: python.yml on gizmodata/adbc-driver-quack

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file adbc_driver_quack-0.1.0a3-py3-none-macosx_15_0_universal2.whl.

File metadata

File hashes

Hashes for adbc_driver_quack-0.1.0a3-py3-none-macosx_15_0_universal2.whl
Algorithm Hash digest
SHA256 da928375f442aa0ce9d866b319b626579de4c3e34fc88afe83d7b15e60a7ae85
MD5 fc4c28a59661a31279249f0d82bdead3
BLAKE2b-256 29c887a017c6e186d7ca163f4f9e142d28ff8abd27b296f3ec9a9e91de11d825

See more details on using hashes here.

Provenance

The following attestation bundles were made for adbc_driver_quack-0.1.0a3-py3-none-macosx_15_0_universal2.whl:

Publisher: python.yml on gizmodata/adbc-driver-quack

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

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