From 667b5ab6b82f1188d53b37e2fa1d86faf4f49e21 Mon Sep 17 00:00:00 2001 From: yikaifei Date: Mon, 18 Dec 2023 21:36:54 +0800 Subject: [PATCH] [KYUUBI #5865] Support get SQL keywords from Hive engine through API MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit # :mag: Description ## Issue References ๐Ÿ”— This pull request implement the https://github.com/apache/kyuubi/issues/5865, it support get SQL keywords from Hive engine through API. ## Describe Your Solution ๐Ÿ”ง Please include a summary of the change and which issue is fixed. Please also include relevant motivation and context. List any dependencies that are required for this change. ## Types of changes :bookmark: - [ ] Bugfix (non-breaking change which fixes an issue) - [x] 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 :coffin: #### Behavior With This Pull Request :tada: #### Related Unit Tests --- # Checklists ## ๐Ÿ“ Author Self Checklist - [x] My code follows the [style guidelines](https://kyuubi.readthedocs.io/en/master/contributing/code/style.html) of this project - [x] I have performed a self-review - [ ] I have commented my code, particularly in hard-to-understand areas - [ ] I have made corresponding changes to the documentation - [ ] My changes generate no new warnings - [ ] I have added tests that prove my fix is effective or that my feature works - [ ] New and existing unit tests pass locally with my changes - [x] This patch was not authored or co-authored using [Generative Tooling](https://www.apache.org/legal/generative-tooling.html) ## ๐Ÿ“ Committer Pre-Merge Checklist - [x] Pull request title is okay. - [x] No license issues. - [x] Milestone correctly set? - [x] Test coverage is ok - [x] Assignees are selected. - [x] Minimum number of approvals - [x] No changes are requested **Be nice. Be informative.** Closes #5866 from Yikf/hive-keywords. Closes #5865 e54945d94 [yikaifei] Hive engine CLI_ODBC_KEYWORDS Authored-by: yikaifei Signed-off-by: Cheng Pan --- .../engine/hive/session/HiveSessionImpl.scala | 18 +++++++++++++++++- ...KyuubiOperationHiveEnginePerUserSuite.scala | 14 ++++++++++++++ 2 files changed, 31 insertions(+), 1 deletion(-) diff --git a/externals/kyuubi-hive-sql-engine/src/main/scala/org/apache/kyuubi/engine/hive/session/HiveSessionImpl.scala b/externals/kyuubi-hive-sql-engine/src/main/scala/org/apache/kyuubi/engine/hive/session/HiveSessionImpl.scala index 6d1185c70..91db1cb8d 100644 --- a/externals/kyuubi-hive-sql-engine/src/main/scala/org/apache/kyuubi/engine/hive/session/HiveSessionImpl.scala +++ b/externals/kyuubi-hive-sql-engine/src/main/scala/org/apache/kyuubi/engine/hive/session/HiveSessionImpl.scala @@ -31,6 +31,7 @@ import org.apache.kyuubi.events.EventBus import org.apache.kyuubi.operation.{Operation, OperationHandle} import org.apache.kyuubi.session.{AbstractSession, SessionHandle, SessionManager} import org.apache.kyuubi.shaded.hive.service.rpc.thrift.{TGetInfoType, TGetInfoValue, TProtocolVersion} +import org.apache.kyuubi.util.reflect.{DynFields, DynMethods} class HiveSessionImpl( protocol: TProtocolVersion, @@ -63,7 +64,22 @@ class HiveSessionImpl( case TGetInfoType.CLI_SERVER_NAME => TGetInfoValue.stringValue("Hive") case TGetInfoType.CLI_DBMS_NAME => TGetInfoValue.stringValue("Apache Hive") case TGetInfoType.CLI_DBMS_VER => TGetInfoValue.stringValue(HiveVersionInfo.getVersion) - case TGetInfoType.CLI_ODBC_KEYWORDS => TGetInfoValue.stringValue("Unimplemented") + case TGetInfoType.CLI_ODBC_KEYWORDS => + try { + // HIVE-17765 expose Hive keywords. + // exclude these keywords to be consistent with Hive behavior. + val excludes = DynFields.builder() + .hiddenImpl("org.apache.hive.service.cli.session.HiveSessionImpl", "ODBC_KEYWORDS") + .buildStaticChecked[util.Set[String]]().get() + val keywords = DynMethods.builder("getKeywords") + .impl("org.apache.hadoop.hive.ql.parse.ParseUtils", classOf[util.Set[String]]) + .buildStaticChecked() + .invoke[String](excludes) + TGetInfoValue.stringValue(keywords) + } catch { + case _: ReflectiveOperationException => + TGetInfoValue.stringValue("Unimplemented") + } case TGetInfoType.CLI_MAX_COLUMN_NAME_LEN | TGetInfoType.CLI_MAX_SCHEMA_NAME_LEN | TGetInfoType.CLI_MAX_TABLE_NAME_LEN => TGetInfoValue.lenValue(128) diff --git a/integration-tests/kyuubi-hive-it/src/test/scala/org/apache/kyuubi/it/hive/operation/KyuubiOperationHiveEnginePerUserSuite.scala b/integration-tests/kyuubi-hive-it/src/test/scala/org/apache/kyuubi/it/hive/operation/KyuubiOperationHiveEnginePerUserSuite.scala index 3f9465b37..fd9e76bc3 100644 --- a/integration-tests/kyuubi-hive-it/src/test/scala/org/apache/kyuubi/it/hive/operation/KyuubiOperationHiveEnginePerUserSuite.scala +++ b/integration-tests/kyuubi-hive-it/src/test/scala/org/apache/kyuubi/it/hive/operation/KyuubiOperationHiveEnginePerUserSuite.scala @@ -61,6 +61,20 @@ class KyuubiOperationHiveEnginePerUserSuite extends WithKyuubiServer with HiveEn } } + test("[KYUUBI #5865] Hive engine CLI_ODBC_KEYWORDS") { + withSessionConf(Map(KyuubiConf.SERVER_INFO_PROVIDER.key -> "ENGINE"))()() { + withSessionHandle { (client, handle) => + val req = new TGetInfoReq() + req.setSessionHandle(handle) + req.setInfoType(TGetInfoType.CLI_ODBC_KEYWORDS) + val value = client.GetInfo(req).getInfoValue.getStringValue + assert(value.contains("DATABASE") || value === "Unimplemented") + // excluded keywords + assert(!value.contains("ADD")) + } + } + } + test("kyuubi defined function - system_user, session_user") { withJdbcStatement("hive_engine_test") { statement => val rs = statement.executeQuery("SELECT system_user(), session_user()")