Skip to content

Commit 0db373a

Browse files
petermaxleerxin
authored andcommitted
[SPARK-17011][SQL] Support testing exceptions in SQLQueryTestSuite
## What changes were proposed in this pull request? This patch adds exception testing to SQLQueryTestSuite. When there is an exception in query execution, the query result contains the the exception class along with the exception message. As part of this, I moved some additional test cases for limit from SQLQuerySuite over to SQLQueryTestSuite. ## How was this patch tested? This is a test harness change. Author: petermaxlee <petermaxlee@gmail.com> Closes #14592 from petermaxlee/SPARK-17011.
1 parent 7a6a3c3 commit 0db373a

File tree

9 files changed

+161
-68
lines changed

9 files changed

+161
-68
lines changed
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
2+
-- limit on various data types
3+
select * from testdata limit 2;
4+
select * from arraydata limit 2;
5+
select * from mapdata limit 2;
6+
7+
-- foldable non-literal in limit
8+
select * from testdata limit 2 + 1;
9+
10+
select * from testdata limit CAST(1 AS int);
11+
12+
-- limit must be non-negative
13+
select * from testdata limit -1;
14+
15+
-- limit must be foldable
16+
select * from testdata limit key > 3;
17+
18+
-- limit must be integer
19+
select * from testdata limit true;
20+
select * from testdata limit 'a';

sql/core/src/test/resources/sql-tests/inputs/number-format.sql

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,10 +3,13 @@
33
-- parse as ints
44
select 1, -1;
55

6-
-- parse as longs
6+
-- parse as longs (Int.MaxValue + 1, and Int.MinValue - 1)
77
select 2147483648, -2147483649;
88

9-
-- parse as decimals
9+
-- parse long min and max value
10+
select 9223372036854775807, -9223372036854775808;
11+
12+
-- parse as decimals (Long.MaxValue + 1, and Long.MinValue - 1)
1013
select 9223372036854775808, -9223372036854775809;
1114

1215
-- various floating point (decimal) formats

sql/core/src/test/resources/sql-tests/results/datetime.sql.out

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
-- Automatically generated by org.apache.spark.sql.SQLQueryTestSuite
1+
-- Automatically generated by SQLQueryTestSuite
22
-- Number of queries: 1
33

44

sql/core/src/test/resources/sql-tests/results/having.sql.out

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
-- Automatically generated by org.apache.spark.sql.SQLQueryTestSuite
1+
-- Automatically generated by SQLQueryTestSuite
22
-- Number of queries: 4
33

44

Lines changed: 83 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,83 @@
1+
-- Automatically generated by SQLQueryTestSuite
2+
-- Number of queries: 9
3+
4+
5+
-- !query 0
6+
select * from testdata limit 2
7+
-- !query 0 schema
8+
struct<key:int,value:string>
9+
-- !query 0 output
10+
1 1
11+
2 2
12+
13+
14+
-- !query 1
15+
select * from arraydata limit 2
16+
-- !query 1 schema
17+
struct<arraycol:array<int>,nestedarraycol:array<array<int>>>
18+
-- !query 1 output
19+
[1,2,3] [[1,2,3]]
20+
[2,3,4] [[2,3,4]]
21+
22+
23+
-- !query 2
24+
select * from mapdata limit 2
25+
-- !query 2 schema
26+
struct<mapcol:map<int,string>>
27+
-- !query 2 output
28+
{1:"a1",2:"b1",3:"c1",4:"d1",5:"e1"}
29+
{1:"a2",2:"b2",3:"c2",4:"d2"}
30+
31+
32+
-- !query 3
33+
select * from testdata limit 2 + 1
34+
-- !query 3 schema
35+
struct<key:int,value:string>
36+
-- !query 3 output
37+
1 1
38+
2 2
39+
3 3
40+
41+
42+
-- !query 4
43+
select * from testdata limit CAST(1 AS int)
44+
-- !query 4 schema
45+
struct<key:int,value:string>
46+
-- !query 4 output
47+
1 1
48+
49+
50+
-- !query 5
51+
select * from testdata limit -1
52+
-- !query 5 schema
53+
struct<>
54+
-- !query 5 output
55+
org.apache.spark.sql.AnalysisException
56+
The limit expression must be equal to or greater than 0, but got -1;
57+
58+
59+
-- !query 6
60+
select * from testdata limit key > 3
61+
-- !query 6 schema
62+
struct<>
63+
-- !query 6 output
64+
org.apache.spark.sql.AnalysisException
65+
The limit expression must evaluate to a constant value, but got (testdata.`key` > 3);
66+
67+
68+
-- !query 7
69+
select * from testdata limit true
70+
-- !query 7 schema
71+
struct<>
72+
-- !query 7 output
73+
org.apache.spark.sql.AnalysisException
74+
The limit expression must be integer type, but got boolean;
75+
76+
77+
-- !query 8
78+
select * from testdata limit 'a'
79+
-- !query 8 schema
80+
struct<>
81+
-- !query 8 output
82+
org.apache.spark.sql.AnalysisException
83+
The limit expression must be integer type, but got string;

