You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@spark.apache.org by we...@apache.org on 2025/03/26 07:00:38 UTC

(spark) branch master updated: [SPARK-51350][SQL] Implement Show Procedures

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

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


The following commit(s) were added to refs/heads/master by this push:
     new 100d4a0ce5e3 [SPARK-51350][SQL] Implement Show Procedures
100d4a0ce5e3 is described below

commit 100d4a0ce5e37ddfea6ea64197c77906850b8d62
Author: Szehon Ho <sz...@gmail.com>
AuthorDate: Wed Mar 26 15:00:22 2025 +0800

    [SPARK-51350][SQL] Implement Show Procedures
    
    ### What changes were proposed in this pull request?
    Implement Show Procedures
    
    ### Why are the changes needed?
    Following SPARK-44167, we want to be able to list stored procedures of a given catalog.
    
    ### Does this PR introduce _any_ user-facing change?
    Adds a new SQL statement
    
    ### How was this patch tested?
    Unit tests in ProcedureSuite
    
    ### Was this patch authored or co-authored using generative AI tooling?
    No
    
    Closes #50109 from szehon-ho/SPARK-51350.
    
    Authored-by: Szehon Ho <sz...@gmail.com>
    Signed-off-by: Wenchen Fan <we...@databricks.com>
---
 docs/sql-ref-ansi-compliance.md                    |   1 +
 .../spark/sql/catalyst/parser/SqlBaseLexer.g4      |   1 +
 .../spark/sql/catalyst/parser/SqlBaseParser.g4     |   3 +
 .../sql/connector/catalog/ProcedureCatalog.java    |   6 ++
 .../sql/connector/catalog/InMemoryCatalog.scala    |   1 -
 .../connector/catalog/InMemoryTableCatalog.scala   |  11 +++
 .../spark/sql/execution/SparkSqlParser.scala       |  11 ++-
 .../execution/command/ShowProceduresCommand.scala  |  64 +++++++++++++
 .../sql-tests/results/keywords-enforced.sql.out    |   1 +
 .../resources/sql-tests/results/keywords.sql.out   |   1 +
 .../sql-tests/results/nonansi/keywords.sql.out     |   1 +
 .../spark/sql/connector/ProcedureSuite.scala       | 106 ++++++++++++++++++++-
 .../ThriftServerWithSparkContextSuite.scala        |   2 +-
 13 files changed, 204 insertions(+), 5 deletions(-)

diff --git a/docs/sql-ref-ansi-compliance.md b/docs/sql-ref-ansi-compliance.md
index 73a53b6deba5..53e9183dbafc 100644
--- a/docs/sql-ref-ansi-compliance.md
+++ b/docs/sql-ref-ansi-compliance.md
@@ -649,6 +649,7 @@ Below is a list of all the keywords in Spark SQL.
 |PRECEDING|non-reserved|non-reserved|non-reserved|
 |PRIMARY|reserved|non-reserved|reserved|
 |PRINCIPALS|non-reserved|non-reserved|non-reserved|
+|PROCEDURES|non-reserved|non-reserved|non-reserved|
 |PROPERTIES|non-reserved|non-reserved|non-reserved|
 |PURGE|non-reserved|non-reserved|non-reserved|
 |QUARTER|non-reserved|non-reserved|non-reserved|
diff --git a/sql/api/src/main/antlr4/org/apache/spark/sql/catalyst/parser/SqlBaseLexer.g4 b/sql/api/src/main/antlr4/org/apache/spark/sql/catalyst/parser/SqlBaseLexer.g4
index b868eea41b69..dad27b8524b3 100644
--- a/sql/api/src/main/antlr4/org/apache/spark/sql/catalyst/parser/SqlBaseLexer.g4
+++ b/sql/api/src/main/antlr4/org/apache/spark/sql/catalyst/parser/SqlBaseLexer.g4
@@ -362,6 +362,7 @@ POSITION: 'POSITION';
 PRECEDING: 'PRECEDING';
 PRIMARY: 'PRIMARY';
 PRINCIPALS: 'PRINCIPALS';
+PROCEDURES: 'PROCEDURES';
 PROPERTIES: 'PROPERTIES';
 PURGE: 'PURGE';
 QUARTER: 'QUARTER';
