Skip to content

Add config-matrix tests in enforce_distribution.rs for range-satisfaction settings - #23627

Open
blinding-pixels wants to merge 4 commits into
apache:mainfrom
blinding-pixels:agent/range-satisfaction-config-matrix
Open

Add config-matrix tests in enforce_distribution.rs for range-satisfaction settings#23627
blinding-pixels wants to merge 4 commits into
apache:mainfrom
blinding-pixels:agent/range-satisfaction-config-matrix

Conversation

@blinding-pixels

@blinding-pixels blinding-pixels commented Jul 16, 2026

Copy link
Copy Markdown

Which issue does this PR close?

Rationale for this change

Range partitioning reuse is controlled by shared optimizer settings, but the same configuration combinations were repeated across operator-specific SQL logic tests. This PR moves that shared coverage into one table-driven Rust test while retaining the operator-specific cases that test separate planning behavior.

What changes are included in this PR?

  • Extends RequirementsTestExec with a configurable input distribution.
  • Adds a 12-row configuration matrix covering 36 combinations of key compatibility, subset threshold, preserve-file setting, and target partition count.
  • Requires reuse cases to contain no repartition and Hash cases to contain exactly one Hash repartition.
  • Removes three redundant aggregate SLT cases and renumbers the remaining tests.

Are these changes tested?

Yes. The 36-cell matrix and range_partitioning.slt pass.

Are there any user-facing changes?

No. These changes only affect tests and test utilities.

@github-actions github-actions Bot added core Core DataFusion crate physical-plan Changes to the physical-plan crate labels Jul 16, 2026
@blinding-pixels
blinding-pixels marked this pull request as ready for review July 17, 2026 01:12
@blinding-pixels

Copy link
Copy Markdown
Author

Hi @gabotechs, this is my first contribution to DataFusion. Would you be able to trigger CI and review this PR when you have a chance? I’m happy to explain any of the decisions I made here. I’m looking forward to being a useful member of the community. Thank you!

@gene-bordegaray gene-bordegaray left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

overall looks good, thanks for banging this one out, this is very very much appreaciated 🙇

One goal was to keep range_partitioning.slt a bit leaner. I think we can do some of that now by eliminating some repetitive tests. I was thnking:

  • TEST 4: Exact Range Aggregate Below Subset Threshold
  • TEST 5: Range Subset Aggregate Rehashes Below Subset Threshold
  • TEST 6: Aggregate Rehashes Below Subset Threshold
  • TEST 7: Aggregate Preserves Range When Preserve File Threshold Met
  • TEST 8: Aggregate Rehashes When Preserve File Threshold Not Met
  • TEST 13: Compatible Range Join Repartitions to Increase Parallelism
  • TEST 14: Preserve File Partitions Preserves Range Join Inputs

cc: @gabotechs let me know what you think. This reduces the noise in that file to focus on range end to end and this unit now covers all the tricky "above this" "below that" distribution stuff 👍

let plan = config.to_plan(requirement, &DISTRIB_DISTRIB_SORT);
let plan = displayable(plan.as_ref()).indent(true).to_string();
let has_hash_repartition =
plan.contains("RepartitionExec: partitioning=Hash");

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

I think we should be checking for any repartition. For example we can have a RoundRobin inserted if we choose to increase parallelism when less than target_partitions and threshld values

@blinding-pixels

Copy link
Copy Markdown
Author

Thanks for the review! I checked the RoundRobin concern and the proposed SLT deletions together.

I agree that a Reuse expectation should reject any repartition. Though, checking only for “any repartition” would allow a Hash case to pass with RoundRobin. I therefore tested an assertion split by expected outcome:

  • Reuse requires zero RepartitionExec nodes.
  • Hash requires exactly one RepartitionExec, and it must be Hash.

I ran this assertion across all 24 matrix cells at datafusion/core/tests/physical_optimizer/enforce_distribution.rs:803; every cell passed.

let repartitions = plan
    .lines()
    .filter(|line| line.contains("RepartitionExec:"))
    .collect::<Vec<_>>();

match expected_plan {
    ExpectedPlan::Reuse => {
        assert!(repartitions.is_empty(), "{plan}");
    }
    ExpectedPlan::Hash => {
        assert_eq!(repartitions.len(), 1, "{plan}");
        assert!(
            repartitions[0].contains("partitioning=Hash"),
            "{plan}"
        );
    }
}

This assertion is a prerequisite for relying on the matrix after trimming configuration SLTs. The existing assertion at enforce_distribution.rs:890–898 only checks whether Hash appears. A future neutral plan containing RoundRobin could therefore pass a Reuse row because Hash is absent, while a plan containing both Hash and RoundRobin could pass a Hash row because Hash is present. The existing SLT plan comparisons would fail loudly in either situation.

It is also worth making the two test layers explicit. KeyPartitioningRequirementExec enables Range satisfaction itself at datafusion/physical-plan/src/test/exec.rs:331–335. Therefore, changing or removing a production operator’s opt-in cannot affect the 24 neutral matrix cells. The matrix tests the shared decision after an operator has opted in; the per-operator SLTs demonstrably test production operators using that decision. At least one positive Range-reuse case must remain for every production operator, with additional cases retained where operator-specific branches require them.

I mutation-tested the production branches associated with the proposed deletions. The locations below distinguish the complete expression from the specific condition changed. The first and fourth mutations intentionally overlap: preserve_partial_aggregate_partitioning is an input to the later add_roundrobin decision.

Production mutation Exact mutation location Failures within range_partitioning.slt
Force aggregate Range preservation to false Expression at datafusion/physical-optimizer/src/ensure_requirements/enforce_distribution.rs:1309–1315; result forced false at :1315 Test 7 only, query at range_partitioning.slt:218
Force the join preserve shortcut to false Expression at enforce_distribution.rs:1356–1360; result forced false at :1360 Test 14 only, query at range_partitioning.slt:476
Remove the partitioned-join guard Removed && !is_partitioned_join at enforce_distribution.rs:1304 Test 13 only, query at range_partitioning.slt:440
Force RoundRobin insertion to false add_roundrobin expression at enforce_distribution.rs:1317–1323; result forced false at :1323 Tests 6 and 8, queries at range_partitioning.slt:186 and :247

