diff --git a/kyuubi-common/src/main/scala/org/apache/kyuubi/KyuubiSQLException.scala b/kyuubi-common/src/main/scala/org/apache/kyuubi/KyuubiSQLException.scala index f1eea4eaf..7739d3be8 100644 --- a/kyuubi-common/src/main/scala/org/apache/kyuubi/KyuubiSQLException.scala +++ b/kyuubi-common/src/main/scala/org/apache/kyuubi/KyuubiSQLException.scala @@ -18,8 +18,10 @@ package org.apache.kyuubi import java.io.{PrintWriter, StringWriter} +import java.lang.reflect.{InvocationTargetException, UndeclaredThrowableException} import java.sql.SQLException +import scala.annotation.tailrec import scala.collection.JavaConverters._ import org.apache.hive.service.rpc.thrift.{TStatus, TStatusCode} @@ -46,10 +48,11 @@ object KyuubiSQLException { private final val SEPARATOR: Char = ':' def apply(msg: String, throwable: Throwable): KyuubiSQLException = { - new KyuubiSQLException(msg, throwable) + new KyuubiSQLException(msg, findCause(throwable)) } def apply(cause: Throwable): KyuubiSQLException = { - new KyuubiSQLException(cause.getMessage, cause) + val theCause = findCause(cause) + new KyuubiSQLException(theCause.getMessage, theCause) } def apply(msg: String): KyuubiSQLException = new KyuubiSQLException(msg, null) @@ -157,4 +160,10 @@ object KyuubiSQLException { stm.toString } + @tailrec + def findCause(t: Throwable): Throwable = t match { + case e @ (_: UndeclaredThrowableException | _: InvocationTargetException) + if e.getCause != null => findCause(e.getCause) + case e => e + } } diff --git a/kyuubi-common/src/test/scala/org/apache/kyuubi/KyuubiSQLExceptionSuite.scala b/kyuubi-common/src/test/scala/org/apache/kyuubi/KyuubiSQLExceptionSuite.scala index 658a55fe9..76964180e 100644 --- a/kyuubi-common/src/test/scala/org/apache/kyuubi/KyuubiSQLExceptionSuite.scala +++ b/kyuubi-common/src/test/scala/org/apache/kyuubi/KyuubiSQLExceptionSuite.scala @@ -17,6 +17,8 @@ package org.apache.kyuubi +import java.lang.reflect.{InvocationTargetException, UndeclaredThrowableException} + import org.apache.hive.service.rpc.thrift.TStatusCode class KyuubiSQLExceptionSuite extends KyuubiFunSuite { @@ -50,4 +52,18 @@ class KyuubiSQLExceptionSuite extends KyuubiFunSuite { assert(e5.getMessage === msg0) assert(e5.getCause === e0) } + + test("find the root cause") { + val theCause = new RuntimeException("this is just a dummy message but shall be seen") + val ite1 = new InvocationTargetException(theCause) + val ute1 = new UndeclaredThrowableException(ite1) + val ute2 = new UndeclaredThrowableException(ute1) + val ite2 = new InvocationTargetException(ute2) + val ke = KyuubiSQLException(ite2) + assert(ke.getMessage == theCause.getMessage) + assert(ke.getCause == theCause) + + val cornerCase = new InvocationTargetException(null) + assert(KyuubiSQLException(cornerCase).getCause === cornerCase) + } }