Commit 4c0f944
feat(physical-expr): DynamicFilterTracker for cheap dynamic-filter change detection (#22460)
Extracted from a design discussion around the duplicated "does this
filter have a dynamic portion that might change?" / "has the filter
changed?" patterns (e.g. #22450, `FilePruner`).
## Rationale for this change
`DynamicFilterPhysicalExpr` has a rich *producer* API (`update()`,
`mark_complete()`, `wait_update()`, `wait_complete()`), but *consumers*
that hold a predicate which *contains* dynamic filters only had a bare,
recursive `snapshot_generation() -> u64`. Call sites hand-rolled the
same boilerplate around it: store a `last_generation`, recompute
`snapshot_generation(&predicate)` (a full tree walk) on **every** check,
diff it, and rebuild an expensive `PruningPredicate` on change.
`FilePruner` did exactly this, and none of these consumers exploited
`mark_complete()`.
This adds a small consumer-side counterpart so the pattern lives in one
place, driven by the existing `watch` channel rather than by re-walking
the tree.
This immediately eliminates some tree traversals (we were constantly
traversing the expression tree to check if any filters updated). Long
term I hope this makes changes like #22450 easier.
## What changes are included in this PR?
**New public API (`datafusion_physical_expr`):**
- `DynamicFilterTracking` (`classify` → `Static` / `AllComplete` /
`Watching`, plus `contains_dynamic_filter` / `watcher`) and
`DynamicFilterTracker` (`changed`). A tracker walks a (possibly
composite) predicate **once**, subscribes to every still-incomplete
dynamic filter, and answers `changed()` by polling only that shrinking
set — steady-state is one atomic load per filter, no tree walk, no lock
until something actually moves.
- Lives in the `expressions::dynamic_filters` module
(`dynamic_filters.rs` → `dynamic_filters/mod.rs`, tracker in
`dynamic_filters/tracker.rs`). The subscription plumbing (`subscribe`,
`DynamicFilterSubscription`, `DynamicFilterChange`, `observe`,
`is_complete`) is `pub(crate)`; test-only constructors are
`#[cfg(test)]`.
**Consumers:**
- `FilePruner` is driven by `DynamicFilterTracking` instead of
`snapshot_generation` polling, and now decides its own existence in
`try_new` (a static predicate with no usable stats builds no pruner).
- The Parquet opener skips wrapping the scan in `EarlyStoppingStream`
when nothing can change, and no longer needs an "is it dynamic?" gate.
## Are these changes tested?
Yes — unit tests for the tracker (classification, detect-update-once,
`mark_complete` is not a change, coalesced update+complete,
multi-filter), plus the existing `datafusion-pruning` /
`datafusion-datasource-parquet` suites (incl. the
static/dynamic/partition opener pruning test) pass unchanged.
## Are there any user-facing changes?
New public API as above (additive). One **deprecation** and one behavior
change, both documented in the [DataFusion 55.0.0 upgrade
guide](docs/source/library-user-guide/upgrading/55.0.0.md):
-
`datafusion_physical_expr_common::physical_expr::is_dynamic_physical_expr`
is **deprecated (since 55.0.0)** — downcast to
`DynamicFilterPhysicalExpr` or use `DynamicFilterTracking`.
(`snapshot_generation` itself is unchanged — still backing the FFI
vtable and proto roundtrip.)
- `FilePruner::try_new` now returns `None` for a purely static predicate
over a file with no usable column statistics (previously `Some` whenever
a statistics struct was present).
## Followups
I noticed a possible follow-up gate refinement, tracked in #22495.
This also opens up the possibility to deprecate / remove the `snapshot`
/ `generation` machinery from the public physical expr APIs. These new
APIs (the watchers, tracker) subsumes much of the functionality, and I
don't think we want to add `PhysicalExpr::watch`. And after several
releases the only thing using it right now is dynamic filters, i.e. no
other legitimate use case has materialized.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
---------
Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>1 parent e634472 commit 4c0f944
9 files changed
Lines changed: 612 additions & 67 deletions
File tree
- datafusion
- datasource-parquet/src/opener
- physical-expr-common/src
- physical-expr/src
- expressions
- dynamic_filters
- pruning/src
- docs/source/library-user-guide/upgrading
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
52 | 52 | | |
53 | 53 | | |
54 | 54 | | |
55 | | - | |
56 | | - | |
57 | | - | |
| 55 | + | |
58 | 56 | | |
59 | 57 | | |
60 | 58 | | |
| |||
618 | 616 | | |
619 | 617 | | |
620 | 618 | | |
621 | | - | |
622 | | - | |
623 | | - | |
624 | | - | |
625 | | - | |
626 | | - | |
627 | | - | |
628 | | - | |
629 | | - | |
630 | | - | |
631 | | - | |
632 | | - | |
| 619 | + | |
| 620 | + | |
| 621 | + | |
| 622 | + | |
| 623 | + | |
| 624 | + | |
| 625 | + | |
| 626 | + | |
| 627 | + | |
| 628 | + | |
| 629 | + | |
| 630 | + | |
| 631 | + | |
633 | 632 | | |
634 | 633 | | |
635 | 634 | | |
| |||
677 | 676 | | |
678 | 677 | | |
679 | 678 | | |
680 | | - | |
681 | | - | |
682 | | - | |
683 | | - | |
684 | | - | |
685 | | - | |
686 | | - | |
687 | | - | |
688 | | - | |
689 | | - | |
690 | | - | |
691 | | - | |
692 | | - | |
693 | | - | |
| 679 | + | |
| 680 | + | |
| 681 | + | |
| 682 | + | |
| 683 | + | |
| 684 | + | |
| 685 | + | |
| 686 | + | |
694 | 687 | | |
695 | | - | |
696 | | - | |
697 | | - | |
698 | | - | |
699 | | - | |
700 | | - | |
701 | | - | |
702 | | - | |
703 | | - | |
| 688 | + | |
| 689 | + | |
| 690 | + | |
| 691 | + | |
| 692 | + | |
| 693 | + | |
704 | 694 | | |
705 | 695 | | |
706 | 696 | | |
| |||
1247 | 1237 | | |
1248 | 1238 | | |
1249 | 1239 | | |
1250 | | - | |
1251 | | - | |
1252 | | - | |
1253 | | - | |
1254 | | - | |
1255 | | - | |
1256 | | - | |
1257 | | - | |
1258 | | - | |
1259 | | - | |
| 1240 | + | |
| 1241 | + | |
| 1242 | + | |
| 1243 | + | |
| 1244 | + | |
| 1245 | + | |
| 1246 | + | |
| 1247 | + | |
| 1248 | + | |
| 1249 | + | |
| 1250 | + | |
| 1251 | + | |
| 1252 | + | |
| 1253 | + | |
| 1254 | + | |
1260 | 1255 | | |
1261 | 1256 | | |
1262 | 1257 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
870 | 870 | | |
871 | 871 | | |
872 | 872 | | |
| 873 | + | |
| 874 | + | |
| 875 | + | |
| 876 | + | |
| 877 | + | |
| 878 | + | |
873 | 879 | | |
874 | 880 | | |
875 | 881 | | |
| |||
Lines changed: 99 additions & 0 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
29 | 29 | | |
30 | 30 | | |
31 | 31 | | |
| 32 | + | |
| 33 | + | |
| 34 | + | |
32 | 35 | | |
33 | 36 | | |
34 | 37 | | |
| |||
326 | 329 | | |
327 | 330 | | |
328 | 331 | | |
| 332 | + | |
| 333 | + | |
| 334 | + | |
| 335 | + | |
| 336 | + | |
| 337 | + | |
| 338 | + | |
| 339 | + | |
| 340 | + | |
| 341 | + | |
| 342 | + | |
| 343 | + | |
| 344 | + | |
| 345 | + | |
| 346 | + | |
| 347 | + | |
| 348 | + | |
| 349 | + | |
| 350 | + | |
| 351 | + | |
| 352 | + | |
| 353 | + | |
| 354 | + | |
| 355 | + | |
| 356 | + | |
329 | 357 | | |
330 | 358 | | |
331 | 359 | | |
| |||
522 | 550 | | |
523 | 551 | | |
524 | 552 | | |
| 553 | + | |
| 554 | + | |
| 555 | + | |
| 556 | + | |
| 557 | + | |
| 558 | + | |
| 559 | + | |
| 560 | + | |
| 561 | + | |
| 562 | + | |
| 563 | + | |
| 564 | + | |
| 565 | + | |
| 566 | + | |
| 567 | + | |
| 568 | + | |
| 569 | + | |
| 570 | + | |
| 571 | + | |
| 572 | + | |
| 573 | + | |
| 574 | + | |
| 575 | + | |
| 576 | + | |
| 577 | + | |
| 578 | + | |
| 579 | + | |
| 580 | + | |
| 581 | + | |
| 582 | + | |
| 583 | + | |
| 584 | + | |
| 585 | + | |
| 586 | + | |
| 587 | + | |
| 588 | + | |
| 589 | + | |
| 590 | + | |
| 591 | + | |
| 592 | + | |
| 593 | + | |
| 594 | + | |
| 595 | + | |
| 596 | + | |
| 597 | + | |
| 598 | + | |
| 599 | + | |
| 600 | + | |
| 601 | + | |
| 602 | + | |
| 603 | + | |
| 604 | + | |
| 605 | + | |
| 606 | + | |
| 607 | + | |
| 608 | + | |
| 609 | + | |
| 610 | + | |
| 611 | + | |
| 612 | + | |
| 613 | + | |
| 614 | + | |
| 615 | + | |
| 616 | + | |
| 617 | + | |
| 618 | + | |
| 619 | + | |
| 620 | + | |
| 621 | + | |
| 622 | + | |
| 623 | + | |
525 | 624 | | |
526 | 625 | | |
527 | 626 | | |
| |||
0 commit comments