Skip to content

ADBC Scanner

Connect DuckDB to any database with an Arrow Database Connectivity (ADBC) driver — SQLite, PostgreSQL, Snowflake, Flight SQL, and more — using Arrow's columnar wire format end to end.

261,822
extension loads · last 90 days
On this page

Technical Overview

Arrow all the way from the remote database

What is ADBC?

  • Standard API, many drivers: Drivers exist for SQLite, PostgreSQL, Snowflake, BigQuery, Flight SQL, DuckDB itself, and a growing list of others — anywhere data already lives in or near Arrow.
  • No row-format intermediate: Result batches arrive as Arrow record batches and feed straight into DuckDB's vectorized executor without transposition or per-row allocation. A batch is a contiguous block of columns the driver hands DuckDB by pointer; DuckDB reads it in place.
  • Pluggable driver model: Drivers are loaded as shared libraries (or via lightweight manifest.toml files) at runtime — no recompiling DuckDB to add support for a new database.

Two execution models

  • Catalog mode — declarative, read-only: An ATTACH mounts the remote database as a DuckDB catalog: its schemas and tables appear under an alias, and the optimizer pushes projections and filters down into the driver while streaming Arrow batches into the vectorized executor. A join against local Parquet plans as one query — LIMIT can short-circuit the upstream scan, exactly like reading a Parquet file. The tradeoff is that the catalog interface is read-only — no DDL or DML flows through it.
  • Function mode — imperative, full control: A connection handle lets you script the session explicitly: run server-side DDL/DML, set your own transaction boundaries, and perform Arrow-native bulk inserts that hand the driver columnar batches with no row-format detour. You trade automatic pushdown (here it only reaches as far as the SQL string you send) for the ability to write and to control transactions yourself.
  • How to choose: Reach for catalog mode whenever the work is read-only analytics — it's less code and the optimizer does the pushdown for you. Drop into function mode the moment you need to mutate the remote, manage transactions explicitly, or bulk-load Arrow batches in. Because both target the same driver, a common pattern is catalog mode for the queries and function mode for the occasional write, in the same session.

Driver Setup

  • By name (manifest-resolved): 'driver': 'sqlite' looks up a .toml manifest in the standard ADBC search paths. Most install methods — pip install adbc-driver-postgresql, Homebrew, system packages — drop manifests in the right place automatically.
  • By explicit path: 'driver': '/path/to/libadbc_driver_xxx.dylib' skips manifest resolution — useful for vendored drivers or unusual install locations.
  • Custom search paths: Pass 'search_paths': '/opt/adbc/drivers' inside the connect options to add manifest directories without changing OS-level config.
  • Drivers run as trusted native code: However it's resolved, a driver loads into DuckDB's address space and runs with the user's privileges — treat it like LOAD. In multi-tenant or hosted DuckDB, restrict ADBC access to roles that already have arbitrary-code-execution authority, and load only vetted upstream drivers.

ADBC Scanner vs Airport

  • Use ADBC Scanner: When the system on the other end is a database with an ADBC driver — SQLite, PostgreSQL, Snowflake, BigQuery, MySQL, etc. ADBC is a client API standard.
  • Use Airport: When the system on the other end speaks Arrow Flight directly — typically custom services or Flight-native systems like Dremio. Flight is an RPC protocol, not a client API. See the airport extension.
  • vs purpose-built scanners: DuckDB's postgres_scanner / mysql_scanner / sqlite_scanner are often faster for the one database they target. Reach for ADBC Scanner when no purpose-built extension exists, when you want a single client surface across many backends, or when you specifically want Arrow end-to-end (Snowflake, BigQuery).

Deep Dive

Technical Details

Install

INSTALL adbc_scanner FROM community;
LOAD adbc_scanner;

Quick Start

Connect to SQLite via its ADBC driver

SET VARIABLE conn = (SELECT adbc_connect({'driver':'sqlite', 'uri':':memory:'}));

Run a query — result is a regular DuckDB table

SET VARIABLE conn = (SELECT adbc_connect({'driver':'sqlite', 'uri':':memory:'}));
SELECT * FROM adbc_scan(getvariable('conn')::BIGINT, 'SELECT * FROM my_table');

Run DDL / DML on the remote database

SET VARIABLE conn = (SELECT adbc_connect({'driver':'sqlite', 'uri':':memory:'}));
SELECT adbc_execute(getvariable('conn')::BIGINT, 'CREATE TABLE users(id INT, name TEXT)');

Disconnect when done

SET VARIABLE conn = (SELECT adbc_connect({'driver':'sqlite', 'uri':':memory:'}));
SELECT adbc_disconnect(getvariable('conn')::BIGINT);

Reference

Extension Contents

Quick reference to all available functions and settings organized by category.

