brijrajk commented on PR #12151:
URL: https://github.com/apache/gluten/pull/12151#issuecomment-5196402896

   @zhztheplayer Yes, still needed. I tried both ways of removing it; both 
fail, for independent reasons. Branch is rebased onto current main, where the 
baseline is `GlutenBloomFilterFallbackSuite` 8/8 and 
`GlutenBloomFilterAggregateQuerySuite` + `GlutenInjectRuntimeFilterSuite` 43/43.
   
   **1. Joint rule ported to a physical rule at `injectPre`** -- 3/8 fallback 
tests fail with the original crash back (`kBloomFilterV1 == version`, 1 vs 0).
   
   The producer is unreachable from a physical rule. Instrumenting the reach-in 
shows:
   
   ```
   subqPlanClass=SubqueryExec  child0=AdaptiveSparkPlanExec
   aggsReachedByTransform=0    planUnchanged=true    
treeStringMentionsVanillaAgg=true
   ```
   
   The vanilla `bloom_filter_agg` is present in the subquery's tree, but 
`AdaptiveSparkPlanExec` is a `LeafExecNode`, so traversal stops there and the 
aggregate is untouchable. The consumer still gets rewritten to Velox, which is 
exactly the v1/v0 split that crashes. The mismatch is concrete: Velox 
serializes the version as a single `int8` of 1, while Spark's 
`BloomFilterImpl.writeTo` writes a 4-byte big-endian int, so vanilla bytes 
present `0x00` as their first byte, hence "version: 0".
   
   Independently, AQE compiles the subquery from the logical plan 
(`InsertAdaptiveSparkPlan.compileSubquery(LogicalPlan)`), so a physical 
mutation would not be what executes.
   
   This is not about choosing an earlier hook. AQE compiles the scalar subquery 
into its own `AdaptiveSparkPlanExec` with independent fallback decisions, so 
the last point at which any rule Gluten can inject sees both sides in one 
rewritable tree is the optimized logical plan.
   
   **2. One unified logical rule registered twice** (normal optimizer batch 
plus `spark.experimental.extraOptimizations`, so it also fires after 
`InjectRuntimeFilter`), replacing both rules. This passes the fallback suite 
8/8 with no native crashes, but fails 11/43:
   
   ```
   scala.MatchError: velox_bloom_filter_agg(xxhash64(c2#10018, 42), ...) AS 
bloomFilter#10054
     at 
...InjectRuntimeFilterSuite...applyOrElse(InjectRuntimeFilterSuite.scala:259)
   ```
   
   `getNumBloomFilters` matches over `optimizedPlan` expecting the vanilla 
shape. One of the 11 is `GLUTEN-9849: bloom filter applied to partition 
filter`, which is Gluten's own test, so this cannot be waved off as inherited 
expectations. Also, `extraOptimizations` is a public mutable var: any user 
assigning to it silently drops the rule and reintroduces a native crash.
   
   **Why the split is right.** The two populations differ in one property: 
`InjectRuntimeFilter` stamps `XxHash64` on both producer and consumer, so each 
side is self-identifying and can be rewritten independently at the physical 
level, keeping the logical plan vanilla. User-written `might_contain(<scalar 
subquery>, <value>)` has no such marker, so the rewrite must be joint, and 
therefore logical.
   
   Longer term this constraint could be dissolved by teaching the native side 
to read Spark's bloom-filter layout, but that is a Velox-side change.
   


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