sql/core/src/test/resources/sql-tests/results/natural-join.sql.out

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
-- Automatically generated by org.apache.spark.sql.SQLQueryTestSuite
1+
-- Automatically generated by SQLQueryTestSuite
22
-- Number of queries: 6
33

44

sql/core/src/test/resources/sql-tests/results/number-format.sql.out

Lines changed: 15 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
1-
-- Automatically generated by org.apache.spark.sql.SQLQueryTestSuite
2-
-- Number of queries: 4
1+
-- Automatically generated by SQLQueryTestSuite
2+
-- Number of queries: 5
33

44

55
-- !query 0
@@ -19,16 +19,24 @@ struct<2147483648:bigint,(-2147483649):bigint>
1919

2020

2121
-- !query 2
22-
select 9223372036854775808, -9223372036854775809
22+
select 9223372036854775807, -9223372036854775808
2323
-- !query 2 schema
24-
struct<9223372036854775808:decimal(19,0),(-9223372036854775809):decimal(19,0)>
24+
struct<9223372036854775807:bigint,(-9223372036854775808):decimal(19,0)>
2525
-- !query 2 output
26-
9223372036854775808 -9223372036854775809
26+
9223372036854775807 -9223372036854775808
2727

2828

2929
-- !query 3
30-
select 0.3, -0.8, .5, -.18, 0.1111
30+
select 9223372036854775808, -9223372036854775809
3131
-- !query 3 schema
32-
struct<0.3:decimal(1,1),(-0.8):decimal(1,1),0.5:decimal(1,1),(-0.18):decimal(2,2),0.1111:decimal(4,4)>
32+
struct<9223372036854775808:decimal(19,0),(-9223372036854775809):decimal(19,0)>
3333
-- !query 3 output
34+
9223372036854775808 -9223372036854775809
35+
36+
37+
-- !query 4
38+
select 0.3, -0.8, .5, -.18, 0.1111
39+
-- !query 4 schema
40+
struct<0.3:decimal(1,1),(-0.8):decimal(1,1),0.5:decimal(1,1),(-0.18):decimal(2,2),0.1111:decimal(4,4)>
41+
-- !query 4 output
3442
0.3 -0.8 0.5 -0.18 0.1111

sql/core/src/test/scala/org/apache/spark/sql/SQLQuerySuite.scala

Lines changed: 0 additions & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -650,51 +650,12 @@ class SQLQuerySuite extends QueryTest with SharedSQLContext {
650650
sortTest()
651651
}
652652

653-
test("limit") {
654-
checkAnswer(
655-
sql("SELECT * FROM testData LIMIT 9 + 1"),
656-
testData.take(10).toSeq)
657-
658-
checkAnswer(
659-
sql("SELECT * FROM arrayData LIMIT CAST(1 AS Integer)"),
660-
arrayData.collect().take(1).map(Row.fromTuple).toSeq)
661-
662-
checkAnswer(
663-
sql("SELECT * FROM mapData LIMIT 1"),
664-
mapData.collect().take(1).map(Row.fromTuple).toSeq)
665-
}
666-
667-
test("non-foldable expressions in LIMIT") {
668-
val e = intercept[AnalysisException] {
669-
sql("SELECT * FROM testData LIMIT key > 3")
670-
}.getMessage
671-
assert(e.contains("The limit expression must evaluate to a constant value, " +
672-
"but got (testdata.`key` > 3)"))
673-
}
674-
675-
test("Expressions in limit clause are not integer") {
676-
var e = intercept[AnalysisException] {
677-
sql("SELECT * FROM testData LIMIT true")
678-
}.getMessage
679-
assert(e.contains("The limit expression must be integer type, but got boolean"))
680-
681-
e = intercept[AnalysisException] {
682-
sql("SELECT * FROM testData LIMIT 'a'")
683-
}.getMessage
684-
assert(e.contains("The limit expression must be integer type, but got string"))
685-
}
686-
687653
test("negative in LIMIT or TABLESAMPLE") {
688654
val expected = "The limit expression must be equal to or greater than 0, but got -1"
689655
var e = intercept[AnalysisException] {
690656
sql("SELECT * FROM testData TABLESAMPLE (-1 rows)")
691657
}.getMessage
692658
assert(e.contains(expected))
693-
694-
e = intercept[AnalysisException] {
695-
sql("SELECT * FROM testData LIMIT -1")
696-
}.getMessage
697-
assert(e.contains(expected))
698659
}
699660

700661
test("CTE feature") {
@@ -1337,17 +1298,6 @@ class SQLQuerySuite extends QueryTest with SharedSQLContext {
13371298
}
13381299
}
13391300

