Skip to content

Commit 00bef6b

Browse files
committed
Add basic tests.
1 parent 5fe425c commit 00bef6b

File tree

2 files changed

+114
-10
lines changed
  • sql/catalyst/src

2 files changed

+114
-10
lines changed

sql/catalyst/src/main/scala/org/apache/spark/sql/catalyst/expressions/codegen/javaCode.scala

Lines changed: 16 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -114,15 +114,17 @@ object JavaCode {
114114
}
115115

116116
def block(code: String): Block = {
117-
CodeBlock(codeParts = Seq(code), exprValues = Seq.empty)
117+
CodeBlock(codeParts = Seq(code), blockInputs = Seq.empty)
118118
}
119119
}
120120

121121
/**
122-
* A block of java code which involves some expressions represented by `ExprValue`.
122+
* A trait representing a block of java code.
123123
*/
124124
trait Block extends JavaCode {
125-
def exprValues: Seq[Any]
125+
126+
// The expressions to be evaluated inside this block.
127+
def exprValues: Seq[ExprValue]
126128

127129
// This will be called during string interpolation.
128130
override def toString: String = _marginChar match {
@@ -169,16 +171,20 @@ object Block {
169171
}
170172

171173
/**
172-
* A block of java code.
174+
* A block of java code. Including a sequence of code parts and some inputs to this block.
175+
* The actual java code is generated by embedding the inputs into the code parts.
173176
*/
174-
case class CodeBlock(codeParts: Seq[String], exprValues: Seq[Any]) extends Block {
177+
case class CodeBlock(codeParts: Seq[String], blockInputs: Seq[Any]) extends Block {
178+
override def exprValues: Seq[ExprValue] = blockInputs.filter(_.isInstanceOf[ExprValue])
179+
.asInstanceOf[Seq[ExprValue]]
180+
175181
override def code: String = {
176182
val strings = codeParts.iterator
177-
val expressions = exprValues.iterator
183+
val inputs = blockInputs.iterator
178184
var buf = new StringBuffer(strings.next)
179185
while (strings.hasNext) {
180-
if (expressions.hasNext) {
181-
buf append expressions.next
186+
if (inputs.hasNext) {
187+
buf append inputs.next
182188
buf append strings.next
183189
}
184190
}
@@ -193,7 +199,7 @@ case class CodeBlock(codeParts: Seq[String], exprValues: Seq[Any]) extends Block
193199
}
194200

195201
case class Blocks(blocks: Seq[Block]) extends Block {
196-
override def exprValues: Seq[Any] = blocks.flatMap(_.exprValues)
202+
override def exprValues: Seq[ExprValue] = blocks.flatMap(_.exprValues)
197203
override def code: String = blocks.map(_.toString).mkString
198204

199205
override def + (other: Block): Block = other match {
@@ -205,7 +211,7 @@ case class Blocks(blocks: Seq[Block]) extends Block {
205211

206212
object EmptyBlock extends Block with Serializable {
207213
override def code: String = ""
208-
override def exprValues: Seq[Any] = Seq.empty
214+
override def exprValues: Seq[ExprValue] = Seq.empty
209215

210216
override def + (other: Block): Block = other
211217
}
Lines changed: 98 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,98 @@
1+
/*
2+
* Licensed to the Apache Software Foundation (ASF) under one or more
3+
* contributor license agreements. See the NOTICE file distributed with
4+
* this work for additional information regarding copyright ownership.
5+
* The ASF licenses this file to You under the Apache License, Version 2.0
6+
* (the "License"); you may not use this file except in compliance with
7+
* the License. You may obtain a copy of the License at
8+
*
9+
* http://www.apache.org/licenses/LICENSE-2.0
10+
*
11+
* Unless required by applicable law or agreed to in writing, software
12+
* distributed under the License is distributed on an "AS IS" BASIS,
13+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14+
* See the License for the specific language governing permissions and
15+
* limitations under the License.
16+
*/
17+
18+
package org.apache.spark.sql.catalyst.expressions.codegen
19+
20+
import org.apache.spark.SparkFunSuite
21+
import org.apache.spark.sql.catalyst.expressions.codegen.Block._
22+
import org.apache.spark.sql.types.{BooleanType, IntegerType}
23+
24+
class CodeBlockSuite extends SparkFunSuite {
25+
26+
test("Block can interpolate string and ExprValue inputs") {
27+
val isNull = JavaCode.isNullVariable("expr1_isNull")
28+
val code = code"boolean ${isNull} = ${JavaCode.defaultLiteral(BooleanType)};"
29+
assert(code.toString == "boolean expr1_isNull = false;")
30+
}
31+
32+
test("Block.stripMargin") {
33+
val isNull = JavaCode.isNullVariable("expr1_isNull")
34+
val value = JavaCode.variable("expr1", IntegerType)
35+
val code1 =
36+
code"""
37+
|boolean $isNull = false;
38+
|int $value = ${JavaCode.defaultLiteral(IntegerType)};""".stripMargin
39+
val expected =
40+
s"""
41+
|boolean expr1_isNull = false;
42+
|int expr1 = ${JavaCode.defaultLiteral(IntegerType)};""".stripMargin
43+
assert(code1.toString == expected)
44+
45+
val code2 =
46+
code"""
47+
>boolean $isNull = false;
48+
>int $value = ${JavaCode.defaultLiteral(IntegerType)};""".stripMargin('>')
49+
assert(code2.toString == expected)
50+
}
51+
52+
test("Block can capture input expr values") {
53+
val isNull = JavaCode.isNullVariable("expr1_isNull")
54+
val value = JavaCode.variable("expr1", IntegerType)
55+
val code =
56+
code"""
57+
|boolean $isNull = false;
58+
|int $value = -1;
59+
""".stripMargin
60+
val exprValues = code.exprValues
61+
assert(exprValues.length == 2)
62+
assert(exprValues(0).isInstanceOf[VariableValue] && exprValues(0).code == "expr1_isNull")
63+
assert(exprValues(1).isInstanceOf[VariableValue] && exprValues(1).code == "expr1")
64+
}
65+
66+
test("concatenate blocks") {
67+
val isNull1 = JavaCode.isNullVariable("expr1_isNull")
68+
val value1 = JavaCode.variable("expr1", IntegerType)
69+
val isNull2 = JavaCode.isNullVariable("expr2_isNull")
70+
val value2 = JavaCode.variable("expr2", IntegerType)
71+
val literal = JavaCode.literal("100", IntegerType)
72+
73+
val code =
74+
code"""
75+
|boolean $isNull1 = false;
76+
|int $value1 = -1;""".stripMargin +
77+
code"""
78+
|boolean $isNull2 = true;
79+
|int $value2 = $literal;""".stripMargin
80+
81+
val expected =
82+
"""
83+
|boolean expr1_isNull = false;
84+
|int expr1 = -1;
85+
|boolean expr2_isNull = true;
86+
|int expr2 = 100;""".stripMargin
87+
88+
assert(code.toString == expected)
89+
90+
val exprValues = code.exprValues
91+
assert(exprValues.length == 5)
92+
assert(exprValues(0).isInstanceOf[VariableValue] && exprValues(0).code == "expr1_isNull")
93+
assert(exprValues(1).isInstanceOf[VariableValue] && exprValues(1).code == "expr1")
94+
assert(exprValues(2).isInstanceOf[VariableValue] && exprValues(2).code == "expr2_isNull")
95+
assert(exprValues(3).isInstanceOf[VariableValue] && exprValues(3).code == "expr2")
96+
assert(exprValues(4).isInstanceOf[LiteralValue] && exprValues(4).code == "100")
97+
}
98+
}

0 commit comments

Comments
 (0)