aboutsummaryrefslogtreecommitdiff
path: root/sql/core/src/main
diff options
context:
space:
mode:
authorHerman van Hovell <hvanhovell@questtec.nl>2016-03-31 09:25:09 -0700
committerReynold Xin <rxin@databricks.com>2016-03-31 09:25:09 -0700
commita9b93e07391faede77dde4c0b3c21c9b3f97f8eb (patch)
treeebcdf8cef08c6c14efadd5186097c7ceb8fc1738 /sql/core/src/main
parent26445c2e472bad137fd350e4089dd0ff43a42039 (diff)
downloadspark-a9b93e07391faede77dde4c0b3c21c9b3f97f8eb.tar.gz
spark-a9b93e07391faede77dde4c0b3c21c9b3f97f8eb.tar.bz2
spark-a9b93e07391faede77dde4c0b3c21c9b3f97f8eb.zip
[SPARK-14211][SQL] Remove ANTLR3 based parser
### What changes were proposed in this pull request? This PR removes the ANTLR3 based parser, and moves the new ANTLR4 based parser into the `org.apache.spark.sql.catalyst.parser package`. ### How was this patch tested? Existing unit tests. cc rxin andrewor14 yhuai Author: Herman van Hovell <hvanhovell@questtec.nl> Closes #12071 from hvanhovell/SPARK-14211.
Diffstat (limited to 'sql/core/src/main')
-rw-r--r--sql/core/src/main/scala/org/apache/spark/sql/execution/SparkQl.scala387
-rw-r--r--sql/core/src/main/scala/org/apache/spark/sql/execution/SparkSqlParser.scala6
-rw-r--r--sql/core/src/main/scala/org/apache/spark/sql/execution/command/AlterTableCommandParser.scala431
-rw-r--r--sql/core/src/main/scala/org/apache/spark/sql/internal/SQLConf.scala20
4 files changed, 4 insertions, 840 deletions
diff --git a/sql/core/src/main/scala/org/apache/spark/sql/execution/SparkQl.scala b/sql/core/src/main/scala/org/apache/spark/sql/execution/SparkQl.scala
deleted file mode 100644
index 6fe04757ba..0000000000
--- a/sql/core/src/main/scala/org/apache/spark/sql/execution/SparkQl.scala
+++ /dev/null
@@ -1,387 +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.spark.sql.execution
-
-import org.apache.spark.sql.{AnalysisException, SaveMode}
-import org.apache.spark.sql.catalyst.TableIdentifier
-import org.apache.spark.sql.catalyst.parser._
-import org.apache.spark.sql.catalyst.plans.logical.{LogicalPlan, OneRowRelation}
-import org.apache.spark.sql.execution.command._
-import org.apache.spark.sql.execution.datasources._
-import org.apache.spark.sql.types.StructType
-
-private[sql] class SparkQl(conf: ParserConf = SimpleParserConf()) extends CatalystQl(conf) {
- import ParserUtils._
-
- /** Check if a command should not be explained. */
- protected def isNoExplainCommand(command: String): Boolean = {
- "TOK_DESCTABLE" == command || "TOK_ALTERTABLE" == command
- }
-
- /**
- * For each node, extract properties in the form of a list
- * ['key_part1', 'key_part2', 'key_part3', 'value']
- * into a pair (key_part1.key_part2.key_part3, value).
- *
- * Example format:
- *
- * TOK_TABLEPROPERTY
- * :- 'k1'
- * +- 'v1'
- * TOK_TABLEPROPERTY
- * :- 'k2'
- * +- 'v2'
- * TOK_TABLEPROPERTY
- * :- 'k3'
- * +- 'v3'
- */
- private def extractProps(
- props: Seq[ASTNode],
- expectedNodeText: String): Seq[(String, String)] = {
- props.map {
- case Token(x, keysAndValue) if x == expectedNodeText =>
- val key = keysAndValue.init.map { x => unquoteString(x.text) }.mkString(".")
- val value = unquoteString(keysAndValue.last.text)
- (key, value)
- case p =>
- parseFailed(s"Expected property '$expectedNodeText' in command", p)
- }
- }
-
- protected override def nodeToPlan(node: ASTNode): LogicalPlan = {
- node match {
- case Token("TOK_SETCONFIG", Nil) =>
- val keyValueSeparatorIndex = node.remainder.indexOf('=')
- if (keyValueSeparatorIndex >= 0) {
- val key = node.remainder.substring(0, keyValueSeparatorIndex).trim
- val value = node.remainder.substring(keyValueSeparatorIndex + 1).trim
- SetCommand(Some(key -> Option(value)))
- } else if (node.remainder.nonEmpty) {
- SetCommand(Some(node.remainder -> None))
- } else {
- SetCommand(None)
- }
-
- // Just fake explain for any of the native commands.
- case Token("TOK_EXPLAIN", explainArgs) if isNoExplainCommand(explainArgs.head.text) =>
- ExplainCommand(OneRowRelation)
-
- case Token("TOK_EXPLAIN", explainArgs) if "TOK_CREATETABLE" == explainArgs.head.text =>
- val Some(crtTbl) :: _ :: extended :: Nil =
- getClauses(Seq("TOK_CREATETABLE", "FORMATTED", "EXTENDED"), explainArgs)
- ExplainCommand(nodeToPlan(crtTbl), extended = extended.isDefined)
-
- case Token("TOK_EXPLAIN", explainArgs) =>
- // Ignore FORMATTED if present.
- val Some(query) :: _ :: extended :: Nil =
- getClauses(Seq("TOK_QUERY", "FORMATTED", "EXTENDED"), explainArgs)
- ExplainCommand(nodeToPlan(query), extended = extended.isDefined)
-
- case Token("TOK_REFRESHTABLE", nameParts :: Nil) =>
- val tableIdent = extractTableIdent(nameParts)
- RefreshTable(tableIdent)
-
- // CREATE DATABASE [IF NOT EXISTS] database_name [COMMENT database_comment]
- // [LOCATION path] [WITH DBPROPERTIES (key1=val1, key2=val2, ...)];
- case Token("TOK_CREATEDATABASE", Token(dbName, Nil) :: args) =>
- val databaseName = cleanIdentifier(dbName)
- val Seq(ifNotExists, dbLocation, databaseComment, dbprops) = getClauses(Seq(
- "TOK_IFNOTEXISTS",
- "TOK_DATABASELOCATION",
- "TOK_DATABASECOMMENT",
- "TOK_DATABASEPROPERTIES"), args)
- val location = dbLocation.map {
- case Token("TOK_DATABASELOCATION", Token(loc, Nil) :: Nil) => unquoteString(loc)
- case _ => parseFailed("Invalid CREATE DATABASE command", node)
- }
- val comment = databaseComment.map {
- case Token("TOK_DATABASECOMMENT", Token(com, Nil) :: Nil) => unquoteString(com)
- case _ => parseFailed("Invalid CREATE DATABASE command", node)
- }
- val props = dbprops.toSeq.flatMap {
- case Token("TOK_DATABASEPROPERTIES", Token("TOK_DBPROPLIST", propList) :: Nil) =>
- // Example format:
- //
- // TOK_DATABASEPROPERTIES
- // +- TOK_DBPROPLIST
- // :- TOK_TABLEPROPERTY
- // : :- 'k1'
- // : +- 'v1'
- // :- TOK_TABLEPROPERTY
- // :- 'k2'
- // +- 'v2'
- extractProps(propList, "TOK_TABLEPROPERTY")
- case _ => parseFailed("Invalid CREATE DATABASE command", node)
- }.toMap
- CreateDatabase(databaseName, ifNotExists.isDefined, location, comment, props)
-
- // DROP DATABASE [IF EXISTS] database_name [RESTRICT|CASCADE];
- case Token("TOK_DROPDATABASE", Token(dbName, Nil) :: otherArgs) =>
- // Example format:
- //
- // TOK_DROPDATABASE
- // :- database_name
- // :- TOK_IFEXISTS
- // +- TOK_RESTRICT/TOK_CASCADE
- val databaseName = cleanIdentifier(dbName)
- // The default is RESTRICT
- val Seq(ifExists, _, cascade) = getClauses(Seq(
- "TOK_IFEXISTS", "TOK_RESTRICT", "TOK_CASCADE"), otherArgs)
- DropDatabase(databaseName, ifExists.isDefined, cascade.isDefined)
-
- // ALTER (DATABASE|SCHEMA) database_name SET DBPROPERTIES (property_name=property_value, ...)
- case Token("TOK_ALTERDATABASE_PROPERTIES", Token(dbName, Nil) :: args) =>
- val databaseName = cleanIdentifier(dbName)
- val dbprops = getClause("TOK_DATABASEPROPERTIES", args)
- val props = dbprops match {
- case Token("TOK_DATABASEPROPERTIES", Token("TOK_DBPROPLIST", propList) :: Nil) =>
- // Example format:
- //
- // TOK_DATABASEPROPERTIES
- // +- TOK_DBPROPLIST
- // :- TOK_TABLEPROPERTY
- // : :- 'k1'
- // : +- 'v1'
- // :- TOK_TABLEPROPERTY
- // :- 'k2'
- // +- 'v2'
- extractProps(propList, "TOK_TABLEPROPERTY")
- case _ => parseFailed("Invalid ALTER DATABASE command", node)
- }
- AlterDatabaseProperties(databaseName, props.toMap)
-
- // DESCRIBE DATABASE [EXTENDED] db_name
- case Token("TOK_DESCDATABASE", Token(dbName, Nil) :: describeArgs) =>
- val databaseName = cleanIdentifier(dbName)
- val extended = getClauseOption("EXTENDED", describeArgs)
- DescribeDatabase(databaseName, extended.isDefined)
-
- // CREATE [TEMPORARY] FUNCTION [db_name.]function_name AS class_name
- // [USING JAR|FILE|ARCHIVE 'file_uri' [, JAR|FILE|ARCHIVE 'file_uri'] ];
- case Token("TOK_CREATEFUNCTION", args) =>
- // Example format:
- //
- // TOK_CREATEFUNCTION
- // :- db_name
- // :- func_name
- // :- alias
- // +- TOK_RESOURCE_LIST
- // :- TOK_RESOURCE_URI
- // : :- TOK_JAR
- // : +- '/path/to/jar'
- // +- TOK_RESOURCE_URI
- // :- TOK_FILE
- // +- 'path/to/file'
- val (funcNameArgs, otherArgs) = args.partition {
- case Token("TOK_RESOURCE_LIST", _) => false
- case Token("TOK_TEMPORARY", _) => false
- case Token(_, Nil) => true
- case _ => parseFailed("Invalid CREATE FUNCTION command", node)
- }
- // If database name is specified, there are 3 tokens, otherwise 2.
- val (dbName, funcName, alias) = funcNameArgs match {
- case Token(dbName, Nil) :: Token(fname, Nil) :: Token(aname, Nil) :: Nil =>
- (Some(unquoteString(dbName)), unquoteString(fname), unquoteString(aname))
- case Token(fname, Nil) :: Token(aname, Nil) :: Nil =>
- (None, unquoteString(fname), unquoteString(aname))
- case _ =>
- parseFailed("Invalid CREATE FUNCTION command", node)
- }
- // Extract other keywords, if they exist
- val Seq(rList, temp) = getClauses(Seq("TOK_RESOURCE_LIST", "TOK_TEMPORARY"), otherArgs)
- val resources: Seq[(String, String)] = rList.toSeq.flatMap {
- case Token("TOK_RESOURCE_LIST", resList) =>
- resList.map {
- case Token("TOK_RESOURCE_URI", rType :: Token(rPath, Nil) :: Nil) =>
- val resourceType = rType match {
- case Token("TOK_JAR", Nil) => "jar"
- case Token("TOK_FILE", Nil) => "file"
- case Token("TOK_ARCHIVE", Nil) => "archive"
- case Token(f, _) => parseFailed(s"Unexpected resource format '$f'", node)
- }
- (resourceType, unquoteString(rPath))
- case _ => parseFailed("Invalid CREATE FUNCTION command", node)
- }
- case _ => parseFailed("Invalid CREATE FUNCTION command", node)
- }
- CreateFunction(dbName, funcName, alias, resources, temp.isDefined)(node.source)
-
- // DROP [TEMPORARY] FUNCTION [IF EXISTS] function_name;
- case Token("TOK_DROPFUNCTION", args) =>
- // Example format:
- //
- // TOK_DROPFUNCTION
- // :- db_name
- // :- func_name
- // :- TOK_IFEXISTS
- // +- TOK_TEMPORARY
- val (funcNameArgs, otherArgs) = args.partition {
- case Token("TOK_IFEXISTS", _) => false
- case Token("TOK_TEMPORARY", _) => false
- case Token(_, Nil) => true
- case _ => parseFailed("Invalid DROP FUNCTION command", node)
- }
- // If database name is specified, there are 2 tokens, otherwise 1.
- val (dbName, funcName) = funcNameArgs match {
- case Token(dbName, Nil) :: Token(fname, Nil) :: Nil =>
- (Some(unquoteString(dbName)), unquoteString(fname))
- case Token(fname, Nil) :: Nil =>
- (None, unquoteString(fname))
- case _ =>
- parseFailed("Invalid DROP FUNCTION command", node)
- }
-
- val Seq(ifExists, temp) = getClauses(Seq(
- "TOK_IFEXISTS", "TOK_TEMPORARY"), otherArgs)
-
- DropFunction(dbName, funcName, ifExists.isDefined, temp.isDefined)(node.source)
-
- case Token("TOK_ALTERTABLE", alterTableArgs) =>
- AlterTableCommandParser.parse(node)
-
- case Token("TOK_CREATETABLEUSING", createTableArgs) =>
- val Seq(
- temp,
- ifNotExists,
- Some(tabName),
- tableCols,
- Some(Token("TOK_TABLEPROVIDER", providerNameParts)),
- tableOpts,
- tableAs) = getClauses(Seq(
- "TEMPORARY",
- "TOK_IFNOTEXISTS",
- "TOK_TABNAME", "TOK_TABCOLLIST",
- "TOK_TABLEPROVIDER",
- "TOK_TABLEOPTIONS",
- "TOK_QUERY"), createTableArgs)
- val tableIdent: TableIdentifier = extractTableIdent(tabName)
- val columns = tableCols.map {
- case Token("TOK_TABCOLLIST", fields) => StructType(fields.map(nodeToStructField))
- case _ => parseFailed("Invalid CREATE TABLE command", node)
- }
- val provider = providerNameParts.map {
- case Token(name, Nil) => name
- case _ => parseFailed("Invalid CREATE TABLE command", node)
- }.mkString(".")
- val options = tableOpts.toSeq.flatMap {
- case Token("TOK_TABLEOPTIONS", opts) => extractProps(opts, "TOK_TABLEOPTION")
- case _ => parseFailed("Invalid CREATE TABLE command", node)
- }.toMap
- val asClause = tableAs.map(nodeToPlan)
-
- if (temp.isDefined && ifNotExists.isDefined) {
- throw new AnalysisException(
- "a CREATE TEMPORARY TABLE statement does not allow IF NOT EXISTS clause.")
- }
-
- if (asClause.isDefined) {
- if (columns.isDefined) {
- throw new AnalysisException(
- "a CREATE TABLE AS SELECT statement does not allow column definitions.")
- }
-
- val mode = if (ifNotExists.isDefined) {
- SaveMode.Ignore
- } else if (temp.isDefined) {
- SaveMode.Overwrite
- } else {
- SaveMode.ErrorIfExists
- }
-
- CreateTableUsingAsSelect(tableIdent,
- provider,
- temp.isDefined,
- Array.empty[String],
- bucketSpec = None,
- mode,
- options,
- asClause.get)
- } else {
- CreateTableUsing(
- tableIdent,
- columns,
- provider,
- temp.isDefined,
- options,
- ifNotExists.isDefined,
- managedIfNoPath = false)
- }
-
- case Token("TOK_SWITCHDATABASE", Token(database, Nil) :: Nil) =>
- SetDatabaseCommand(cleanIdentifier(database))
-
- case Token("TOK_DESCTABLE", describeArgs) =>
- // Reference: https://cwiki.apache.org/confluence/display/Hive/LanguageManual+DDL
- val Some(tableType) :: formatted :: extended :: pretty :: Nil =
- getClauses(Seq("TOK_TABTYPE", "FORMATTED", "EXTENDED", "PRETTY"), describeArgs)
- if (formatted.isDefined || pretty.isDefined) {
- // FORMATTED and PRETTY are not supported and this statement will be treated as
- // a Hive native command.
- nodeToDescribeFallback(node)
- } else {
- tableType match {
- case Token("TOK_TABTYPE", Token("TOK_TABNAME", nameParts) :: Nil) =>
- nameParts match {
- case Token(dbName, Nil) :: Token(tableName, Nil) :: Nil =>
- // It is describing a table with the format like "describe db.table".
- // TODO: Actually, a user may mean tableName.columnName. Need to resolve this
- // issue.
- val tableIdent = TableIdentifier(
- cleanIdentifier(tableName), Some(cleanIdentifier(dbName)))
- datasources.DescribeCommand(tableIdent, isExtended = extended.isDefined)
- case Token(dbName, Nil) :: Token(tableName, Nil) :: Token(colName, Nil) :: Nil =>
- // It is describing a column with the format like "describe db.table column".
- nodeToDescribeFallback(node)
- case tableName :: Nil =>
- // It is describing a table with the format like "describe table".
- datasources.DescribeCommand(
- TableIdentifier(cleanIdentifier(tableName.text)),
- isExtended = extended.isDefined)
- case _ =>
- nodeToDescribeFallback(node)
- }
- // All other cases.
- case _ =>
- nodeToDescribeFallback(node)
- }
- }
-
- case Token("TOK_CACHETABLE", Token(tableName, Nil) :: args) =>
- val Seq(lzy, selectAst) = getClauses(Seq("LAZY", "TOK_QUERY"), args)
- CacheTableCommand(tableName, selectAst.map(nodeToPlan), lzy.isDefined)
-
- case Token("TOK_UNCACHETABLE", Token(tableName, Nil) :: Nil) =>
- UncacheTableCommand(tableName)
-
- case Token("TOK_CLEARCACHE", Nil) =>
- ClearCacheCommand
-
- case Token("TOK_SHOWTABLES", args) =>
- val databaseName = args match {
- case Nil => None
- case Token("TOK_FROM", Token(dbName, Nil) :: Nil) :: Nil => Option(dbName)
- case _ => noParseRule("SHOW TABLES", node)
- }
- ShowTablesCommand(databaseName)
-
- case _ =>
- super.nodeToPlan(node)
- }
- }
-
- protected def nodeToDescribeFallback(node: ASTNode): LogicalPlan = noParseRule("Describe", node)
-}
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 8333074eca..b4687c985d 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
@@ -20,8 +20,8 @@ import scala.collection.JavaConverters._
import org.apache.spark.sql.SaveMode
import org.apache.spark.sql.catalyst.TableIdentifier
-import org.apache.spark.sql.catalyst.parser.ng.{AbstractSqlParser, AstBuilder, ParseException}
-import org.apache.spark.sql.catalyst.parser.ng.SqlBaseParser._
+import org.apache.spark.sql.catalyst.parser.{AbstractSqlParser, AstBuilder, ParseException}
+import org.apache.spark.sql.catalyst.parser.SqlBaseParser._
import org.apache.spark.sql.catalyst.plans.logical.{LogicalPlan, OneRowRelation}
import org.apache.spark.sql.execution.command.{DescribeCommand => _, _}
import org.apache.spark.sql.execution.datasources._
@@ -37,7 +37,7 @@ object SparkSqlParser extends AbstractSqlParser{
* Builder that converts an ANTLR ParseTree into a LogicalPlan/Expression/TableIdentifier.
*/
class SparkSqlAstBuilder extends AstBuilder {
- import org.apache.spark.sql.catalyst.parser.ng.ParserUtils._
+ import org.apache.spark.sql.catalyst.parser.ParserUtils._
/**
* Create a [[SetCommand]] logical plan.
diff --git a/sql/core/src/main/scala/org/apache/spark/sql/execution/command/AlterTableCommandParser.scala b/sql/core/src/main/scala/org/apache/spark/sql/execution/command/AlterTableCommandParser.scala
deleted file mode 100644
index 9fbe6db467..0000000000
--- a/sql/core/src/main/scala/org/apache/spark/sql/execution/command/AlterTableCommandParser.scala
+++ /dev/null
@@ -1,431 +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.spark.sql.execution.command
-
-import scala.collection.mutable.ArrayBuffer
-
-import org.apache.spark.sql.catalyst.TableIdentifier
-import org.apache.spark.sql.catalyst.catalog.ExternalCatalog.TablePartitionSpec
-import org.apache.spark.sql.catalyst.expressions.{Ascending, Descending, SortDirection}
-import org.apache.spark.sql.catalyst.parser._
-import org.apache.spark.sql.catalyst.plans.logical.LogicalPlan
-import org.apache.spark.sql.execution.datasources._
-import org.apache.spark.sql.types.StructType
-
-
-/**
- * Helper object to parse alter table commands.
- */
-object AlterTableCommandParser {
- import ParserUtils._
-
- /**
- * Parse the given node assuming it is an alter table command.
- */
- def parse(node: ASTNode): LogicalPlan = {
- node.children match {
- case (tabName @ Token("TOK_TABNAME", _)) :: otherNodes =>
- val tableIdent = extractTableIdent(tabName)
- val partSpec = getClauseOption("TOK_PARTSPEC", node.children).map(parsePartitionSpec)
- matchAlterTableCommands(node, otherNodes, tableIdent, partSpec)
- case _ =>
- parseFailed("Could not parse ALTER TABLE command", node)
- }
- }
-
- private def cleanAndUnquoteString(s: String): String = {
- cleanIdentifier(unquoteString(s))
- }
-
- /**
- * Extract partition spec from the given [[ASTNode]] as a map, assuming it exists.
- *
- * Example format:
- *
- * TOK_PARTSPEC
- * :- TOK_PARTVAL
- * : :- dt
- * : +- '2008-08-08'
- * +- TOK_PARTVAL
- * :- country
- * +- 'us'
- */
- private def parsePartitionSpec(node: ASTNode): Map[String, String] = {
- node match {
- case Token("TOK_PARTSPEC", partitions) =>
- partitions.map {
- // Note: sometimes there's a "=", "<" or ">" between the key and the value
- // (e.g. when dropping all partitions with value > than a certain constant)
- case Token("TOK_PARTVAL", ident :: conj :: constant :: Nil) =>
- (cleanAndUnquoteString(ident.text), cleanAndUnquoteString(constant.text))
- case Token("TOK_PARTVAL", ident :: constant :: Nil) =>
- (cleanAndUnquoteString(ident.text), cleanAndUnquoteString(constant.text))
- case Token("TOK_PARTVAL", ident :: Nil) =>
- (cleanAndUnquoteString(ident.text), null)
- case _ =>
- parseFailed("Invalid ALTER TABLE command", node)
- }.toMap
- case _ =>
- parseFailed("Expected partition spec in ALTER TABLE command", node)
- }
- }
-
- /**
- * Extract table properties from the given [[ASTNode]] as a map, assuming it exists.
- *
- * Example format:
- *
- * TOK_TABLEPROPERTIES
- * +- TOK_TABLEPROPLIST
- * :- TOK_TABLEPROPERTY
- * : :- 'test'
- * : +- 'value'
- * +- TOK_TABLEPROPERTY
- * :- 'comment'
- * +- 'new_comment'
- */
- private def extractTableProps(node: ASTNode): Map[String, String] = {
- node match {
- case Token("TOK_TABLEPROPERTIES", propsList) =>
- propsList.flatMap {
- case Token("TOK_TABLEPROPLIST", props) =>
- props.map { case Token("TOK_TABLEPROPERTY", key :: value :: Nil) =>
- val k = cleanAndUnquoteString(key.text)
- val v = value match {
- case Token("TOK_NULL", Nil) => null
- case _ => cleanAndUnquoteString(value.text)
- }
- (k, v)
- }
- case _ =>
- parseFailed("Invalid ALTER TABLE command", node)
- }.toMap
- case _ =>
- parseFailed("Expected table properties in ALTER TABLE command", node)
- }
- }
-
- /**
- * Parse an alter table command from a [[ASTNode]] into a [[LogicalPlan]].
- * This follows https://cwiki.apache.org/confluence/display/Hive/LanguageManual+DDL.
- *
- * @param node the original [[ASTNode]] to parse.
- * @param otherNodes the other [[ASTNode]]s after the first one containing the table name.
- * @param tableIdent identifier of the table, parsed from the first [[ASTNode]].
- * @param partition spec identifying the partition this command is concerned with, if any.
- */
- // TODO: This method is massive. Break it down.
- private def matchAlterTableCommands(
- node: ASTNode,
- otherNodes: Seq[ASTNode],
- tableIdent: TableIdentifier,
- partition: Option[TablePartitionSpec]): LogicalPlan = {
- otherNodes match {
- // ALTER TABLE table_name RENAME TO new_table_name;
- case Token("TOK_ALTERTABLE_RENAME", renameArgs) :: _ =>
- val tableNameClause = getClause("TOK_TABNAME", renameArgs)
- val newTableIdent = extractTableIdent(tableNameClause)
- AlterTableRename(tableIdent, newTableIdent)(node.source)
-
- // ALTER TABLE table_name SET TBLPROPERTIES ('comment' = new_comment);
- case Token("TOK_ALTERTABLE_PROPERTIES", args) :: _ =>
- val properties = extractTableProps(args.head)
- AlterTableSetProperties(tableIdent, properties)(node.source)
-
- // ALTER TABLE table_name UNSET TBLPROPERTIES IF EXISTS ('comment', 'key');
- case Token("TOK_ALTERTABLE_DROPPROPERTIES", args) :: _ =>
- val properties = extractTableProps(args.head)
- val ifExists = getClauseOption("TOK_IFEXISTS", args).isDefined
- AlterTableUnsetProperties(tableIdent, properties, ifExists)(node.source)
-
- // ALTER TABLE table_name [PARTITION spec] SET SERDE serde_name [WITH SERDEPROPERTIES props];
- case Token("TOK_ALTERTABLE_SERIALIZER", Token(serdeClassName, Nil) :: serdeArgs) :: _ =>
- AlterTableSerDeProperties(
- tableIdent,
- Some(cleanAndUnquoteString(serdeClassName)),
- serdeArgs.headOption.map(extractTableProps),
- partition)(node.source)
-
- // ALTER TABLE table_name [PARTITION spec] SET SERDEPROPERTIES serde_properties;
- case Token("TOK_ALTERTABLE_SERDEPROPERTIES", args) :: _ =>
- AlterTableSerDeProperties(
- tableIdent,
- None,
- Some(extractTableProps(args.head)),
- partition)(node.source)
-
- // ALTER TABLE table_name CLUSTERED BY (col, ...) [SORTED BY (col, ...)] INTO n BUCKETS;
- case Token("TOK_ALTERTABLE_CLUSTER_SORT", Token("TOK_ALTERTABLE_BUCKETS", b) :: Nil) :: _ =>
- val clusterCols: Seq[String] = b.head match {
- case Token("TOK_TABCOLNAME", children) => children.map(_.text)
- case _ => parseFailed("Invalid ALTER TABLE command", node)
- }
- // If sort columns are specified, num buckets should be the third arg.
- // If sort columns are not specified, num buckets should be the second arg.
- // TODO: actually use `sortDirections` once we actually store that in the metastore
- val (sortCols: Seq[String], sortDirections: Seq[SortDirection], numBuckets: Int) = {
- b.tail match {
- case Token("TOK_TABCOLNAME", children) :: numBucketsNode :: Nil =>
- val (cols, directions) = children.map {
- case Token("TOK_TABSORTCOLNAMEASC", Token(col, Nil) :: Nil) => (col, Ascending)
- case Token("TOK_TABSORTCOLNAMEDESC", Token(col, Nil) :: Nil) => (col, Descending)
- }.unzip
- (cols, directions, numBucketsNode.text.toInt)
- case numBucketsNode :: Nil =>
- (Nil, Nil, numBucketsNode.text.toInt)
- case _ =>
- parseFailed("Invalid ALTER TABLE command", node)
- }
- }
- AlterTableStorageProperties(
- tableIdent,
- BucketSpec(numBuckets, clusterCols, sortCols))(node.source)
-
- // ALTER TABLE table_name NOT CLUSTERED
- case Token("TOK_ALTERTABLE_CLUSTER_SORT", Token("TOK_NOT_CLUSTERED", Nil) :: Nil) :: _ =>
- AlterTableNotClustered(tableIdent)(node.source)
-
- // ALTER TABLE table_name NOT SORTED
- case Token("TOK_ALTERTABLE_CLUSTER_SORT", Token("TOK_NOT_SORTED", Nil) :: Nil) :: _ =>
- AlterTableNotSorted(tableIdent)(node.source)
-
- // ALTER TABLE table_name SKEWED BY (col1, col2)
- // ON ((col1_value, col2_value) [, (col1_value, col2_value), ...])
- // [STORED AS DIRECTORIES];
- case Token("TOK_ALTERTABLE_SKEWED",
- Token("TOK_TABLESKEWED",
- Token("TOK_TABCOLNAME", colNames) :: colValues :: rest) :: Nil) :: _ =>
- // Example format:
- //
- // TOK_ALTERTABLE_SKEWED
- // :- TOK_TABLESKEWED
- // : :- TOK_TABCOLNAME
- // : : :- dt
- // : : +- country
- // :- TOK_TABCOLVALUE_PAIR
- // : :- TOK_TABCOLVALUES
- // : : :- TOK_TABCOLVALUE
- // : : : :- '2008-08-08'
- // : : : +- 'us'
- // : :- TOK_TABCOLVALUES
- // : : :- TOK_TABCOLVALUE
- // : : : :- '2009-09-09'
- // : : : +- 'uk'
- // +- TOK_STOREASDIR
- val names = colNames.map { n => cleanAndUnquoteString(n.text) }
- val values = colValues match {
- case Token("TOK_TABCOLVALUE", vals) =>
- Seq(vals.map { n => cleanAndUnquoteString(n.text) })
- case Token("TOK_TABCOLVALUE_PAIR", pairs) =>
- pairs.map {
- case Token("TOK_TABCOLVALUES", Token("TOK_TABCOLVALUE", vals) :: Nil) =>
- vals.map { n => cleanAndUnquoteString(n.text) }
- case _ =>
- parseFailed("Invalid ALTER TABLE command", node)
- }
- case _ =>
- parseFailed("Invalid ALTER TABLE command", node)
- }
- val storedAsDirs = rest match {
- case Token("TOK_STOREDASDIRS", Nil) :: Nil => true
- case _ => false
- }
- AlterTableSkewed(
- tableIdent,
- names,
- values,
- storedAsDirs)(node.source)
-
- // ALTER TABLE table_name NOT SKEWED
- case Token("TOK_ALTERTABLE_SKEWED", Nil) :: _ =>
- AlterTableNotSkewed(tableIdent)(node.source)
-
- // ALTER TABLE table_name NOT STORED AS DIRECTORIES
- case Token("TOK_ALTERTABLE_SKEWED", Token("TOK_STOREDASDIRS", Nil) :: Nil) :: _ =>
- AlterTableNotStoredAsDirs(tableIdent)(node.source)
-
- // ALTER TABLE table_name SET SKEWED LOCATION (col1="loc1" [, (col2, col3)="loc2", ...] );
- case Token("TOK_ALTERTABLE_SKEWED_LOCATION",
- Token("TOK_SKEWED_LOCATIONS",
- Token("TOK_SKEWED_LOCATION_LIST", locationMaps) :: Nil) :: Nil) :: _ =>
- // Example format:
- //
- // TOK_ALTERTABLE_SKEWED_LOCATION
- // +- TOK_SKEWED_LOCATIONS
- // +- TOK_SKEWED_LOCATION_LIST
- // :- TOK_SKEWED_LOCATION_MAP
- // : :- 'col1'
- // : +- 'loc1'
- // +- TOK_SKEWED_LOCATION_MAP
- // :- TOK_TABCOLVALUES
- // : +- TOK_TABCOLVALUE
- // : :- 'col2'
- // : +- 'col3'
- // +- 'loc2'
- val skewedMaps = locationMaps.flatMap {
- case Token("TOK_SKEWED_LOCATION_MAP", col :: loc :: Nil) =>
- col match {
- case Token(const, Nil) =>
- Seq((cleanAndUnquoteString(const), cleanAndUnquoteString(loc.text)))
- case Token("TOK_TABCOLVALUES", Token("TOK_TABCOLVALUE", keys) :: Nil) =>
- keys.map { k => (cleanAndUnquoteString(k.text), cleanAndUnquoteString(loc.text)) }
- }
- case _ =>
- parseFailed("Invalid ALTER TABLE command", node)
- }.toMap
- AlterTableSkewedLocation(tableIdent, skewedMaps)(node.source)
-
- // ALTER TABLE table_name ADD [IF NOT EXISTS] PARTITION spec [LOCATION 'loc1']
- // spec [LOCATION 'loc2'] ...;
- case Token("TOK_ALTERTABLE_ADDPARTS", args) :: _ =>
- val (ifNotExists, parts) = args.head match {
- case Token("TOK_IFNOTEXISTS", Nil) => (true, args.tail)
- case _ => (false, args)
- }
- // List of (spec, location) to describe partitions to add
- // Each partition spec may or may not be followed by a location
- val parsedParts = new ArrayBuffer[(TablePartitionSpec, Option[String])]
- parts.foreach {
- case t @ Token("TOK_PARTSPEC", _) =>
- parsedParts += ((parsePartitionSpec(t), None))
- case Token("TOK_PARTITIONLOCATION", loc :: Nil) =>
- // Update the location of the last partition we just added
- if (parsedParts.nonEmpty) {
- val (spec, _) = parsedParts.remove(parsedParts.length - 1)
- parsedParts += ((spec, Some(unquoteString(loc.text))))
- }
- case _ =>
- parseFailed("Invalid ALTER TABLE command", node)
- }
- AlterTableAddPartition(tableIdent, parsedParts, ifNotExists)(node.source)
-
- // ALTER TABLE table_name PARTITION spec1 RENAME TO PARTITION spec2;
- case Token("TOK_ALTERTABLE_RENAMEPART", spec :: Nil) :: _ =>
- val newPartition = parsePartitionSpec(spec)
- val oldPartition = partition.getOrElse {
- parseFailed("Expected old partition spec in ALTER TABLE rename partition command", node)
- }
- AlterTableRenamePartition(tableIdent, oldPartition, newPartition)(node.source)
-
- // ALTER TABLE table_name_1 EXCHANGE PARTITION spec WITH TABLE table_name_2;
- case Token("TOK_ALTERTABLE_EXCHANGEPARTITION", spec :: newTable :: Nil) :: _ =>
- val parsedSpec = parsePartitionSpec(spec)
- val newTableIdent = extractTableIdent(newTable)
- AlterTableExchangePartition(tableIdent, newTableIdent, parsedSpec)(node.source)
-
- // ALTER TABLE table_name DROP [IF EXISTS] PARTITION spec1[, PARTITION spec2, ...] [PURGE];
- case Token("TOK_ALTERTABLE_DROPPARTS", args) :: _ =>
- val parts = args.collect { case p @ Token("TOK_PARTSPEC", _) => parsePartitionSpec(p) }
- val ifExists = getClauseOption("TOK_IFEXISTS", args).isDefined
- val purge = getClauseOption("PURGE", args).isDefined
- AlterTableDropPartition(tableIdent, parts, ifExists, purge)(node.source)
-
- // ALTER TABLE table_name ARCHIVE PARTITION spec;
- case Token("TOK_ALTERTABLE_ARCHIVE", spec :: Nil) :: _ =>
- AlterTableArchivePartition(tableIdent, parsePartitionSpec(spec))(node.source)
-
- // ALTER TABLE table_name UNARCHIVE PARTITION spec;
- case Token("TOK_ALTERTABLE_UNARCHIVE", spec :: Nil) :: _ =>
- AlterTableUnarchivePartition(tableIdent, parsePartitionSpec(spec))(node.source)
-
- // ALTER TABLE table_name [PARTITION spec] SET FILEFORMAT file_format;
- case Token("TOK_ALTERTABLE_FILEFORMAT", args) :: _ =>
- val Seq(fileFormat, genericFormat) =
- getClauses(Seq("TOK_TABLEFILEFORMAT", "TOK_FILEFORMAT_GENERIC"), args)
- // Note: the AST doesn't contain information about which file format is being set here.
- // E.g. we can't differentiate between INPUTFORMAT and OUTPUTFORMAT if either is set.
- // Right now this just stores the values, but we should figure out how to get the keys.
- val fFormat = fileFormat
- .map { _.children.map { n => cleanAndUnquoteString(n.text) }}
- .getOrElse(Seq())
- val gFormat = genericFormat.map { f => cleanAndUnquoteString(f.children(0).text) }
- AlterTableSetFileFormat(tableIdent, partition, fFormat, gFormat)(node.source)
-
- // ALTER TABLE table_name [PARTITION spec] SET LOCATION "loc";
- case Token("TOK_ALTERTABLE_LOCATION", Token(loc, Nil) :: Nil) :: _ =>
- AlterTableSetLocation(tableIdent, partition, cleanAndUnquoteString(loc))(node.source)
-
- // ALTER TABLE table_name TOUCH [PARTITION spec];
- case Token("TOK_ALTERTABLE_TOUCH", args) :: _ =>
- // Note: the partition spec, if it exists, comes after TOUCH, so `partition` should
- // always be None here. Instead, we need to parse it from the TOUCH node's children.
- val part = getClauseOption("TOK_PARTSPEC", args).map(parsePartitionSpec)
- AlterTableTouch(tableIdent, part)(node.source)
-
- // ALTER TABLE table_name [PARTITION spec] COMPACT 'compaction_type';
- case Token("TOK_ALTERTABLE_COMPACT", Token(compactType, Nil) :: Nil) :: _ =>
- AlterTableCompact(tableIdent, partition, cleanAndUnquoteString(compactType))(node.source)
-
- // ALTER TABLE table_name [PARTITION spec] CONCATENATE;
- case Token("TOK_ALTERTABLE_MERGEFILES", _) :: _ =>
- AlterTableMerge(tableIdent, partition)(node.source)
-
- // ALTER TABLE table_name [PARTITION spec] CHANGE [COLUMN] col_old_name col_new_name
- // column_type [COMMENT col_comment] [FIRST|AFTER column_name] [CASCADE|RESTRICT];
- case Token("TOK_ALTERTABLE_RENAMECOL", oldName :: newName :: dataType :: args) :: _ =>
- val afterColName: Option[String] =
- getClauseOption("TOK_ALTERTABLE_CHANGECOL_AFTER_POSITION", args).map { ap =>
- ap.children match {
- case Token(col, Nil) :: Nil => col
- case _ => parseFailed("Invalid ALTER TABLE command", node)
- }
- }
- val restrict = getClauseOption("TOK_RESTRICT", args).isDefined
- val cascade = getClauseOption("TOK_CASCADE", args).isDefined
- val comment = args.headOption.map {
- case Token("TOK_ALTERTABLE_CHANGECOL_AFTER_POSITION", _) => null
- case Token("TOK_RESTRICT", _) => null
- case Token("TOK_CASCADE", _) => null
- case Token(commentStr, Nil) => cleanAndUnquoteString(commentStr)
- case _ => parseFailed("Invalid ALTER TABLE command", node)
- }
- AlterTableChangeCol(
- tableIdent,
- partition,
- oldName.text,
- newName.text,
- nodeToDataType(dataType),
- comment,
- afterColName,
- restrict,
- cascade)(node.source)
-
- // ALTER TABLE table_name [PARTITION spec] ADD COLUMNS (name type [COMMENT comment], ...)
- // [CASCADE|RESTRICT]
- case Token("TOK_ALTERTABLE_ADDCOLS", args) :: _ =>
- val columnNodes = getClause("TOK_TABCOLLIST", args).children
- val columns = StructType(columnNodes.map(nodeToStructField))
- val restrict = getClauseOption("TOK_RESTRICT", args).isDefined
- val cascade = getClauseOption("TOK_CASCADE", args).isDefined
- AlterTableAddCol(tableIdent, partition, columns, restrict, cascade)(node.source)
-
- // ALTER TABLE table_name [PARTITION spec] REPLACE COLUMNS (name type [COMMENT comment], ...)
- // [CASCADE|RESTRICT]
- case Token("TOK_ALTERTABLE_REPLACECOLS", args) :: _ =>
- val columnNodes = getClause("TOK_TABCOLLIST", args).children
- val columns = StructType(columnNodes.map(nodeToStructField))
- val restrict = getClauseOption("TOK_RESTRICT", args).isDefined
- val cascade = getClauseOption("TOK_CASCADE", args).isDefined
- AlterTableReplaceCol(tableIdent, partition, columns, restrict, cascade)(node.source)
-
- case _ =>
- parseFailed("Unsupported ALTER TABLE command", node)
- }
- }
-
-}
diff --git a/sql/core/src/main/scala/org/apache/spark/sql/internal/SQLConf.scala b/sql/core/src/main/scala/org/apache/spark/sql/internal/SQLConf.scala
index d06e9086a3..6cc72fba48 100644
--- a/sql/core/src/main/scala/org/apache/spark/sql/internal/SQLConf.scala
+++ b/sql/core/src/main/scala/org/apache/spark/sql/internal/SQLConf.scala
@@ -26,7 +26,6 @@ import org.apache.parquet.hadoop.ParquetOutputCommitter
import org.apache.spark.internal.Logging
import org.apache.spark.sql.catalyst.CatalystConf
-import org.apache.spark.sql.catalyst.parser.ParserConf
import org.apache.spark.util.Utils
////////////////////////////////////////////////////////////////////////////////////////////////////
@@ -500,19 +499,6 @@ object SQLConf {
doc = "When true, we could use `datasource`.`path` as table in SQL query."
)
- val PARSER_SUPPORT_QUOTEDID = booleanConf("spark.sql.parser.supportQuotedIdentifiers",
- defaultValue = Some(true),
- isPublic = false,
- doc = "Whether to use quoted identifier.\n false: default(past) behavior. Implies only" +
- "alphaNumeric and underscore are valid characters in identifiers.\n" +
- " true: implies column names can contain any character.")
-
- val PARSER_SUPPORT_SQL11_RESERVED_KEYWORDS = booleanConf(
- "spark.sql.parser.supportSQL11ReservedKeywords",
- defaultValue = Some(false),
- isPublic = false,
- doc = "This flag should be set to true to enable support for SQL2011 reserved keywords.")
-
val WHOLESTAGE_CODEGEN_ENABLED = booleanConf("spark.sql.codegen.wholeStage",
defaultValue = Some(true),
doc = "When true, the whole stage (of multiple operators) will be compiled into single java" +
@@ -573,7 +559,7 @@ object SQLConf {
*
* SQLConf is thread-safe (internally synchronized, so safe to be used in multiple threads).
*/
-class SQLConf extends Serializable with CatalystConf with ParserConf with Logging {
+class SQLConf extends Serializable with CatalystConf with Logging {
import SQLConf._
/** Only low degree of contention is expected for conf, thus NOT using ConcurrentHashMap. */
@@ -674,10 +660,6 @@ class SQLConf extends Serializable with CatalystConf with ParserConf with Loggin
def runSQLOnFile: Boolean = getConf(RUN_SQL_ON_FILES)
- def supportQuotedId: Boolean = getConf(PARSER_SUPPORT_QUOTEDID)
-
- def supportSQL11ReservedKeywords: Boolean = getConf(PARSER_SUPPORT_SQL11_RESERVED_KEYWORDS)
-
override def orderByOrdinal: Boolean = getConf(ORDER_BY_ORDINAL)
override def groupByOrdinal: Boolean = getConf(GROUP_BY_ORDINAL)