sunchao commented on code in PR #7155:
URL: https://github.com/apache/datafusion-comet/pull/7155#discussion_r4344266566


##########
spark/src/main/scala/org/apache/comet/rules/CometExecRule.scala:
##########
@@ -1176,11 +1174,46 @@ case class CometExecRule(session: SparkSession, 
queryStagePrep: Boolean = false)
           serde.convert(op, builder)
         }
       }
-      return nativeOp.map { nativeOp =>
-        val exec = serde.createExec(nativeOp, op)
-        rollUpInfoMessages(op, exec)
-        exec
-      }
+      return nativeOp
+        .filter { proto =>
+          // A serde may emit several native nodes for one Spark operator. 
Inspect those nodes,
+          // but stop at real Spark children, whose consumption context was 
tagged independently.
+          def containsOwnAssertion(node: Operator): Boolean =
+            
CometAssertNotNull.containsNativeAssertion(node.toBuilder.clearChildren().build())
 ||
+              node.getChildrenList.asScala.exists { child =>
+                child.getPlanId == proto.getPlanId && 
containsOwnAssertion(child)
+              }
+
+          def hasNativeAssertion: Boolean = op match {
+            // TopK's sink proto omits its runtime projection over the 
selected rows.
+            case topK: TakeOrderedAndProjectExec =>
+              QueryPlanSerde.withSharedSubexpressions(topK.projectList) {
+                topK.projectList.exists { expression =>
+                  QueryPlanSerde
+                    .exprToProto(expression, topK.child.output)
+                    .exists(CometAssertNotNull.containsNativeAssertion)
+                }
+              }
+            case _: HashAggregateExec | _: ObjectHashAggregateExec =>
+              // Input/grouping expressions consume all rows; only the result 
projection is lazy.
+              proto.hasProjection && 
CometAssertNotNull.containsNativeAssertion(
+                proto.getProjection)
+            case _ => containsOwnAssertion(proto)
+          }
+          op.getTagValue(CometExecRule.PARTIAL_READER) match {

Review Comment:
   [P2] Preserve early-exit semantics in semi/anti join conditions. This guard 
only checks assertions when an external consumer supplied `PARTIAL_READER`, but 
a broadcast semi/anti join also stops evaluating candidates after its first 
match. For a `BuildRight` join with left IDs `[0]`, right IDs `[0, 1]`, and 
Catalyst condition `IF(l.id = r.id, true, AssertNotNull(NULL::BOOLEAN))`, Spark 
returns `[0]` for LEFT SEMI and no rows for LEFT ANTI without evaluating the 
assertion. The native join evaluates the second candidate and throws 
`NOT_NULL_ASSERT_VIOLATION`. `If` is admitted by the new expression guard, and 
the join receives no partial-reader tag, so the previously unsupported 
assertion now enables this failing native path. Please decline native 
assertions in these early-exit join conditions until their candidate-level 
short-circuit behavior is preserved.
   
   Evidence: Ran the four exact-head native assertion unit tests successfully. 
A disposable Rust test used the exact-head `assert_not_null.rs`, locked 
DataFusion 55.2.0, batches `[0]` and `[0,1]`, a lazy CASE equivalent to the IF 
condition, and `NestedLoopJoinExec::try_new(...).swap_inputs()` matching 
Comet's BuildRight planner. Both LeftSemi and LeftAnti returned 
NOT_NULL_ASSERT_VIOLATION. A Spark 4.1.3 JVM probe tested interpreted and 
generated predicates with `buildRows.exists`, the consumer used by 
`BroadcastNestedLoopJoinExec.leftExistenceJoin`: both stopped after one 
candidate and succeeded. Evaluating the skipped candidate separately raised the 
assertion. SimplifyConditionals, NullPropagation, ConstantFolding, and 
PushPredicateThroughJoin retained the conditional assertion. Sources: Spark 
v4.1.3 BroadcastNestedLoopJoinExec.scala:221–224, Comet 
predicates.scala:505–508, and 
native/core/src/execution/planner/join.rs:309–318. Reproduction files and logs 
are under `/tmp/come
 t7155-review/probe/`. A full Comet JVM query was not executed locally.



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