Skip to content

Commit 54d159f

Browse files
committed
Address Codegen support
1 parent 462bc4a commit 54d159f

2 files changed

Lines changed: 52 additions & 4 deletions

File tree

sql/core/src/main/scala/org/apache/spark/sql/execution/streaming/statefulOperators.scala

Lines changed: 47 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -25,8 +25,8 @@ import scala.collection.JavaConverters._
2525
import org.apache.spark.rdd.RDD
2626
import org.apache.spark.sql.catalyst.InternalRow
2727
import org.apache.spark.sql.catalyst.errors._
28-
import org.apache.spark.sql.catalyst.expressions._
29-
import org.apache.spark.sql.catalyst.expressions.codegen.{GenerateUnsafeProjection, Predicate}
28+
import org.apache.spark.sql.catalyst.expressions.{Predicate => _, _}
29+
import org.apache.spark.sql.catalyst.expressions.codegen._
3030
import org.apache.spark.sql.catalyst.plans.logical.EventTimeWatermark
3131
import org.apache.spark.sql.catalyst.plans.physical.{AllTuples, ClusteredDistribution, Distribution, Partitioning}
3232
import org.apache.spark.sql.catalyst.streaming.InternalOutputModes._
@@ -40,7 +40,7 @@ import org.apache.spark.util.{CompletionIterator, NextIterator, Utils}
4040
case class CountLateRowsExec(
4141
eventTimeWatermark: Option[Long] = None,
4242
child: SparkPlan)
43-
extends UnaryExecNode with WatermarkSupport {
43+
extends UnaryExecNode with WatermarkSupport with CodegenSupport {
4444

4545
// No need to determine key expressions here.
4646
override def keyExpressions: Seq[Attribute] = Seq.empty
@@ -70,6 +70,50 @@ case class CountLateRowsExec(
7070
}
7171
}
7272
}
73+
74+
override def inputRDDs(): Seq[RDD[InternalRow]] = {
75+
child.asInstanceOf[CodegenSupport].inputRDDs()
76+
}
77+
78+
override protected def doProduce(ctx: CodegenContext): String = {
79+
child.asInstanceOf[CodegenSupport].produce(ctx, this)
80+
}
81+
82+
override def doConsume(ctx: CodegenContext, input: Seq[ExprCode], row: ExprCode): String = {
83+
val numLateRows = metricTerm(ctx, "numLateRows")
84+
85+
val generated = watermarkExpression match {
86+
case Some(expr) =>
87+
val bound = BindReferences.bindReference(expr, child.output)
88+
val evaluated = evaluateRequiredVariables(child.output, input, expr.references)
89+
90+
// Generate the code for the predicate.
91+
val ev = ExpressionCanonicalizer.execute(bound).genCode(ctx)
92+
val nullCheck = if (bound.nullable) {
93+
s"${ev.isNull} || "
94+
} else {
95+
s""
96+
}
97+
98+
s"""
99+
|$evaluated
100+
|${ev.code}
101+
|if (${nullCheck}${ev.value}) {
102+
| $numLateRows.add(1);
103+
|}
104+
""".stripMargin
105+
106+
case None => ""
107+
}
108+
109+
// Note: wrap in "do { } while(false);", so the generated checks can jump out with "continue;"
110+
s"""
111+
|do {
112+
| $generated
113+
| ${consume(ctx, input)}
114+
|} while(false);
115+
""".stripMargin
116+
}
73117
}
74118

75119
/** Used to identify the state store for a given operator. */

sql/core/src/test/scala/org/apache/spark/sql/streaming/EventTimeWatermarkSuite.scala

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -500,15 +500,19 @@ class EventTimeWatermarkSuite extends StreamTest with BeforeAndAfter with Matche
500500
testStream(windowedAggregation, OutputMode.Complete)(
501501
AddData(inputData, 10, 11, 12),
502502
CheckAnswer((10, 3)),
503+
assertNumLateRows(0),
503504
AddData(inputData, 25),
504505
CheckAnswer((10, 3), (25, 1)),
506+
assertNumLateRows(0),
505507
AddData(inputData, 25),
506508
CheckAnswer((10, 3), (25, 2)),
509+
assertNumLateRows(0),
507510
AddData(inputData, 10),
508511
CheckAnswer((10, 4), (25, 2)),
509512
assertNumLateRows(1),
510513
AddData(inputData, 25),
511-
CheckAnswer((10, 4), (25, 3))
514+
CheckAnswer((10, 4), (25, 3)),
515+
assertNumLateRows(0)
512516
)
513517
}
514518

0 commit comments

Comments
 (0)