diff --git a/sql/api/src/main/antlr4/org/apache/spark/sql/catalyst/parser/SqlBaseParser.g4 b/sql/api/src/main/antlr4/org/apache/spark/sql/catalyst/parser/SqlBaseParser.g4
index eda084ce2a4e..03111b5bf19e 100644
--- a/sql/api/src/main/antlr4/org/apache/spark/sql/catalyst/parser/SqlBaseParser.g4
+++ b/sql/api/src/main/antlr4/org/apache/spark/sql/catalyst/parser/SqlBaseParser.g4
@@ -304,6 +304,7 @@ statement
     | SHOW PARTITIONS identifierReference partitionSpec?               #showPartitions
     | SHOW identifier? FUNCTIONS ((FROM | IN) ns=identifierReference)?
         (LIKE? (legacy=multipartIdentifier | pattern=stringLit))?      #showFunctions
+    | SHOW PROCEDURES ((FROM | IN) identifierReference)?               #showProcedures
     | SHOW CREATE TABLE identifierReference (AS SERDE)?                #showCreateTable
     | SHOW CURRENT namespace                                           #showCurrentNamespace
     | SHOW CATALOGS (LIKE? pattern=stringLit)?                            #showCatalogs
@@ -1782,6 +1783,7 @@ ansiNonReserved
     | POSITION
     | PRECEDING
     | PRINCIPALS
+    | PROCEDURES
     | PROPERTIES
     | PURGE
     | QUARTER
@@ -2162,6 +2164,7 @@ nonReserved
     | PRECEDING
     | PRIMARY
     | PRINCIPALS
+    | PROCEDURES
     | PROPERTIES
     | PURGE
     | QUARTER
diff --git a/sql/catalyst/src/main/java/org/apache/spark/sql/connector/catalog/ProcedureCatalog.java b/sql/catalyst/src/main/java/org/apache/spark/sql/connector/catalog/ProcedureCatalog.java
index 6eaacf340cb8..ef799a6c30df 100644
--- a/sql/catalyst/src/main/java/org/apache/spark/sql/connector/catalog/ProcedureCatalog.java
+++ b/sql/catalyst/src/main/java/org/apache/spark/sql/connector/catalog/ProcedureCatalog.java
@@ -34,4 +34,10 @@ public interface ProcedureCatalog extends CatalogPlugin {
    * @return the loaded unbound procedure
    */
   UnboundProcedure loadProcedure(Identifier ident);
+
+  /**
+   * List all procedures in the specified namespace.
+   *
+   */
+  Identifier[] listProcedures(String[] namespace);
 }
diff --git a/sql/catalyst/src/test/scala/org/apache/spark/sql/connector/catalog/InMemoryCatalog.scala b/sql/catalyst/src/test/scala/org/apache/spark/sql/connector/catalog/InMemoryCatalog.scala
index 14e857e1dae3..4f0588498ec4 100644
--- a/sql/catalyst/src/test/scala/org/apache/spark/sql/connector/catalog/InMemoryCatalog.scala
+++ b/sql/catalyst/src/test/scala/org/apache/spark/sql/connector/catalog/InMemoryCatalog.scala
@@ -33,7 +33,6 @@ class InMemoryCatalog extends InMemoryTableCatalog with FunctionCatalog with Pro
   override protected def allNamespaces: Seq[Seq[String]] =
     (super.allNamespaces ++ functions.keySet.asScala.map(_.namespace.toSeq)).distinct
 
