You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@kyuubi.apache.org by ul...@apache.org on 2023/01/05 11:10:33 UTC

[kyuubi] branch master updated: [KYUUBI #4080] Support GetTables for Trino Fe

This is an automated email from the ASF dual-hosted git repository.

ulyssesyou pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/kyuubi.git


The following commit(s) were added to refs/heads/master by this push:
     new bed47ce71 [KYUUBI #4080] Support GetTables for Trino Fe
bed47ce71 is described below

commit bed47ce7176cf8b5622925ff8854e48d6f92673b
Author: Yikf <yi...@gmail.com>
AuthorDate: Thu Jan 5 19:10:21 2023 +0800

    [KYUUBI #4080] Support GetTables for Trino Fe
    
    ### _Why are the changes needed?_
    
    Close https://github.com/apache/kyuubi/issues/4080, This pr aims to support `GetTables` for Trino Fe
    
    ### _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.apache.org/docs/latest/develop_tools/testing.html#running-tests) locally before make a pull request
    
    Closes #4081 from Yikf/getTables.
    
    Closes #4080
    
    c00564e2 [Yikf] Support GetTables for Trino Fe
    
    Authored-by: Yikf <yi...@gmail.com>
    Signed-off-by: ulysses-you <ul...@apache.org>
---
 .../org/apache/kyuubi/sql/KyuubiSqlBaseLexer.g4    |  19 ++-
 .../apache/kyuubi/sql/KyuubiTrinoFeBaseParser.g4   |  38 +++++-
 .../trino/api/KyuubiTrinoOperationTranslator.scala |  13 +-
 .../sql/parser/trino/KyuubiTrinoFeAstBuilder.scala |  62 +++++++++-
 .../kyuubi/sql/plan/trino/TrinoFeOperations.scala  |   9 ++
 .../parser/trino/KyuubiTrinoFeParserSuite.scala    | 132 ++++++++++++++++++++-
 6 files changed, 258 insertions(+), 15 deletions(-)

diff --git a/kyuubi-server/src/main/antlr4/org/apache/kyuubi/sql/KyuubiSqlBaseLexer.g4 b/kyuubi-server/src/main/antlr4/org/apache/kyuubi/sql/KyuubiSqlBaseLexer.g4
index cdf0ce5e7..978b14703 100644
--- a/kyuubi-server/src/main/antlr4/org/apache/kyuubi/sql/KyuubiSqlBaseLexer.g4
+++ b/kyuubi-server/src/main/antlr4/org/apache/kyuubi/sql/KyuubiSqlBaseLexer.g4
@@ -59,12 +59,15 @@ GTE : '>=' | '!<';
 LEFT_PAREN: '(';
 RIGHT_PAREN: ')';
 OR: 'OR';
+SEARCH_STRING_ESCAPE: '\'' '\\' '\'';
 
 DESC: 'DESC';
 DESCRIBE: 'DESCRIBE';
 FROM: 'FROM';
-
+FALSE: 'FALSE';
 LIKE: 'LIKE';
+IN: 'IN';
+WHERE: 'WHERE';
 
 KYUUBI: 'KYUUBI';
 KYUUBIADMIN: 'KYUUBIADMIN';
@@ -73,16 +76,21 @@ AUTO_INCREMENT: 'AUTO_INCREMENT';
 CASE_SENSITIVE: 'CASE_SENSITIVE';
 CREATE_PARAMS: 'CREATE_PARAMS';
 DATA_TYPE: 'DATA_TYPE';
+ESCAPE: 'ESCAPE';
 FIXED_PREC_SCALE: 'FIXED_PREC_SCALE';
+IS: 'IS';
 LITERAL_PREFIX: 'LITERAL_PREFIX';
 LITERAL_SUFFIX: 'LITERAL_SUFFIX';
 LOCAL_TYPE_NAME: 'LOCAL_TYPE_NAME';
 MAXIMUM_SCALE: 'MAXIMUM_SCALE';
 MINIMUM_SCALE: 'MINIMUM_SCALE';
+NULL: 'NULL';
 NULLABLE: 'NULLABLE';
 NUM_PREC_RADIX: 'NUM_PREC_RADIX';
 ORDER: 'ORDER';
 PRECISION: 'PRECISION';
+REMARKS: 'REMARKS';
+REF_GENERATION: 'REF_GENERATION';
 SEARCHABLE: 'SEARCHABLE';
 SELECT: 'SELECT';
 SESSION: 'SESSION';
@@ -90,16 +98,19 @@ SQL_DATA_TYPE: 'SQL_DATA_TYPE';
 SQL_DATETIME_SUB: 'SQL_DATETIME_SUB';
 SYSTEM_JDBC_CATALOGS: 'SYSTEM.JDBC.CATALOGS';
 SYSTEM_JDBC_SCHEMAS: 'SYSTEM.JDBC.SCHEMAS';
+SYSTEM_JDBC_TABLES: 'SYSTEM.JDBC.TABLES';
 SYSTEM_JDBC_TABLE_TYPES: 'SYSTEM.JDBC.TABLE_TYPES';
 SYSTEM_JDBC_TYPES: 'SYSTEM.JDBC.TYPES';
+SELF_REFERENCING_COL_NAME: 'SELF_REFERENCING_COL_NAME';
 UNSIGNED_ATTRIBUTE: 'UNSIGNED_ATTRIBUTE';
 TABLE_CAT: 'TABLE_CAT';
 TABLE_CATALOG: 'TABLE_CATALOG';
+TABLE_NAME: 'TABLE_NAME';
 TABLE_SCHEM: 'TABLE_SCHEM';
 TABLE_TYPE: 'TABLE_TYPE';
+TYPE_CAT: 'TYPE_CAT';
 TYPE_NAME: 'TYPE_NAME';
-
-WHERE: 'WHERE';
+TYPE_SCHEM: 'TYPE_SCHEM';
 
 BACKQUOTED_IDENTIFIER
     : '`' ( ~'`' | '``' )* '`'
@@ -118,7 +129,7 @@ IDENTIFIER
     ;
 
 STRING
-    : '\'' ( ~('\''|'\\') | ('\\' .) )* '\''
+    : '\'' ( ~'\'' | '\'\'' )* '\''
     | 'R\'' (~'\'')* '\''
     | 'R"'(~'"')* '"'
     ;
diff --git a/kyuubi-server/src/main/antlr4/org/apache/kyuubi/sql/KyuubiTrinoFeBaseParser.g4 b/kyuubi-server/src/main/antlr4/org/apache/kyuubi/sql/KyuubiTrinoFeBaseParser.g4
index 7bf4c6656..304fabad9 100644
--- a/kyuubi-server/src/main/antlr4/org/apache/kyuubi/sql/KyuubiTrinoFeBaseParser.g4
+++ b/kyuubi-server/src/main/antlr4/org/apache/kyuubi/sql/KyuubiTrinoFeBaseParser.g4
@@ -26,13 +26,41 @@ singleStatement
 statement
     : SELECT TABLE_SCHEM COMMA TABLE_CATALOG FROM SYSTEM_JDBC_SCHEMAS
       (WHERE (TABLE_CATALOG EQ catalog=STRING+)? AND? (TABLE_SCHEM LIKE schema=STRING+)?)?
-      ORDER BY TABLE_CATALOG COMMA TABLE_SCHEM                                                #getSchemas
-    | SELECT TABLE_CAT FROM SYSTEM_JDBC_CATALOGS ORDER BY TABLE_CAT                           #getCatalogs
-    | SELECT TABLE_TYPE FROM SYSTEM_JDBC_TABLE_TYPES ORDER BY TABLE_TYPE                      #getTableTypes
+      ORDER BY TABLE_CATALOG COMMA TABLE_SCHEM                                                      #getSchemas
+    | SELECT TABLE_CAT FROM SYSTEM_JDBC_CATALOGS ORDER BY TABLE_CAT                                 #getCatalogs
+    | SELECT TABLE_TYPE FROM SYSTEM_JDBC_TABLE_TYPES ORDER BY TABLE_TYPE                            #getTableTypes
     | SELECT TYPE_NAME COMMA DATA_TYPE COMMA PRECISION COMMA LITERAL_PREFIX COMMA
       LITERAL_SUFFIX COMMA CREATE_PARAMS COMMA NULLABLE COMMA CASE_SENSITIVE COMMA
       SEARCHABLE COMMA UNSIGNED_ATTRIBUTE COMMA FIXED_PREC_SCALE COMMA AUTO_INCREMENT
       COMMA LOCAL_TYPE_NAME COMMA MINIMUM_SCALE COMMA MAXIMUM_SCALE COMMA SQL_DATA_TYPE
-      COMMA SQL_DATETIME_SUB COMMA NUM_PREC_RADIX FROM SYSTEM_JDBC_TYPES ORDER BY DATA_TYPE   #getTypeInfo
-    | .*?                                                                                     #passThrough
+      COMMA SQL_DATETIME_SUB COMMA NUM_PREC_RADIX FROM SYSTEM_JDBC_TYPES ORDER BY DATA_TYPE         #getTypeInfo
+    | SELECT TABLE_CAT COMMA TABLE_SCHEM COMMA TABLE_NAME COMMA TABLE_TYPE COMMA REMARKS COMMA
+      TYPE_CAT COMMA TYPE_SCHEM COMMA TYPE_NAME COMMA SELF_REFERENCING_COL_NAME COMMA REF_GENERATION
+      FROM SYSTEM_JDBC_TABLES
+      (WHERE tableCatalogFilter? AND? tableSchemaFilter? AND? tableNameFilter? AND? tableTypeFilter?)?
+      ORDER BY TABLE_TYPE COMMA TABLE_CAT COMMA TABLE_SCHEM COMMA TABLE_NAME                        #getTables
+    | .*?                                                                                           #passThrough
+    ;
+
+tableCatalogFilter
+    : TABLE_CAT IS NULL                                                                             #nullCatalog
+    | TABLE_CAT EQ catalog=STRING+                                                                  #catalogFilter
+    ;
+
+tableSchemaFilter
+    : TABLE_SCHEM IS NULL                                                                           #nulTableSchema
+    | TABLE_SCHEM LIKE schemaPattern=STRING+ ESCAPE SEARCH_STRING_ESCAPE                            #schemaFilter
+    ;
+
+tableNameFilter
+    : TABLE_NAME LIKE tableNamePattern=STRING+ ESCAPE SEARCH_STRING_ESCAPE
+    ;
+
+tableTypeFilter
+    : FALSE                                                                                         #tableTypesAlwaysFalse
+    | TABLE_TYPE IN '(' stirngInValue (',' stirngInValue)* ')'                                      #typesFilter
+    ;
+
+stirngInValue
+    : STRING+
     ;
diff --git a/kyuubi-server/src/main/scala/org/apache/kyuubi/server/trino/api/KyuubiTrinoOperationTranslator.scala b/kyuubi-server/src/main/scala/org/apache/kyuubi/server/trino/api/KyuubiTrinoOperationTranslator.scala
index 15608d6c2..5e8460883 100644
--- a/kyuubi-server/src/main/scala/org/apache/kyuubi/server/trino/api/KyuubiTrinoOperationTranslator.scala
+++ b/kyuubi-server/src/main/scala/org/apache/kyuubi/server/trino/api/KyuubiTrinoOperationTranslator.scala
@@ -17,13 +17,15 @@
 
 package org.apache.kyuubi.server.trino.api
 
+import scala.collection.JavaConverters._
+
 import org.apache.hive.service.rpc.thrift.TProtocolVersion
 
 import org.apache.kyuubi.operation.OperationHandle
 import org.apache.kyuubi.service.BackendService
 import org.apache.kyuubi.sql.parser.trino.KyuubiTrinoFeParser
 import org.apache.kyuubi.sql.plan.PassThroughNode
-import org.apache.kyuubi.sql.plan.trino.{GetCatalogs, GetSchemas, GetTableTypes, GetTypeInfo}
+import org.apache.kyuubi.sql.plan.trino.{GetCatalogs, GetSchemas, GetTables, GetTableTypes, GetTypeInfo}
 
 class KyuubiTrinoOperationTranslator(backendService: BackendService) {
   lazy val parser = new KyuubiTrinoFeParser()
@@ -50,6 +52,15 @@ class KyuubiTrinoOperationTranslator(backendService: BackendService) {
         backendService.getTableTypes(sessionHandle)
       case GetTypeInfo() =>
         backendService.getTypeInfo(sessionHandle)
+      case GetTables(catalogName, schemaPattern, tableNamePattern, tableTypes, emptyResult) =>
+        val operationHandle = backendService.getTables(
+          sessionHandle,
+          catalogName,
+          schemaPattern,
+          tableNamePattern,
+          tableTypes.asJava)
+        operationHandle.setHasResultSet(!emptyResult)
+        operationHandle
       case PassThroughNode() =>
         backendService.executeStatement(sessionHandle, statement, configs, runAsync, queryTimeout)
     }
diff --git a/kyuubi-server/src/main/scala/org/apache/kyuubi/sql/parser/trino/KyuubiTrinoFeAstBuilder.scala b/kyuubi-server/src/main/scala/org/apache/kyuubi/sql/parser/trino/KyuubiTrinoFeAstBuilder.scala
index 86df35bc5..a257ee0c6 100644
--- a/kyuubi-server/src/main/scala/org/apache/kyuubi/sql/parser/trino/KyuubiTrinoFeAstBuilder.scala
+++ b/kyuubi-server/src/main/scala/org/apache/kyuubi/sql/parser/trino/KyuubiTrinoFeAstBuilder.scala
@@ -17,14 +17,25 @@
 
 package org.apache.kyuubi.sql.parser.trino
 
+import scala.collection.JavaConverters._
+
+import org.antlr.v4.runtime.tree.ParseTree
+
 import org.apache.kyuubi.sql.KyuubiTrinoFeBaseParser._
 import org.apache.kyuubi.sql.KyuubiTrinoFeBaseParserBaseVisitor
-import org.apache.kyuubi.sql.parser.KyuubiParser
+import org.apache.kyuubi.sql.parser.KyuubiParser.unescapeSQLString
 import org.apache.kyuubi.sql.plan.{KyuubiTreeNode, PassThroughNode}
-import org.apache.kyuubi.sql.plan.trino.{GetCatalogs, GetSchemas, GetTableTypes, GetTypeInfo}
+import org.apache.kyuubi.sql.plan.trino.{GetCatalogs, GetSchemas, GetTables, GetTableTypes, GetTypeInfo}
 
 class KyuubiTrinoFeAstBuilder extends KyuubiTrinoFeBaseParserBaseVisitor[AnyRef] {
 
+  override def visit(tree: ParseTree): AnyRef = {
+    Option(tree) match {
+      case Some(_) => super.visit(tree)
+      case _ => null
+    }
+
+  }
   override def visitSingleStatement(
       ctx: SingleStatementContext): KyuubiTreeNode = {
     visit(ctx.statement).asInstanceOf[KyuubiTreeNode]
@@ -38,12 +49,12 @@ class KyuubiTrinoFeAstBuilder extends KyuubiTrinoFeBaseParserBaseVisitor[AnyRef]
     val catalog = if (ctx.catalog == null) {
       null
     } else {
-      KyuubiParser.unescapeSQLString(ctx.catalog.getText)
+      unescapeSQLString(ctx.catalog.getText)
     }
     val schema = if (ctx.schema == null) {
       null
     } else {
-      KyuubiParser.unescapeSQLString(ctx.schema.getText)
+      unescapeSQLString(ctx.schema.getText)
     }
 
     GetSchemas(catalog, schema)
@@ -60,4 +71,47 @@ class KyuubiTrinoFeAstBuilder extends KyuubiTrinoFeBaseParserBaseVisitor[AnyRef]
   override def visitGetTypeInfo(ctx: GetTypeInfoContext): KyuubiTreeNode = {
     GetTypeInfo()
   }
+
+  override def visitGetTables(ctx: GetTablesContext): KyuubiTreeNode = {
+    val catalog = visit(ctx.tableCatalogFilter()).asInstanceOf[String]
+    val schemaPattern = visit(ctx.tableSchemaFilter()).asInstanceOf[String]
+    val tableNamePattern = visit(ctx.tableNameFilter()).asInstanceOf[String]
+
+    var emptyResult = false
+    var tableTypes: List[String] = null
+
+    ctx.tableTypeFilter() match {
+      case _: TableTypesAlwaysFalseContext =>
+        emptyResult = true
+      case typesFilter: TypesFilterContext =>
+        tableTypes = visitTypesFilter(typesFilter)
+      case _ => // ctx.tableTypeFilter is null.
+    }
+
+    GetTables(catalog, schemaPattern, tableNamePattern, tableTypes, emptyResult)
+  }
+
+  override def visitNullCatalog(ctx: NullCatalogContext): AnyRef = {
+    null
+  }
+
+  override def visitCatalogFilter(ctx: CatalogFilterContext): String = {
+    unescapeSQLString(ctx.catalog.getText)
+  }
+
+  override def visitNulTableSchema(ctx: NulTableSchemaContext): AnyRef = {
+    null
+  }
+
+  override def visitSchemaFilter(ctx: SchemaFilterContext): String = {
+    unescapeSQLString(ctx.schemaPattern.getText)
+  }
+
+  override def visitTableNameFilter(ctx: TableNameFilterContext): String = {
+    unescapeSQLString(ctx.tableNamePattern.getText)
+  }
+
+  override def visitTypesFilter(ctx: TypesFilterContext): List[String] = {
+    ctx.stirngInValue().asScala.map(v => unescapeSQLString(v.getText)).toList
+  }
 }
diff --git a/kyuubi-server/src/main/scala/org/apache/kyuubi/sql/plan/trino/TrinoFeOperations.scala b/kyuubi-server/src/main/scala/org/apache/kyuubi/sql/plan/trino/TrinoFeOperations.scala
index a1841bcaa..60a4abd7d 100644
--- a/kyuubi-server/src/main/scala/org/apache/kyuubi/sql/plan/trino/TrinoFeOperations.scala
+++ b/kyuubi-server/src/main/scala/org/apache/kyuubi/sql/plan/trino/TrinoFeOperations.scala
@@ -38,3 +38,12 @@ case class GetTableTypes() extends KyuubiTreeNode {
 case class GetTypeInfo() extends KyuubiTreeNode {
   override def name(): String = "Get Type Info"
 }
+
+case class GetTables(
+    catalogName: String,
+    schemaPattern: String,
+    tableNamePattern: String,
+    tableTypes: List[String],
+    emptyResult: Boolean = false) extends KyuubiTreeNode {
+  override def name(): String = "Get Tables"
+}
diff --git a/kyuubi-server/src/test/scala/org/apache/kyuubi/parser/trino/KyuubiTrinoFeParserSuite.scala b/kyuubi-server/src/test/scala/org/apache/kyuubi/parser/trino/KyuubiTrinoFeParserSuite.scala
index 333f5a0d8..c57a12228 100644
--- a/kyuubi-server/src/test/scala/org/apache/kyuubi/parser/trino/KyuubiTrinoFeParserSuite.scala
+++ b/kyuubi-server/src/test/scala/org/apache/kyuubi/parser/trino/KyuubiTrinoFeParserSuite.scala
@@ -20,7 +20,7 @@ package org.apache.kyuubi.parser.trino
 import org.apache.kyuubi.KyuubiFunSuite
 import org.apache.kyuubi.sql.parser.trino.KyuubiTrinoFeParser
 import org.apache.kyuubi.sql.plan.{KyuubiTreeNode, PassThroughNode}
-import org.apache.kyuubi.sql.plan.trino.{GetCatalogs, GetSchemas, GetTableTypes, GetTypeInfo}
+import org.apache.kyuubi.sql.plan.trino.{GetCatalogs, GetSchemas, GetTables, GetTableTypes, GetTypeInfo}
 
 class KyuubiTrinoFeParserSuite extends KyuubiFunSuite {
   val parser = new KyuubiTrinoFeParser()
@@ -108,4 +108,134 @@ class KyuubiTrinoFeParserSuite extends KyuubiFunSuite {
 
     assert(kyuubiTreeNode.isInstanceOf[GetTypeInfo])
   }
+
+  test("Support GetTables for Trino Fe") {
+    def check(
+        query: String,
+        catalog: String = null,
+        schema: String = null,
+        tableName: String = null,
+        types: List[String] = null,
+        emptyRes: Boolean = false): Unit = {
+      parse(query) match {
+        case GetTables(catalogName, schemaPattern, tableNamePattern, tableTypes, emptyResult) =>
+          assert(catalog == catalogName)
+          assert(schema == schemaPattern)
+          assert(tableName == tableNamePattern)
+          assert(types == tableTypes)
+          assert(emptyRes == emptyResult)
+        case _ => fail(s"Query $query parse failed. ")
+      }
+    }
+
+    check(
+      """
+        | SELECT TABLE_CAT, TABLE_SCHEM, TABLE_NAME, TABLE_TYPE, REMARKS,
+        | TYPE_CAT, TYPE_SCHEM, TYPE_NAME,
+        | SELF_REFERENCING_COL_NAME, REF_GENERATION
+        | FROM system.jdbc.tables
+        | ORDER BY TABLE_TYPE, TABLE_CAT, TABLE_SCHEM, TABLE_NAME
+        |""".stripMargin)
+
+    check(
+      """
+        | SELECT TABLE_CAT, TABLE_SCHEM, TABLE_NAME, TABLE_TYPE, REMARKS,
+        | TYPE_CAT, TYPE_SCHEM, TYPE_NAME,
+        | SELF_REFERENCING_COL_NAME, REF_GENERATION
+        | FROM system.jdbc.tables
+        | WHERE TABLE_CAT IS NULL
+        | ORDER BY TABLE_TYPE, TABLE_CAT, TABLE_SCHEM, TABLE_NAME
+        |""".stripMargin)
+
+    check(
+      """
+        | SELECT TABLE_CAT, TABLE_SCHEM, TABLE_NAME, TABLE_TYPE, REMARKS,
+        | TYPE_CAT, TYPE_SCHEM, TYPE_NAME,
+        | SELF_REFERENCING_COL_NAME, REF_GENERATION
+        | FROM system.jdbc.tables
+        | WHERE TABLE_CAT = 'ykf_catalog'
+        | ORDER BY TABLE_TYPE, TABLE_CAT, TABLE_SCHEM, TABLE_NAME
+        |""".stripMargin,
+      catalog = "ykf_catalog")
+
+    check(
+      """
+        | SELECT TABLE_CAT, TABLE_SCHEM, TABLE_NAME, TABLE_TYPE, REMARKS,
+        | TYPE_CAT, TYPE_SCHEM, TYPE_NAME,
+        | SELF_REFERENCING_COL_NAME, REF_GENERATION
+        | FROM system.jdbc.tables
+        | WHERE TABLE_CAT = 'ykf_catalog' AND TABLE_SCHEM IS NULL
+        | ORDER BY TABLE_TYPE, TABLE_CAT, TABLE_SCHEM, TABLE_NAME
+        |""".stripMargin,
+      catalog = "ykf_catalog")
+
+    check(
+      """
+        | SELECT TABLE_CAT, TABLE_SCHEM, TABLE_NAME, TABLE_TYPE, REMARKS,
+        | TYPE_CAT, TYPE_SCHEM, TYPE_NAME,
+        | SELF_REFERENCING_COL_NAME, REF_GENERATION
+        | FROM system.jdbc.tables
+        | WHERE TABLE_CAT = 'ykf_catalog' AND TABLE_SCHEM LIKE '%aa' ESCAPE '\'
+        | ORDER BY TABLE_TYPE, TABLE_CAT, TABLE_SCHEM, TABLE_NAME
+        |""".stripMargin,
+      catalog = "ykf_catalog",
+      "%aa")
+
+    check(
+      """
+        | SELECT TABLE_CAT, TABLE_SCHEM, TABLE_NAME, TABLE_TYPE, REMARKS,
+        | TYPE_CAT, TYPE_SCHEM, TYPE_NAME,
+        | SELF_REFERENCING_COL_NAME, REF_GENERATION
+        | FROM system.jdbc.tables
+        | WHERE TABLE_CAT = 'ykf_catalog' AND TABLE_NAME LIKE '%aa' ESCAPE '\'
+        | ORDER BY TABLE_TYPE, TABLE_CAT, TABLE_SCHEM, TABLE_NAME
+        |""".stripMargin,
+      catalog = "ykf_catalog",
+      tableName = "%aa")
+
+    check(
+      """
+        | SELECT TABLE_CAT, TABLE_SCHEM, TABLE_NAME, TABLE_TYPE, REMARKS,
+        | TYPE_CAT, TYPE_SCHEM, TYPE_NAME,
+        | SELF_REFERENCING_COL_NAME, REF_GENERATION
+        | FROM system.jdbc.tables
+        | WHERE TABLE_CAT = 'ykf_catalog' AND TABLE_NAME LIKE '%aa' ESCAPE '\' AND FALSE
+        | ORDER BY TABLE_TYPE, TABLE_CAT, TABLE_SCHEM, TABLE_NAME
+        |""".stripMargin,
+      catalog = "ykf_catalog",
+      tableName = "%aa",
+      emptyRes = true)
+
+    check(
+      """
+        | SELECT TABLE_CAT, TABLE_SCHEM, TABLE_NAME, TABLE_TYPE, REMARKS,
+        | TYPE_CAT, TYPE_SCHEM, TYPE_NAME,
+        | SELF_REFERENCING_COL_NAME, REF_GENERATION
+        | FROM system.jdbc.tables
+        | WHERE TABLE_CAT = 'ykf_catalog' AND TABLE_SCHEM LIKE '%aa' ESCAPE '\' AND
+        | TABLE_TYPE IN ('ykf_type', 'ykf2_type')
+        | ORDER BY TABLE_TYPE, TABLE_CAT, TABLE_SCHEM, TABLE_NAME
+        |""".stripMargin,
+      catalog = "ykf_catalog",
+      schema = "%aa",
+      types = List("ykf_type", "ykf2_type"))
+
+    check(
+      """
+        | SELECT TABLE_CAT, TABLE_SCHEM, TABLE_NAME, TABLE_TYPE, REMARKS,
+        | TYPE_CAT, TYPE_SCHEM, TYPE_NAME,
+        | SELF_REFERENCING_COL_NAME, REF_GENERATION
+        | FROM system.jdbc.tables
+        | WHERE
+        | TABLE_CAT = 'ykf_catalog' AND
+        | TABLE_SCHEM LIKE '%aa' ESCAPE '\' AND
+        | TABLE_NAME LIKE 'bb%' ESCAPE '\' AND
+        | TABLE_TYPE IN ('ykf_type', 'ykf2_type')
+        | ORDER BY TABLE_TYPE, TABLE_CAT, TABLE_SCHEM, TABLE_NAME
+        |""".stripMargin,
+      catalog = "ykf_catalog",
+      schema = "%aa",
+      tableName = "bb%",
+      types = List("ykf_type", "ykf2_type"))
+  }
 }