Name Description
ADBC Catalog
adbc Attach an ADBC-driven database as a DuckDB catalog.
Connection
adbc_clear_cache() Drop any cached driver / connection state.
adbc_connect() Open a connection to a remote database via an ADBC driver.
adbc_disconnect() Close a connection opened with adbc_connect and free its resources.
adbc_info() Return driver and server metadata for an open connection — vendor name, version strings, supported features.
Database Connection
adbc Stored credentials and connection details for ADBC drivers.
Mutation
adbc_execute() Execute a non-SELECT statement (DDL or DML).
adbc_insert() Bulk-insert into a remote table — passes Arrow record batches directly through the driver's bulk-load path.
Query
adbc_scan() Execute a SELECT and return its rows as a DuckDB table.
adbc_scan_table() Stream an entire remote table by name, without writing SQL — equivalent to adbc_scan(conn, 'SELECT * FROM <table>') but routed through ADBC's bulk-read API where supported.
Schema
adbc_columns() Describe the columns of a table — name, type, nullability, default — pulled from the driver's catalog API.
adbc_schema() Return the full Arrow schema for a query result without executing it.
adbc_table_types() List the table-type categories the driver/server distinguishes (e.g.
adbc_tables() List tables visible to the connection.
Transactions
adbc_commit() Commit the current transaction on the connection.
adbc_rollback() Roll back the current transaction.
adbc_set_autocommit() Toggle autocommit mode.

API Reference

Function Documentation

Database Storage

Storage Extensions

Catalog implementations that attach external storage as a DuckDB database.

adbc

Description
Parameters
Parameter Type Required Description
driver VARCHAR Required Driver identifier — a registered name (e.g. 'sqlite', 'postgresql'), an absolute path to a libadbc_driver_* shared library, or a manifest name resolved via the ADBC search paths.
entrypoint VARCHAR Optional Custom driver entrypoint function name. Only needed for drivers that don't follow the standard AdbcDriverInit symbol convention.
search_paths VARCHAR Optional Extra colon-separated directories to look in for ADBC manifest (*.toml) files, in addition to the platform defaults.
use_manifests VARCHAR Optional Default: true Set to 'false' to skip manifest resolution entirely (load the driver only by absolute path).
batch_size INTEGER Optional Hint for the number of rows per Arrow batch when scanning. Larger values reduce per-batch overhead at the cost of memory.
Examples
1
-- libpq pulls credentials from the URI; ATTACH parameters don't interpolate bind variables.
ATTACH 'postgresql://reader:secret@localhost/mydb' AS pg (
  TYPE adbc,
  driver 'postgresql'
);

-- Query as if it were local — projection + filter pushdown happen automatically
SELECT user_id, COUNT(*) AS events
FROM pg.public.activity
WHERE ts >= CURRENT_DATE - 7
GROUP BY user_id;
2
ATTACH '/data/app.db' AS local_app (
  TYPE adbc,
  driver 'sqlite'
);

SHOW TABLES FROM local_app.main;
3
ATTACH 'snowflake://account.snowflakecomputing.com' AS sf (
  TYPE adbc,
  driver '/opt/adbc/lib/libadbc_driver_snowflake.dylib',
  username :sf_user,
  password :sf_password,
  use_manifests 'false'
);

Security

Secrets

DuckDB secrets for storing the credentials and keys used by the adbc scanner extension.

adbc

Description
Parameters
Parameter driver Type VARCHAR Required Required Description ADBC driver name (e.g. 'sqlite', 'postgresql') or path to a shared library.
Parameter uri Type VARCHAR Required Optional Description Connection URI passed to the driver. Driver-specific format.
Parameter username Type VARCHAR Required Optional Description Database username.
Parameter password Type VARCHAR Required Optional Description Database password. Automatically redacted in logs.
Parameter database Type VARCHAR Required Optional Description Database name, when not encoded in the URI.
Parameter entrypoint Type VARCHAR Required Optional Description Custom driver entrypoint function name (rarely needed).
Examples
1

PostgreSQL with credentials and a SCOPE for auto-lookup

CREATE SECRET my_postgres (
  TYPE adbc,
  SCOPE 'postgresql://prod-server:5432',
  driver 'postgresql',
  uri 'postgresql://prod-server:5432/mydb',
  username 'app_user',
  password 'secret_password'
);
2

Local SQLite

CREATE SECRET my_sqlite (
  TYPE adbc,
  SCOPE 'sqlite://data',
  driver 'sqlite',
  uri '/var/data/app.db'
);
3

Use the secret explicitly by name

SET VARIABLE conn = (SELECT adbc_connect({'secret': 'my_postgres'}));
4

Auto-lookup — DuckDB picks the secret whose SCOPE matches the URI

SET VARIABLE conn = (SELECT adbc_connect({
  'uri': 'postgresql://prod-server:5432/mydb'
}));
5

Persist the secret to ~/.duckdb/secrets/

CREATE PERSISTENT SECRET my_postgres (
  TYPE adbc,
  SCOPE 'postgresql://prod-server:5432',
  driver 'postgresql',
  uri 'postgresql://prod-server:5432/mydb',
  username 'app_user',
  password 'secret_password'
);

Practical Examples

Cookbook

Real-world recipes and patterns for common use cases.

Platform Support

Compatibility

Extension availability may vary by platform and DuckDB version. Check below to ensure this extension supports your environment before installation.

Quick Facts

Release status Stable
Software License MIT
Pricing Free
Written In C++
Source Available Yes
View on GitHub
Usage
261,822
loads · last 90 days

Platforms

  • Linux x86_64 aarch64
  • Linux (musl) Not available
  • macOS Intel Apple Silicon
  • Windows x86_64
  • WASM Not available
Compiled binary sizes
Platform Architecture Size
Linux x86_64 11.14 MB
Linux aarch64 9.87 MB
macOS Intel 8.47 MB
macOS Apple Silicon 7.46 MB
Windows x86_64 7.64 MB

Compressed download size from the Haybarn extension repository.

DuckDB & Haybarn

Release calendar