-
   override def listFunctions(namespace: Array[String]): Array[Identifier] = {
     if (namespace.isEmpty || namespaceExists(namespace)) {
       functions.keySet.asScala.filter(_.namespace.sameElements(namespace)).toArray
diff --git a/sql/catalyst/src/test/scala/org/apache/spark/sql/connector/catalog/InMemoryTableCatalog.scala b/sql/catalyst/src/test/scala/org/apache/spark/sql/connector/catalog/InMemoryTableCatalog.scala
index 3bf3c6582b45..1b223eae9839 100644
--- a/sql/catalyst/src/test/scala/org/apache/spark/sql/connector/catalog/InMemoryTableCatalog.scala
+++ b/sql/catalyst/src/test/scala/org/apache/spark/sql/connector/catalog/InMemoryTableCatalog.scala
@@ -277,6 +277,17 @@ class InMemoryTableCatalog extends BasicInMemoryTableCatalog with SupportsNamesp
     procedure
   }
 
+  override def listProcedures(namespace: Array[String]): Array[Identifier] = {
+    val result =
+      if (namespaceExists(namespace)) {
+        procedures.keySet.asScala
+          .filter(_.namespace.sameElements(namespace))
+      } else {
+        throw new NoSuchNamespaceException(namespace)
+      }
+    result.filter(!_.namespace.sameElements(Array("dummy"))).toArray
+  }
+
   object UnboundIncrement extends UnboundProcedure {
     override def name: String = "dummy_increment"
     override def description: String = "test method to increment an in-memory counter"
diff --git a/sql/core/src/main/scala/org/apache/spark/sql/execution/SparkSqlParser.scala b/sql/core/src/main/scala/org/apache/spark/sql/execution/SparkSqlParser.scala
index 8859b7b421b3..eab76f4c7d88 100644
--- a/sql/core/src/main/scala/org/apache/spark/sql/execution/SparkSqlParser.scala
+++ b/sql/core/src/main/scala/org/apache/spark/sql/execution/SparkSqlParser.scala
@@ -27,7 +27,7 @@ import org.antlr.v4.runtime.tree.TerminalNode
 
 import org.apache.spark.SparkException
 import org.apache.spark.sql.catalyst.{FunctionIdentifier, TableIdentifier}
-import org.apache.spark.sql.catalyst.analysis.{GlobalTempView, LocalTempView, PersistedView, PlanWithUnresolvedIdentifier, SchemaEvolution, SchemaTypeEvolution, UnresolvedAttribute, UnresolvedFunctionName, UnresolvedIdentifier, UnresolvedNamespace}
+import org.apache.spark.sql.catalyst.analysis.{CurrentNamespace, GlobalTempView, LocalTempView, PersistedView, PlanWithUnresolvedIdentifier, SchemaEvolution, SchemaTypeEvolution, UnresolvedAttribute, UnresolvedFunctionName, UnresolvedIdentifier, UnresolvedNamespace}
 import org.apache.spark.sql.catalyst.catalog._
 import org.apache.spark.sql.catalyst.expressions.{Expression, Literal}
 import org.apache.spark.sql.catalyst.parser._
@@ -1179,4 +1179,13 @@ class SparkSqlAstBuilder extends AstBuilder {
       }
     }
   }
+
+  override def visitShowProcedures(ctx: ShowProceduresContext): LogicalPlan = withOrigin(ctx) {
+    val ns = if (ctx.identifierReference != null) {
+      withIdentClause(ctx.identifierReference, UnresolvedNamespace(_))
+    } else {
+      CurrentNamespace
+    }
+    ShowProceduresCommand(ns)
+  }
 }
diff --git a/sql/core/src/main/scala/org/apache/spark/sql/execution/command/ShowProceduresCommand.scala b/sql/core/src/main/scala/org/apache/spark/sql/execution/command/ShowProceduresCommand.scala
new file mode 100644
index 000000000000..f08d0924d7cd
--- /dev/null
+++ b/sql/core/src/main/scala/org/apache/spark/sql/execution/command/ShowProceduresCommand.scala
@@ -0,0 +1,64 @@
+/*
+ * 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.spark.sql.execution.command
+
+import org.apache.spark.sql.{Row, SparkSession}
+import org.apache.spark.sql.catalyst.analysis.ResolvedNamespace
+import org.apache.spark.sql.catalyst.expressions.{Attribute, AttributeReference}
+import org.apache.spark.sql.catalyst.plans.logical.LogicalPlan
+import org.apache.spark.sql.connector.catalog.CatalogV2Implicits._
+import org.apache.spark.sql.types.{ArrayType, StringType}
+
+/**
+ * A command for users to get procedures.
+ * If a namespace is not given, the current namespace will be used.
+ * The syntax of using this command in SQL is:
+ * {{{
+ *   SHOW PROCEDURES [(IN|FROM) namespace]]
+ * }}}
+ */
+case class ShowProceduresCommand(
+    child: LogicalPlan,
+    override val output: Seq[Attribute] = Seq(
+      AttributeReference("catalog", StringType, nullable = false)(),
+      AttributeReference("namespace", ArrayType(StringType, containsNull = false))(),
+      AttributeReference("schema", StringType)(),
+      AttributeReference("procedure_name", StringType, nullable = false)()
+    )) extends UnaryRunnableCommand {
+
+  override def run(sparkSession: SparkSession): Seq[Row] = {
+    child match {
+      case ResolvedNamespace(catalog, ns, _) =>
+        val procedureCatalog = catalog.asProcedureCatalog
+        val procedures = procedureCatalog.listProcedures(ns.toArray)
+
+        procedures.toSeq.map{ p =>
+          val schema = if (p.namespace() != null && p.namespace().nonEmpty) {
+            p.namespace().last
+          } else {
+            null
+          }
+          Row(catalog.name, p.namespace(), schema, p.name)
+        }
+    }
+  }
+
+  override protected def withNewChildInternal(newChild: LogicalPlan): LogicalPlan = {
+    copy(child = newChild)
+  }
+}
diff --git a/sql/core/src/test/resources/sql-tests/results/keywords-enforced.sql.out b/sql/core/src/test/resources/sql-tests/results/keywords-enforced.sql.out
index 6ee2b12be068..4e4e1eff3a7b 100644
--- a/sql/core/src/test/resources/sql-tests/results/keywords-enforced.sql.out
+++ b/sql/core/src/test/resources/sql-tests/results/keywords-enforced.sql.out
@@ -249,6 +249,7 @@ POSITION	false
 PRECEDING	false
 PRIMARY	true
 PRINCIPALS	false
