diff --git a/externals/kyuubi-spark-sql-engine/src/main/scala/org/apache/kyuubi/engine/spark/operation/GetTables.scala b/externals/kyuubi-spark-sql-engine/src/main/scala/org/apache/kyuubi/engine/spark/operation/GetTables.scala index 1df2f57d2..674423701 100644 --- a/externals/kyuubi-spark-sql-engine/src/main/scala/org/apache/kyuubi/engine/spark/operation/GetTables.scala +++ b/externals/kyuubi-spark-sql-engine/src/main/scala/org/apache/kyuubi/engine/spark/operation/GetTables.scala @@ -52,7 +52,7 @@ class GetTables( .add(TABLE_TYPE, "string", nullable = true, "The table type, e.g. \"TABLE\", \"VIEW\"") .add(REMARKS, "string", nullable = true, "Comments about the table.") .add("TYPE_CAT", "string", nullable = true, "The types catalog." ) - .add("TYPE_SCHEM", "string", nullable = true, "The types catalog") + .add("TYPE_SCHEM", "string", nullable = true, "the types schema (may be null)") .add("TYPE_NAME", "string", nullable = true, "Type name.") .add("SELF_REFERENCING_COL_NAME", "string", nullable = true, "Name of the designated \"identifier\" column of a typed table.") diff --git a/externals/kyuubi-spark-sql-engine/src/test/scala/org/apache/kyuubi/engine/spark/operation/SparkOperationSuite.scala b/externals/kyuubi-spark-sql-engine/src/test/scala/org/apache/kyuubi/engine/spark/operation/SparkOperationSuite.scala index 65d31ea5c..527fef9ff 100644 --- a/externals/kyuubi-spark-sql-engine/src/test/scala/org/apache/kyuubi/engine/spark/operation/SparkOperationSuite.scala +++ b/externals/kyuubi-spark-sql-engine/src/test/scala/org/apache/kyuubi/engine/spark/operation/SparkOperationSuite.scala @@ -17,10 +17,12 @@ package org.apache.kyuubi.engine.spark.operation -import java.sql.{Date, ResultSet, SQLException, Timestamp} +import java.sql.{DatabaseMetaData, Date, ResultSet, SQLException, SQLFeatureNotSupportedException, Timestamp} import scala.collection.JavaConverters._ +import scala.util.Random +import org.apache.hive.common.util.HiveVersionInfo import org.apache.hive.service.cli.HiveSQLException import org.apache.hive.service.rpc.thrift._ import org.apache.spark.sql.catalyst.analysis.FunctionRegistry @@ -473,16 +475,19 @@ class SparkOperationSuite extends WithSparkSQLEngine { test("get functions") { withJdbcStatement() { statement => val metaData = statement.getConnection.getMetaData + val apis = Seq(metaData.getFunctions _, metaData.getProcedures _) Seq("to_timestamp", "date_part", "lpad", "date_format", "cos", "sin").foreach { func => - val resultSet = metaData.getFunctions("", dftSchema, func) - while (resultSet.next()) { - val exprInfo = FunctionRegistry.expressions(func)._1 - assert(resultSet.getString(FUNCTION_CAT).isEmpty) - assert(resultSet.getString(FUNCTION_SCHEM) === null) - assert(resultSet.getString(FUNCTION_NAME) === exprInfo.getName) - assert(resultSet.getString(REMARKS) === - s"Usage: ${exprInfo.getUsage}\nExtended Usage:${exprInfo.getExtended}") - assert(resultSet.getString(SPECIFIC_NAME) === exprInfo.getClassName) + apis.foreach { apiFunc => + val resultSet = apiFunc("", dftSchema, func) + while (resultSet.next()) { + val exprInfo = FunctionRegistry.expressions(func)._1 + assert(resultSet.getString(FUNCTION_CAT).isEmpty) + assert(resultSet.getString(FUNCTION_SCHEM) === null) + assert(resultSet.getString(FUNCTION_NAME) === exprInfo.getName) + assert(resultSet.getString(REMARKS) === + s"Usage: ${exprInfo.getUsage}\nExtended Usage:${exprInfo.getExtended}") + assert(resultSet.getString(SPECIFIC_NAME) === exprInfo.getClassName) + } } } } @@ -878,4 +883,187 @@ class SparkOperationSuite extends WithSparkSQLEngine { assert(tFetchResultsResp.getStatus.getStatusCode === TStatusCode.SUCCESS_STATUS) } } + + test("Hive JDBC Database MetaData API Auditing") { + withJdbcStatement() { statement => + val metaData = statement.getConnection.getMetaData + Seq( + () => metaData.allProceduresAreCallable(), + () => metaData.getURL, + () => metaData.getUserName, + () => metaData.isReadOnly, + () => metaData.nullsAreSortedHigh, + () => metaData.nullsAreSortedLow, + () => metaData.nullsAreSortedAtStart(), + () => metaData.nullsAreSortedAtEnd(), + () => metaData.usesLocalFiles(), + () => metaData.usesLocalFilePerTable(), + () => metaData.supportsMixedCaseIdentifiers(), + () => metaData.supportsMixedCaseQuotedIdentifiers(), + () => metaData.storesUpperCaseIdentifiers(), + () => metaData.storesUpperCaseQuotedIdentifiers(), + () => metaData.storesLowerCaseIdentifiers(), + () => metaData.storesLowerCaseQuotedIdentifiers(), + () => metaData.storesMixedCaseIdentifiers(), + () => metaData.storesMixedCaseQuotedIdentifiers(), + () => metaData.getSQLKeywords, + () => metaData.nullPlusNonNullIsNull, + () => metaData.supportsConvert, + () => metaData.supportsTableCorrelationNames, + () => metaData.supportsDifferentTableCorrelationNames, + () => metaData.supportsExpressionsInOrderBy(), + () => metaData.supportsOrderByUnrelated, + () => metaData.supportsGroupByUnrelated, + () => metaData.supportsGroupByBeyondSelect, + () => metaData.supportsLikeEscapeClause, + () => metaData.supportsMultipleTransactions, + () => metaData.supportsMinimumSQLGrammar, + () => metaData.supportsCoreSQLGrammar, + () => metaData.supportsExtendedSQLGrammar, + () => metaData.supportsANSI92EntryLevelSQL, + () => metaData.supportsANSI92IntermediateSQL, + () => metaData.supportsANSI92FullSQL, + () => metaData.supportsIntegrityEnhancementFacility, + () => metaData.isCatalogAtStart, + () => metaData.supportsSubqueriesInComparisons, + () => metaData.supportsSubqueriesInExists, + () => metaData.supportsSubqueriesInIns, + () => metaData.supportsSubqueriesInQuantifieds, + // Spark support this, see https://issues.apache.org/jira/browse/SPARK-18455 + () => metaData.supportsCorrelatedSubqueries, + () => metaData.supportsOpenCursorsAcrossCommit, + () => metaData.supportsOpenCursorsAcrossRollback, + () => metaData.supportsOpenStatementsAcrossCommit, + () => metaData.supportsOpenStatementsAcrossRollback, + () => metaData.getMaxBinaryLiteralLength, + () => metaData.getMaxCharLiteralLength, + () => metaData.getMaxColumnsInGroupBy, + () => metaData.getMaxColumnsInIndex, + () => metaData.getMaxColumnsInOrderBy, + () => metaData.getMaxColumnsInSelect, + () => metaData.getMaxColumnsInTable, + () => metaData.getMaxConnections, + () => metaData.getMaxCursorNameLength, + () => metaData.getMaxIndexLength, + () => metaData.getMaxSchemaNameLength, + () => metaData.getMaxProcedureNameLength, + () => metaData.getMaxCatalogNameLength, + () => metaData.getMaxRowSize, + () => metaData.doesMaxRowSizeIncludeBlobs, + () => metaData.getMaxStatementLength, + () => metaData.getMaxStatements, + () => metaData.getMaxTableNameLength, + () => metaData.getMaxTablesInSelect, + () => metaData.getMaxUserNameLength, + () => metaData.supportsTransactionIsolationLevel(1), + () => metaData.supportsDataDefinitionAndDataManipulationTransactions, + () => metaData.supportsDataManipulationTransactionsOnly, + () => metaData.dataDefinitionCausesTransactionCommit, + () => metaData.dataDefinitionIgnoredInTransactions, + () => metaData.getColumnPrivileges("", "%", "%", "%"), + () => metaData.getTablePrivileges("", "%", "%"), + () => metaData.getBestRowIdentifier("", "%", "%", 0, true), + () => metaData.getVersionColumns("", "%", "%"), + () => metaData.getExportedKeys("", "default", ""), + () => metaData.supportsResultSetConcurrency(ResultSet.TYPE_FORWARD_ONLY, 2), + () => metaData.ownUpdatesAreVisible(ResultSet.TYPE_FORWARD_ONLY), + () => metaData.ownDeletesAreVisible(ResultSet.TYPE_FORWARD_ONLY), + () => metaData.ownInsertsAreVisible(ResultSet.TYPE_FORWARD_ONLY), + () => metaData.othersUpdatesAreVisible(ResultSet.TYPE_FORWARD_ONLY), + () => metaData.othersDeletesAreVisible(ResultSet.TYPE_FORWARD_ONLY), + () => metaData.othersInsertsAreVisible(ResultSet.TYPE_FORWARD_ONLY), + () => metaData.updatesAreDetected(ResultSet.TYPE_FORWARD_ONLY), + () => metaData.deletesAreDetected(ResultSet.TYPE_FORWARD_ONLY), + () => metaData.insertsAreDetected(ResultSet.TYPE_FORWARD_ONLY), + () => metaData.supportsNamedParameters(), + () => metaData.supportsMultipleOpenResults, + () => metaData.supportsGetGeneratedKeys, + () => metaData.getSuperTypes("", "%", "%"), + () => metaData.getSuperTables("", "%", "%"), + () => metaData.getAttributes("", "%", "%", "%"), + () => metaData.getResultSetHoldability, + () => metaData.locatorsUpdateCopy, + () => metaData.supportsStatementPooling, + () => metaData.getRowIdLifetime, + () => metaData.supportsStoredFunctionsUsingCallSyntax, + () => metaData.autoCommitFailureClosesAllResultSets, + () => metaData.getClientInfoProperties, + () => metaData.getFunctionColumns("", "%", "%", "%"), + () => metaData.getPseudoColumns("", "%", "%", "%"), + () => metaData.generatedKeyAlwaysReturned).foreach { func => + val e = intercept[SQLFeatureNotSupportedException](func()) + assert(e.getMessage === "Method not supported") + } + + import org.apache.kyuubi.KYUUBI_VERSION + assert(metaData.allTablesAreSelectable) + assert(metaData.getDatabaseProductName === "Spark SQL") + assert(metaData.getDatabaseProductVersion === KYUUBI_VERSION) + assert(metaData.getDriverName === "Hive JDBC") + assert(metaData.getDriverVersion === HiveVersionInfo.getVersion) + assert(metaData.getDatabaseMajorVersion === Utils.majorVersion(KYUUBI_VERSION)) + assert(metaData.getDatabaseMinorVersion === Utils.minorVersion(KYUUBI_VERSION)) + assert(metaData.getIdentifierQuoteString === " ", + "This method returns a space \" \" if identifier quoting is not supported") + assert(metaData.getNumericFunctions === "") + assert(metaData.getStringFunctions === "") + assert(metaData.getSystemFunctions === "") + assert(metaData.getTimeDateFunctions === "") + assert(metaData.getSearchStringEscape === "\\") + assert(metaData.getExtraNameCharacters === "") + assert(metaData.supportsAlterTableWithAddColumn()) + assert(!metaData.supportsAlterTableWithDropColumn()) + assert(metaData.supportsColumnAliasing()) + assert(metaData.supportsGroupBy) + assert(!metaData.supportsMultipleResultSets) + assert(!metaData.supportsNonNullableColumns) + assert(metaData.supportsOuterJoins) + assert(metaData.supportsFullOuterJoins) + assert(metaData.supportsLimitedOuterJoins) + assert(metaData.getSchemaTerm === "database") + assert(metaData.getProcedureTerm === "UDF") + assert(metaData.getCatalogTerm === "instance") + assert(metaData.getCatalogSeparator === ".") + assert(metaData.supportsSchemasInDataManipulation) + assert(!metaData.supportsSchemasInProcedureCalls) + assert(metaData.supportsSchemasInTableDefinitions) + assert(!metaData.supportsSchemasInIndexDefinitions) + assert(!metaData.supportsSchemasInPrivilegeDefinitions) + // This is actually supported, but hive jdbc package return false + assert(!metaData.supportsCatalogsInDataManipulation) + assert(!metaData.supportsCatalogsInProcedureCalls) + // This is actually supported, but hive jdbc package return false + assert(!metaData.supportsCatalogsInTableDefinitions) + assert(!metaData.supportsCatalogsInIndexDefinitions) + assert(!metaData.supportsCatalogsInPrivilegeDefinitions) + assert(!metaData.supportsPositionedDelete) + assert(!metaData.supportsPositionedUpdate) + assert(!metaData.supportsSelectForUpdate) + assert(!metaData.supportsStoredProcedures) + // This is actually supported, but hive jdbc package return false + assert(!metaData.supportsUnion) + assert(metaData.supportsUnionAll) + assert(metaData.getMaxColumnNameLength === 128) + assert(metaData.getDefaultTransactionIsolation === java.sql.Connection.TRANSACTION_NONE) + assert(!metaData.supportsTransactions) + assert(!metaData.getProcedureColumns("", "%", "%", "%").next()) + intercept[HiveSQLException](metaData.getPrimaryKeys("", "default", "")) + assert(!metaData.getImportedKeys("", "default", "").next()) + intercept[HiveSQLException] { + metaData.getCrossReference("", "default", "src", "", "default", "src2") + } + assert(!metaData.getIndexInfo("", "default", "src", true, true).next()) + + assert(metaData.supportsResultSetType(new Random().nextInt())) + assert(!metaData.supportsBatchUpdates) + assert(!metaData.getUDTs(",", "%", "%", null).next()) + assert(!metaData.supportsSavepoints) + assert(!metaData.supportsResultSetHoldability(ResultSet.HOLD_CURSORS_OVER_COMMIT)) + assert(metaData.getJDBCMajorVersion === 3) + assert(metaData.getJDBCMinorVersion === 0) + assert(metaData.getSQLStateType === DatabaseMetaData.sqlStateSQL) + assert(metaData.getMaxLogicalLobSize === 0) + assert(!metaData.supportsRefCursors) + } + } } diff --git a/kyuubi-common/src/main/scala/org/apache/kyuubi/Utils.scala b/kyuubi-common/src/main/scala/org/apache/kyuubi/Utils.scala index e3b839547..8a346bd82 100644 --- a/kyuubi-common/src/main/scala/org/apache/kyuubi/Utils.scala +++ b/kyuubi-common/src/main/scala/org/apache/kyuubi/Utils.scala @@ -106,4 +106,47 @@ private[kyuubi] object Utils extends Logging { } def currentUser: String = UserGroupInformation.getCurrentUser.getShortUserName + + private val majorMinorRegex = """^(\d+)\.(\d+)(\..*)?$""".r + private val shortVersionRegex = """^(\d+\.\d+\.\d+)(.*)?$""".r + + /** + * Given a Kyuubi/Spark/Hive version string, return the major version number. + * E.g., for 2.0.1-SNAPSHOT, return 2. + */ + def majorVersion(version: String): Int = majorMinorVersion(version)._1 + + /** + * Given a Kyuubi/Spark/Hive version string, return the minor version number. + * E.g., for 2.0.1-SNAPSHOT, return 0. + */ + def minorVersion(version: String): Int = majorMinorVersion(version)._2 + + /** + * Given a Kyuubi/Spark/Hive version string, return the short version string. + * E.g., for 3.0.0-SNAPSHOT, return '3.0.0'. + */ + def shortVersion(version: String): String = { + shortVersionRegex.findFirstMatchIn(version) match { + case Some(m) => m.group(1) + case None => + throw new IllegalArgumentException(s"Tried to parse '$version' as a project" + + s" version string, but it could not find the major/minor/maintenance version numbers.") + } + } + + /** + * Given a Kyuubi/Spark/Hive version string, + * return the (major version number, minor version number). + * E.g., for 2.0.1-SNAPSHOT, return (2, 0). + */ + def majorMinorVersion(version: String): (Int, Int) = { + majorMinorRegex.findFirstMatchIn(version) match { + case Some(m) => + (m.group(1).toInt, m.group(2).toInt) + case None => + throw new IllegalArgumentException(s"Tried to parse '$version' as a project" + + s" version string, but it could not find the major and minor version numbers.") + } + } } diff --git a/kyuubi-common/src/main/scala/org/apache/kyuubi/config/ConfigProvider.scala b/kyuubi-common/src/main/scala/org/apache/kyuubi/config/ConfigProvider.scala index 391c1d8d9..e11a9db75 100644 --- a/kyuubi-common/src/main/scala/org/apache/kyuubi/config/ConfigProvider.scala +++ b/kyuubi-common/src/main/scala/org/apache/kyuubi/config/ConfigProvider.scala @@ -20,7 +20,7 @@ package org.apache.kyuubi.config private[kyuubi] class ConfigProvider(conf: java.util.Map[String, String]) { def get(key: String): Option[String] = { - if (key.startsWith(KYUUBI_PREFIX)) { + if (key.startsWith("kyuubi.")) { Option(conf.get(key)) } else { None diff --git a/kyuubi-common/src/main/scala/org/apache/kyuubi/config/KyuubiConf.scala b/kyuubi-common/src/main/scala/org/apache/kyuubi/config/KyuubiConf.scala index b27cb1cbb..cbb960820 100644 --- a/kyuubi-common/src/main/scala/org/apache/kyuubi/config/KyuubiConf.scala +++ b/kyuubi-common/src/main/scala/org/apache/kyuubi/config/KyuubiConf.scala @@ -33,7 +33,7 @@ case class KyuubiConf(loadSysDefault: Boolean = true) extends Logging { } private def loadFromMap(props: Map[String, String] = Utils.getSystemProperties): KyuubiConf = { - for ((key, value) <- props if key.startsWith(KYUUBI_PREFIX)) { + for ((key, value) <- props if key.startsWith("kyuubi.")) { set(key, value) } this @@ -110,7 +110,9 @@ case class KyuubiConf(loadSysDefault: Boolean = true) extends Logging { } def toSparkPrefixedConf: Map[String, String] = { - settings.entrySet().asScala.map { e => SPARK_PREFIX + e.getKey -> e.getValue}.toMap + settings.entrySet().asScala.map { e => + "spark." + e.getKey -> e.getValue + }.toMap } } @@ -132,7 +134,7 @@ object KyuubiConf { } def buildConf(key: String): ConfigBuilder = { - new ConfigBuilder(KYUUBI_PREFIX + key).onCreate(register) + new ConfigBuilder("kyuubi." + key).onCreate(register) } val EMBEDDED_ZK_PORT: ConfigEntry[Int] = buildConf("embedded.zookeeper.port") diff --git a/kyuubi-common/src/main/scala/org/apache/kyuubi/config/package.scala b/kyuubi-common/src/main/scala/org/apache/kyuubi/config/package.scala deleted file mode 100644 index 2eaf6d98c..000000000 --- a/kyuubi-common/src/main/scala/org/apache/kyuubi/config/package.scala +++ /dev/null @@ -1,23 +0,0 @@ -/* - * 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 - -package object config { - final val KYUUBI_PREFIX = "kyuubi." - final val SPARK_PREFIX = "spark." -} diff --git a/kyuubi-common/src/main/scala/org/apache/kyuubi/operation/meta/ResultSetSchemaConstant.scala b/kyuubi-common/src/main/scala/org/apache/kyuubi/operation/meta/ResultSetSchemaConstant.scala index ceb999751..88f628e50 100644 --- a/kyuubi-common/src/main/scala/org/apache/kyuubi/operation/meta/ResultSetSchemaConstant.scala +++ b/kyuubi-common/src/main/scala/org/apache/kyuubi/operation/meta/ResultSetSchemaConstant.scala @@ -24,6 +24,11 @@ object ResultSetSchemaConstant { * Catalog name. NULL if not applicable */ final val TABLE_CAT = "TABLE_CAT" + + /** + * String type. + * Catalog name. NULL if not applicable + */ final val TABLE_CATALOG = "TABLE_CATALOG" /** @@ -37,16 +42,52 @@ object ResultSetSchemaConstant { * Table Name */ final val TABLE_NAME = "TABLE_NAME" + + /** + * String + * table type. Typical types are "TABLE", "VIEW", ... + */ final val TABLE_TYPE = "TABLE_TYPE" + /** + * String => explanatory comment on the table + */ final val REMARKS = "REMARKS" + /** + * String => column name + */ final val COLUMN_NAME = "COLUMN_NAME" + + /** + * int => SQL type from [[java.sql.Types]] + */ final val DATA_TYPE = "DATA_TYPE" + + /** + * String => Data source dependent type name, for a UDT the type name is fully qualified + */ final val TYPE_NAME = "TYPE_NAME" + + /** + * int => column size + */ final val COLUMN_SIZE = "COLUMN_SIZE" + + /** + * is not used. + */ final val BUFFER_LENGTH = "BUFFER_LENGTH" + + /** + * int => the number of fractional digits. + * Null is returned for data types where DECIMAL_DIGITS is not applicable. + */ final val DECIMAL_DIGITS = "DECIMAL_DIGITS" + + /** + * int => Radix (typically either 10 or 2) + */ final val NUM_PREC_RADIX = "NUM_PREC_RADIX" /** @@ -54,11 +95,38 @@ object ResultSetSchemaConstant { * Can you use NULL for this type? */ final val NULLABLE = "NULLABLE" + + /** + * String => default value for the column, which should be interpreted as a string when the value + * is enclosed in single quotes (may be null) + */ final val COLUMN_DEF = "COLUMN_DEF" + + /** + * is not used. + */ final val SQL_DATA_TYPE = "SQL_DATA_TYPE" + + /** + * is not used. + */ final val SQL_DATETIME_SUB = "SQL_DATETIME_SUB" + + /** + * int => for char types the maximum number of bytes in the column + */ final val CHAR_OCTET_LENGTH = "CHAR_OCTET_LENGTH" + + /** + * int => index of column in table (starting at 1) + */ final val ORDINAL_POSITION = "ORDINAL_POSITION" + /** + * String => ISO rules are used to determine the nullability for a column. + * - YES --- if the column can include NULLs + * - NO --- if the column cannot include NULLs + * - empty string --- if the nullability for the column is unknown + */ final val IS_NULLABLE = "IS_NULLABLE" final val SCOPE_CATALOG = "SCOPE_CATALOG" final val SCOPE_SCHEMA = "SCOPE_SCHEMA" @@ -83,9 +151,33 @@ object ResultSetSchemaConstant { */ final val SEARCHABLE = "SEARCHABLE" + /** + * String => function catalog (may be null) + */ final val FUNCTION_CAT = "FUNCTION_CAT" + + /** + * String => function schema (may be null) + */ final val FUNCTION_SCHEM = "FUNCTION_SCHEM" + + /** + * String => function name. This is the name used to invoke the function + */ final val FUNCTION_NAME = "FUNCTION_NAME" + + /** + * short => kind of function: + * - functionResultUnknown - Cannot determine if a return value or table will be returned + * - functionNoTable- Does not return a table + * - functionReturnsTable - Returns a table + */ final val FUNCTION_TYPE = "FUNCTION_TYPE" + + /** + * String => the name which uniquely identifies this function within its schema. + * This is a user specified, or DBMS generated, name that may be different then the FUNCTION_NAME + * for example with overload functions + */ final val SPECIFIC_NAME = "SPECIFIC_NAME" } diff --git a/kyuubi-common/src/test/scala/org/apache/kyuubi/UtilsSuite.scala b/kyuubi-common/src/test/scala/org/apache/kyuubi/UtilsSuite.scala index 6110b69e8..4dbf25f95 100644 --- a/kyuubi-common/src/test/scala/org/apache/kyuubi/UtilsSuite.scala +++ b/kyuubi-common/src/test/scala/org/apache/kyuubi/UtilsSuite.scala @@ -108,4 +108,17 @@ class UtilsSuite extends KyuubiFunSuite { } ) } + + test("version test") { + assert(Utils.majorVersion(KYUUBI_VERSION) === + Utils.majorMinorVersion(KYUUBI_VERSION)._1) + assert(Utils.majorVersion(SPARK_COMPILE_VERSION) === + Utils.majorMinorVersion(SPARK_COMPILE_VERSION)._1) + assert(Utils.majorVersion(HADOOP_COMPILE_VERSION) === + Utils.majorMinorVersion(HADOOP_COMPILE_VERSION)._1) + assert(Utils.minorVersion(KYUUBI_VERSION) === + Utils.majorMinorVersion(KYUUBI_VERSION)._2) + assert(Utils.shortVersion(KYUUBI_VERSION) === + KYUUBI_VERSION.stripSuffix("-SNAPSHOT")) + } } diff --git a/kyuubi-common/src/test/scala/org/apache/kyuubi/config/ConfigProviderSuite.scala b/kyuubi-common/src/test/scala/org/apache/kyuubi/config/ConfigProviderSuite.scala index 30593591a..84148df74 100644 --- a/kyuubi-common/src/test/scala/org/apache/kyuubi/config/ConfigProviderSuite.scala +++ b/kyuubi-common/src/test/scala/org/apache/kyuubi/config/ConfigProviderSuite.scala @@ -29,7 +29,5 @@ class ConfigProviderSuite extends KyuubiFunSuite { assert(provider.get("kyuubi.abc").get === "1") assert(provider.get("kyuubi.xyz").get === "2") assert(provider.get("spark.abc") === None) - } - }