Skip to content

[SPARK-59250][SQL] Translate an empty runtime IN filter to AlwaysFalse in DSv2 runtime filtering - #58524

Open
pan3793 wants to merge 3 commits into
apache:masterfrom
pan3793:dpp-empty-in
Open

[SPARK-59250][SQL] Translate an empty runtime IN filter to AlwaysFalse in DSv2 runtime filtering#58524
pan3793 wants to merge 3 commits into
apache:masterfrom
pan3793:dpp-empty-in

Conversation

@pan3793

@pan3793 pan3793 commented Sep 4, 2026

Copy link
Copy Markdown
Member

What changes were proposed in this pull request?

In DataSourceV2Strategy.translateRuntimeFilterV2, match an InSubqueryExec whose subquery result is empty before the pushable-column check, and translate it to AlwaysFalse.

expr IN () is false for every row regardless of expr, so the translation is valid even when expr itself is untranslatable, e.g. a join key wrapped in a cast inserted by type coercion (cast(col as bigint) IN dynamicpruning#x).

The test connector scans InMemoryTableWithV2Filter and InMemoryBaseTable.InMemoryBatchScan are updated to honor AlwaysFalse by pruning all partitions.

Why are the changes needed?

When the build side of a DPP join produces no rows, the runtime filter degenerates to key IN (). Today this is either emitted as a zero-value IN predicate that connectors cannot interpret meaningfully (Spark's own InMemoryTableWithV2Filter ignores it: its filter() requires children().length > 1), or, when the key is wrapped in a cast, dropped entirely with "Can't translate ... unsupported expression". Either way the scan reads every partition to produce zero output rows.

Translating to AlwaysFalse prunes everything and makes the connector contract explicit: connectors receive a well-defined predicate instead of a degenerate IN.

Does this PR introduce any user-facing change?

No correctness change. DSv2 scans receiving an empty runtime IN filter can now prune all partitions instead of reading everything.

How was this patch tested?

New tests in DynamicPartitionPruningV2Suite covering a bare pruning key and a cast-wrapped pruning key; both assert filteredPartitions is empty. The tests run through V1 Filter, V2 Predicate, and Catalyst runtime filtering. Previously all 25 partitions were read.

Was this patch authored or co-authored using generative AI tooling?

Generated-by: Claude Fable 5

@pan3793

pan3793 commented Sep 4, 2026

Copy link
Copy Markdown
Member Author

cc @szehon-ho

@szehon-ho szehon-ho left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Optimization makes sense to me

spark.conf.set("spark.sql.catalog.testcat", classOf[InMemoryTableWithV2FilterCatalog].getName)
}

import testImplicits._

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

nit: can we put it on top or more natural place ?

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

Moved the import and helper into the shared DynamicPartitionPruningV2Suite.

scans.head
}

test("SPARK-59250: DPP prunes all DSv2 partitions when the runtime IN filter is empty",

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Could we also cover the SupportsRuntimeFiltering (V1 Filter) path? This PR updates InMemoryBaseTable.InMemoryBatchScan to handle AlwaysFalse, but these tests run only with InMemoryTableWithV2FilterCatalog, so they exercise InMemoryV2FilterBatchScan and leave the V1 compatibility path untested. It may be possible to share the tests with DynamicPartitionPruningV2Suite so both implementations run them.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

Moved the tests into DynamicPartitionPruningV2Suite, so they now run through V1 Filter, V2 Predicate, and Catalyst runtime filtering.

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.

2 participants