DuckDB ORC Extension (Rust)
July 14, 2026 · View on GitHub
A DuckDB extension for reading Apache ORC files, written in pure Rust.
Built on top of orc-rust, a native Rust ORC reader.
Features
read_orc(file_path)— read.orcfiles directly into DuckDB- All ORC data types: primitives, struct, list, map
- All ORC encodings and compression codecs (Zlib, Snappy, LZO, LZ4, ZSTD)
- Projection pushdown — column pruning via DuckDB's optimizer
- Multi-batch streaming — files of any size, read in 2048-row batches
Limitations
| Feature | Status | Notes |
|---|---|---|
| Filter / predicate pushdown | ❌ | Blocked — DuckDB C extension API does not expose duckdb_table_function_supports_filter_pushdown. Requires upstream DuckDB change. Workaround: DuckDB still applies filters after scan; projection pushdown works. |
| Multi-file / glob | ✅ | read_orc('data/*.orc') — all files must have identical schema. |
| Write support | ⚠️ | orc-rust 0.8+ now has ArrowWriter with full write support, but compression is not yet implemented (uncompressed ORC only). Write support will be added to duckdb_orc once orc-rust supports compressed writes. |
| Parallel scan | ❌ | Currently single-threaded sequential scan. For single large files, DuckDB's native Parquet reader is ~5x faster due to built-in row-group parallelism. See Parallelism below. |
| Community extension | ❌ | PR submitted, pending review. |
Installation
-- Load from local build (unsigned — requires `duckdb -unsigned`)
LOAD './build/debug/extension/orc/orc.duckdb_extension';
-- Read an ORC file
SELECT * FROM read_orc('data.orc');
Usage
-- Basic read
SELECT * FROM read_orc('sales.orc');
-- Filter and aggregate (DuckDB applies filters post-scan)
SELECT region, SUM(amount)
FROM read_orc('sales.orc')
WHERE year = 2024
GROUP BY region;
Building
Prerequisites: Rust toolchain, Python 3, Make.
git clone git@github.com:alitrack/duckdb_orc.git
cd duckdb_orc
# Debug build
make debug
# Release build (optimized, ~10MB)
make release
# Rust integration test (client mode, not loadable-extension mode)
cargo test --test integration_test -- --nocapture
Parallelism
read_orc currently scans files sequentially in a single thread. This is a known limitation:
- Single file: ~5x slower than DuckDB's native Parquet reader on large files (100M rows: 42s vs 7.6s). DuckDB's Parquet reader parallelizes across row groups natively.
- Multi-file glob: each file is read sequentially in alphabetical order.
Workaround for better performance
For single-file performance, convert ORC to Parquet first:
python3 -c "
import pyarrow.orc as orc; import pyarrow.parquet as pq
pq.write_table(orc.read_table('data.orc'), 'data.parquet')
"
Then query the Parquet file in DuckDB — it will benefit from native row-group parallelism.
Future improvements
ORC files are organized in stripes (analogous to Parquet row groups). orc-rust exposes with_file_byte_range() for reading specific byte ranges, which could enable stripe-level parallelism in a future version of duckdb_orc.
Development notes
This repository intentionally separates extension build mode from Rust client/test mode:
make debug/make releasebuild the loadable DuckDB extension with--features extensioncargo testruns without that feature soduckdb::Connection::open_in_memory()works normally
Why this matters:
duckdb/loadable-extensionreplaces parts of the regular DuckDB client API with extension-entrypoint wrappers- if that feature is enabled during normal Rust tests,
Connection::open_in_memory()can fail with:DuckDB API not initialized or DuckDB feature omitted
Recommended workflow:
- Build the extension with
make debugormake release - Run Rust integration tests with plain
cargo test ... - Optionally verify the built artifact in DuckDB CLI with
duckdb -unsigned
Load with DuckDB (requires -unsigned for locally-built extensions):
duckdb -unsigned
LOAD './build/debug/extension/orc/orc.duckdb_extension';
SELECT * FROM read_orc('test.orc');
Credits
orc-rust— native Rust ORC reader (Arrow output)duckdb-rs— Rust bindings for DuckDBquack-rs— alternative Rust SDK for DuckDB extensions (evaluated, not adopted)
License
MIT