peter-toth opened a new pull request, #58928:
URL: https://github.com/apache/spark/pull/58928

   ### What changes were proposed in this pull request?
   
   Five `Partitioning.satisfies0` implementations spelled out the same 
two-branch test on `ClusteredDistribution.requireAllClusterKeys`:
   
   ```scala
   if (requireAllClusterKeys) {
     c.areAllClusterKeysMatched(expressions)
   } else {
     expressions.forall(x => requiredClustering.exists(_.semanticEquals(x)))
   }
   ```
   
   So the flag was read in five places and the membership test written out five 
times. `ClusteredDistribution.matchesClusterKeys` is that pair, beside the 
`areAllClusterKeysMatched` it wraps and the `isClusterKey` it is built from, 
and the five callers ask it: `HashPartitioningLike`, 
`NullAwareHashPartitioning`, `CoalescedNullAwareHashPartitioning`, 
`RangePartitioning` and `ShufflePartitionIdPassThrough`.
   
   Three hand-written zip-and-compare folds become one `Seq.corresponds` each: 
`ClusteredDistribution.areAllClusterKeysMatched`, 
`OrderedDistribution.areAllClusterKeysMatched`, and the 
`StatefulOpClusteredDistribution` arm of `HashPartitioningLike.satisfies0` that 
spelled the first one out at a call site rather than calling it.
   
   `AQEUtils.getRequiredDistribution`'s mirror fold, which asks whether a 
project list covers the clustering rather than the other way round, is 
`allClusterKeysAmong`.
   
   Net 28 lines removed, no new API beyond `matchesClusterKeys` on a 
`private[sql]`-reachable case class in `sql.catalyst`.
   
   ### Why are the changes needed?
   
   `requireAllClusterKeys` is one rule about what a partitioning has to be 
partitioned on, and it was five copies of that rule. A change to it had to be 
made in five places, and a reader comparing two `satisfies0` implementations 
had to diff the copies to see that they agree. `isClusterKey` and 
`allClusterKeysAmong` already exist on `ClusteredDistribution` for exactly this 
reason, added by SPARK-59289; this finishes the set and uses them.
   
   ### Does this PR introduce _any_ user-facing change?
   
   No. This is behaviour neutral, and three things are worth stating because 
each is a place it could have failed to be:
   
   - `Seq.corresponds` is same-length-and-element-wise, which is what each of 
the three folds computed.
   - The argument order of every `semanticEquals` is preserved, so nothing 
relies on it being symmetric.
   - Replacing the `case c @ ClusteredDistribution(...)` extractor patterns 
with `case c: ClusteredDistribution` matches the same set: the physical 
`ClusteredDistribution` is a leaf case class. The `ClusteredDistributionImpl` 
in `connector.distributions` extends the connector interface of that name, not 
this one.
   
   ### How was this patch tested?
   
   No new tests: there is no new behaviour to pin, and the existing suites 
already cover each rewritten site.
   
   Green: `DistributionSuite`, `ShuffleSpecSuite`, `PlannerSuite`, 
`EnsureRequirementsSuite`, `ValidateRequirementsSuite`, 
`KeyGroupedPartitioningSuite`, `GroupPartitionsExecSuite`, 
`AdaptiveQueryExecSuite` and `ExchangeSuite`, 593 tests.
   
   The touched arms that are easy to miss got their own runs. 
`StatefulOpClusteredDistribution` and the two null-aware partitionings: 
`StreamingAggregationDistributionSuite`, 
`StreamingDeduplicationDistributionSuite`, 
`StreamingSessionWindowDistributionSuite`, 
`FlatMapGroupsWithStateDistributionSuite` and 
`StreamingQueryHashPartitionVerifySuite`, 12 tests. And since `satisfies0` runs 
on every query, all five plan-stability suites, 172 tests, so no golden TPCDS 
or TPCH plan changed.
   
   `dev/lint-scala` is clean.
   
   ### Was this patch authored or co-authored using generative AI tooling?
   
   Generated-by: Claude Code (Opus 5)
   


-- 
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: [email protected]

For queries about this service, please contact Infrastructure at:
[email protected]


---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to