Safe to delete

Test Current location Evidence
Test 4 Heading range_partitioning.slt:122; query :137 Its exact-key, threshold-not-met, equal-target configuration is covered by the matrix row at datafusion/core/tests/physical_optimizer/enforce_distribution.rs:813–818. Aggregate opt-in removal would remain caught by Tests 1, 3, and 16 at SLT lines 41, 101, and 551, independently of Test 7.
Test 5 Heading range_partitioning.slt:146; query :161 Its subset-key, threshold-not-met, equal-target configuration is covered by the same matrix row at enforce_distribution.rs:813–818.
Test 6 Heading range_partitioning.slt:172; query :186 Its shared Hash decision is covered by the matrix row at enforce_distribution.rs:819–824. Tests 6 and 8 both failed when RoundRobin insertion was disabled, so either one can carry the aggregate-specific RoundRobin coverage. I propose retaining Test 8 because it pairs directly with Test 7’s preserve-threshold-met case.

Retain under the proposed trim

Test Current location Evidence
Test 7 Heading range_partitioning.slt:204; query :218 It was the only failure in this SLT file when preserve_partial_aggregate_partitioning was forced false at enforce_distribution.rs:1315.
Test 8 Heading range_partitioning.slt:233; query :247 Either Test 6 or Test 8 must remain to detect loss of aggregate RoundRobin insertion. Under the proposed deletion of Test 6, Test 8 carries that coverage and forms the threshold-not-met counterpart to Test 7.
Test 13 Heading range_partitioning.slt:431; query :440 It was the only failure in this SLT file when the partitioned-join guard at enforce_distribution.rs:1304 was removed.
Test 14 Heading range_partitioning.slt:468; query :476 It was the only failure in this SLT file when preserve_satisfying_file_partitioning was forced false at enforce_distribution.rs:1360.

The proposed sequence is therefore:

  1. Replace the Hash-only assertion with the verified outcome-specific assertion.
  2. Delete Tests 4, 5, and 6.
  3. Retain Tests 7, 8, 13, and 14 because the mutations show they protect production-operator behavior the neutral matrix does not exercise.

If this sounds like it is in the right direction, I can make these and push.

@gabotechs

Copy link
Copy Markdown
Contributor

Hi @blinding-pixels, thanks for the PR! in order to be respectful with the time of the reviewers, please try to be concise in the PR description and the comments. If you are using an LLM for auto-responding feedback, please curate the answer before publishing it so that readers invest a reasonable amount of time digesting the information.

@blinding-pixels

Copy link
Copy Markdown
Author

Apologies, my bad on the length.

Here is the short version-

I agree on the assertion, split it by expected outcome so a Hash row can't pass with a RoundRobin. Reuse asserts zero RepartitionExec, Hash asserts exactly one and that it's Hash.

On the trim, mutations say 4/5/6 are safe but 7, 13, and 14 are each the only test catching a specific branch.

A reason I hesitated on the trim is that the neutral matrix enables the Range opt-in itself, so it stays green no matter what a production operator does. Only the SLTs catch that.

Happy to push that and paste the mutation detail if you want it.

The previous comment wasn't auto-generated but I did let an LLM write it up and didn't cut it down before posting.

@gene-bordegaray

Copy link
Copy Markdown
Contributor

On the trim, mutations say 4/5/6 are safe but 7, 13, and 14 are each the only test catching a specific branch.

@blinding-pixels I am confused what you mea by brnach specific here. The tests I am sugesting to remove are in range_partitioning.slt which are mostly there to guarantee subset, file preserving, and target partitions behavior in enforce_distribution.rs. They behavior in these are not really specific to an operator rather just showing that intended behavior is happening. Now with the dedicated matrix testing we are locking in a contract of where repartitioning should happen based on these thresholds and the given key distribution.

@blinding-pixels

Copy link
Copy Markdown
Author

I see how my wording was confusing. The matrix uses a neutral synthetic operator, so it's a shared-contract test, not a universal operator contract test.

It proves that once an operator enables Range satisfaction, the shared optimizer handles all 24 matrix combinations correctly. It does not prove that production aggregates, joins, and windows enable Range satisfaction or reach that shared logic correctly. KeyPartitioningRequirementExec enables Range satisfaction itself, so removing an opt-in or breaking an operator-specific path would leave the matrix green.

The mutations show this:

  • Test 7 — aggregate preservation path
  • Test 13 — partitioned-join guard
  • Test 14 — join preservation path
  • Tests 6 and 8 — same aggregate RoundRobin path, so one is redundant

To make the SLT file leaner, I could keep the neutral matrix for the shared contract and add a second Rust table using real aggregate and join plans. That would replace the optimizer-plan coverage of all the proposed SLT cases and allow them to be removed. The existing window SLTs would still protect the window operators. This would add roughly 80–100 lines to the existing Rust test file.

I'm new to this codebase, so I'll defer to you on whether the added Rust coverage is worthwhile or you'd rather just drop the SLT cases.

@gene-bordegaray

Copy link
Copy Markdown
Contributor

I see how my wording was confusing. The matrix uses a neutral synthetic operator, so it's a shared-contract test, not a universal operator contract test.

It proves that once an operator enables Range satisfaction, the shared optimizer handles all 24 matrix combinations correctly. It does not prove that production aggregates, joins, and windows enable Range satisfaction or reach that shared logic correctly. KeyPartitioningRequirementExec enables Range satisfaction itself, so removing an opt-in or breaking an operator-specific path would leave the matrix green.

The mutations show this:

  • Test 7 — aggregate preservation path
  • Test 13 — partitioned-join guard
  • Test 14 — join preservation path
  • Tests 6 and 8 — same aggregate RoundRobin path, so one is redundant

