@@ -106,6 +106,13 @@ trait NonLeafStatementExec extends CompoundStatementExec {
106
106
}
107
107
}
108
108
109
+ /**
110
+ * Conditional node in the execution tree. It is a conditional non-leaf node.
111
+ */
112
+ trait ConditionalStatementExec extends NonLeafStatementExec {
113
+ protected [scripting] var interrupted : Boolean = false
114
+ }
115
+
109
116
/**
110
117
* Executable node for SingleStatement.
111
118
* @param parsedPlan
@@ -401,7 +408,7 @@ class IfElseStatementExec(
401
408
conditions : Seq [SingleStatementExec ],
402
409
conditionalBodies : Seq [CompoundBodyExec ],
403
410
elseBody : Option [CompoundBodyExec ],
404
- session : SparkSession ) extends NonLeafStatementExec {
411
+ session : SparkSession ) extends ConditionalStatementExec {
405
412
private object IfElseState extends Enumeration {
406
413
val Condition, Body = Value
407
414
}
@@ -415,7 +422,7 @@ class IfElseStatementExec(
415
422
416
423
private lazy val treeIterator : Iterator [CompoundStatementExec ] =
417
424
new Iterator [CompoundStatementExec ] {
418
- override def hasNext : Boolean = curr.nonEmpty
425
+ override def hasNext : Boolean = ! interrupted && curr.nonEmpty
419
426
420
427
override def next (): CompoundStatementExec = {
421
428
if (curr.exists(_.isInstanceOf [LeaveStatementExec ])) {
@@ -467,6 +474,7 @@ class IfElseStatementExec(
467
474
state = IfElseState .Condition
468
475
curr = Some (conditions.head)
469
476
clauseIdx = 0
477
+ interrupted = false
470
478
conditions.foreach(c => c.reset())
471
479
conditionalBodies.foreach(b => b.reset())
472
480
elseBody.foreach(b => b.reset())
@@ -484,7 +492,7 @@ class WhileStatementExec(
484
492
condition : SingleStatementExec ,
485
493
body : CompoundBodyExec ,
486
494
label : Option [String ],
487
- session : SparkSession ) extends NonLeafStatementExec {
495
+ session : SparkSession ) extends ConditionalStatementExec {
488
496
489
497
private object WhileState extends Enumeration {
490
498
val Condition, Body = Value
@@ -495,7 +503,7 @@ class WhileStatementExec(
495
503
496
504
private lazy val treeIterator : Iterator [CompoundStatementExec ] =
497
505
new Iterator [CompoundStatementExec ] {
498
- override def hasNext : Boolean = curr.nonEmpty
506
+ override def hasNext : Boolean = ! interrupted && curr.nonEmpty
499
507
500
508
override def next (): CompoundStatementExec = state match {
501
509
case WhileState .Condition =>
@@ -551,6 +559,7 @@ class WhileStatementExec(
551
559
override def reset (): Unit = {
552
560
state = WhileState .Condition
553
561
curr = Some (condition)
562
+ interrupted = false
554
563
condition.reset()
555
564
body.reset()
556
565
}
@@ -575,7 +584,7 @@ class SearchedCaseStatementExec(
575
584
conditions : Seq [SingleStatementExec ],
576
585
conditionalBodies : Seq [CompoundBodyExec ],
577
586
elseBody : Option [CompoundBodyExec ],
578
- session : SparkSession ) extends NonLeafStatementExec {
587
+ session : SparkSession ) extends ConditionalStatementExec {
579
588
private object CaseState extends Enumeration {
580
589
val Condition, Body = Value
581
590
}
@@ -588,7 +597,7 @@ class SearchedCaseStatementExec(
588
597
589
598
private lazy val treeIterator : Iterator [CompoundStatementExec ] =
590
599
new Iterator [CompoundStatementExec ] {
591
- override def hasNext : Boolean = curr.nonEmpty
600
+ override def hasNext : Boolean = ! interrupted && curr.nonEmpty
592
601
593
602
override def next (): CompoundStatementExec = {
594
603
if (curr.exists(_.isInstanceOf [LeaveStatementExec ])) {
@@ -640,6 +649,7 @@ class SearchedCaseStatementExec(
640
649
state = CaseState .Condition
641
650
curr = Some (conditions.head)
642
651
clauseIdx = 0
652
+ interrupted = false
643
653
conditions.foreach(c => c.reset())
644
654
conditionalBodies.foreach(b => b.reset())
645
655
elseBody.foreach(b => b.reset())
@@ -662,7 +672,7 @@ class SimpleCaseStatementExec(
662
672
conditionalBodies : Seq [CompoundBodyExec ],
663
673
elseBody : Option [CompoundBodyExec ],
664
674
session : SparkSession ,
665
- context : SqlScriptingExecutionContext ) extends NonLeafStatementExec {
675
+ context : SqlScriptingExecutionContext ) extends ConditionalStatementExec {
666
676
private object CaseState extends Enumeration {
667
677
val Condition, Body = Value
668
678
}
@@ -699,7 +709,7 @@ class SimpleCaseStatementExec(
699
709
700
710
private lazy val treeIterator : Iterator [CompoundStatementExec ] =
701
711
new Iterator [CompoundStatementExec ] {
702
- override def hasNext : Boolean = state match {
712
+ override def hasNext : Boolean = ! interrupted && ( state match {
703
713
case CaseState .Condition =>
704
714
// Equivalent to the "iteration hasn't started yet" - to avoid computing cache
705
715
// before the first actual iteration.
@@ -710,7 +720,7 @@ class SimpleCaseStatementExec(
710
720
cachedConditionBodyIterator.hasNext ||
711
721
elseBody.isDefined
712
722
case CaseState .Body => bodyExec.exists(_.getTreeIterator.hasNext)
713
- }
723
+ })
714
724
715
725
override def next (): CompoundStatementExec = state match {
716
726
case CaseState .Condition =>
@@ -779,6 +789,7 @@ class SimpleCaseStatementExec(
779
789
bodyExec = None
780
790
curr = None
781
791
isCacheValid = false
792
+ interrupted = false
782
793
caseVariableExec.reset()
783
794
conditionalBodies.foreach(b => b.reset())
784
795
elseBody.foreach(b => b.reset())
@@ -797,7 +808,7 @@ class RepeatStatementExec(
797
808
condition : SingleStatementExec ,
798
809
body : CompoundBodyExec ,
799
810
label : Option [String ],
800
- session : SparkSession ) extends NonLeafStatementExec {
811
+ session : SparkSession ) extends ConditionalStatementExec {
801
812
802
813
private object RepeatState extends Enumeration {
803
814
val Condition, Body = Value
@@ -808,7 +819,7 @@ class RepeatStatementExec(
808
819
809
820
private lazy val treeIterator : Iterator [CompoundStatementExec ] =
810
821
new Iterator [CompoundStatementExec ] {
811
- override def hasNext : Boolean = curr.nonEmpty
822
+ override def hasNext : Boolean = ! interrupted && curr.nonEmpty
812
823
813
824
override def next (): CompoundStatementExec = state match {
814
825
case RepeatState .Condition =>
@@ -863,6 +874,7 @@ class RepeatStatementExec(
863
874
override def reset (): Unit = {
864
875
state = RepeatState .Body
865
876
curr = Some (body)
877
+ interrupted = false
866
878
body.reset()
867
879
condition.reset()
868
880
}
@@ -989,7 +1001,7 @@ class ForStatementExec(
989
1001
statements : Seq [CompoundStatementExec ],
990
1002
val label : Option [String ],
991
1003
session : SparkSession ,
992
- context : SqlScriptingExecutionContext ) extends NonLeafStatementExec {
1004
+ context : SqlScriptingExecutionContext ) extends ConditionalStatementExec {
993
1005
994
1006
private object ForState extends Enumeration {
995
1007
val VariableAssignment, Body = Value
@@ -1015,11 +1027,6 @@ class ForStatementExec(
1015
1027
1016
1028
private var bodyWithVariables : Option [CompoundBodyExec ] = None
1017
1029
1018
- /**
1019
- * For can be interrupted by LeaveStatementExec
1020
- */
1021
- private var interrupted : Boolean = false
1022
-
1023
1030
/**
1024
1031
* Whether this iteration of the FOR loop is the first one.
1025
1032
*/
@@ -1028,6 +1035,7 @@ class ForStatementExec(
1028
1035
private lazy val treeIterator : Iterator [CompoundStatementExec ] =
1029
1036
new Iterator [CompoundStatementExec ] {
1030
1037
1038
+ // Variable interrupted is being used by both EXIT and CONTINUE handlers
1031
1039
override def hasNext : Boolean = ! interrupted && (state match {
1032
1040
// `firstIteration` NEEDS to be the first condition! This is to handle edge-cases when
1033
1041
// query fails with an exception. If the `cachedQueryResult().hasNext` is first, this
0 commit comments