feat: add read_parquet, read_csv, read_json, read_avro SQL table functions - #21367
feat: add read_parquet, read_csv, read_json, read_avro SQL table functions#21367crm26 wants to merge 3 commits into
Conversation
…tions Built-in table functions that read files directly from SQL without prior registration. Each wraps ListingTable with the appropriate FileFormat, inheriting full optimizer support (filter pushdown, projection pushdown, partition pruning, limit pushdown) automatically. Parquet and Avro are feature-gated; CSV and JSON are always available. Schema inference uses block_in_place to bridge the sync TableFunctionImpl trait with async ListingOptions::infer_schema. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
…tions
Adds four inline SQL table functions that create ListingTable-backed
scans, enabling DuckDB-style ad-hoc file querying:
SELECT * FROM read_parquet('/path/to/*.parquet')
SELECT * FROM read_csv('/data/file.csv')
SELECT * FROM read_json('/data/file.json')
SELECT * FROM read_avro('/data/file.avro')
Each function is a thin wrapper (~60 lines) over ListingTable:
1. Extracts path from SQL literal argument
2. Constructs ListingOptions with the format's FileFormat
3. Infers schema via blocking bridge (std::thread::scope)
4. Returns ListingTable as TableProvider
Since the SQL planner wraps UDTF output as LogicalPlan::TableScan,
all optimizer rules apply automatically — filter pushdown, projection
pushdown, and partition pruning work out of the box.
Feature gating:
- read_parquet: requires `parquet` feature (default on)
- read_avro: requires `avro` feature (default off)
- read_csv/read_json: always available (no heavy deps)
Async bridge: uses std::thread::scope + Handle::block_on instead of
block_in_place, so it works on both multi-thread and current-thread
Tokio runtimes. Tested with single-threaded runtime.
16 tests covering: basic read, filtered read, projection, aggregation,
glob multi-file, error paths, filter/projection pushdown verification,
and single-threaded runtime safety.
Closes apache#3773
- cargo fmt: reformat read_table_functions.rs, read_parquet.rs, read_csv.rs, read_json.rs, read_avro.rs, and functions-table/lib.rs per current rustfmt rules (line wrapping on long paths and format! calls). - taplo: reformat datafusion/core/Cargo.toml per the repo's taplo.toml config. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
|
@alamb — also sitting since 2026-04-09 with no reviewer pickup. Is the scope/approach right for what you'd want from |
Hi @crm26 -- thank you for the ping and I am sorry I don't have time to review this project / help drive it forward at this time. I am overwhelmed with other things at the moment |
|
Thank you for your contribution. Unfortunately, this pull request is stale because it has been open 60 days with no activity. Please remove the stale label or comment or this will be closed in 7 days. |
Summary
Adds four inline SQL table functions for ad-hoc file querying:
Closes #3773
Design
Each function is a thin
TableFunctionImplwrapper (~60 lines) overListingTable:Expr::LiteralListingOptionswith the format'sFileFormatListingTableasTableProviderSince the SQL planner wraps UDTF output as
LogicalPlan::TableScan, all optimizer rules apply automatically:ListingTableAsync bridge
call_with_argsis a sync fn butinfer_schemais async. Usesstd::thread::scope+Handle::block_on(notblock_in_place) so it works on both multi-thread and current-thread Tokio runtimes. Tested with single-threaded runtime.Feature gating
read_parquet— requiresparquetfeature (default on)read_avro— requiresavrofeature (default off)read_csv/read_json— always available (no heavy optional dependencies)Limitations (v1)
has_header => trueThese can be addressed in follow-on PRs.
Tests
16 tests covering: basic read, filtered read, projection, aggregation, glob multi-file, error paths (no args, wrong type), filter/projection pushdown verification, and single-threaded runtime safety.