To make the SLT file leaner, I could keep the neutral matrix for the shared contract and add a second Rust table using real aggregate and join plans. That would replace the optimizer-plan coverage of all the proposed SLT cases and allow them to be removed. The existing window SLTs would still protect the window operators. This would add roughly 80–100 lines to the existing Rust test file.

I'm new to this codebase, so I'll defer to you on whether the added Rust coverage is worthwhile or you'd rather just drop the SLT cases.

@blinding-pixels this makes sense. Can we also add a disabled option for the preserve file partition in the matrix 👍

@blinding-pixels

Copy link
Copy Markdown
Author

Yes, for sure. I can add that. Including disabled as a third preserve_file_partitions state would take the matrix from 24 to 36 cells.
To confirm the intended scope, would you also like me to add the focused aggregate and join Rust cases before removing the proposed SLTs, or only add the disabled state to the current matrix?

@gene-bordegaray

Copy link
Copy Markdown
Contributor

just the dabled and we can leave the SLTs and no focused aggregation or join case

@blinding-pixels

Copy link
Copy Markdown
Author

@gene-bordegaray I’ve added the requested rows for the disabled state. Please let me know if anything else needs to be added or removed!

@github-actions

github-actions Bot commented Jul 22, 2026

Copy link
Copy Markdown

Thank you for opening this pull request!

Reviewer note: 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
     Cloning apache/main
    Building datafusion v54.1.0 (current)
