|
18 | 18 | package org.apache.spark.sql.hive.thriftserver |
19 | 19 |
|
20 | 20 | import java.io.File |
21 | | -import java.sql.{DriverManager, SQLException, Statement, Timestamp} |
22 | | -import java.util.Locale |
| 21 | +import java.sql.{DriverManager, Statement, Timestamp} |
| 22 | +import java.util.{Locale, MissingFormatArgumentException} |
23 | 23 |
|
24 | 24 | import scala.util.{Random, Try} |
25 | 25 | import scala.util.control.NonFatal |
26 | 26 |
|
| 27 | +import org.apache.commons.lang3.exception.ExceptionUtils |
27 | 28 | import org.apache.hadoop.hive.conf.HiveConf.ConfVars |
28 | 29 | import org.apache.hive.service.cli.HiveSQLException |
29 | 30 |
|
30 | | -import org.apache.spark.sql.{AnalysisException, SQLQueryTestSuite} |
| 31 | +import org.apache.spark.SparkException |
| 32 | +import org.apache.spark.sql.SQLQueryTestSuite |
| 33 | +import org.apache.spark.sql.catalyst.analysis.NoSuchTableException |
31 | 34 | import org.apache.spark.sql.catalyst.util.fileToString |
32 | 35 | import org.apache.spark.sql.execution.HiveResult |
33 | 36 | import org.apache.spark.sql.internal.SQLConf |
@@ -169,19 +172,47 @@ class ThriftServerQueryTestSuite extends SQLQueryTestSuite { |
169 | 172 | || d.sql.toUpperCase(Locale.ROOT).startsWith("DESC\n") |
170 | 173 | || d.sql.toUpperCase(Locale.ROOT).startsWith("DESCRIBE ") |
171 | 174 | || d.sql.toUpperCase(Locale.ROOT).startsWith("DESCRIBE\n") => |
| 175 | + |
172 | 176 | // Skip show command, see HiveResult.hiveResultString |
173 | 177 | case s if s.sql.toUpperCase(Locale.ROOT).startsWith("SHOW ") |
174 | 178 | || s.sql.toUpperCase(Locale.ROOT).startsWith("SHOW\n") => |
175 | | - // AnalysisException should exactly match. |
176 | | - // SQLException should not exactly match. We only assert the result contains Exception. |
177 | | - case _ if output.output.startsWith(classOf[SQLException].getName) => |
| 179 | + |
| 180 | + case _ if output.output.startsWith(classOf[RuntimeException].getName) => |
178 | 181 | assert(expected.output.contains("Exception"), |
179 | 182 | s"Exception did not match for query #$i\n${expected.sql}, " + |
180 | 183 | s"expected: ${expected.output}, but got: ${output.output}") |
| 184 | + |
| 185 | + case _ if output.output.startsWith(classOf[NoSuchTableException].getPackage.getName) => |
| 186 | + assert(expected.output.startsWith(classOf[NoSuchTableException].getPackage.getName), |
| 187 | + s"Exception did not match for query #$i\n${expected.sql}, " + |
| 188 | + s"expected: ${expected.output}, but got: ${output.output}") |
| 189 | + |
| 190 | + case _ if output.output.startsWith(classOf[SparkException].getName) |
| 191 | + && output.output.contains("overflow") => |
| 192 | + assert(expected.output.contains(classOf[ArithmeticException].getName) |
| 193 | + && expected.output.contains("overflow"), |
| 194 | + s"Exception did not match for query #$i\n${expected.sql}, " + |
| 195 | + s"expected: ${expected.output}, but got: ${output.output}") |
| 196 | + |
| 197 | + case _ if output.output.startsWith(classOf[ArithmeticException].getName) |
| 198 | + && output.output.contains("causes overflow") => |
| 199 | + assert(expected.output.contains(classOf[ArithmeticException].getName) |
| 200 | + && expected.output.contains("causes overflow"), |
| 201 | + s"Exception did not match for query #$i\n${expected.sql}, " + |
| 202 | + s"expected: ${expected.output}, but got: ${output.output}") |
| 203 | + |
| 204 | + case _ if output.output.startsWith(classOf[MissingFormatArgumentException].getName) |
| 205 | + && output.output.contains("Format specifier") => |
| 206 | + assert(expected.output.contains(classOf[MissingFormatArgumentException].getName) |
| 207 | + && expected.output.contains("Format specifier"), |
| 208 | + s"Exception did not match for query #$i\n${expected.sql}, " + |
| 209 | + s"expected: ${expected.output}, but got: ${output.output}") |
| 210 | + |
181 | 211 | // HiveSQLException is usually a feature that our ThriftServer cannot support. |
182 | 212 | // Please add SQL to blackList. |
183 | 213 | case _ if output.output.startsWith(classOf[HiveSQLException].getName) => |
184 | 214 | assert(false, s"${output.output} for query #$i\n${expected.sql}") |
| 215 | + |
185 | 216 | case _ => |
186 | 217 | assertResult(expected.output, s"Result did not match for query #$i\n${expected.sql}") { |
187 | 218 | output.output |
@@ -244,15 +275,10 @@ class ThriftServerQueryTestSuite extends SQLQueryTestSuite { |
244 | 275 | answer |
245 | 276 | } |
246 | 277 | } catch { |
247 | | - case a: AnalysisException => |
248 | | - // Do not output the logical plan tree which contains expression IDs. |
249 | | - // Also implement a crude way of masking expression IDs in the error message |
250 | | - // with a generic pattern "###". |
251 | | - val msg = if (a.plan.nonEmpty) a.getSimpleMessage else a.getMessage |
252 | | - Seq(a.getClass.getName, msg.replaceAll("#\\d+", "#x")).sorted |
253 | 278 | case NonFatal(e) => |
| 279 | + val rootCause = ExceptionUtils.getRootCause(e) |
254 | 280 | // If there is an exception, put the exception class followed by the message. |
255 | | - Seq(e.getClass.getName, e.getMessage) |
| 281 | + Seq(rootCause.getClass.getName, rootCause.getMessage) |
256 | 282 | } |
257 | 283 | } |
258 | 284 |
|
|
0 commit comments