dusantism-db commented on code in PR #50026:
URL: https://github.com/apache/spark/pull/50026#discussion_r1965190136


##########
sql/core/src/main/scala/org/apache/spark/sql/scripting/SqlScriptingExecutionNode.scala:
##########
@@ -823,35 +827,41 @@ class ForStatementExec(
 
       override def hasNext: Boolean = !interrupted && (state match {
           case ForState.VariableAssignment => cachedQueryResult().hasNext
-          case ForState.Body => true
-          case ForState.VariableCleanup => 
dropVariablesExec.getTreeIterator.hasNext
+          case ForState.Body => bodyWithVariables.getTreeIterator.hasNext
         })
 
       @scala.annotation.tailrec
       override def next(): CompoundStatementExec = state match {
 
         case ForState.VariableAssignment =>
-          variablesMap = createVariablesMapFromRow(cachedQueryResult().next())
-
-          if (!areVariablesDeclared) {
-            // create and execute declare var statements
-            variablesMap.keys.toSeq
-              .map(colName => createDeclareVarExec(colName, 
variablesMap(colName)))
-              .foreach(declareVarExec => 
declareVarExec.buildDataFrame(session).collect())
-            areVariablesDeclared = true
-          }
-
-          // create and execute set var statements
-          variablesMap.keys.toSeq
-            .map(colName => createSetVarExec(colName, variablesMap(colName)))
-            .foreach(setVarExec => 
setVarExec.buildDataFrame(session).collect())
+          val row = cachedQueryResult().next()
+
+          val variableInitStatements = row.schema.names.toSeq
+            .map { colName => (colName, 
createExpressionFromValue(row.getAs(colName))) }
+            .flatMap { case (colName, expr) => Seq(
+              createDeclareVarExec(colName, expr),
+              createSetVarExec(colName, expr)
+            ) }
+
+          bodyWithVariables = new CompoundBodyExec(
+            // NoOpStatementExec appended to end of body to prevent
+            // dropping variables before last statement is executed.

Review Comment:
   If the last statement in the FOR uses one of the local variables, we have to 
call drop variables after that statement has been executed. Before this PR we 
achieved this with a third state, `ForState.VariableCleanup`. In this state we 
passed back `DropVariableStatements` to the iterator.
   ```
           case ForState.VariableCleanup =>
             dropVariablesExec.getTreeIterator.next()
   ```
   As we no longer use `DropVariable`, and drop variables with `exitScope`, we 
don't have anything to return here. This is why NOOP is needed. To simplify the 
code i removed the third state and appended the NOOP to the exec body, but the 
principle is the same to something like this:
   ```
           case ForState.VariableCleanup =>
             exitScope()
             NoOpStatementExec()
   ```



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