+PROCEDURES	false
 PROPERTIES	false
 PURGE	false
 QUARTER	false
diff --git a/sql/core/src/test/resources/sql-tests/results/keywords.sql.out b/sql/core/src/test/resources/sql-tests/results/keywords.sql.out
index 16c2835bd695..e0f72b5814e3 100644
--- a/sql/core/src/test/resources/sql-tests/results/keywords.sql.out
+++ b/sql/core/src/test/resources/sql-tests/results/keywords.sql.out
@@ -249,6 +249,7 @@ POSITION	false
 PRECEDING	false
 PRIMARY	false
 PRINCIPALS	false
+PROCEDURES	false
 PROPERTIES	false
 PURGE	false
 QUARTER	false
diff --git a/sql/core/src/test/resources/sql-tests/results/nonansi/keywords.sql.out b/sql/core/src/test/resources/sql-tests/results/nonansi/keywords.sql.out
index 16c2835bd695..e0f72b5814e3 100644
--- a/sql/core/src/test/resources/sql-tests/results/nonansi/keywords.sql.out
+++ b/sql/core/src/test/resources/sql-tests/results/nonansi/keywords.sql.out
@@ -249,6 +249,7 @@ POSITION	false
 PRECEDING	false
 PRIMARY	false
 PRINCIPALS	false
+PROCEDURES	false
 PROPERTIES	false
 PURGE	false
 QUARTER	false
diff --git a/sql/core/src/test/scala/org/apache/spark/sql/connector/ProcedureSuite.scala b/sql/core/src/test/scala/org/apache/spark/sql/connector/ProcedureSuite.scala
index f5a750a26a74..b11116039a91 100644
--- a/sql/core/src/test/scala/org/apache/spark/sql/connector/ProcedureSuite.scala
+++ b/sql/core/src/test/scala/org/apache/spark/sql/connector/ProcedureSuite.scala
@@ -19,6 +19,8 @@ package org.apache.spark.sql.connector
 
 import java.util.Collections
 
+import scala.collection.immutable.ArraySeq
+
 import org.scalatest.BeforeAndAfter
 
 import org.apache.spark.{SPARK_DOC_ROOT, SparkException, SparkNumberFormatException}
@@ -40,15 +42,19 @@ class ProcedureSuite extends QueryTest with SharedSparkSession with BeforeAndAft
 
   before {
     spark.conf.set(s"spark.sql.catalog.cat", classOf[InMemoryCatalog].getName)
+    spark.conf.set(s"spark.sql.catalog.cat2", classOf[InMemoryCatalog].getName)
   }
 
   after {
     spark.sessionState.catalogManager.reset()
     spark.sessionState.conf.unsetConf(s"spark.sql.catalog.cat")
+    spark.sessionState.conf.unsetConf(s"spark.sql.catalog.cat2")
   }
 
