[KYUUBI #1648] Implement Flink GetTypeInfo operation

<!--
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/apache/incubator-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.
-->
Implement GetTypeInfo operation.

### _How was this patch tested?_
- [ ] 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/develop_tools/testing.html#running-tests) locally before make a pull request

Closes #1777 from SteNicholas/KYUUBI-1648.

Closes #1648

1c7c0417 [SteNicholas] [KYUUBI #1648] Implement GetTypeInfo operation
abdba44c [SteNicholas] [KYUUBI #1648] Implement GetTypeInfo operation

Authored-by: SteNicholas <programgeek@163.com>
Signed-off-by: Cheng Pan <chengpan@apache.org>
This commit is contained in:
SteNicholas 2022-01-17 18:14:34 +08:00 committed by Cheng Pan
parent 61e6022162
commit 7dcddafa6c
No known key found for this signature in database
GPG Key ID: 8001952629BCC75D
4 changed files with 397 additions and 9 deletions

View File

@ -37,7 +37,10 @@ class FlinkSQLOperationManager extends OperationManager("FlinkSQLOperationManage
addOperation(op)
}
override def newGetTypeInfoOperation(session: Session): Operation = null
override def newGetTypeInfoOperation(session: Session): Operation = {
val op = new GetTypeInfo(session)
addOperation(op)
}
override def newGetCatalogsOperation(session: Session): Operation = {
val op = new GetCatalogs(session)

View File

@ -0,0 +1,122 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.kyuubi.engine.flink.operation
import java.lang
import java.sql.Types._
import org.apache.flink.table.api.{DataTypes, ResultKind}
import org.apache.flink.table.catalog.Column
import org.apache.flink.table.types.logical.LogicalTypeRoot
import org.apache.flink.types.Row
import org.apache.kyuubi.engine.flink.result.ResultSet
import org.apache.kyuubi.operation.OperationType
import org.apache.kyuubi.operation.meta.ResultSetSchemaConstant._
import org.apache.kyuubi.session.Session
class GetTypeInfo(session: Session)
extends FlinkOperation(OperationType.GET_TYPE_INFO, session) {
private def isNumericType(javaType: Int): Boolean = {
javaType == TINYINT || javaType == SMALLINT || javaType == INTEGER || javaType == BIGINT ||
javaType == FLOAT || javaType == DOUBLE || javaType == DECIMAL
}
private def toRow(name: String, javaType: Int, precision: Integer = null): Row = {
Row.of(
name, // TYPE_NAME
Integer.valueOf(javaType), // DATA_TYPE
precision, // PRECISION
null, // LITERAL_PREFIX
null, // LITERAL_SUFFIX
null, // CREATE_PARAMS
lang.Short.valueOf("1"), // NULLABLE
lang.Boolean.valueOf(javaType == VARCHAR), // CASE_SENSITIVE
if (javaType < 1111) lang.Short.valueOf("3") else lang.Short.valueOf("0"), // SEARCHABLE
lang.Boolean.valueOf(!isNumericType(javaType)), // UNSIGNED_ATTRIBUTE
lang.Boolean.valueOf(false), // FIXED_PREC_SCALE
lang.Boolean.valueOf(false), // AUTO_INCREMENT
null, // LOCAL_TYPE_NAME
lang.Short.valueOf("1"), // MINIMUM_SCALE
lang.Short.valueOf("1"), // MAXIMUM_SCALE
null, // SQL_DATA_TYPE
null, // SQL_DATETIME_SUB
if (isNumericType(javaType)) Integer.valueOf(10) else null // NUM_PREC_RADIX
)
}
override protected def runInternal(): Unit = {
try {
val dataTypes: Array[Row] = Array(
toRow(LogicalTypeRoot.CHAR.name(), CHAR),
toRow(LogicalTypeRoot.VARCHAR.name(), VARCHAR),
toRow(LogicalTypeRoot.BOOLEAN.name(), BOOLEAN),
toRow(LogicalTypeRoot.BINARY.name(), BINARY),
toRow(LogicalTypeRoot.VARBINARY.name(), VARBINARY),
toRow(LogicalTypeRoot.DECIMAL.name(), DECIMAL, 38),
toRow(LogicalTypeRoot.TINYINT.name(), TINYINT, 3),
toRow(LogicalTypeRoot.SMALLINT.name(), SMALLINT, 5),
toRow(LogicalTypeRoot.INTEGER.name(), INTEGER, 10),
toRow(LogicalTypeRoot.BIGINT.name(), BIGINT, 19),
toRow(LogicalTypeRoot.FLOAT.name(), FLOAT, 7),
toRow(LogicalTypeRoot.DOUBLE.name(), DOUBLE, 15),
toRow(LogicalTypeRoot.DATE.name(), DATE),
toRow(LogicalTypeRoot.TIME_WITHOUT_TIME_ZONE.name(), TIME),
toRow(LogicalTypeRoot.TIMESTAMP_WITHOUT_TIME_ZONE.name(), TIMESTAMP),
toRow(LogicalTypeRoot.TIMESTAMP_WITH_TIME_ZONE.name(), TIMESTAMP_WITH_TIMEZONE),
toRow(LogicalTypeRoot.TIMESTAMP_WITH_LOCAL_TIME_ZONE.name(), TIMESTAMP_WITH_TIMEZONE),
toRow(LogicalTypeRoot.INTERVAL_YEAR_MONTH.name(), OTHER),
toRow(LogicalTypeRoot.INTERVAL_DAY_TIME.name(), OTHER),
toRow(LogicalTypeRoot.ARRAY.name(), ARRAY),
toRow(LogicalTypeRoot.MULTISET.name(), JAVA_OBJECT),
toRow(LogicalTypeRoot.MAP.name(), JAVA_OBJECT),
toRow(LogicalTypeRoot.ROW.name(), JAVA_OBJECT),
toRow(LogicalTypeRoot.DISTINCT_TYPE.name(), OTHER),
toRow(LogicalTypeRoot.STRUCTURED_TYPE.name(), OTHER),
toRow(LogicalTypeRoot.NULL.name(), NULL),
toRow(LogicalTypeRoot.RAW.name(), OTHER),
toRow(LogicalTypeRoot.SYMBOL.name(), OTHER),
toRow(LogicalTypeRoot.UNRESOLVED.name(), OTHER))
resultSet = ResultSet.builder.resultKind(ResultKind.SUCCESS_WITH_CONTENT)
.columns(
Column.physical(TYPE_NAME, DataTypes.STRING()),
Column.physical(DATA_TYPE, DataTypes.INT()),
Column.physical(PRECISION, DataTypes.INT()),
Column.physical("LITERAL_PREFIX", DataTypes.STRING()),
Column.physical("LITERAL_SUFFIX", DataTypes.STRING()),
Column.physical("CREATE_PARAMS", DataTypes.STRING()),
Column.physical(NULLABLE, DataTypes.SMALLINT()),
Column.physical(CASE_SENSITIVE, DataTypes.BOOLEAN()),
Column.physical(SEARCHABLE, DataTypes.SMALLINT()),
Column.physical("UNSIGNED_ATTRIBUTE", DataTypes.BOOLEAN()),
Column.physical("FIXED_PREC_SCALE", DataTypes.BOOLEAN()),
Column.physical("AUTO_INCREMENT", DataTypes.BOOLEAN()),
Column.physical("LOCAL_TYPE_NAME", DataTypes.STRING()),
Column.physical("MINIMUM_SCALE", DataTypes.SMALLINT()),
Column.physical("MAXIMUM_SCALE", DataTypes.SMALLINT()),
Column.physical(SQL_DATA_TYPE, DataTypes.INT()),
Column.physical(SQL_DATETIME_SUB, DataTypes.INT()),
Column.physical(NUM_PREC_RADIX, DataTypes.INT()))
.data(dataTypes)
.build
} catch {
onError()
}
}
}

View File

@ -19,19 +19,14 @@ package org.apache.kyuubi.engine.flink.operation
import org.apache.flink.table.api.EnvironmentSettings.DEFAULT_BUILTIN_CATALOG
import org.apache.flink.table.api.EnvironmentSettings.DEFAULT_BUILTIN_DATABASE
import org.apache.flink.table.types.logical.LogicalTypeRoot
import org.scalatest.concurrent.PatienceConfiguration.Timeout
import org.scalatest.time.SpanSugar._
import org.apache.kyuubi.engine.flink.WithFlinkSQLEngine
import org.apache.kyuubi.engine.flink.result.Constants
import org.apache.kyuubi.operation.HiveJDBCTestHelper
import org.apache.kyuubi.operation.meta.ResultSetSchemaConstant.FUNCTION_CAT
import org.apache.kyuubi.operation.meta.ResultSetSchemaConstant.FUNCTION_NAME
import org.apache.kyuubi.operation.meta.ResultSetSchemaConstant.FUNCTION_SCHEM
import org.apache.kyuubi.operation.meta.ResultSetSchemaConstant.TABLE_CAT
import org.apache.kyuubi.operation.meta.ResultSetSchemaConstant.TABLE_CATALOG
import org.apache.kyuubi.operation.meta.ResultSetSchemaConstant.TABLE_SCHEM
import org.apache.kyuubi.operation.meta.ResultSetSchemaConstant.TABLE_TYPE
import org.apache.kyuubi.operation.meta.ResultSetSchemaConstant._
import org.apache.kyuubi.service.ServiceState._
class FlinkOperationSuite extends WithFlinkSQLEngine with HiveJDBCTestHelper {
@ -62,6 +57,274 @@ class FlinkOperationSuite extends WithFlinkSQLEngine with HiveJDBCTestHelper {
}
}
test("get type info") {
withJdbcStatement() { statement =>
val typeInfo = statement.getConnection.getMetaData.getTypeInfo
typeInfo.next()
assert(typeInfo.getString(TYPE_NAME) === LogicalTypeRoot.CHAR.name())
assert(typeInfo.getInt(DATA_TYPE) === java.sql.Types.CHAR)
assert(typeInfo.getInt(PRECISION) === 0)
assert(typeInfo.getShort(NULLABLE) === 1)
assert(!typeInfo.getBoolean(CASE_SENSITIVE))
assert(typeInfo.getShort(SEARCHABLE) === 3)
assert(typeInfo.getInt(NUM_PREC_RADIX) === 0)
typeInfo.next()
assert(typeInfo.getString(TYPE_NAME) === LogicalTypeRoot.VARCHAR.name())
assert(typeInfo.getInt(DATA_TYPE) === java.sql.Types.VARCHAR)
assert(typeInfo.getInt(PRECISION) === 0)
assert(typeInfo.getShort(NULLABLE) === 1)
assert(typeInfo.getBoolean(CASE_SENSITIVE))
assert(typeInfo.getShort(SEARCHABLE) === 3)
assert(typeInfo.getInt(NUM_PREC_RADIX) === 0)
typeInfo.next()
assert(typeInfo.getString(TYPE_NAME) === LogicalTypeRoot.BOOLEAN.name())
assert(typeInfo.getInt(DATA_TYPE) === java.sql.Types.BOOLEAN)
assert(typeInfo.getInt(PRECISION) === 0)
assert(typeInfo.getShort(NULLABLE) === 1)
assert(!typeInfo.getBoolean(CASE_SENSITIVE))
assert(typeInfo.getShort(SEARCHABLE) === 3)
assert(typeInfo.getInt(NUM_PREC_RADIX) === 0)
typeInfo.next()
assert(typeInfo.getString(TYPE_NAME) === LogicalTypeRoot.BINARY.name())
assert(typeInfo.getInt(DATA_TYPE) === java.sql.Types.BINARY)
assert(typeInfo.getInt(PRECISION) === 0)
assert(typeInfo.getShort(NULLABLE) === 1)
assert(!typeInfo.getBoolean(CASE_SENSITIVE))
assert(typeInfo.getShort(SEARCHABLE) === 3)
assert(typeInfo.getInt(NUM_PREC_RADIX) === 0)
typeInfo.next()
assert(typeInfo.getString(TYPE_NAME) === LogicalTypeRoot.VARBINARY.name())
assert(typeInfo.getInt(DATA_TYPE) === java.sql.Types.VARBINARY)
assert(typeInfo.getInt(PRECISION) === 0)
assert(typeInfo.getShort(NULLABLE) === 1)
assert(!typeInfo.getBoolean(CASE_SENSITIVE))
assert(typeInfo.getShort(SEARCHABLE) === 3)
assert(typeInfo.getInt(NUM_PREC_RADIX) === 0)
typeInfo.next()
assert(typeInfo.getString(TYPE_NAME) === LogicalTypeRoot.DECIMAL.name())
assert(typeInfo.getInt(DATA_TYPE) === java.sql.Types.DECIMAL)
assert(typeInfo.getInt(PRECISION) === 38)
assert(typeInfo.getShort(NULLABLE) === 1)
assert(!typeInfo.getBoolean(CASE_SENSITIVE))
assert(typeInfo.getShort(SEARCHABLE) === 3)
assert(typeInfo.getInt(NUM_PREC_RADIX) === 10)
typeInfo.next()
assert(typeInfo.getString(TYPE_NAME) === LogicalTypeRoot.TINYINT.name())
assert(typeInfo.getInt(DATA_TYPE) === java.sql.Types.TINYINT)
assert(typeInfo.getInt(PRECISION) === 3)
assert(typeInfo.getShort(NULLABLE) === 1)
assert(!typeInfo.getBoolean(CASE_SENSITIVE))
assert(typeInfo.getShort(SEARCHABLE) === 3)
assert(typeInfo.getInt(NUM_PREC_RADIX) === 10)
typeInfo.next()
assert(typeInfo.getString(TYPE_NAME) === LogicalTypeRoot.SMALLINT.name())
assert(typeInfo.getInt(DATA_TYPE) === java.sql.Types.SMALLINT)
assert(typeInfo.getInt(PRECISION) === 5)
assert(typeInfo.getShort(NULLABLE) === 1)
assert(!typeInfo.getBoolean(CASE_SENSITIVE))
assert(typeInfo.getShort(SEARCHABLE) === 3)
assert(typeInfo.getInt(NUM_PREC_RADIX) === 10)
typeInfo.next()
assert(typeInfo.getString(TYPE_NAME) === LogicalTypeRoot.INTEGER.name())
assert(typeInfo.getInt(DATA_TYPE) === java.sql.Types.INTEGER)
assert(typeInfo.getInt(PRECISION) === 10)
assert(typeInfo.getShort(NULLABLE) === 1)
assert(!typeInfo.getBoolean(CASE_SENSITIVE))
assert(typeInfo.getShort(SEARCHABLE) === 3)
assert(typeInfo.getInt(NUM_PREC_RADIX) === 10)
typeInfo.next()
assert(typeInfo.getString(TYPE_NAME) === LogicalTypeRoot.BIGINT.name())
assert(typeInfo.getInt(DATA_TYPE) === java.sql.Types.BIGINT)
assert(typeInfo.getInt(PRECISION) === 19)
assert(typeInfo.getShort(NULLABLE) === 1)
assert(!typeInfo.getBoolean(CASE_SENSITIVE))
assert(typeInfo.getShort(SEARCHABLE) === 3)
assert(typeInfo.getInt(NUM_PREC_RADIX) === 10)
typeInfo.next()
assert(typeInfo.getString(TYPE_NAME) === LogicalTypeRoot.FLOAT.name())
assert(typeInfo.getInt(DATA_TYPE) === java.sql.Types.FLOAT)
assert(typeInfo.getInt(PRECISION) === 7)
assert(typeInfo.getShort(NULLABLE) === 1)
assert(!typeInfo.getBoolean(CASE_SENSITIVE))
assert(typeInfo.getShort(SEARCHABLE) === 3)
assert(typeInfo.getInt(NUM_PREC_RADIX) === 10)
typeInfo.next()
assert(typeInfo.getString(TYPE_NAME) === LogicalTypeRoot.DOUBLE.name())
assert(typeInfo.getInt(DATA_TYPE) === java.sql.Types.DOUBLE)
assert(typeInfo.getInt(PRECISION) === 15)
assert(typeInfo.getShort(NULLABLE) === 1)
assert(!typeInfo.getBoolean(CASE_SENSITIVE))
assert(typeInfo.getShort(SEARCHABLE) === 3)
assert(typeInfo.getInt(NUM_PREC_RADIX) === 10)
typeInfo.next()
assert(typeInfo.getString(TYPE_NAME) === LogicalTypeRoot.DATE.name())
assert(typeInfo.getInt(DATA_TYPE) === java.sql.Types.DATE)
assert(typeInfo.getInt(PRECISION) === 0)
assert(typeInfo.getShort(NULLABLE) === 1)
assert(!typeInfo.getBoolean(CASE_SENSITIVE))
assert(typeInfo.getShort(SEARCHABLE) === 3)
assert(typeInfo.getInt(NUM_PREC_RADIX) === 0)
typeInfo.next()
assert(typeInfo.getString(TYPE_NAME) === LogicalTypeRoot.TIME_WITHOUT_TIME_ZONE.name())
assert(typeInfo.getInt(DATA_TYPE) === java.sql.Types.TIME)
assert(typeInfo.getInt(PRECISION) === 0)
assert(typeInfo.getShort(NULLABLE) === 1)
assert(!typeInfo.getBoolean(CASE_SENSITIVE))
assert(typeInfo.getShort(SEARCHABLE) === 3)
assert(typeInfo.getInt(NUM_PREC_RADIX) === 0)
typeInfo.next()
assert(typeInfo.getString(TYPE_NAME) === LogicalTypeRoot.TIMESTAMP_WITHOUT_TIME_ZONE.name())
assert(typeInfo.getInt(DATA_TYPE) === java.sql.Types.TIMESTAMP)
assert(typeInfo.getInt(PRECISION) === 0)
assert(typeInfo.getShort(NULLABLE) === 1)
assert(!typeInfo.getBoolean(CASE_SENSITIVE))
assert(typeInfo.getShort(SEARCHABLE) === 3)
assert(typeInfo.getInt(NUM_PREC_RADIX) === 0)
typeInfo.next()
assert(typeInfo.getString(TYPE_NAME) === LogicalTypeRoot.TIMESTAMP_WITH_TIME_ZONE.name())
assert(typeInfo.getInt(DATA_TYPE) === java.sql.Types.TIMESTAMP_WITH_TIMEZONE)
assert(typeInfo.getInt(PRECISION) === 0)
assert(typeInfo.getShort(NULLABLE) === 1)
assert(!typeInfo.getBoolean(CASE_SENSITIVE))
assert(typeInfo.getShort(SEARCHABLE) === 0)
assert(typeInfo.getInt(NUM_PREC_RADIX) === 0)
typeInfo.next()
assert(
typeInfo.getString(TYPE_NAME) === LogicalTypeRoot.TIMESTAMP_WITH_LOCAL_TIME_ZONE.name())
assert(typeInfo.getInt(DATA_TYPE) === java.sql.Types.TIMESTAMP_WITH_TIMEZONE)
assert(typeInfo.getInt(PRECISION) === 0)
assert(typeInfo.getShort(NULLABLE) === 1)
assert(!typeInfo.getBoolean(CASE_SENSITIVE))
assert(typeInfo.getShort(SEARCHABLE) === 0)
assert(typeInfo.getInt(NUM_PREC_RADIX) === 0)
typeInfo.next()
assert(typeInfo.getString(TYPE_NAME) === LogicalTypeRoot.INTERVAL_YEAR_MONTH.name())
assert(typeInfo.getInt(DATA_TYPE) === java.sql.Types.OTHER)
assert(typeInfo.getInt(PRECISION) === 0)
assert(typeInfo.getShort(NULLABLE) === 1)
assert(!typeInfo.getBoolean(CASE_SENSITIVE))
assert(typeInfo.getShort(SEARCHABLE) === 0)
assert(typeInfo.getInt(NUM_PREC_RADIX) === 0)
typeInfo.next()
assert(typeInfo.getString(TYPE_NAME) === LogicalTypeRoot.INTERVAL_DAY_TIME.name())
assert(typeInfo.getInt(DATA_TYPE) === java.sql.Types.OTHER)
assert(typeInfo.getInt(PRECISION) === 0)
assert(typeInfo.getShort(NULLABLE) === 1)
assert(!typeInfo.getBoolean(CASE_SENSITIVE))
assert(typeInfo.getShort(SEARCHABLE) === 0)
assert(typeInfo.getInt(NUM_PREC_RADIX) === 0)
typeInfo.next()
assert(typeInfo.getString(TYPE_NAME) === LogicalTypeRoot.ARRAY.name())
assert(typeInfo.getInt(DATA_TYPE) === java.sql.Types.ARRAY)
assert(typeInfo.getInt(PRECISION) === 0)
assert(typeInfo.getShort(NULLABLE) === 1)
assert(!typeInfo.getBoolean(CASE_SENSITIVE))
assert(typeInfo.getShort(SEARCHABLE) === 0)
assert(typeInfo.getInt(NUM_PREC_RADIX) === 0)
typeInfo.next()
assert(typeInfo.getString(TYPE_NAME) === LogicalTypeRoot.MULTISET.name())
assert(typeInfo.getInt(DATA_TYPE) === java.sql.Types.JAVA_OBJECT)
assert(typeInfo.getInt(PRECISION) === 0)
assert(typeInfo.getShort(NULLABLE) === 1)
assert(!typeInfo.getBoolean(CASE_SENSITIVE))
assert(typeInfo.getShort(SEARCHABLE) === 0)
assert(typeInfo.getInt(NUM_PREC_RADIX) === 0)
typeInfo.next()
assert(typeInfo.getString(TYPE_NAME) === LogicalTypeRoot.MAP.name())
assert(typeInfo.getInt(DATA_TYPE) === java.sql.Types.JAVA_OBJECT)
assert(typeInfo.getInt(PRECISION) === 0)
assert(typeInfo.getShort(NULLABLE) === 1)
assert(!typeInfo.getBoolean(CASE_SENSITIVE))
assert(typeInfo.getShort(SEARCHABLE) === 0)
assert(typeInfo.getInt(NUM_PREC_RADIX) === 0)
typeInfo.next()
assert(typeInfo.getString(TYPE_NAME) === LogicalTypeRoot.ROW.name())
assert(typeInfo.getInt(DATA_TYPE) === java.sql.Types.JAVA_OBJECT)
assert(typeInfo.getInt(PRECISION) === 0)
assert(typeInfo.getShort(NULLABLE) === 1)
assert(!typeInfo.getBoolean(CASE_SENSITIVE))
assert(typeInfo.getShort(SEARCHABLE) === 0)
assert(typeInfo.getInt(NUM_PREC_RADIX) === 0)
typeInfo.next()
assert(typeInfo.getString(TYPE_NAME) === LogicalTypeRoot.DISTINCT_TYPE.name())
assert(typeInfo.getInt(DATA_TYPE) === java.sql.Types.OTHER)
assert(typeInfo.getInt(PRECISION) === 0)
assert(typeInfo.getShort(NULLABLE) === 1)
assert(!typeInfo.getBoolean(CASE_SENSITIVE))
assert(typeInfo.getShort(SEARCHABLE) === 0)
assert(typeInfo.getInt(NUM_PREC_RADIX) === 0)
typeInfo.next()
assert(typeInfo.getString(TYPE_NAME) === LogicalTypeRoot.STRUCTURED_TYPE.name())
assert(typeInfo.getInt(DATA_TYPE) === java.sql.Types.OTHER)
assert(typeInfo.getInt(PRECISION) === 0)
assert(typeInfo.getShort(NULLABLE) === 1)
assert(!typeInfo.getBoolean(CASE_SENSITIVE))
assert(typeInfo.getShort(SEARCHABLE) === 0)
assert(typeInfo.getInt(NUM_PREC_RADIX) === 0)
typeInfo.next()
assert(typeInfo.getString(TYPE_NAME) === LogicalTypeRoot.NULL.name())
assert(typeInfo.getInt(DATA_TYPE) === java.sql.Types.NULL)
assert(typeInfo.getInt(PRECISION) === 0)
assert(typeInfo.getShort(NULLABLE) === 1)
assert(!typeInfo.getBoolean(CASE_SENSITIVE))
assert(typeInfo.getShort(SEARCHABLE) === 3)
assert(typeInfo.getInt(NUM_PREC_RADIX) === 0)
typeInfo.next()
assert(typeInfo.getString(TYPE_NAME) === LogicalTypeRoot.RAW.name())
assert(typeInfo.getInt(DATA_TYPE) === java.sql.Types.OTHER)
assert(typeInfo.getInt(PRECISION) === 0)
assert(typeInfo.getShort(NULLABLE) === 1)
assert(!typeInfo.getBoolean(CASE_SENSITIVE))
assert(typeInfo.getShort(SEARCHABLE) === 0)
assert(typeInfo.getInt(NUM_PREC_RADIX) === 0)
typeInfo.next()
assert(typeInfo.getString(TYPE_NAME) === LogicalTypeRoot.SYMBOL.name())
assert(typeInfo.getInt(DATA_TYPE) === java.sql.Types.OTHER)
assert(typeInfo.getInt(PRECISION) === 0)
assert(typeInfo.getShort(NULLABLE) === 1)
assert(!typeInfo.getBoolean(CASE_SENSITIVE))
assert(typeInfo.getShort(SEARCHABLE) === 0)
assert(typeInfo.getInt(NUM_PREC_RADIX) === 0)
typeInfo.next()
assert(typeInfo.getString(TYPE_NAME) === LogicalTypeRoot.UNRESOLVED.name())
assert(typeInfo.getInt(DATA_TYPE) === java.sql.Types.OTHER)
assert(typeInfo.getInt(PRECISION) === 0)
assert(typeInfo.getShort(NULLABLE) === 1)
assert(!typeInfo.getBoolean(CASE_SENSITIVE))
assert(typeInfo.getShort(SEARCHABLE) === 0)
assert(typeInfo.getInt(NUM_PREC_RADIX) === 0)
}
}
test("get schemas") {
withJdbcStatement() { statement =>
val metaData = statement.getConnection.getMetaData

View File

@ -77,7 +77,7 @@ class GetTypeInfo(session: Session)
private def isNumericType(javaType: Int): Boolean = {
javaType == TINYINT || javaType == SMALLINT || javaType == INTEGER || javaType == BIGINT ||
javaType == FLOAT || javaType == FLOAT || javaType == DOUBLE || javaType == DECIMAL
javaType == FLOAT || javaType == DOUBLE || javaType == DECIMAL
}
private def toRow(name: String, javaType: Int, precision: Integer = null): Row = {