1340-
test("Test to check we can use Long.MinValue") {
1341-
checkAnswer(
1342-
sql(s"SELECT ${Long.MinValue} FROM testData ORDER BY key LIMIT 1"), Row(Long.MinValue)
1343-
)
1344-
1345-
checkAnswer(
1346-
sql(s"SELECT key FROM testData WHERE key > ${Long.MinValue}"),
1347-
(1 to 100).map(Row(_)).toSeq
1348-
)
1349-
}
1350-
13511301
test("Test to check we can apply sign to expression") {
13521302

13531303
checkAnswer(

sql/core/src/test/scala/org/apache/spark/sql/SQLQueryTestSuite.scala

Lines changed: 35 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,8 @@ package org.apache.spark.sql
2020
import java.io.File
2121
import java.util.{Locale, TimeZone}
2222

23+
import scala.util.control.NonFatal
24+
2325
import org.apache.spark.sql.catalyst.planning.PhysicalOperation
2426
import org.apache.spark.sql.catalyst.plans.logical._
2527
import org.apache.spark.sql.catalyst.rules.RuleExecutor
@@ -132,6 +134,7 @@ class SQLQueryTestSuite extends QueryTest with SharedSQLContext {
132134
// Create a local SparkSession to have stronger isolation between different test cases.
133135
// This does not isolate catalog changes.
134136
val localSparkSession = spark.newSession()
137+
loadTestData(localSparkSession)
135138

136139
// Run the SQL queries preparing them for comparison.
137140
val outputs: Seq[QueryOutput] = queries.map { sql =>
@@ -146,7 +149,7 @@ class SQLQueryTestSuite extends QueryTest with SharedSQLContext {
146149
if (regenerateGoldenFiles) {
147150
// Again, we are explicitly not using multi-line string due to stripMargin removing "|".
148151
val goldenOutput = {
149-
s"-- Automatically generated by ${getClass.getName}\n" +
152+
s"-- Automatically generated by ${getClass.getSimpleName}\n" +
150153
s"-- Number of queries: ${outputs.size}\n\n\n" +
151154
outputs.zipWithIndex.map{case (qr, i) => qr.toString(i)}.mkString("\n\n\n") + "\n"
152155
}
@@ -192,12 +195,19 @@ class SQLQueryTestSuite extends QueryTest with SharedSQLContext {
192195
case _ => plan.children.iterator.exists(isSorted)
193196
}
194197

195-
val df = session.sql(sql)
196-
val schema = df.schema
197-
val answer = df.queryExecution.hiveResultString()
198+
try {
199+
val df = session.sql(sql)
200+
val schema = df.schema
201+
val answer = df.queryExecution.hiveResultString()
202+
203+
// If the output is not pre-sorted, sort it.
204+
if (isSorted(df.queryExecution.analyzed)) (schema, answer) else (schema, answer.sorted)
198205

199-
// If the output is not pre-sorted, sort it.
200-
if (isSorted(df.queryExecution.analyzed)) (schema, answer) else (schema, answer.sorted)
206+
} catch {
207+
case NonFatal(e) =>
208+
// If there is an exception, put the exception class followed by the message.
209+
(StructType(Seq.empty), Seq(e.getClass.getName, e.getMessage))
210+
}
201211
}
202212

203213
private def listTestCases(): Seq[TestCase] = {
@@ -213,6 +223,25 @@ class SQLQueryTestSuite extends QueryTest with SharedSQLContext {
213223
files ++ dirs.flatMap(listFilesRecursively)
214224
}
215225

226+
/** Load built-in test tables into the SparkSession. */
227+
private def loadTestData(session: SparkSession): Unit = {
228+
import session.implicits._
229+
230+
(1 to 100).map(i => (i, i.toString)).toDF("key", "value").createOrReplaceTempView("testdata")
231+
232+
((Seq(1, 2, 3), Seq(Seq(1, 2, 3))) :: (Seq(2, 3, 4), Seq(Seq(2, 3, 4))) :: Nil)
233+
.toDF("arraycol", "nestedarraycol")
234+
.createOrReplaceTempView("arraydata")
235+
236+
(Tuple1(Map(1 -> "a1", 2 -> "b1", 3 -> "c1", 4 -> "d1", 5 -> "e1")) ::
237+
Tuple1(Map(1 -> "a2", 2 -> "b2", 3 -> "c2", 4 -> "d2")) ::
238+
Tuple1(Map(1 -> "a3", 2 -> "b3", 3 -> "c3")) ::
239+
Tuple1(Map(1 -> "a4", 2 -> "b4")) ::
240+
Tuple1(Map(1 -> "a5")) :: Nil)
241+
.toDF("mapcol")
242+
.createOrReplaceTempView("mapdata")
243+
}
244+
216245
private val originalTimeZone = TimeZone.getDefault
217246
private val originalLocale = Locale.getDefault
218247

0 commit comments

Comments
 (0)