-  private def catalog: InMemoryCatalog = {
-    val catalog = spark.sessionState.catalogManager.catalog("cat")
+  private def catalog: InMemoryCatalog = catalog("cat")
+
+  private def catalog(name: String): InMemoryCatalog = {
+    val catalog = spark.sessionState.catalogManager.catalog(name)
     catalog.asInstanceOf[InMemoryCatalog]
   }
 
@@ -143,6 +149,14 @@ class ProcedureSuite extends QueryTest with SharedSparkSession with BeforeAndAft
         condition = "_LEGACY_ERROR_TEMP_1184",
         parameters = Map("plugin" -> "testcat", "ability" -> "procedures")
       )
+
+      checkError(
+        exception = intercept[AnalysisException](
+          sql("SHOW PROCEDURES IN testcat")
+        ),
+        condition = "_LEGACY_ERROR_TEMP_1184",
+        parameters = Map("plugin" -> "testcat", "ability" -> "procedures")
+      )
     }
   }
 
@@ -348,6 +362,94 @@ class ProcedureSuite extends QueryTest with SharedSparkSession with BeforeAndAft
     }
   }
 
+  test("SPARK-51350: Implement SHOW procedures") {
+    catalog.createProcedure(Identifier.of(Array("ns"), "foo"), UnboundSum)
+    catalog.createProcedure(Identifier.of(Array("ns"), "abc"), UnboundLongSum)
+    catalog.createProcedure(Identifier.of(Array(""), "xyz"), UnboundComplexProcedure)
+    catalog.createProcedure(Identifier.of(Array(), "xxx"), UnboundStructProcedure)
+
+    sql("USE cat")
+    withNamespace("cat2.db_1") {
+      sql("CREATE NAMESPACE cat2.db_1")
+
+      catalog("cat2").createProcedure(Identifier.of(Array("ns_1", "db_1"), "foo"),
+        UnboundVoidProcedure)
+      catalog("cat2").createProcedure(Identifier.of(Array("ns_1", "db_1"), "bar"),
+        UnboundMultiResultProcedure)
+      catalog("cat2").createProcedure(Identifier.of(Array(""), "foo"),
+        UnboundVoidProcedure)
+      catalog("cat2").createProcedure(Identifier.of(Array(), "bar"),
+        UnboundMultiResultProcedure)
+
+      checkAnswer(
+        // uses default catalog and ns
+        sql("SHOW PROCEDURES"),
+        Row("cat", ArraySeq(), null, "xxx") :: Nil)
+
+      checkAnswer(
+        sql("SHOW PROCEDURES IN ns"),
+        Row("cat", Array("ns"), "ns", "abc") ::
+          Row("cat", Array("ns"), "ns", "foo") :: Nil)
+
+      checkAnswer(
+        sql("SHOW PROCEDURES IN cat.ns"),
+        Row("cat", Array("ns"), "ns", "abc") ::
+          Row("cat", Array("ns"), "ns", "foo") :: Nil)
+
+      checkAnswer(
+        sql("SHOW PROCEDURES FROM cat.ns"),
+        Row("cat", Array("ns"), "ns", "abc") ::
+          Row("cat", Array("ns"), "ns", "foo") :: Nil)
+
+      checkAnswer(
+        sql("SHOW PROCEDURES FROM ``"),
+        Row("cat", Array(""), "", "xyz") :: Nil)
+
+      checkAnswer(
+        sql("SHOW PROCEDURES FROM cat.``"),
+        Row("cat", Array(""), "", "xyz") :: Nil)
+
+      checkAnswer(
+        sql("SHOW PROCEDURES FROM cat2.ns_1.db_1"),
+        Row("cat2", ArraySeq("ns_1", "db_1"), "db_1", "foo") ::
+        Row("cat2", ArraySeq("ns_1", "db_1"), "db_1", "bar") :: Nil)
+
+      // Switch catalog.
+      sql("USE cat2")
+
+      checkAnswer(
+        sql("SHOW PROCEDURES IN cat.ns"),
+        Row("cat", Array("ns"), "ns", "abc") ::
+          Row("cat", Array("ns"), "ns", "foo") :: Nil)
+
+      checkAnswer(
+        // uses default catalog and ns
+        sql("SHOW PROCEDURES"),
+        Row("cat2", ArraySeq(), null, "bar") :: Nil)
+
+      checkAnswer(
+        sql("SHOW PROCEDURES FROM ns_1.db_1"),
+        Row("cat2", ArraySeq("ns_1", "db_1"), "db_1", "foo") ::
+          Row("cat2", ArraySeq("ns_1", "db_1"), "db_1", "bar") :: Nil)
+
+      checkAnswer(
+        sql("SHOW PROCEDURES FROM cat2.ns_1.db_1"),
+        Row("cat2", ArraySeq("ns_1", "db_1"), "db_1", "foo") ::
+          Row("cat2", ArraySeq("ns_1", "db_1"), "db_1", "bar") :: Nil)
+
+      checkAnswer(
+        sql("SHOW PROCEDURES FROM ``"),
+        Row("cat2", Array(""), "", "foo") :: Nil)
+
+      checkAnswer(
+        sql("SHOW PROCEDURES FROM cat2.``"),
+        Row("cat2", Array(""), "", "foo") :: Nil)
+
+      // Switch catalog back to 'cat' before clean up.
+      sql("USE cat")
+    }
+  }
+
   object UnboundVoidProcedure extends UnboundProcedure {
     override def name: String = "void"
     override def description: String = "void procedure"
diff --git a/sql/hive-thriftserver/src/test/scala/org/apache/spark/sql/hive/thriftserver/ThriftServerWithSparkContextSuite.scala b/sql/hive-thriftserver/src/test/scala/org/apache/spark/sql/hive/thriftserver/ThriftServerWithSparkContextSuite.scala
index 5cf7cfc58ef2..f05f5c788fa0 100644
--- a/sql/hive-thriftserver/src/test/scala/org/apache/spark/sql/hive/thriftserver/ThriftServerWithSparkContextSuite.scala
+++ b/sql/hive-thriftserver/src/test/scala/org/apache/spark/sql/hive/thriftserver/ThriftServerWithSparkContextSuite.scala
@@ -214,7 +214,7 @@ trait ThriftServerWithSparkContextSuite extends SharedThriftServer {
       val sessionHandle = client.openSession(user, "")
       val infoValue = client.getInfo(sessionHandle, GetInfoType.CLI_ODBC_KEYWORDS)
       // scalastyle:off line.size.limit
-      assert(infoValue.getStringValue == "ADD,AFTER,AGGREGATE,ALL,ALTER,ALWAYS,ANALYZE,AND,ANTI,ANY,ANY_VALUE,ARCHIVE,ARRAY,AS,ASC,AT,AUTHORIZATION,BEGIN,BETWEEN,BIGINT,BINARY,BINDING,BOOLEAN,BOTH,BUCKET,BUCKETS,BY,BYTE,CACHE,CALL,CALLED,CASCADE,CASE,CAST,CATALOG,CATALOGS,CHANGE,CHAR,CHARACTER,CHECK,CLEAR,CLUSTER,CLUSTERED,CODEGEN,COLLATE,COLLATION,COLLECTION,COLUMN,COLUMNS,COMMENT,COMMIT,COMPACT,COMPACTIONS,COMPENSATION,COMPUTE,CONCATENATE,CONDITION,CONSTRAINT,CONTAINS,CONTINUE,COST,CRE [...]
+      assert(infoValue.getStringValue == "ADD,AFTER,AGGREGATE,ALL,ALTER,ALWAYS,ANALYZE,AND,ANTI,ANY,ANY_VALUE,ARCHIVE,ARRAY,AS,ASC,AT,AUTHORIZATION,BEGIN,BETWEEN,BIGINT,BINARY,BINDING,BOOLEAN,BOTH,BUCKET,BUCKETS,BY,BYTE,CACHE,CALL,CALLED,CASCADE,CASE,CAST,CATALOG,CATALOGS,CHANGE,CHAR,CHARACTER,CHECK,CLEAR,CLUSTER,CLUSTERED,CODEGEN,COLLATE,COLLATION,COLLECTION,COLUMN,COLUMNS,COMMENT,COMMIT,COMPACT,COMPACTIONS,COMPENSATION,COMPUTE,CONCATENATE,CONDITION,CONSTRAINT,CONTAINS,CONTINUE,COST,CRE [...]
       // scalastyle:on line.size.limit
     }
   }


---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@spark.apache.org
For additional commands, e-mail: commits-help@spark.apache.org