[KYUUBI #670] KyuubiSQLException support sqlState and errorCode

<!--
Thanks for sending a pull request!

Here are some tips for you:
  1. If this is your first time, please read our contributor guidelines: https://kyuubi.readthedocs.io/en/latest/community/contributions.html
  2. If the PR is related to an issue in https://github.com/NetEase/kyuubi/issues, add '[KYUUBI #XXXX]' in your PR title, e.g., '[KYUUBI #XXXX] Your PR title ...'.
  3. If the PR is unfinished, add '[WIP]' in your PR title, e.g., '[WIP][KYUUBI #XXXX] Your PR title ...'.
-->

### _Why are the changes needed?_
<!--
Please clarify why the changes are needed. For instance,
  1. If you add a feature, you can talk about the use case of it.
  2. If you fix a bug, you can clarify why it is a bug.
-->
#670

### _How was this patch tested?_
- [x] Add some test cases that check the changes thoroughly including negative and positive cases if possible

- [ ] Add screenshots for manual tests if appropriate

- [x] [Run test](https://kyuubi.readthedocs.io/en/latest/tools/testing.html#running-tests) locally before make a pull request

Closes #674 from pan3793/sql-error-code.

Closes #670

08c95915 [Cheng Pan] address comments
e0808bc5 [Cheng Pan] address comments
e14e884b [Cheng Pan] KyuubiSQLException support sqlState and errorCode

Authored-by: Cheng Pan <379377944@qq.com>
Signed-off-by: ulysses-you <ulyssesyou18@gmail.com>
This commit is contained in:
Cheng Pan 2021-06-09 13:41:00 +08:00 committed by ulysses-you
parent b9079b698d
commit 43d60bd1b1
4 changed files with 32 additions and 10 deletions

View File

@ -26,7 +26,20 @@ import scala.collection.JavaConverters._
import org.apache.hive.service.rpc.thrift.{TStatus, TStatusCode}
class KyuubiSQLException(msg: String, cause: Throwable) extends SQLException(msg, cause) {
/**
* @param reason a description of the exception
* @param sqlState an XOPEN or SQL:2003 code identifying the exception
* @param vendorCode a database vendor-specific exception code
* @param cause the underlying reason for this [[SQLException]]
* (which is saved for later retrieval by the `getCause()` method);
* may be null indicating the cause is non-existent or unknown.
*/
class KyuubiSQLException(reason: String, sqlState: String, vendorCode: Int, cause: Throwable)
extends SQLException(reason, sqlState, vendorCode, cause) {
// for reflection
def this(msg: String, cause: Throwable) = this(msg, null, 0, cause)
/**
* Converts current object to a [[TStatus]] object
*
@ -47,22 +60,24 @@ object KyuubiSQLException {
private final val HEAD_MARK: String = "*"
private final val SEPARATOR: Char = ':'
def apply(msg: String, throwable: Throwable): KyuubiSQLException = {
new KyuubiSQLException(msg, findCause(throwable))
def apply(
msg: String,
cause: Throwable = null,
sqlState: String = null,
vendorCode: Int = 0): KyuubiSQLException = {
new KyuubiSQLException(msg, sqlState, vendorCode, findCause(cause))
}
def apply(cause: Throwable): KyuubiSQLException = {
val theCause = findCause(cause)
new KyuubiSQLException(theCause.getMessage, theCause)
apply(theCause.getMessage, theCause)
}
def apply(msg: String): KyuubiSQLException = new KyuubiSQLException(msg, null)
def apply(tStatus: TStatus): KyuubiSQLException = {
val msg = tStatus.getErrorMessage
val cause = toCause(tStatus.getInfoMessages.asScala)
cause match {
case k: KyuubiSQLException if k.getMessage == msg => k
case _ => apply(msg, cause)
case _ => apply(msg, cause, tStatus.getSqlState, tStatus.getErrorCode)
}
}

View File

@ -119,7 +119,7 @@ class OperationLog(path: Path) extends Logging {
case e: IOException =>
val absPath = path.toAbsolutePath
val opHandle = absPath.getFileName
throw new KyuubiSQLException(s"Operation[$opHandle] log file $absPath is not found", e)
throw KyuubiSQLException(s"Operation[$opHandle] log file $absPath is not found", e)
}
val tColumn = TColumn.stringVal(new TStringColumn(logs, ByteBuffer.allocate(0)))
val tRow = new TRowSet(0, new java.util.ArrayList[TRow](logs.size()))

View File

@ -117,7 +117,7 @@ object KyuubiAuthenticationFactory {
}
} catch {
case e: IOException =>
throw new KyuubiSQLException(
throw KyuubiSQLException(
"Failed to validate proxy privilege of " + realUser + " for " + proxyUser, e)
}
}

View File

@ -30,7 +30,7 @@ class KyuubiSQLExceptionSuite extends KyuubiFunSuite {
val e0 = new KyuubiException(msg0)
val e1 = new KyuubiException(msg1, e0)
val e2 = new KyuubiSQLException(msg2, e1)
val e2 = KyuubiSQLException(msg2, e1)
assert(e2.toTStatus === KyuubiSQLException.toTStatus(e2))
val e3 = KyuubiSQLException(e2.toTStatus)
@ -51,6 +51,13 @@ class KyuubiSQLExceptionSuite extends KyuubiFunSuite {
val e5 = KyuubiSQLException(e0)
assert(e5.getMessage === msg0)
assert(e5.getCause === e0)
val ts1 = KyuubiSQLException(msg2, e0, "01001", 1).toTStatus
assert(ts1.getStatusCode === TStatusCode.ERROR_STATUS)
assert(ts1.getSqlState === "01001")
assert(ts1.getErrorCode === 1)
assert(ts1.getErrorMessage === msg2)
assert(ts1.getInfoMessages.get(0).startsWith("*"))
}
test("find the root cause") {