LuciferYang commented on code in PR #58419:
URL: https://github.com/apache/spark/pull/58419#discussion_r4027816125


##########
sql/core/src/main/scala/org/apache/spark/sql/execution/adaptive/AdaptiveSparkPlanExec.scala:
##########
@@ -134,7 +134,15 @@ case class AdaptiveSparkPlanExec(
     Seq(
       CoalesceBucketsInJoin,
       RemoveRedundantProjects,
+      // Must run before `ensureRequirements`, which asks a `UnionExec` what 
it reports: it
+      // records the conf that answer depends on, so the following 
`StampUnionDecisions` freezes the
+      // decision under the same value the exchanges were planned against.
+      SnapshotUnionOutputPartitioningConf,

Review Comment:
   Added in `AdaptiveQueryExecSuite`: `queryStagePreparationRules` is now 
`private[adaptive]`, and the case asserts the snapshot sits immediately before 
`EnsureRequirements`, the stamp immediately after it, and the trailing barrier 
last in the list.
   
   My first version took only the first stamp index, which the trailing barrier 
satisfies on its own, so deleting the load-bearing one left the test green. 
Collecting every index closes that.
   
   A behavioural discriminator is not reachable single-threaded. With the two 
rules adjacent, the only way the answers diverge is another thread writing the 
conf inside that one-rule window, so what the case pins is the order, as the 
non-AQE half does.



##########
sql/catalyst/src/main/scala/org/apache/spark/sql/internal/SQLConf.scala:
##########
@@ -2938,7 +2938,9 @@ object SQLConf {
       .doc("When both this conf and `spark.sql.codegen.wholeStage` are true, " 
+
         "UnionExec participates in whole-stage codegen on its " +
         "non-partitioning-aware path: the parent and all children fuse into " +
-        "a single WholeStageCodegenExec stage.")
+        "a single WholeStageCodegenExec stage. The value is read when a 
UnionExec's " +
+        "decision is fixed during physical preparation, so a change does not 
reach a " +

Review Comment:
   Fixed, and four more cases in the same suite had the same shape: BHJ child 
union, the BHJ case feeding a downstream aggregate, SMJ child union, and column 
pruning. Each compared a plan's output against its own, since the expected 
value came from the plan the flag-on preparation had already stamped.
   
   All five now build a fresh DataFrame per flag value through 
`assertFlagParity`, which takes a builder for exactly this reason, and the 
helper itself now asserts the flag-off half took no union into codegen, so 
every parity case gets that.
   
   That assertion needed a discriminator the suite did not have. Asking whether 
a codegen stage holds a `UnionExec` somewhere is true even when 
`CollapseCodegenStages` left it under an `InputAdapter`, taking no part in 
codegen, and `fusedUnions` asks for the union to root its own stage, which 
misses one fused into a parent operator's stage: the aggregate case is that 
shape. The new `codegenUnions` walks each stage and stops at `InputAdapter`, 
and it replaced the former `unionInsideWSCG` at every call site, several of 
which were asserting the weaker property while their names claimed fusion.



-- 
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