error: running cargo-doc on crate 'datafusion' failed with output:
-----
   Compiling proc-macro2 v1.0.107
   Compiling unicode-ident v1.0.24
   Compiling quote v1.0.47
   Compiling libc v0.2.189
    Checking cfg-if v1.0.4
   Compiling shlex v2.0.1
   Compiling find-msvc-tools v0.1.9
   Compiling autocfg v1.5.1
    Checking memchr v2.8.3
   Compiling libm v0.2.16
   Compiling syn v2.0.119
   Compiling syn v3.0.3
   Compiling num-traits v0.2.19
   Compiling jobserver v0.1.35
   Compiling cc v1.4.0
   Compiling version_check v0.9.5
   Compiling zerocopy v0.8.55
    Checking bytes v1.12.1
   Compiling serde_core v1.0.229
   Compiling getrandom v0.3.4
    Checking itoa v1.0.18
    Checking allocator-api2 v0.2.21
    Checking foldhash v0.2.0
    Checking equivalent v1.0.2
    Checking once_cell v1.21.4
    Checking hashbrown v0.17.1
   Compiling zmij v1.0.23
   Compiling synstructure v0.13.2
    Checking indexmap v2.14.0
    Checking num-integer v0.1.46
   Compiling serde v1.0.229
   Compiling serde_json v1.0.151
    Checking num-bigint v0.4.8
   Compiling serde_derive v1.0.229
   Compiling pkg-config v0.3.33
   Compiling zerocopy-derive v0.8.55
   Compiling zerofrom-derive v0.1.7
    Checking iana-time-zone v0.1.65
    Checking siphasher v1.0.3
    Checking phf_shared v0.12.1
    Checking chrono v0.4.45
    Checking zerofrom v0.1.8
   Compiling yoke-derive v0.8.2
   Compiling ahash v0.8.12
    Checking stable_deref_trait v1.2.1
   Compiling chrono-tz v0.10.4
    Checking phf v0.12.1
    Checking yoke v0.8.3
   Compiling zerovec-derive v0.11.3
    Checking arrow-schema v59.1.0
    Checking num-complex v0.4.6
    Checking zerovec v0.11.6
   Compiling displaydoc v0.2.7
   Compiling zstd-sys v2.0.16+zstd.1.5.7
    Checking pin-project-lite v0.2.17
    Checking tinystr v0.8.3
    Checking writeable v0.6.3
    Checking smallvec v1.15.2
    Checking lexical-util v1.0.7
    Checking half v2.7.1
    Checking arrow-buffer v59.1.0
   Compiling object v0.39.1
    Checking futures-sink v0.3.33
   Compiling zstd-safe v7.2.4
    Checking futures-core v0.3.33
    Checking litemap v0.8.2
    Checking arrow-data v59.1.0
    Checking icu_locale_core v2.2.0
    Checking zerotrie v0.2.4
    Checking potential_utf v0.1.5
   Compiling icu_properties_data v2.2.0
    Checking utf8_iter v1.0.4
   Compiling icu_normalizer_data v2.2.0
    Checking icu_collections v2.2.0
    Checking icu_provider v2.2.0
    Checking arrow-array v59.1.0
   Compiling tokio-macros v2.7.2
   Compiling crc32fast v1.5.0
   Compiling semver v1.0.28
   Compiling rustc_version v0.4.1
    Checking tokio v1.53.1
    Checking arrow-select v59.1.0
    Checking futures-channel v0.3.33
    Checking lexical-write-integer v1.0.6
    Checking lexical-parse-integer v1.0.6
   Compiling futures-macro v0.3.33
   Compiling ar_archive_writer v0.5.3
    Checking futures-task v0.3.33
   Compiling parking_lot_core v0.9.12
    Checking bitflags v2.13.1
    Checking slab v0.4.12
    Checking adler2 v2.0.1
    Checking simd-adler32 v0.3.10
    Checking futures-io v0.3.33
    Checking futures-util v0.3.33
    Checking miniz_oxide v0.8.9
   Compiling psm v0.1.32
    Checking lexical-parse-float v1.0.6
    Checking lexical-write-float v1.0.6
    Checking icu_normalizer v2.2.0
    Checking icu_properties v2.2.0
   Compiling flatbuffers v25.12.19
    Checking aho-corasick v1.1.4
    Checking unicode-width v0.2.2
    Checking scopeguard v1.2.0
    Checking zlib-rs v0.6.6
   Compiling getrandom v0.4.3
    Checking base64 v0.22.1
    Checking unicode-segmentation v1.13.3
    Checking ryu v1.0.23
    Checking regex-syntax v0.8.11
    Checking comfy-table v7.2.2
    Checking lock_api v0.4.14
    Checking idna_adapter v1.2.2
    Checking lexical-core v1.0.6
    Checking flate2 v1.1.9
    Checking arrow-ord v59.1.0
    Checking regex-automata v0.4.16
   Compiling stacker v0.1.25
    Checking atoi v2.0.0
    Checking either v1.17.0
    Checking alloc-no-stdlib v2.0.4
   Compiling thiserror v2.0.19
   Compiling snap v1.1.2
    Checking twox-hash v2.1.3
    Checking percent-encoding v2.3.2
    Checking form_urlencoded v1.2.2
    Checking lz4_flex v0.13.1
    Checking alloc-stdlib v0.2.4
    Checking arrow-cast v59.1.0
    Checking regex v1.13.1
    Checking idna v1.1.0
    Checking futures-executor v0.3.33
   Compiling tracing-attributes v0.1.31
   Compiling thiserror-impl v2.0.19
    Checking tracing-core v0.1.36
   Compiling ring v0.17.14
    Checking csv-core v0.1.13
    Checking same-file v1.0.6
    Checking simdutf8 v0.1.5
   Compiling paste v1.0.15
    Checking walkdir v2.5.0
    Checking csv v1.4.0
    Checking tracing v0.1.44
    Checking futures v0.3.33
    Checking url v2.5.8
    Checking brotli-decompressor v5.0.3
    Checking itertools v0.14.0
    Checking parking_lot v0.12.5
   Compiling recursive-proc-macro-impl v0.1.1
   Compiling async-trait v0.1.91
    Checking http v1.5.0
    Checking zstd v0.13.3
    Checking arrow-ipc v59.1.0
    Checking getrandom v0.2.17
    Checking untrusted v0.9.0
    Checking log v0.4.33
    Checking humantime v2.4.0
    Checking recursive v0.1.1
    Checking brotli v8.0.4
    Checking object_store v0.13.2
    Checking arrow-csv v59.1.0
    Checking arrow-json v59.1.0
    Checking uuid v1.24.0
    Checking arrow-string v59.1.0
    Checking arrow-arith v59.1.0
    Checking arrow-row v59.1.0
   Compiling sqlparser_derive v0.5.0
   Compiling seq-macro v0.3.6
    Checking arrow v59.1.0
    Checking itertools v0.15.0
    Checking typenum v1.20.1
    Checking sqlparser v0.62.0
    Checking parquet v59.1.0
    Checking hex v0.4.3
   Compiling pin-project-internal v1.1.13
   Compiling generic-array v0.14.7
    Checking datafusion-doc v54.1.0 (/home/runner/work/datafusion/datafusion/datafusion/doc)
    Checking hybrid-array v0.4.14
    Checking ppv-lite86 v0.2.21
    Checking pin-project v1.1.13
    Checking rand_core v0.9.5
    Checking foldhash v0.1.5
   Compiling rustix v1.1.4
   Compiling crossbeam-utils v0.8.22
    Checking rand_chacha v0.9.0
    Checking hashbrown v0.15.5
    Checking linux-raw-sys v0.12.1
    Checking fixedbitset v0.5.7
    Checking petgraph v0.8.3
    Checking rand v0.9.5
    Checking block-buffer v0.12.1
    Checking crypto-common v0.2.2
    Checking tokio-util v0.7.19
    Checking hashbrown v0.14.5
    Checking const-oid v0.10.2
    Checking fastrand v2.5.0
    Checking dashmap v6.2.1
    Checking digest v0.11.3
    Checking tempfile v3.27.0
    Checking block-buffer v0.10.4
    Checking crypto-common v0.1.7
   Compiling datafusion-macros v54.1.0 (/home/runner/work/datafusion/datafusion/datafusion/macros)
   Compiling blake3 v1.8.5
    Checking cpufeatures v0.3.0
    Checking subtle v2.6.1
    Checking digest v0.10.7
    Checking arrayvec v0.7.8
    Checking constant_time_eq v0.4.2
    Checking arrayref v0.3.9
    Checking blake2 v0.10.6
    Checking sha2 v0.11.0
    Checking md-5 v0.11.0
   Compiling liblzma-sys v0.4.7
    Checking base64 v0.23.0
    Checking libbz2-rs-sys v0.2.5
    Checking datafusion-common-runtime v54.1.0 (/home/runner/work/datafusion/datafusion/datafusion/common-runtime)
    Checking compression-core v0.4.32
    Checking glob v0.3.4
   Compiling bigdecimal v0.4.10
    Checking bzip2 v0.6.1
   Compiling heck v0.5.0
    Checking crc-catalog v2.5.0
    Checking crc v3.4.0
   Compiling strum_macros v0.28.0
    Checking tokio-stream v0.1.19
    Checking liblzma v0.4.7
    Checking compression-codecs v0.4.38
    Checking arrow-avro v59.1.0
    Checking async-compression v0.4.43
    Checking datafusion-common v54.1.0 (/home/runner/work/datafusion/datafusion/datafusion/common)
    Checking datafusion-expr-common v54.1.0 (/home/runner/work/datafusion/datafusion/datafusion/expr-common)
    Checking datafusion-physical-expr-common v54.1.0 (/home/runner/work/datafusion/datafusion/datafusion/physical-expr-common)
    Checking datafusion-functions-window-common v54.1.0 (/home/runner/work/datafusion/datafusion/datafusion/functions-window-common)
    Checking datafusion-functions-aggregate-common v54.1.0 (/home/runner/work/datafusion/datafusion/datafusion/functions-aggregate-common)
    Checking datafusion-expr v54.1.0 (/home/runner/work/datafusion/datafusion/datafusion/expr)
    Checking datafusion-physical-expr v54.1.0 (/home/runner/work/datafusion/datafusion/datafusion/physical-expr)
    Checking datafusion-execution v54.1.0 (/home/runner/work/datafusion/datafusion/datafusion/execution)
    Checking datafusion-functions v54.1.0 (/home/runner/work/datafusion/datafusion/datafusion/functions)
    Checking datafusion-functions-aggregate v54.1.0 (/home/runner/work/datafusion/datafusion/datafusion/functions-aggregate)
    Checking datafusion-functions-window v54.1.0 (/home/runner/work/datafusion/datafusion/datafusion/functions-window)
    Checking datafusion-optimizer v54.1.0 (/home/runner/work/datafusion/datafusion/datafusion/optimizer)
    Checking datafusion-physical-plan v54.1.0 (/home/runner/work/datafusion/datafusion/datafusion/physical-plan)
    Checking datafusion-physical-expr-adapter v54.1.0 (/home/runner/work/datafusion/datafusion/datafusion/physical-expr-adapter)
    Checking datafusion-functions-nested v54.1.0 (/home/runner/work/datafusion/datafusion/datafusion/functions-nested)
    Checking datafusion-sql v54.1.0 (/home/runner/work/datafusion/datafusion/datafusion/sql)
