cloud-fan commented on code in PR #58867:
URL: https://github.com/apache/spark/pull/58867#discussion_r4047296328


##########
sql/catalyst/src/main/scala/org/apache/spark/sql/catalyst/expressions/misc.scala:
##########
@@ -412,6 +416,26 @@ case class CurrentUser()
   final override val nodePatterns: Seq[TreePattern] = Seq(CURRENT_LIKE)
 }
 
+private object AesEncryptDeterminism {
+  def apply(arguments: Seq[Expression]): Boolean = {
+    arguments.forall(_.deterministic) &&
+      (hasNonEmptyLiteral(arguments(4)) || isEcbLiteral(arguments(2)))

Review Comment:
   **Blocking (P1):** Spark documents fixed IVs in forms such as `unhex(...)`, 
but this helper recognizes only `Literal` or `Cast(Literal)`. Analyzer checks 
read `deterministic` before constant folding reduces `Unhex`, so an otherwise 
fixed AES call can be rejected as nondeterministic in a join condition and 
loses valid folding in projections.
   
   See **Shared repair plan 1** in the review body.



##########
sql/catalyst/src/main/scala/org/apache/spark/sql/catalyst/expressions/misc.scala:
##########
@@ -471,12 +495,15 @@ case class AesEncrypt(
     aad: Expression)
   extends RuntimeReplaceable with ImplicitCastInputTypes {
 
+  override lazy val deterministic: Boolean = AesEncryptDeterminism(children)

Review Comment:
   **Blocking (P1):** The wrapper now reports nondeterministic for an omitted 
or empty IV, but `NondeterministicExpressionCollection` cannot find anything to 
extract: `AesEncrypt` is neither `Nondeterministic` nor a UDF, and its 
nondeterministic replacement is not a child. `GROUP BY aes_encrypt(...)` can 
therefore hit the rule's internal error, while `Sort` leaves the call in place 
for `CheckAnalysis` to reject.
   
   See **Shared repair plan 1** in the review body.



##########
sql/catalyst/src/test/scala/org/apache/spark/sql/catalyst/expressions/MiscExpressionsSuite.scala:
##########
@@ -117,6 +120,36 @@ class MiscExpressionsSuite extends SparkFunSuite with 
ExpressionEvalHelper {
     assert(outputEval.contains(s"Result of $inputExpr is 1"))
   }
 
+  test("DynamicPruningExpression is not foldable") {
+    assert(!DynamicPruningExpression(Literal.TrueLiteral).foldable)
+  }
+
+  test("AesEncrypt determinism reflects whether it generates an IV") {
+    val randomIvExpression = new AesEncrypt(Literal("Spark"), 
Literal("0000111122223333"))
+    assert(!randomIvExpression.deterministic)
+    assert(!randomIvExpression.replacement.deterministic)
+    assert(!randomIvExpression.replacement.foldable)
+
+    val explicitIvExpression = new AesEncrypt(
+      Literal("Spark"),
+      Literal("0000111122223333"),
+      Literal("GCM"),
+      Literal("DEFAULT"),
+      Literal(Array.fill[Byte](12)(0)))

Review Comment:
   **Non-blocking (P2):** These direct `Literal` constructions bypass 
analyzer-resolved forms and plan consumers. They remain green for the 
documented `unhex` fixed-IV misclassification, do not test a nondeterministic 
child, and never exercise `PullOutNondeterministic` through Aggregate or Sort, 
so the material parts of the new contract are not regression-covered.
   
   See **Shared repair plan 1** in the review body.



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