[KYUUBI #5374][FOLLOWUP] Fix JDBC ClickHouse TRowSet Generator

# 🔍 Description
## Issue References 🔗

## Describe Your Solution 🔧
Some data type like `UInt8` in ck can not cast to `short`,  we should fix it

## Types of changes 🔖

- [x] Bugfix (non-breaking change which fixes an issue)
- [ ] New feature (non-breaking change which adds functionality)
- [ ] Breaking change (fix or feature that would cause existing functionality to change)

## Test Plan 🧪

#### Behavior Without This Pull Request ⚰️

#### Behavior With This Pull Request 🎉

#### Related Unit Tests

---

# Checklist 📝

- [ ] This patch was not authored or co-authored using [Generative Tooling](https://www.apache.org/legal/generative-tooling.html)

**Be nice. Be informative.**

Closes #6270 from lsm1/branch-fix-jdbc-ck-short.

Closes #5374

b5dac0f59 [senmiaoliu] ck fix RowSetGenerator

Authored-by: senmiaoliu <senmiaoliu@trip.com>
Signed-off-by: Cheng Pan <chengpan@apache.org>
This commit is contained in:
senmiaoliu 2024-04-07 21:05:35 +08:00 committed by Cheng Pan
parent 4fcc5c72a2
commit 10e3dec478
No known key found for this signature in database
GPG Key ID: 8001952629BCC75D
4 changed files with 106 additions and 15 deletions

View File

@ -16,6 +16,7 @@
*/
package org.apache.kyuubi.engine.jdbc.clickhouse
import java.lang.{Long => JLong, Short => JShort}
import java.sql.Types.{ARRAY, OTHER}
import org.apache.kyuubi.engine.jdbc.schema.DefaultJdbcTRowSetGenerator
@ -26,6 +27,39 @@ class ClickHouseTRowSetGenerator extends DefaultJdbcTRowSetGenerator {
super.asByteTColumn(rows, ordinal)
}
override def toSmallIntTColumn(rows: Seq[Seq[_]], ordinal: Int): TColumn = {
val colHead = if (rows.isEmpty) None else rows.head(ordinal)
colHead match {
case _: JShort => super.toSmallIntTColumn(rows, ordinal)
case _ => super.asShortTColumn(
rows,
ordinal,
convertFunc = (row, ordinal) => JShort.valueOf(row(ordinal).toString))
}
}
override def toIntegerTColumn(rows: Seq[Seq[_]], ordinal: Int): TColumn = {
val colHead = if (rows.isEmpty) None else rows.head(ordinal)
colHead match {
case _: Integer => super.toIntegerTColumn(rows, ordinal)
case _ => super.asIntegerTColumn(
rows,
ordinal,
convertFunc = (row, ordinal) => Integer.valueOf(row(ordinal).toString))
}
}
override def toBigIntTColumn(rows: Seq[Seq[_]], ordinal: Int): TColumn = {
val colHead = if (rows.isEmpty) None else rows.head(ordinal)
colHead match {
case _: JLong => super.toBigIntTColumn(rows, ordinal)
case _ => super.asLongTColumn(
rows,
ordinal,
convertFunc = (row, ordinal) => JLong.valueOf(row(ordinal).toString))
}
}
override def toVarcharTColumn(rows: Seq[Seq[_]], ordinal: Int): TColumn = {
val colHead = if (rows.isEmpty) None else rows.head(ordinal)
colHead match {
@ -39,6 +73,17 @@ class ClickHouseTRowSetGenerator extends DefaultJdbcTRowSetGenerator {
super.asByteTColumnValue(row, ordinal)
}
override def toSmallIntTColumnValue(row: Seq[_], ordinal: Int): TColumnValue = {
asShortTColumnValue(row, ordinal, rawValue => JShort.valueOf(rawValue.toString))
}
override def toIntegerTColumnValue(row: Seq[_], ordinal: Int): TColumnValue =
asIntegerTColumnValue(row, ordinal, rawValue => Integer.valueOf(rawValue.toString))
override def toBigIntTColumnValue(row: Seq[_], ordinal: Int): TColumnValue = {
asLongTColumnValue(row, ordinal, rawValue => JLong.valueOf(rawValue.toString))
}
override def toHiveString(data: Any, sqlType: Int): String =
(data, sqlType) match {
case (array: Array[_], ARRAY) => arrayToString(array)

View File

@ -64,17 +64,25 @@ class ClickHouseStatementSuite extends WithClickHouseEngine with HiveJDBCTestHel
| boolean_col boolean,
| double_col double,
| float_col float,
| x UUID)
| x UUID,
| ui8 UInt8,
| ui16 UInt16,
| ui32 UInt32,
| ui64 UInt64,
| ui128 UInt128,
| ui256 UInt256,
| i128 Int128,
| i256 Int256)
| ENGINE=File(TabSeparated)
|""".stripMargin)
statement.execute(
""" insert into db1.type_test
| (id, tiny_col, smallint_col, int_col, bigint_col, largeint_col, decimal_col,
| date_col, datetime_col, char_col, varchar_col, string_col, boolean_col,
| double_col, float_col, x)
| double_col, float_col, x, ui8, ui16, ui32, ui64, ui128, ui256, i128, i256)
| VALUES (1, 2, 3, 4, 5, 6, 7.7,
| '2022-05-08', '2022-05-08 17:47:45', 'a', 'Hello', 'Hello, Kyuubi', true,
| 8.8, 9.9, generateUUIDv4())
| 8.8, 9.9, generateUUIDv4(), 8, 16, 32, 64, 128, 256, -128, -256)
|""".stripMargin)
val resultSet1 = statement.executeQuery("select * from db1.type_test")
while (resultSet1.next()) {
@ -94,6 +102,14 @@ class ClickHouseStatementSuite extends WithClickHouseEngine with HiveJDBCTestHel
assert(resultSet1.getObject(14) == 8.8)
assert(resultSet1.getObject(15) == 9.9)
assert(resultSet1.getString(16).length == 36)
assert(resultSet1.getObject(17) == 8)
assert(resultSet1.getObject(18) == 16)
assert(resultSet1.getObject(19) == 32)
assert(resultSet1.getObject(20) == "64")
assert(resultSet1.getObject(21) == "128")
assert(resultSet1.getObject(22) == "256")
assert(resultSet1.getObject(23) == "-128")
assert(resultSet1.getObject(24) == "-256")
}
}
}

View File

@ -62,18 +62,27 @@ trait TColumnGenerator[RowT] extends TRowSetColumnGetter[RowT] {
TColumn.byteVal(new TByteColumn(values, nulls))
}
def asShortTColumn(rows: Seq[RowT], ordinal: Int): TColumn = {
val (values, nulls) = getColumnToList[JShort](rows, ordinal, 0.toShort)
def asShortTColumn(
rows: Seq[RowT],
ordinal: Int,
convertFunc: (RowT, Int) => JShort = null): TColumn = {
val (values, nulls) = getColumnToList[JShort](rows, ordinal, 0.toShort, convertFunc)
TColumn.i16Val(new TI16Column(values, nulls))
}
def asIntegerTColumn(rows: Seq[RowT], ordinal: Int): TColumn = {
val (values, nulls) = getColumnToList[Integer](rows, ordinal, 0)
def asIntegerTColumn(
rows: Seq[RowT],
ordinal: Int,
convertFunc: (RowT, Int) => Integer = null): TColumn = {
val (values, nulls) = getColumnToList[Integer](rows, ordinal, 0, convertFunc)
TColumn.i32Val(new TI32Column(values, nulls))
}
def asLongTColumn(rows: Seq[RowT], ordinal: Int): TColumn = {
val (values, nulls) = getColumnToList[JLong](rows, ordinal, 0.toLong)
def asLongTColumn(
rows: Seq[RowT],
ordinal: Int,
convertFunc: (RowT, Int) => JLong = null): TColumn = {
val (values, nulls) = getColumnToList[JLong](rows, ordinal, 0.toLong, convertFunc)
TColumn.i64Val(new TI64Column(values, nulls))
}

View File

@ -39,26 +39,47 @@ trait TColumnValueGenerator[RowT] extends TRowSetColumnGetter[RowT] {
TColumnValue.byteVal(tValue)
}
def asShortTColumnValue(row: RowT, ordinal: Int): TColumnValue = {
def asShortTColumnValue(
row: RowT,
ordinal: Int,
convertFunc: Any => JShort = null): TColumnValue = {
val tValue = new TI16Value
if (!isColumnNullAt(row, ordinal)) {
tValue.setValue(getColumnAs[JShort](row, ordinal))
val short = getColumnAs[JShort](row, ordinal) match {
case sObj: JShort => sObj
case obj if convertFunc != null => convertFunc(obj)
}
tValue.setValue(short)
}
TColumnValue.i16Val(tValue)
}
def asIntegerTColumnValue(row: RowT, ordinal: Int): TColumnValue = {
def asIntegerTColumnValue(
row: RowT,
ordinal: Int,
convertFunc: Any => Integer = null): TColumnValue = {
val tValue = new TI32Value
if (!isColumnNullAt(row, ordinal)) {
tValue.setValue(getColumnAs[Integer](row, ordinal))
val integer = getColumnAs[Integer](row, ordinal) match {
case iObj: Integer => iObj
case obj if convertFunc != null => convertFunc(obj)
}
tValue.setValue(integer)
}
TColumnValue.i32Val(tValue)
}
def asLongTColumnValue(row: RowT, ordinal: Int): TColumnValue = {
def asLongTColumnValue(
row: RowT,
ordinal: Int,
convertFunc: Any => JLong = null): TColumnValue = {
val tValue = new TI64Value
if (!isColumnNullAt(row, ordinal)) {
tValue.setValue(getColumnAs[JLong](row, ordinal))
val long = getColumnAs[JLong](row, ordinal) match {
case lObj: JLong => lObj
case obj if convertFunc != null => convertFunc(obj)
}
tValue.setValue(long)
}
TColumnValue.i64Val(tValue)
}