Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[SPARK-19115] [SQL] Supporting Create External Table Like Location #16638

Closed
wants to merge 7 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,7 @@ statement
(TBLPROPERTIES tablePropertyList)?
(AS? query)? #createHiveTable
| CREATE TABLE (IF NOT EXISTS)? target=tableIdentifier
LIKE source=tableIdentifier #createTableLike
LIKE source=tableIdentifier locationSpec? #createTableLike
| ANALYZE TABLE tableIdentifier partitionSpec? COMPUTE STATISTICS
(identifier | FOR COLUMNS identifierSeq)? #analyze
| ALTER (TABLE | VIEW) from=tableIdentifier
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1141,13 +1141,14 @@ class SparkSqlAstBuilder(conf: SQLConf) extends AstBuilder {
* For example:
* {{{
* CREATE TABLE [IF NOT EXISTS] [db_name.]table_name
* LIKE [other_db_name.]existing_table_name
* LIKE [other_db_name.]existing_table_name [locationSpec]
* }}}
*/
override def visitCreateTableLike(ctx: CreateTableLikeContext): LogicalPlan = withOrigin(ctx) {
val targetTable = visitTableIdentifier(ctx.target)
val sourceTable = visitTableIdentifier(ctx.source)
CreateTableLikeCommand(targetTable, sourceTable, ctx.EXISTS != null)
val location = Option(ctx.locationSpec).map(visitLocationSpec)
CreateTableLikeCommand(targetTable, sourceTable, location, ctx.EXISTS != null)
}

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ import org.apache.spark.sql.types._
import org.apache.spark.util.Utils

/**
* A command to create a MANAGED table with the same definition of the given existing table.
* A command to create a table with the same definition of the given existing table.
* In the target table definition, the table comment is always empty but the column comments
* are identical to the ones defined in the source table.
*
Expand All @@ -52,12 +52,13 @@ import org.apache.spark.util.Utils
* The syntax of using this command in SQL is:
* {{{
* CREATE TABLE [IF NOT EXISTS] [db_name.]table_name
* LIKE [other_db_name.]existing_table_name
* LIKE [other_db_name.]existing_table_name [locationSpec]
* }}}
*/
case class CreateTableLikeCommand(
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please update the comment of this class.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ok,i will update it later,Thanks!

targetTable: TableIdentifier,
sourceTable: TableIdentifier,
location: Option[String],
ifNotExists: Boolean) extends RunnableCommand {

override def run(sparkSession: SparkSession): Seq[Row] = {
Expand All @@ -70,12 +71,19 @@ case class CreateTableLikeCommand(
sourceTableDesc.provider
}

// If location is specified, we create an external table internally.
// Else create managed table.
val tblType = if (location.isEmpty) {
CatalogTableType.MANAGED
} else {
CatalogTableType.EXTERNAL
}

val newTableDesc =
CatalogTable(
identifier = targetTable,
tableType = CatalogTableType.MANAGED,
// We are creating a new managed table, which should not have custom table location.
storage = sourceTableDesc.storage.copy(locationUri = None),
tableType = tblType,
storage = sourceTableDesc.storage.copy(locationUri = location),
schema = sourceTableDesc.schema,
provider = newProvider,
partitionColumnNames = sourceTableDesc.partitionColumnNames,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -387,11 +387,11 @@ class HiveDDLCommandSuite extends PlanTest with SQLTestUtils with TestHiveSingle
val query2 = s"$baseQuery SERDE 'org.apache.poof.serde.Baff' WITH SERDEPROPERTIES ('k1'='v1')"
val query3 =
s"""
|$baseQuery DELIMITED FIELDS TERMINATED BY 'x' ESCAPED BY 'y'
|COLLECTION ITEMS TERMINATED BY 'a'
|MAP KEYS TERMINATED BY 'b'
|LINES TERMINATED BY '\n'
|NULL DEFINED AS 'c'
|$baseQuery DELIMITED FIELDS TERMINATED BY 'x' ESCAPED BY 'y'
|COLLECTION ITEMS TERMINATED BY 'a'
|MAP KEYS TERMINATED BY 'b'
|LINES TERMINATED BY '\n'
|NULL DEFINED AS 'c'
""".stripMargin
val (desc1, _) = extractTableDesc(query1)
val (desc2, _) = extractTableDesc(query2)
Expand Down Expand Up @@ -518,24 +518,48 @@ class HiveDDLCommandSuite extends PlanTest with SQLTestUtils with TestHiveSingle

test("create table like") {
val v1 = "CREATE TABLE table1 LIKE table2"
val (target, source, exists) = parser.parsePlan(v1).collect {
case CreateTableLikeCommand(t, s, allowExisting) => (t, s, allowExisting)
val (target, source, location, exists) = parser.parsePlan(v1).collect {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

add an assert to check location is empty

case CreateTableLikeCommand(t, s, l, allowExisting) => (t, s, l, allowExisting)
}.head
assert(exists == false)
assert(target.database.isEmpty)
assert(target.table == "table1")
assert(source.database.isEmpty)
assert(source.table == "table2")
assert(location.isEmpty)

val v2 = "CREATE TABLE IF NOT EXISTS table1 LIKE table2"
val (target2, source2, exists2) = parser.parsePlan(v2).collect {
case CreateTableLikeCommand(t, s, allowExisting) => (t, s, allowExisting)
val (target2, source2, location2, exists2) = parser.parsePlan(v2).collect {
case CreateTableLikeCommand(t, s, l, allowExisting) => (t, s, l, allowExisting)
}.head
assert(exists2)
assert(target2.database.isEmpty)
assert(target2.table == "table1")
assert(source2.database.isEmpty)
assert(source2.table == "table2")
assert(location2.isEmpty)

val v3 = "CREATE TABLE table1 LIKE table2 LOCATION '/spark/warehouse'"
val (target3, source3, location3, exists3) = parser.parsePlan(v3).collect {
case CreateTableLikeCommand(t, s, l, allowExisting) => (t, s, l, allowExisting)
}.head
assert(!exists3)
assert(target3.database.isEmpty)
assert(target3.table == "table1")
assert(source3.database.isEmpty)
assert(source3.table == "table2")
assert(location3 == Some("/spark/warehouse"))

val v4 = "CREATE TABLE IF NOT EXISTS table1 LIKE table2 LOCATION '/spark/warehouse'"
val (target4, source4, location4, exists4) = parser.parsePlan(v4).collect {
case CreateTableLikeCommand(t, s, l, allowExisting) => (t, s, l, allowExisting)
}.head
assert(exists4)
assert(target4.database.isEmpty)
assert(target4.table == "table1")
assert(source4.database.isEmpty)
assert(source4.table == "table2")
assert(location4 == Some("/spark/warehouse"))
}

test("load data") {
Expand Down