You are viewing a plain text version of this content. The canonical link for it is here.
Posted to github@datafusion.apache.org by "adriangb (via GitHub)" <gi...@apache.org> on 2026/05/02 20:48:36 UTC
[PR] feat: type-keyed extensions map for PartitionedFile [datafusion]
adriangb opened a new pull request, #21993:
URL: https://github.com/apache/datafusion/pull/21993
## Which issue does this PR close?
- Closes #.
(no tracking issue yet; happy to file one if this direction is wanted)
## Rationale for this change
`PartitionedFile.extensions` is currently a single `Option<Arc<dyn Any + Send + Sync>>` slot. That means two independent components cannot both attach their own per-file data without colliding — only one of `ParquetAccessPlan`, a custom index entry, a custom reader payload, etc. can be present at a time. Anyone wanting more than one piece of metadata has to define a wrapper struct and have every consumer agree on it.
While exploring this, I noticed DataFusion already has the same `HashMap<TypeId, Arc<dyn Any + Send + Sync>>` pattern in two other places:
- `datafusion/execution/src/config.rs` — backs `SessionConfig.extensions`, with a clever `IdHasher` that avoids rehashing `TypeId`s.
- `datafusion/physical-plan/src/operator_statistics/mod.rs` — backs `ExtendedStatistics.extensions`.
Rather than add a third copy, this PR lifts the pattern into `datafusion-common` as `datafusion_common::extensions::Extensions` and uses it for `PartitionedFile`. `SessionConfig` and `ExtendedStatistics` can adopt it in follow-up PRs to remove the duplication; this PR keeps that scope out.
## What changes are included in this PR?
- New `datafusion_common::extensions::Extensions` (TypeId-keyed `HashMap` with the `IdHasher` lifted from `SessionConfig`). API: `insert` / `insert_arc` / `get` / `get_arc` / `contains` / `remove` / `merge`, all generic over `T`.
- `PartitionedFile.extensions` changes from `Option<Arc<dyn Any + Send + Sync>>` to `FileExtensions` (re-export of `Extensions`).
- New typed builder methods: `with_extension<T>(T)` and `with_extension_arc<T>(Arc<T>)` replace `with_extensions(Arc<dyn Any + Send + Sync>)`. New accessor `extension::<T>()` avoids manual downcasts.
- Parquet opener migrated: `create_initial_plan` now takes `&FileExtensions` and uses `get::<ParquetAccessPlan>()` directly instead of doing the downcast inline.
- In-tree call sites migrated: `parquet/custom_reader.rs` test, `parquet/external_access_plan.rs` test, and the `parquet_advanced_index.rs` example.
- Upgrade guide entry added in `docs/source/library-user-guide/upgrading/54.0.0.md`.
## Are these changes tested?
- New unit tests for `Extensions` (insert/get/remove/replace, merge precedence) in `datafusion-common`.
- Existing parquet tests that exercised the single-slot API (`parquet::custom_reader::route_data_access_ops_to_parquet_file_reader_factory`, all 10 `parquet::external_access_plan::*`) pass after migration.
- Full workspace `cargo check --workspace --all-targets` clean.
- `./dev/rust_lint.sh` clean.
## Are there any user-facing changes?
Yes — breaking public-API change on `PartitionedFile`:
```diff
-let pf = PartitionedFile::new(path, size)
- .with_extensions(Arc::new(access_plan));
+let pf = PartitionedFile::new(path, size)
+ .with_extension(access_plan);
```
```diff
-let plan = pf.extensions
- .as_ref()
- .and_then(|ext| ext.downcast_ref::<ParquetAccessPlan>());
+let plan = pf.extension::<ParquetAccessPlan>();
```
The `extensions` field's public type also changes (`Option<Arc<dyn Any>>` → `FileExtensions`). Upgrade guide entry added.
## Open questions
- Should `SessionConfig.extensions` and `ExtendedStatistics.extensions` migrate to the shared `Extensions` type in this PR, or as follow-ups? I left them alone here to keep the change focused, but happy to fold them in if reviewers prefer.
- Naming: `Extensions` vs `AnyMap` vs `TypeMap`. I went with `Extensions` to match the existing field names; open to bikeshedding.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: github-unsubscribe@datafusion.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
---------------------------------------------------------------------
To unsubscribe, e-mail: github-unsubscribe@datafusion.apache.org
For additional commands, e-mail: github-help@datafusion.apache.org
Re: [PR] feat: type-keyed extensions map for PartitionedFile [datafusion]
Posted by "kosiew (via GitHub)" <gi...@apache.org>.
kosiew commented on code in PR #21993:
URL: https://github.com/apache/datafusion/pull/21993#discussion_r3186092903
##########
datafusion/datasource-parquet/src/source.rs:
##########
@@ -230,7 +230,7 @@ use parquet::encryption::decrypt::FileDecryptionProperties;
/// access_plan.skip(4);
/// // provide the plan as extension to the FileScanConfig
/// let partitioned_file = PartitionedFile::new("my_file.parquet", 1234)
-/// .with_extensions(Arc::new(access_plan));
+/// .with_extension(Arc::new(access_plan));
Review Comment:
I think this example still needs a small adjustment. Passing `Arc::new(access_plan)` means `PartitionedFile::with_extension<T>(value: T)` stores the extension as `Arc<ParquetAccessPlan>`.
Later, `create_initial_plan` looks up `extensions.get::<ParquetAccessPlan>()`, so the access plan from this example would be ignored and all row groups may be scanned.
I think we should pass the concrete value instead:
```rust
.with_extension(access_plan);
```
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: github-unsubscribe@datafusion.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
---------------------------------------------------------------------
To unsubscribe, e-mail: github-unsubscribe@datafusion.apache.org
For additional commands, e-mail: github-help@datafusion.apache.org
Re: [PR] feat: type-keyed extensions map for PartitionedFile [datafusion]
Posted by "kosiew (via GitHub)" <gi...@apache.org>.
kosiew commented on code in PR #21993:
URL: https://github.com/apache/datafusion/pull/21993#discussion_r3186092903
##########
datafusion/datasource-parquet/src/source.rs:
##########
@@ -230,7 +230,7 @@ use parquet::encryption::decrypt::FileDecryptionProperties;
/// access_plan.skip(4);
/// // provide the plan as extension to the FileScanConfig
/// let partitioned_file = PartitionedFile::new("my_file.parquet", 1234)
-/// .with_extensions(Arc::new(access_plan));
+/// .with_extension(Arc::new(access_plan));
Review Comment:
I think this example still needs a small adjustment. Passing `Arc::new(access_plan)` means `PartitionedFile::with_extension<T>(value: T)` stores the extension as `Arc<ParquetAccessPlan>`.
Later, `create_initial_plan` looks up `extensions.get::<ParquetAccessPlan>()`, so the access plan from this example would be ignored and all row groups may be scanned.
Could we pass the concrete value instead?
```rust
.with_extension(access_plan);
```
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: github-unsubscribe@datafusion.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
---------------------------------------------------------------------
To unsubscribe, e-mail: github-unsubscribe@datafusion.apache.org
For additional commands, e-mail: github-help@datafusion.apache.org
Re: [PR] feat: type-keyed extensions map for PartitionedFile [datafusion]
Posted by "adriangb (via GitHub)" <gi...@apache.org>.
adriangb merged PR #21993:
URL: https://github.com/apache/datafusion/pull/21993
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: github-unsubscribe@datafusion.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
---------------------------------------------------------------------
To unsubscribe, e-mail: github-unsubscribe@datafusion.apache.org
For additional commands, e-mail: github-help@datafusion.apache.org
Re: [PR] feat: type-keyed extensions map for PartitionedFile [datafusion]
Posted by "adriangb (via GitHub)" <gi...@apache.org>.
adriangb commented on code in PR #21993:
URL: https://github.com/apache/datafusion/pull/21993#discussion_r3182110407
##########
datafusion/core/tests/parquet/custom_reader.rs:
##########
@@ -71,7 +71,7 @@ async fn route_data_access_ops_to_parquet_file_reader_factory() {
.into_iter()
.map(|meta| {
PartitionedFile::new_from_meta(meta)
Review Comment:
75b6e3d7c
##########
datafusion/physical-plan/src/operator_statistics/mod.rs:
##########
@@ -160,26 +159,22 @@ impl ExtendedStatistics {
/// Get a reference to a custom statistics extension by type.
pub fn get_extension<T: 'static + Send + Sync>(&self) -> Option<&T> {
- self.extensions
- .get(&TypeId::of::<T>())
- .and_then(|ext| ext.downcast_ref())
+ self.extensions.get::<T>()
}
/// Set a custom statistics extension.
- pub fn set_extension<T: 'static + Send + Sync>(&mut self, value: T) {
- self.extensions.insert(TypeId::of::<T>(), Arc::new(value));
+ pub fn set_extension<T: 'static + Send + Sync>(&mut self, value: Arc<T>) {
Review Comment:
bc0a3e030
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: github-unsubscribe@datafusion.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
---------------------------------------------------------------------
To unsubscribe, e-mail: github-unsubscribe@datafusion.apache.org
For additional commands, e-mail: github-help@datafusion.apache.org
Re: [PR] feat: type-keyed extensions map for PartitionedFile [datafusion]
Posted by "adriangb (via GitHub)" <gi...@apache.org>.
adriangb commented on code in PR #21993:
URL: https://github.com/apache/datafusion/pull/21993#discussion_r3188055353
##########
datafusion/datasource-parquet/src/source.rs:
##########
@@ -230,7 +230,7 @@ use parquet::encryption::decrypt::FileDecryptionProperties;
/// access_plan.skip(4);
/// // provide the plan as extension to the FileScanConfig
/// let partitioned_file = PartitionedFile::new("my_file.parquet", 1234)
-/// .with_extensions(Arc::new(access_plan));
+/// .with_extension(Arc::new(access_plan));
Review Comment:
Good catch — fixed in aa1f55176. The wrapped `Arc<ParquetAccessPlan>` would have been stored under the wrong type key and missed by `extensions.get::<ParquetAccessPlan>()`.
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: github-unsubscribe@datafusion.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
---------------------------------------------------------------------
To unsubscribe, e-mail: github-unsubscribe@datafusion.apache.org
For additional commands, e-mail: github-help@datafusion.apache.org
Re: [PR] feat: type-keyed extensions map for PartitionedFile [datafusion]
Posted by "rluvaton (via GitHub)" <gi...@apache.org>.
rluvaton commented on PR #21993:
URL: https://github.com/apache/datafusion/pull/21993#issuecomment-4371963942
Great to see the automatic label is working, so we wont miss API breaking changes now in the release docs
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: github-unsubscribe@datafusion.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
---------------------------------------------------------------------
To unsubscribe, e-mail: github-unsubscribe@datafusion.apache.org
For additional commands, e-mail: github-help@datafusion.apache.org
Re: [PR] feat: type-keyed extensions map for PartitionedFile [datafusion]
Posted by "adriangb (via GitHub)" <gi...@apache.org>.
adriangb commented on PR #21993:
URL: https://github.com/apache/datafusion/pull/21993#issuecomment-4394025020
Sorry I missed that. Is there anything your PR had that we missed here?
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: github-unsubscribe@datafusion.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
---------------------------------------------------------------------
To unsubscribe, e-mail: github-unsubscribe@datafusion.apache.org
For additional commands, e-mail: github-help@datafusion.apache.org
Re: [PR] feat: type-keyed extensions map for PartitionedFile [datafusion]
Posted by "adriangb (via GitHub)" <gi...@apache.org>.
adriangb commented on PR #21993:
URL: https://github.com/apache/datafusion/pull/21993#issuecomment-4388778804
Thanks for the review @kosiew !
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: github-unsubscribe@datafusion.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
---------------------------------------------------------------------
To unsubscribe, e-mail: github-unsubscribe@datafusion.apache.org
For additional commands, e-mail: github-help@datafusion.apache.org
Re: [PR] feat: type-keyed extensions map for PartitionedFile [datafusion]
Posted by "adriangb (via GitHub)" <gi...@apache.org>.
adriangb commented on PR #21993:
URL: https://github.com/apache/datafusion/pull/21993#issuecomment-4366318808
@kosiew mind reviewing this change please?
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: github-unsubscribe@datafusion.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
---------------------------------------------------------------------
To unsubscribe, e-mail: github-unsubscribe@datafusion.apache.org
For additional commands, e-mail: github-help@datafusion.apache.org
Re: [PR] feat: type-keyed extensions map for PartitionedFile [datafusion]
Posted by "adriangb (via GitHub)" <gi...@apache.org>.
adriangb commented on PR #21993:
URL: https://github.com/apache/datafusion/pull/21993#issuecomment-4371708869
Thanks @kosiew ! Addressed both points.
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: github-unsubscribe@datafusion.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
---------------------------------------------------------------------
To unsubscribe, e-mail: github-unsubscribe@datafusion.apache.org
For additional commands, e-mail: github-help@datafusion.apache.org
Re: [PR] feat: type-keyed extensions map for PartitionedFile [datafusion]
Posted by "github-actions[bot] (via GitHub)" <gi...@apache.org>.
github-actions[bot] commented on PR #21993:
URL: https://github.com/apache/datafusion/pull/21993#issuecomment-4364703664
<!-- semver-check-comment -->
Thank you for opening this pull request!
Reviewer note: [cargo-semver-checks](https://github.com/obi1kenobi/cargo-semver-checks) reported the current version number is not SemVer-compatible with the changes in this pull request (compared against the base branch).
<details>
<summary>Details</summary>
```
Cloning origin/main
Building datafusion v53.1.0 (current)
Built [ 77.164s] (current)
Parsing datafusion v53.1.0 (current)
Parsed [ 0.032s] (current)
Building datafusion v53.1.0 (baseline)
Built [ 76.708s] (baseline)
Parsing datafusion v53.1.0 (baseline)
Parsed [ 0.031s] (baseline)
Checking datafusion v53.1.0 -> v53.1.0 (no change; assume patch)
Checked [ 0.711s] 222 checks: 222 pass, 30 skip
Summary no semver update required
Finished [ 156.521s] datafusion
Building datafusion-common v53.1.0 (current)
Built [ 30.319s] (current)
Parsing datafusion-common v53.1.0 (current)
Parsed [ 0.053s] (current)
Building datafusion-common v53.1.0 (baseline)
Built [ 30.285s] (baseline)
Parsing datafusion-common v53.1.0 (baseline)
Parsed [ 0.074s] (baseline)
Checking datafusion-common v53.1.0 -> v53.1.0 (no change; assume patch)
Checked [ 0.731s] 222 checks: 222 pass, 30 skip
Summary no semver update required
Finished [ 63.058s] datafusion-common
Building datafusion-datasource v53.1.0 (current)
Built [ 33.984s] (current)
Parsing datafusion-datasource v53.1.0 (current)
Parsed [ 0.027s] (current)
Building datafusion-datasource v53.1.0 (baseline)
Built [ 33.801s] (baseline)
Parsing datafusion-datasource v53.1.0 (baseline)
Parsed [ 0.028s] (baseline)
Checking datafusion-datasource v53.1.0 -> v53.1.0 (no change; assume patch)
Checked [ 0.298s] 222 checks: 221 pass, 1 fail, 0 warn, 30 skip
--- failure inherent_method_missing: pub method removed or renamed ---
Description:
A publicly-visible method or associated fn is no longer available under its prior name. It may have been renamed or removed entirely.
ref: https://doc.rust-lang.org/cargo/reference/semver.html#item-remove
impl: https://github.com/obi1kenobi/cargo-semver-checks/tree/v0.47.0/src/lints/inherent_method_missing.ron
Failed in:
PartitionedFile::with_extensions, previously in file /home/runner/work/datafusion/datafusion/target/semver-checks/git-origin_main/00843f7f284875069dd6fd28c3d3baba9aea4422/datafusion/datasource/src/mod.rs:263
Summary semver requires new major version: 1 major and 0 minor checks failed
Finished [ 69.850s] datafusion-datasource
Building datafusion-datasource-parquet v53.1.0 (current)
Built [ 39.992s] (current)
Parsing datafusion-datasource-parquet v53.1.0 (current)
Parsed [ 0.023s] (current)
Building datafusion-datasource-parquet v53.1.0 (baseline)
Built [ 39.990s] (baseline)
Parsing datafusion-datasource-parquet v53.1.0 (baseline)
Parsed [ 0.023s] (baseline)
Checking datafusion-datasource-parquet v53.1.0 -> v53.1.0 (no change; assume patch)
Checked [ 0.159s] 222 checks: 222 pass, 30 skip
Summary no semver update required
Finished [ 81.658s] datafusion-datasource-parquet
```
</details>
<!-- semver-check-comment -->
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: github-unsubscribe@datafusion.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
---------------------------------------------------------------------
To unsubscribe, e-mail: github-unsubscribe@datafusion.apache.org
For additional commands, e-mail: github-help@datafusion.apache.org
Re: [PR] feat: type-keyed extensions map for PartitionedFile [datafusion]
Posted by "kosiew (via GitHub)" <gi...@apache.org>.
kosiew commented on code in PR #21993:
URL: https://github.com/apache/datafusion/pull/21993#discussion_r3180936389
##########
datafusion/physical-plan/src/operator_statistics/mod.rs:
##########
@@ -160,26 +159,22 @@ impl ExtendedStatistics {
/// Get a reference to a custom statistics extension by type.
pub fn get_extension<T: 'static + Send + Sync>(&self) -> Option<&T> {
- self.extensions
- .get(&TypeId::of::<T>())
- .and_then(|ext| ext.downcast_ref())
+ self.extensions.get::<T>()
}
/// Set a custom statistics extension.
- pub fn set_extension<T: 'static + Send + Sync>(&mut self, value: T) {
- self.extensions.insert(TypeId::of::<T>(), Arc::new(value));
+ pub fn set_extension<T: 'static + Send + Sync>(&mut self, value: Arc<T>) {
Review Comment:
`ExtendedStatistics::set_extension` now asks callers to allocate and pass an `Arc<T>`, while the existing public API accepted `T` and wrapped it internally. That makes this a source-breaking API change, even though the refactor is mainly about sharing the backing map.
The documented example nearby still shows `stats.set_extension(HistogramStats { ... })`, so existing users following that pattern will no longer compile. Could we keep the existing method shape, for example `set_extension<T>(value: T) { self.extensions.insert(Arc::new(value)); }`, and add a separate `set_extension_arc` only if callers need to avoid the allocation?
##########
datafusion/core/tests/parquet/custom_reader.rs:
##########
@@ -71,7 +71,7 @@ async fn route_data_access_ops_to_parquet_file_reader_factory() {
.into_iter()
.map(|meta| {
PartitionedFile::new_from_meta(meta)
Review Comment:
It would be great to add one integration regression test that attaches both a `ParquetAccessPlan` and a custom reader payload to the same `PartitionedFile`. The test could then assert that the custom reader still sees its payload and that the parquet access plan is honored.
The current tests cover the generic map and the two consumers separately, but not quite the end-to-end invariant this PR is trying to protect.
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: github-unsubscribe@datafusion.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
---------------------------------------------------------------------
To unsubscribe, e-mail: github-unsubscribe@datafusion.apache.org
For additional commands, e-mail: github-help@datafusion.apache.org
Re: [PR] feat: type-keyed extensions map for PartitionedFile [datafusion]
Posted by "cetra3 (via GitHub)" <gi...@apache.org>.
cetra3 commented on PR #21993:
URL: https://github.com/apache/datafusion/pull/21993#issuecomment-4393762010
Guessing you guys didn't see this one: https://github.com/apache/datafusion/pull/21192
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: github-unsubscribe@datafusion.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
---------------------------------------------------------------------
To unsubscribe, e-mail: github-unsubscribe@datafusion.apache.org
For additional commands, e-mail: github-help@datafusion.apache.org