error[E0599]: no method named `allow_range_satisfaction_for_key_partitioning` found for struct `InputDistributionRequirements` in the current scope
   --> /home/runner/work/datafusion/datafusion/datafusion/physical-plan/src/test/exec.rs:332:10
    |
329 | /         InputDistributionRequirements::new(vec![Distribution::KeyPartitioned(
330 | |             self.partition_keys.clone(),
331 | |         )])
332 | |         .allow_range_satisfaction_for_key_partitioning()
    | |         -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ method not found in `InputDistributionRequirements`
    | |_________|
    |
    |
   ::: /home/runner/work/datafusion/datafusion/datafusion/physical-plan/src/distribution_requirements.rs:59:1
    |
 59 |   pub struct InputDistributionRequirements {
    |   ---------------------------------------- method `allow_range_satisfaction_for_key_partitioning` not found for this struct

For more information about this error, try `rustc --explain E0599`.
error: could not compile `datafusion-physical-plan` (lib) due to 1 previous error

-----

error: failed to build rustdoc for crate datafusion v54.1.0
note: this is usually due to a compilation error in the crate,
      and is unlikely to be a bug in cargo-semver-checks
note: the following command can be used to reproduce the error:
      cargo new --lib example &&
          cd example &&
          echo '[workspace]' >> Cargo.toml &&
          cargo add --path /home/runner/work/datafusion/datafusion/datafusion/core --features array_expressions,avro,backtrace,bzip2,compression,crypto_expressions,datafusion-datasource-avro,datafusion-datasource-parquet,datafusion-functions-nested,datafusion-sql,datetime_expressions,default,encoding_expressions,extended_tests,flate2,force_hash_collisions,liblzma,math_expressions,nested_expressions,parquet,parquet_encryption,recursive_protection,regex_expressions,serde,sql,sqlparser,string_expressions,unicode_expressions,zstd &&
          cargo check &&
          cargo doc

    Building datafusion-physical-plan v54.1.0 (current)
       Built [  39.070s] (current)
     Parsing datafusion-physical-plan v54.1.0 (current)
      Parsed [   0.137s] (current)
    Building datafusion-physical-plan v54.1.0 (baseline)
       Built [  38.685s] (baseline)
     Parsing datafusion-physical-plan v54.1.0 (baseline)
      Parsed [   0.141s] (baseline)
    Checking datafusion-physical-plan v54.1.0 -> v54.1.0 (no change; assume patch)
     Checked [   0.629s] 223 checks: 223 pass, 30 skip
     Summary no semver update required
    Finished [  79.811s] datafusion-physical-plan
    Building datafusion-sqllogictest v54.1.0 (current)
error: running cargo-doc on crate 'datafusion-sqllogictest' failed with output:
-----
   Compiling proc-macro2 v1.0.107
   Compiling unicode-ident v1.0.24
   Compiling quote v1.0.47
   Compiling libc v0.2.189
    Checking cfg-if v1.0.4
    Checking bytes v1.12.1
    Checking memchr v2.8.3
   Compiling serde_core v1.0.229
   Compiling syn v2.0.119
   Compiling syn v3.0.3
   Compiling autocfg v1.5.1
   Compiling jobserver v0.1.35
   Compiling find-msvc-tools v0.1.9
   Compiling shlex v2.0.1
   Compiling cc v1.4.0
    Checking itoa v1.0.18
    Checking equivalent v1.0.2
    Checking foldhash v0.2.0
    Checking once_cell v1.21.4
    Checking allocator-api2 v0.2.21
   Compiling libm v0.2.16
   Compiling num-traits v0.2.19
    Checking hashbrown v0.17.1
    Checking indexmap v2.14.0
    Checking pin-project-lite v0.2.17
   Compiling zmij v1.0.23
    Checking futures-core v0.3.33
   Compiling zerocopy v0.8.55
    Checking futures-sink v0.3.33
    Checking errno v0.3.14
   Compiling tokio-macros v2.7.2
    Checking signal-hook-registry v1.4.8
    Checking socket2 v0.6.5
    Checking mio v1.2.2
   Compiling version_check v0.9.5
   Compiling serde v1.0.229
    Checking num-integer v0.1.46
    Checking tokio v1.53.1
   Compiling serde_derive v1.0.229
   Compiling zerocopy-derive v0.8.55
    Checking slab v0.4.12
   Compiling serde_json v1.0.151
    Checking futures-channel v0.3.33
    Checking smallvec v1.15.2
   Compiling getrandom v0.3.4
    Checking num-bigint v0.4.8
   Compiling futures-macro v0.3.33
   Compiling synstructure v0.13.2
    Checking http v1.5.0
    Checking base64 v0.22.1
    Checking futures-io v0.3.33
    Checking futures-task v0.3.33
    Checking futures-util v0.3.33
    Checking iana-time-zone v0.1.65
    Checking chrono v0.4.45
   Compiling zerofrom-derive v0.1.7
   Compiling tracing-attributes v0.1.31
    Checking tracing-core v0.1.36
    Checking siphasher v1.0.3
    Checking zerofrom v0.1.8
   Compiling yoke-derive v0.8.2
    Checking rand_core v0.10.1
   Compiling getrandom v0.4.3
    Checking stable_deref_trait v1.2.1
    Checking num-complex v0.4.6
    Checking tracing v0.1.44
   Compiling zerovec-derive v0.11.3
    Checking getrandom v0.2.17
   Compiling pkg-config v0.3.33
    Checking cpufeatures v0.3.0
    Checking phf_shared v0.12.1
    Checking half v2.7.1
   Compiling ahash v0.8.12
   Compiling displaydoc v0.2.7
    Checking yoke v0.8.3
   Compiling chrono-tz v0.10.4
    Checking percent-encoding v2.3.2
   Compiling thiserror v2.0.19
    Checking arrow-buffer v59.1.0
    Checking zerovec v0.11.6
    Checking phf v0.12.1
    Checking arrow-schema v59.1.0
   Compiling thiserror-impl v2.0.19
   Compiling ring v0.17.14
    Checking arrow-data v59.1.0
   Compiling semver v1.0.28
    Checking log v0.4.33
    Checking tinystr v0.8.3
    Checking chacha20 v0.10.1
    Checking untrusted v0.9.0
    Checking bitflags v2.13.1
    Checking writeable v0.6.3
    Checking litemap v0.8.2
    Checking rand v0.10.2
    Checking icu_locale_core v2.2.0
    Checking potential_utf v0.1.5
    Checking zerotrie v0.2.4
   Compiling zstd-sys v2.0.16+zstd.1.5.7
   Compiling async-trait v0.1.91
    Checking utf8_iter v1.0.4
   Compiling icu_normalizer_data v2.2.0
   Compiling icu_properties_data v2.2.0
    Checking icu_collections v2.2.0
    Checking icu_provider v2.2.0
    Checking tokio-util v0.7.19
    Checking aho-corasick v1.1.4
    Checking regex-syntax v0.8.11
    Checking arrow-array v59.1.0
   Compiling zstd-safe v7.2.4
    Checking lexical-util v1.0.7
    Checking ryu v1.0.23
   Compiling object v0.39.1
    Checking arrow-select v59.1.0
    Checking regex-automata v0.4.16
    Checking icu_properties v2.2.0
    Checking icu_normalizer v2.2.0
   Compiling rustix v1.1.4
    Checking either v1.17.0
    Checking idna_adapter v1.2.2
    Checking form_urlencoded v1.2.2
    Checking unicode-width v0.2.2
   Compiling crc32fast v1.5.0
    Checking regex v1.13.1
   Compiling parking_lot_core v0.9.12
    Checking typenum v1.20.1
    Checking idna v1.1.0
    Checking lexical-parse-integer v1.0.6
    Checking lexical-write-integer v1.0.6
   Compiling rustc_version v0.4.1
    Checking futures-executor v0.3.33
   Compiling pin-project-internal v1.1.13
    Checking simd-adler32 v0.3.10
    Checking scopeguard v1.2.0
    Checking adler2 v2.0.1
    Checking miniz_oxide v0.8.9
    Checking lock_api v0.4.14
    Checking futures v0.3.33
   Compiling flatbuffers v25.12.19
    Checking lexical-write-float v1.0.6
    Checking pin-project v1.1.13
    Checking lexical-parse-float v1.0.6
    Checking url v2.5.8
    Checking unicode-segmentation v1.13.3
    Checking zlib-rs v0.6.6
    Checking comfy-table v7.2.2
    Checking lexical-core v1.0.6
    Checking itertools v0.14.0
   Compiling ar_archive_writer v0.5.3
    Checking flate2 v1.1.9
    Checking arrow-ord v59.1.0
   Compiling psm v0.1.32
    Checking twox-hash v2.1.3
    Checking atoi v2.0.0
   Compiling stacker v0.1.25
    Checking alloc-no-stdlib v2.0.4
   Compiling snap v1.1.2
    Checking hex v0.4.3
    Checking lz4_flex v0.13.1
    Checking alloc-stdlib v0.2.4
    Checking arrow-cast v59.1.0
    Checking parking_lot v0.12.5
    Checking csv-core v0.1.13
   Compiling paste v1.0.15
    Checking humantime v2.4.0
    Checking same-file v1.0.6
    Checking simdutf8 v0.1.5
    Checking walkdir v2.5.0
    Checking csv v1.4.0
    Checking brotli-decompressor v5.0.3
   Compiling recursive-proc-macro-impl v0.1.1
    Checking subtle v2.6.1
    Checking brotli v8.0.4
    Checking arrow-json v59.1.0
    Checking recursive v0.1.1
    Checking arrow-csv v59.1.0
    Checking object_store v0.13.2
    Checking arrow-string v59.1.0
    Checking zstd v0.13.3
    Checking arrow-ipc v59.1.0
    Checking arrow-row v59.1.0
    Checking arrow-arith v59.1.0
    Checking uuid v1.24.0
   Compiling sqlparser_derive v0.5.0
   Compiling seq-macro v0.3.6
    Checking arrow v59.1.0
    Checking itertools v0.15.0
    Checking ppv-lite86 v0.2.21
    Checking sqlparser v0.62.0
    Checking parquet v59.1.0
    Checking hybrid-array v0.4.14
    Checking cmov v0.5.4
    Checking linux-raw-sys v0.12.1
    Checking ctutils v0.4.2
    Checking crypto-common v0.2.2
    Checking block-buffer v0.12.1
    Checking rand_core v0.9.5
   Compiling generic-array v0.14.7
    Checking const-oid v0.10.2
    Checking digest v0.11.3
    Checking rand_chacha v0.9.0
    Checking rand v0.9.5
    Checking datafusion-doc v54.1.0 (/home/runner/work/datafusion/datafusion/datafusion/doc)
    Checking foldhash v0.1.5
   Compiling crossbeam-utils v0.8.22
    Checking hashbrown v0.15.5
    Checking block-buffer v0.10.4
    Checking crypto-common v0.1.7
   Compiling heck v0.5.0
    Checking fastrand v2.5.0
    Checking fixedbitset v0.5.7
    Checking tempfile v3.27.0
    Checking petgraph v0.8.3
    Checking digest v0.10.7
    Checking sha2 v0.11.0
    Checking md-5 v0.11.0
    Checking hashbrown v0.14.5
   Compiling datafusion-macros v54.1.0 (/home/runner/work/datafusion/datafusion/datafusion/macros)
   Compiling blake3 v1.8.5
    Checking dashmap v6.2.1
   Compiling anyhow v1.0.104
    Checking arrayvec v0.7.8
    Checking arrayref v0.3.9
    Checking constant_time_eq v0.4.2
    Checking blake2 v0.10.6
   Compiling liblzma-sys v0.4.7
    Checking base64 v0.23.0
    Checking libbz2-rs-sys v0.2.5
    Checking bzip2 v0.6.1
    Checking datafusion-common-runtime v54.1.0 (/home/runner/work/datafusion/datafusion/datafusion/common-runtime)
   Compiling httparse v1.10.1
   Compiling prost-derive v0.14.4
    Checking compression-core v0.4.32
    Checking http-body v1.1.0
    Checking glob v0.3.4
    Checking tower-service v0.3.3
    Checking try-lock v0.2.5
    Checking atomic-waker v1.1.2
    Checking fnv v1.0.7
    Checking h2 v0.4.15
    Checking want v0.3.1
    Checking tokio-stream v0.1.19
    Checking httpdate v1.0.3
    Checking zeroize v1.9.0
    Checking rustls-pki-types v1.15.1
    Checking hyper v1.11.0
    Checking datafusion-common v54.1.0 (/home/runner/work/datafusion/datafusion/datafusion/common)
   Compiling prost v0.14.4
    Checking hyper-util v0.1.20
    Checking http-body-util v0.1.4
    Checking sync_wrapper v1.0.2
   Compiling rustls v0.23.43
    Checking tower-layer v0.3.3
   Compiling prettyplease v0.2.37
   Compiling prost-types v0.14.4
    Checking liblzma v0.4.7
    Checking compression-codecs v0.4.38
    Checking async-compression v0.4.43
    Checking rustls-webpki v0.103.13
    Checking datafusion-expr-common v54.1.0 (/home/runner/work/datafusion/datafusion/datafusion/expr-common)
   Compiling serde_derive_internals v0.29.1
    Checking mime v0.3.17
   Compiling schemars v0.8.22
    Checking datafusion-physical-expr-common v54.1.0 (/home/runner/work/datafusion/datafusion/datafusion/physical-expr-common)
   Compiling hashbrown v0.16.1
   Compiling schemars_derive v0.8.22
    Checking datafusion-functions-aggregate-common v54.1.0 (/home/runner/work/datafusion/datafusion/datafusion/functions-aggregate-common)
    Checking datafusion-functions-window-common v54.1.0 (/home/runner/work/datafusion/datafusion/datafusion/functions-window-common)
    Checking axum-core v0.5.6
    Checking datafusion-expr v54.1.0 (/home/runner/work/datafusion/datafusion/datafusion/expr)
    Checking tower v0.5.3
    Checking matchit v0.8.4
   Compiling dyn-clone v1.0.20
   Compiling multimap v0.10.1
    Checking axum v0.8.9
   Compiling prost-build v0.14.4
   Compiling regress v0.10.5
    Checking datafusion-physical-expr v54.1.0 (/home/runner/work/datafusion/datafusion/datafusion/physical-expr)
    Checking datafusion-execution v54.1.0 (/home/runner/work/datafusion/datafusion/datafusion/execution)
   Compiling pbjson-build v0.8.0
    Checking datafusion-functions v54.1.0 (/home/runner/work/datafusion/datafusion/datafusion/functions)
    Checking hyper-timeout v0.5.2
   Compiling strsim v0.11.1
   Compiling portable-atomic v1.14.0
   Compiling ident_case v1.0.1
   Compiling darling_core v0.23.0
   Compiling typify-impl v0.5.0
    Checking tonic v0.14.6
   Compiling serde_tokenstream v0.2.3
    Checking ureq-proto v0.6.0
   Compiling bigdecimal v0.4.10
    Checking tinyvec_macros v0.1.1
    Checking crc-catalog v2.5.0
    Checking utf8-zero v0.8.1
    Checking utf8parse v0.2.2
   Compiling bollard-buildkit-proto v0.7.0
    Checking anstyle-parse v1.0.0
    Checking ureq v3.3.0
    Checking datafusion-physical-plan v54.1.0 (/home/runner/work/datafusion/datafusion/datafusion/physical-plan)
    Checking datafusion-physical-expr-adapter v54.1.0 (/home/runner/work/datafusion/datafusion/datafusion/physical-expr-adapter)
   Compiling darling_macro v0.23.0
    Checking crc v3.4.0
    Checking tinyvec v1.12.0
    Checking tonic-prost v0.14.6
    Checking datafusion-functions-aggregate v54.1.0 (/home/runner/work/datafusion/datafusion/datafusion/functions-aggregate)
   Compiling strum_macros v0.28.0
   Compiling typify-macro v0.5.0
   Compiling structmeta-derive v0.3.0
    Checking deranged v0.5.8
   Compiling unsafe-libyaml v0.2.11
    Checking anstyle-query v1.1.5
    Checking is_terminal_polyfill v1.70.2
    Checking colorchoice v1.0.5
    Checking anstyle v1.0.14
    Checking time-core v0.1.9
    Checking num-conv v0.2.2
    Checking powerfmt v0.2.0
    Checking anstream v1.0.0
    Checking time v0.3.55
   Compiling serde_yaml v0.9.34+deprecated
error[E0599]: no method named `allow_range_satisfaction_for_key_partitioning` found for struct `InputDistributionRequirements` in the current scope
   --> /home/runner/work/datafusion/datafusion/datafusion/physical-plan/src/test/exec.rs:332:10
    |
329 | /         InputDistributionRequirements::new(vec![Distribution::KeyPartitioned(
330 | |             self.partition_keys.clone(),
331 | |         )])
332 | |         .allow_range_satisfaction_for_key_partitioning()
    | |         -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ method not found in `InputDistributionRequirements`
    | |_________|
    |
    |
   ::: /home/runner/work/datafusion/datafusion/datafusion/physical-plan/src/distribution_requirements.rs:59:1
    |
 59 |   pub struct InputDistributionRequirements {
    |   ---------------------------------------- method `allow_range_satisfaction_for_key_partitioning` not found for this struct

   Compiling structmeta v0.3.0
    Checking arrow-avro v59.1.0
   Compiling typify v0.5.0
    Checking datafusion-functions-nested v54.1.0 (/home/runner/work/datafusion/datafusion/datafusion/functions-nested)
    Checking unicode-normalization v0.1.25
For more information about this error, try `rustc --explain E0599`.
error: could not compile `datafusion-physical-plan` (lib) due to 1 previous error
warning: build failed, waiting for other jobs to finish...

-----

error: failed to build rustdoc for crate datafusion-sqllogictest v54.1.0
note: this is usually due to a compilation error in the crate,
      and is unlikely to be a bug in cargo-semver-checks
note: the following command can be used to reproduce the error:
      cargo new --lib example &&
          cd example &&
          echo '[workspace]' >> Cargo.toml &&
          cargo add --path /home/runner/work/datafusion/datafusion/datafusion/sqllogictest --features avro,backtrace,bytes,chrono,datafusion-substrait,parquet_encryption,postgres,postgres-types,substrait,testcontainers-modules,tokio-postgres &&
          cargo check &&
          cargo doc

error: aborting due to failure to build rustdoc for crate datafusion v54.1.0

@github-actions github-actions Bot added the auto detected api change Auto detected API change label Jul 22, 2026
@codecov-commenter

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 85.71429% with 7 lines in your changes missing coverage. Please review.
⚠️ Please upload report for BASE (main@7f6cc60). Learn more about missing BASE report.

Files with missing lines Patch % Lines
datafusion/physical-plan/src/test/exec.rs 85.71% 7 Missing ⚠️
Additional details and impacted files
@@           Coverage Diff           @@
##             main   #23627   +/-   ##
=======================================
  Coverage        ?   80.67%           
=======================================
  Files           ?     1088           
  Lines           ?   367640           
  Branches        ?   367640           
=======================================
  Hits            ?   296589           
  Misses          ?    53391           
  Partials        ?    17660           

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

@blinding-pixels

Copy link
Copy Markdown
Author

@gene-bordegaray Is there anything else needed on this? Let me know. Thanks!

@gene-bordegaray

Copy link
Copy Markdown
Contributor

I am going to be very busy for the next week, will get back to this thank you 🙇

@gene-bordegaray gene-bordegaray left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

can we also please remove slt test 4 5 and 6

}

#[derive(Debug, Clone, Copy)]
enum RangeKeyMatch {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Could we collapse all this to a small case structure using something like subset_met: bool, preserve_met: Option, and increase_partitions: bool, keeping the [ExpectedPlan; 3] table?

@github-actions github-actions Bot added the sqllogictest SQL Logic Tests (.slt) label Aug 2, 2026
@blinding-pixels

Copy link
Copy Markdown
Author

@gene-bordegaray I removed the three SLT tests and implemented your simplification suggestion.

On a personal note, thank you for that part of the review. It helped me rethink how I structure test cases and pointed me in a better direction.

@gene-bordegaray gene-bordegaray left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

ok we are starting to get these now notice that we can reuse arts of test_utils.rs rather than repeating boilerplate and we can further simplify the test setup rather than being overly verbose (a test usually shouldn't be hundres of lines long).

Here is what I think should be done to make this test shorter and just as effective for coverage:

  1. Rebase onto the most recent main
  2. We can remove KeyPartitioningRequirementExec and everything indatafusion/physical-plan/src/test/exec.rs
  3. Extend the existing RequirementsTestExec in physical_optimizer/test_utils.rs with a required_input_distribution: Distribution field, with_required_input_distribution(...), input_distribution_requirements().
  4. Make the matrix simpler by doing:
    let requirement = RequirementsTestExec::new(input)
        .with_required_input_distribution(Distribution::KeyPartitioned(
            partition_keys,
        ))
        .into_arc();
  5. Keep the matrix outcomes but do it as a simply:
    const INPUT_PARTITIONS: usize = 4;
    const MET: usize = INPUT_PARTITIONS;
    const NOT_MET: usize = INPUT_PARTITIONS + 1;
    const DISABLED: usize = 0;
    const EQUAL: usize = INPUT_PARTITIONS;
    const GREATER: usize = INPUT_PARTITIONS + 1;
    
    // (subset, preserve, target, [exact, subset, incompatible])
    let config_cases = [
        (NOT_MET, DISABLED, EQUAL, [Reuse, Hash, Hash]),
        (NOT_MET, DISABLED, GREATER, [Hash, Hash, Hash]),
         ...
    ];
  6. Renumber SLT test after deleting 4, 5, and 6

@blinding-pixels
blinding-pixels force-pushed the agent/range-satisfaction-config-matrix branch from 593c96f to 37aeec3 Compare August 3, 2026 21:18
@blinding-pixels

Copy link
Copy Markdown
Author

@gene-bordegaray Done. It was nice being able to reuse RequirementsTestExec here. I also simplified the matrix and renumbered the SLT tests. Please let me know if anything else needs to be addressed.

@github-actions github-actions Bot removed the physical-plan Changes to the physical-plan crate label Aug 3, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

auto detected api change Auto detected API change core Core DataFusion crate sqllogictest SQL Logic Tests (.slt)

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Add config-matrix tests in enforce_distribution.rs for range-satisfaction settings

4 participants