Skip to content

feat: accept and store expressions (including dynamic filters) in Iceberg scan nodes - #855

Open
Perseus wants to merge 6 commits into
datafusion-contrib:mainfrom
Perseus:anirudh.singh/iceberg-dyn-filtering-2
Open

Perseus wants to merge 6 commits into
datafusion-contrib:mainfrom
Perseus:anirudh.singh/iceberg-dyn-filtering-2

Conversation

@Perseus

@Perseus Perseus commented Nov 5, 2026 •

Copy link
Copy Markdown
Contributor

Note

This is part of a stack of PRs that implement dynamic filtering for Iceberg. The previous PR can be found here - #850
Relevant changes will also be ported to datafusion-iceberg.

Summary

This PR adds support for accepting and storing expressions, including dynamic filters, in both Iceberg datasources (Eager and Lazy).

Based on a config, iceberg.dynamic_filtering_enabled, operators like HashJoinExec are also informed that the datasource is a consumer of these dynamic filters.

The dynamic filters also show up in EXPLAIN ANALYZE plans in the DataSource in the following format:

 DataSourceExec: format=iceberg, table=default.taxi, projection=[trip_distance, pickup_date], predicate=trip_distance >= 2, dynamic_filters=DynamicFilter [ pickup_date@1 >= 2024-01-10 AND pickup_date@1 <= 2024-01-10 AND pickup_date@1 IN (SET) ([2024-01-10]) ]

These filters are not yet used for any optimizations - they're only stored and reported.

Future PRs will use them to improve data pruning in the following order -

  • Convert the dynamic filterPhysicalExpr to iceberg::Predicate
  • Use predicates containing partition keys to skip processing FileScanTasks
  • Use predicates containing other columns to skip row groups as soon as the filters become available (dependency on #3351 in iceberg-rust)

@Perseus
Perseus force-pushed the anirudh.singh/iceberg-dyn-filtering-2 branch 5 times, most recently from 6bdc438 to 58786d0 Compare November 6, 2026 13:36
Comment thread iceberg/tests/limit_pushdown.rs Resolved
@@ -18,6 +18,8 @@ extensions_options! {
pub column_stats_enabled: bool, default = false
/// Discover and retain file tasks during physical planning instead of execution.
pub eager_file_planning: bool, default = false
/// (Experimental) Whether to enable dynamic filtering.
pub dynamic_filtering_enabled: bool, default = false

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This was added so that a rolling deploy for workers doesn't cause errors if the coordinator starts producing dynamic filters that the workers don't consume yet - I'm not sure if that's necessarily an issue in practice and this adds something to the public API of this datasource that might not be easily removed later, so I'm open to changing the approach to something better

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These tests are largely just checking that the plumbing works since the filters don't do anything yet

@Perseus
Perseus marked this pull request as ready for review November 7, 2026 17:23
DataFusion offers each scan the filters above it, including the dynamic
filters that joins, top-N sorts and aggregates fill in while the query runs.
Iceberg scans didn't keep them. Keeping them is the first step toward
skipping files with them.

Both scans now keep every pushed filter, ANDed into one predicate. They
answer that they don't apply them, so DataFusion still checks every row.
EXPLAIN shows the dynamic ones on the scan as dynamic_filters=, and the
codecs carry all of them to workers.

With iceberg.dynamic_filtering_enabled on, scans also report the filters
through apply_expressions. Joins and aggregates fill in a dynamic filter only
when a scan reports it, and the coordinator sends updates to the workers
holding those scans. The setting is off by default, and the plan carries it
to workers. Enable it only once every worker supports it: an older worker can
fail a query whose scan reports a dynamic filter.
…ltering is on

With iceberg.dynamic_filtering_enabled off, scans aren't consumers of the
dynamic filters pushed into them, so those filters stay empty. Plans no
longer print them in that case.
@Perseus
Perseus force-pushed the anirudh.singh/iceberg-dyn-filtering-2 branch from d927948 to cab7f00 Compare November 10, 2026 10:21

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant