MaxGekk commented on code in PR #47672:
URL: https://github.com/apache/spark/pull/47672#discussion_r1755469657
##########
sql/catalyst/src/main/scala/org/apache/spark/sql/catalyst/parser/AstBuilder.scala:
##########
@@ -261,6 +261,50 @@ class AstBuilder extends DataTypeAstBuilder
WhileStatement(condition, body, Some(labelText))
}
+ override def visitSearchedCaseStatement(ctx: SearchedCaseStatementContext):
CaseStatement = {
+ val conditions = ctx.conditions.asScala.toList.map(boolExpr =>
withOrigin(boolExpr) {
+ SingleStatement(
+ Project(
+ Seq(Alias(expression(boolExpr), "condition")()),
+ OneRowRelation()))
+ })
+ val conditionalBodies =
+ ctx.conditionalBodies.asScala.toList.map(body => visitCompoundBody(body))
+
+ if (conditions.length != conditionalBodies.length) {
+ throw SparkException.internalError(
+ "Mismatched number of conditions and condition bodies in case
statement")
Review Comment:
nit: Even if it shouldn't happen, let's help to troubleshoot this.
```suggestion
s"Mismatched number of conditions ${conditions.length and condition
bodies ${conditionalBodies.length} in case statement")
```
##########
sql/core/src/test/scala/org/apache/spark/sql/scripting/SqlScriptingInterpreterSuite.scala:
##########
@@ -670,7 +1048,7 @@ class SqlScriptingInterpreterSuite extends QueryTest with
SharedSparkSession {
exception = intercept[SqlScriptingException] (
runSqlScript(commands)
),
- errorClass = "INVALID_BOOLEAN_STATEMENT",
+ condition = "INVALID_BOOLEAN_STATEMENT",
Review Comment:
hmm, strange. Why do you need the changes?
##########
sql/core/src/main/scala/org/apache/spark/sql/scripting/SqlScriptingExecutionNode.scala:
##########
@@ -405,6 +405,79 @@ class WhileStatementExec(
}
}
+/**
+ * Executable node for CaseStatement.
+ * @param conditions Collection of executable conditions which correspond to
WHEN clauses.
+ * @param conditionalBodies Collection of executable bodies that have a
corresponding condition,
+ * in WHEN branches.
+ * @param elseBody Body that is executed if none of the conditions are met,
+ * i.e. ELSE branch.
+ * @param session Spark session that SQL script is executed within.
+ */
+class CaseStatementExec(
+ conditions: Seq[SingleStatementExec],
+ conditionalBodies: Seq[CompoundBodyExec],
+ elseBody: Option[CompoundBodyExec],
+ session: SparkSession) extends NonLeafStatementExec {
+ private object CaseState extends Enumeration {
+ val Condition, Body = Value
+ }
+
+ private var state = CaseState.Condition
+ private var curr: Option[CompoundStatementExec] = Some(conditions.head)
+
+ private var clauseIdx: Int = 0
+ private val conditionsCount = conditions.length
+
+ private lazy val treeIterator: Iterator[CompoundStatementExec] =
+ new Iterator[CompoundStatementExec] {
+ override def hasNext: Boolean = curr.nonEmpty
+
+ override def next(): CompoundStatementExec = state match {
+ case CaseState.Condition =>
+ val condition = curr.get.asInstanceOf[SingleStatementExec]
Review Comment:
Should we add an assert as you did below:
```scala
assert(curr.get.isInstanceOf[CompoundBodyExec])
```
##########
sql/catalyst/src/main/scala/org/apache/spark/sql/catalyst/parser/SqlScriptingLogicalOperators.scala:
##########
@@ -124,3 +124,18 @@ case class LeaveStatement(label: String) extends
CompoundPlanStatement
* @param label Label of the loop to iterate.
*/
case class IterateStatement(label: String) extends CompoundPlanStatement
+
+/**
+ * Logical operator for CASE statement.
+ * @param conditions Collection of conditions which correspond to WHEN clauses.
+ * @param conditionalBodies Collection of bodies that have a corresponding
condition,
+ * in WHEN branches.
+ * @param elseBody Body that is executed if none of the conditions are met,
+ * i.e. ELSE branch.
Review Comment:
nit:
```suggestion
* @param elseBody Body that is executed if none of the conditions are met,
i.e. ELSE branch.
```
##########
sql/catalyst/src/main/scala/org/apache/spark/sql/catalyst/parser/AstBuilder.scala:
##########
@@ -261,6 +261,50 @@ class AstBuilder extends DataTypeAstBuilder
WhileStatement(condition, body, Some(labelText))
}
+ override def visitSearchedCaseStatement(ctx: SearchedCaseStatementContext):
CaseStatement = {
+ val conditions = ctx.conditions.asScala.toList.map(boolExpr =>
withOrigin(boolExpr) {
+ SingleStatement(
+ Project(
+ Seq(Alias(expression(boolExpr), "condition")()),
+ OneRowRelation()))
+ })
+ val conditionalBodies =
+ ctx.conditionalBodies.asScala.toList.map(body => visitCompoundBody(body))
+
+ if (conditions.length != conditionalBodies.length) {
+ throw SparkException.internalError(
+ "Mismatched number of conditions and condition bodies in case
statement")
+ }
+
+ CaseStatement(
+ conditions = conditions,
+ conditionalBodies = conditionalBodies,
+ elseBody = Option(ctx.elseBody).map(body => visitCompoundBody(body)))
+ }
+
+ override def visitSimpleCaseStatement(ctx: SimpleCaseStatementContext):
CaseStatement = {
+ // uses EqualTo to compare the case variable(the main case expression)
+ // to the WHEN clause expressions
+ val conditions = ctx.conditionExpressions.asScala.toList.map(expr =>
withOrigin(expr) {
+ SingleStatement(
+ Project(
+ Seq(Alias(EqualTo(expression(ctx.caseVariable), expression(expr)),
"condition")()),
+ OneRowRelation()))
+ })
+ val conditionalBodies =
+ ctx.conditionalBodies.asScala.toList.map(body => visitCompoundBody(body))
+
+ if (conditions.length != conditionalBodies.length) {
+ throw SparkException.internalError(
+ "Mismatched number of conditions and condition bodies in case
statement")
Review Comment:
The same as above, please, provide the numbers.
##########
sql/core/src/main/scala/org/apache/spark/sql/scripting/SqlScriptingExecutionNode.scala:
##########
@@ -405,6 +405,79 @@ class WhileStatementExec(
}
}
+/**
+ * Executable node for CaseStatement.
+ * @param conditions Collection of executable conditions which correspond to
WHEN clauses.
+ * @param conditionalBodies Collection of executable bodies that have a
corresponding condition,
+ * in WHEN branches.
+ * @param elseBody Body that is executed if none of the conditions are met,
+ * i.e. ELSE branch.
Review Comment:
```suggestion
* @param elseBody Body that is executed if none of the conditions are met,
i.e. ELSE branch.
```
--
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]