Skip to content

[SPARK-16459][SQL] Prevent dropping current database #14115

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

Closed
wants to merge 6 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.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,10 @@ import org.apache.spark.sql.catalyst.expressions.{Expression, ExpressionInfo}
import org.apache.spark.sql.catalyst.plans.logical.{LogicalPlan, SubqueryAlias}
import org.apache.spark.sql.catalyst.util.StringUtils

object SessionCatalog {
val DEFAULT_DATABASE = "default"
}

/**
* An internal catalog that is used by a Spark Session. This internal catalog serves as a
* proxy to the underlying metastore (e.g. Hive Metastore) and it also manages temporary
Expand All @@ -47,6 +51,7 @@ class SessionCatalog(
functionRegistry: FunctionRegistry,
conf: CatalystConf,
hadoopConf: Configuration) extends Logging {
import SessionCatalog._
import CatalogTypes.TablePartitionSpec

// For testing only.
Expand Down Expand Up @@ -77,7 +82,7 @@ class SessionCatalog(
// the corresponding item in the current database.
@GuardedBy("this")
protected var currentDb = {
val defaultName = "default"
val defaultName = DEFAULT_DATABASE
val defaultDbDefinition =
CatalogDatabase(defaultName, "default database", conf.warehousePath, Map())
// Initialize default database if it doesn't already exist
Expand Down Expand Up @@ -146,8 +151,10 @@ class SessionCatalog(

def dropDatabase(db: String, ignoreIfNotExists: Boolean, cascade: Boolean): Unit = {
val dbName = formatDatabaseName(db)
if (dbName == "default") {
if (dbName == DEFAULT_DATABASE) {
throw new AnalysisException(s"Can not drop default database")
} else if (dbName == getCurrentDatabase) {
Copy link
Contributor

Choose a reason for hiding this comment

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

do we need to check case sensitivity?

Copy link
Member Author

Choose a reason for hiding this comment

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

Oops. formatDatabaseName returns the raw string for case sensitive case.
Hm. That is the same situation with "default" database, isn't?

Copy link
Member Author

Choose a reason for hiding this comment

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

I'll add two testcases for both and fix this.

Copy link
Member Author

@dongjoon-hyun dongjoon-hyun Jul 9, 2016

Choose a reason for hiding this comment

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

Oh, I was confused. For case sensitive case, we don't need to handle that.
Dropping with different names will fails due to lookup failure.

throw new AnalysisException(s"Can not drop current database `${dbName}`")
}
externalCatalog.dropDatabase(dbName, ignoreIfNotExists, cascade)
}
Expand Down Expand Up @@ -878,14 +885,14 @@ class SessionCatalog(
* This is mainly used for tests.
*/
private[sql] def reset(): Unit = synchronized {
val default = "default"
listDatabases().filter(_ != default).foreach { db =>
setCurrentDatabase(DEFAULT_DATABASE)
listDatabases().filter(_ != DEFAULT_DATABASE).foreach { db =>
dropDatabase(db, ignoreIfNotExists = false, cascade = true)
}
listTables(default).foreach { table =>
listTables(DEFAULT_DATABASE).foreach { table =>
dropTable(table, ignoreIfNotExists = false)
}
listFunctions(default).map(_._1).foreach { func =>
listFunctions(DEFAULT_DATABASE).map(_._1).foreach { func =>
if (func.database.isDefined) {
dropFunction(func, ignoreIfNotExists = false)
} else {
Expand All @@ -902,7 +909,6 @@ class SessionCatalog(
require(functionBuilder.isDefined, s"built-in function '$f' is missing function builder")
functionRegistry.registerFunction(f, expressionInfo.get, functionBuilder.get)
}
setCurrentDatabase(default)
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -1270,6 +1270,15 @@ class DDLSuite extends QueryTest with SharedSQLContext with BeforeAndAfterEach {
"WITH SERDEPROPERTIES ('spark.sql.sources.me'='anything')")
}

test("drop current database") {
sql("CREATE DATABASE temp")
sql("USE temp")
val m = intercept[AnalysisException] {
sql("DROP DATABASE temp")
}.getMessage
assert(m.contains("Can not drop current database `temp`"))
}

test("drop default database") {
Seq("true", "false").foreach { caseSensitive =>
withSQLConf(SQLConf.CASE_SENSITIVE.key -> caseSensitive) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,7 @@ class HiveContextCompatibilitySuite extends SparkFunSuite with BeforeAndAfterEac
hc.sql("DROP TABLE mee_table")
val tables2 = hc.sql("SHOW TABLES IN mee_db").collect().map(_.getString(0))
assert(tables2.isEmpty)
hc.sql("USE default")
hc.sql("DROP DATABASE mee_db CASCADE")
val databases3 = hc.sql("SHOW DATABASES").collect().map(_.getString(0))
assert(databases3.toSeq == Seq("default"))
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -472,6 +472,7 @@ class HiveDDLSuite
sql(s"DROP TABLE $tabName")

assert(tmpDir.listFiles.isEmpty)
sql("USE default")
sql(s"DROP DATABASE $dbName")
assert(!fs.exists(new Path(tmpDir.toString)))
}
Expand Down Expand Up @@ -526,6 +527,7 @@ class HiveDDLSuite
assert(!tableDirectoryExists(TableIdentifier(tabName), Option(expectedDBLocation)))
}

sql(s"USE default")
val sqlDropDatabase = s"DROP DATABASE $dbName ${if (cascade) "CASCADE" else "RESTRICT"}"
if (tableExists && !cascade) {
val message = intercept[AnalysisException] {
Expand Down