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 22585b6 [SPARK-37478][SQL][TESTS][FOLLOWUP] Unify v1 and v2 DROP
NAMESPACE error
22585b6 is described below
commit 22585b62d83b1594ad237651354e354949f137b7
Author: dch nguyen <[email protected]>
AuthorDate: Thu Dec 30 16:59:54 2021 +0800
[SPARK-37478][SQL][TESTS][FOLLOWUP] Unify v1 and v2 DROP NAMESPACE error
### What changes were proposed in this pull request?
According to
[#cmt](https://github.com/apache/spark/pull/34819#discussion_r763629569), unify
the error of v1, v2 and hive external catalog in DROP NAMESPACE tests.
### Why are the changes needed?
Currently, v1 and hive external catalog command throw `AnalysisException`,
while v2 command throws `SparkException`. The error messages of v1 and hive
catalog are also completely different from v2.
So this PR is for unifying those errors to `AnalysisException`. The error
message will have one difference between v1/hive and v2: `Cannot drop a
non-empty database: ...` vs `Cannot drop a non-empty namespace: ...`
### Does this PR introduce _any_ user-facing change?
No
### How was this patch tested?
v1/v2 and Hive v1 DropNamespaceSuite:
```$ build/sbt -Phive-2.3 -Phive-thriftserver "test:testOnly
*DropNamespaceSuite"```
Closes #35007 from dchvn/unify_dropnamespace_error.
Authored-by: dch nguyen <[email protected]>
Signed-off-by: Wenchen Fan <[email protected]>
---
.../apache/spark/sql/catalyst/catalog/InMemoryCatalog.scala | 7 ++-----
.../org/apache/spark/sql/errors/QueryCompilationErrors.scala | 10 ++++++++--
.../org/apache/spark/sql/errors/QueryExecutionErrors.scala | 6 ------
.../sql/execution/datasources/v2/DropNamespaceExec.scala | 6 +++---
.../spark/sql/execution/command/DropNamespaceSuiteBase.scala | 7 +++++--
.../spark/sql/execution/command/v1/DropNamespaceSuite.scala | 7 +------
.../spark/sql/execution/command/v2/DropNamespaceSuite.scala | 11 +----------
.../scala/org/apache/spark/sql/hive/HiveExternalCatalog.scala | 11 ++++++++++-
.../org/apache/spark/sql/hive/execution/HiveDDLSuite.scala | 2 +-
9 files changed, 31 insertions(+), 36 deletions(-)
diff --git
a/sql/catalyst/src/main/scala/org/apache/spark/sql/catalyst/catalog/InMemoryCatalog.scala
b/sql/catalyst/src/main/scala/org/apache/spark/sql/catalyst/catalog/InMemoryCatalog.scala
index c10e0bb..e3896c5 100644
---
a/sql/catalyst/src/main/scala/org/apache/spark/sql/catalyst/catalog/InMemoryCatalog.scala
+++
b/sql/catalyst/src/main/scala/org/apache/spark/sql/catalyst/catalog/InMemoryCatalog.scala
@@ -139,11 +139,8 @@ class InMemoryCatalog(
if (catalog.contains(db)) {
if (!cascade) {
// If cascade is false, make sure the database is empty.
- if (catalog(db).tables.nonEmpty) {
- throw QueryCompilationErrors.databaseNotEmptyError(db, "tables")
- }
- if (catalog(db).functions.nonEmpty) {
- throw QueryCompilationErrors.databaseNotEmptyError(db, "functions")
+ if (catalog(db).tables.nonEmpty || catalog(db).functions.nonEmpty) {
+ throw QueryCompilationErrors.cannotDropNonemptyDatabaseError(db)
}
}
// Remove the database.
diff --git
a/sql/catalyst/src/main/scala/org/apache/spark/sql/errors/QueryCompilationErrors.scala
b/sql/catalyst/src/main/scala/org/apache/spark/sql/errors/QueryCompilationErrors.scala
index 300ba03..7284d06 100644
---
a/sql/catalyst/src/main/scala/org/apache/spark/sql/errors/QueryCompilationErrors.scala
+++
b/sql/catalyst/src/main/scala/org/apache/spark/sql/errors/QueryCompilationErrors.scala
@@ -540,8 +540,14 @@ object QueryCompilationErrors {
s"rename temporary view from '$oldName' to '$newName': destination view
already exists")
}
- def databaseNotEmptyError(db: String, details: String): Throwable = {
- new AnalysisException(s"Database $db is not empty. One or more $details
exist.")
+ def cannotDropNonemptyDatabaseError(db: String): Throwable = {
+ new AnalysisException(s"Cannot drop a non-empty database: $db. " +
+ "Use CASCADE option to drop a non-empty database.")
+ }
+
+ def cannotDropNonemptyNamespaceError(namespace: Seq[String]): Throwable = {
+ new AnalysisException(s"Cannot drop a non-empty namespace:
${namespace.quoted}. " +
+ "Use CASCADE option to drop a non-empty namespace.")
}
def invalidNameForTableOrDatabaseError(name: String): Throwable = {
diff --git
a/sql/catalyst/src/main/scala/org/apache/spark/sql/errors/QueryExecutionErrors.scala
b/sql/catalyst/src/main/scala/org/apache/spark/sql/errors/QueryExecutionErrors.scala
index eb6e814..4ec57dd 100644
---
a/sql/catalyst/src/main/scala/org/apache/spark/sql/errors/QueryExecutionErrors.scala
+++
b/sql/catalyst/src/main/scala/org/apache/spark/sql/errors/QueryExecutionErrors.scala
@@ -610,12 +610,6 @@ object QueryExecutionErrors {
"Schema of v1 relation: " + v1Schema)
}
- def cannotDropNonemptyNamespaceError(namespace: Seq[String]): Throwable = {
- new SparkException(
- s"Cannot drop a non-empty namespace: ${namespace.quoted}. " +
- "Use CASCADE option to drop a non-empty namespace.")
- }
-
def noRecordsFromEmptyDataReaderError(): Throwable = {
new IOException("No records should be returned from EmptyDataReader")
}
diff --git
a/sql/core/src/main/scala/org/apache/spark/sql/execution/datasources/v2/DropNamespaceExec.scala
b/sql/core/src/main/scala/org/apache/spark/sql/execution/datasources/v2/DropNamespaceExec.scala
index dbd5cbd..9a9d8e1 100644
---
a/sql/core/src/main/scala/org/apache/spark/sql/execution/datasources/v2/DropNamespaceExec.scala
+++
b/sql/core/src/main/scala/org/apache/spark/sql/execution/datasources/v2/DropNamespaceExec.scala
@@ -20,7 +20,7 @@ package org.apache.spark.sql.execution.datasources.v2
import org.apache.spark.sql.catalyst.InternalRow
import org.apache.spark.sql.catalyst.expressions.Attribute
import org.apache.spark.sql.connector.catalog.CatalogPlugin
-import org.apache.spark.sql.errors.{QueryCompilationErrors,
QueryExecutionErrors}
+import org.apache.spark.sql.errors.QueryCompilationErrors
/**
* Physical plan node for dropping a namespace.
@@ -42,12 +42,12 @@ case class DropNamespaceExec(
if (!cascade) {
if (catalog.asTableCatalog.listTables(ns).nonEmpty
|| nsCatalog.listNamespaces(ns).nonEmpty) {
- throw
QueryExecutionErrors.cannotDropNonemptyNamespaceError(namespace)
+ throw
QueryCompilationErrors.cannotDropNonemptyNamespaceError(namespace)
}
}
if (!nsCatalog.dropNamespace(ns)) {
- throw QueryExecutionErrors.cannotDropNonemptyNamespaceError(namespace)
+ throw
QueryCompilationErrors.cannotDropNonemptyNamespaceError(namespace)
}
} else if (!ifExists) {
throw QueryCompilationErrors.noSuchNamespaceError(ns)
diff --git
a/sql/core/src/test/scala/org/apache/spark/sql/execution/command/DropNamespaceSuiteBase.scala
b/sql/core/src/test/scala/org/apache/spark/sql/execution/command/DropNamespaceSuiteBase.scala
index 1ff4e1b..376f376 100644
---
a/sql/core/src/test/scala/org/apache/spark/sql/execution/command/DropNamespaceSuiteBase.scala
+++
b/sql/core/src/test/scala/org/apache/spark/sql/execution/command/DropNamespaceSuiteBase.scala
@@ -36,7 +36,7 @@ trait DropNamespaceSuiteBase extends QueryTest with
DDLCommandTestUtils {
protected def builtinTopNamespaces: Seq[String] = Seq.empty
protected def isCasePreserving: Boolean = true
- protected def assertDropFails(): Unit
+ protected def namespaceAlias: String = "namespace"
protected def checkNamespace(expected: Seq[String]) = {
val df = spark.sql(s"SHOW NAMESPACES IN $catalog")
@@ -72,7 +72,10 @@ trait DropNamespaceSuiteBase extends QueryTest with
DDLCommandTestUtils {
checkNamespace(Seq("ns") ++ builtinTopNamespaces)
// $catalog.ns.table is present, thus $catalog.ns cannot be dropped.
- assertDropFails()
+ val e = intercept[AnalysisException] {
+ sql(s"DROP NAMESPACE $catalog.ns")
+ }
+ assert(e.getMessage.contains(s"Cannot drop a non-empty $namespaceAlias:
ns"))
sql(s"DROP TABLE $catalog.ns.table")
// Now that $catalog.ns is empty, it can be dropped.
diff --git
a/sql/core/src/test/scala/org/apache/spark/sql/execution/command/v1/DropNamespaceSuite.scala
b/sql/core/src/test/scala/org/apache/spark/sql/execution/command/v1/DropNamespaceSuite.scala
index 2db4423..24e5131 100644
---
a/sql/core/src/test/scala/org/apache/spark/sql/execution/command/v1/DropNamespaceSuite.scala
+++
b/sql/core/src/test/scala/org/apache/spark/sql/execution/command/v1/DropNamespaceSuite.scala
@@ -31,12 +31,7 @@ import org.apache.spark.sql.execution.command
trait DropNamespaceSuiteBase extends command.DropNamespaceSuiteBase {
override protected def builtinTopNamespaces: Seq[String] = Seq("default")
- override protected def assertDropFails(): Unit = {
- val e = intercept[AnalysisException] {
- sql(s"DROP NAMESPACE $catalog.ns")
- }
- assert(e.getMessage.contains("Database ns is not empty. One or more tables
exist"))
- }
+ override protected def namespaceAlias(): String = "database"
test("drop default namespace") {
val message = intercept[AnalysisException] {
diff --git
a/sql/core/src/test/scala/org/apache/spark/sql/execution/command/v2/DropNamespaceSuite.scala
b/sql/core/src/test/scala/org/apache/spark/sql/execution/command/v2/DropNamespaceSuite.scala
index ddc913e..6f82ee5 100644
---
a/sql/core/src/test/scala/org/apache/spark/sql/execution/command/v2/DropNamespaceSuite.scala
+++
b/sql/core/src/test/scala/org/apache/spark/sql/execution/command/v2/DropNamespaceSuite.scala
@@ -17,18 +17,9 @@
package org.apache.spark.sql.execution.command.v2
-import org.apache.spark.SparkException
import org.apache.spark.sql.execution.command
/**
* The class contains tests for the `DROP NAMESPACE` command to check V2 table
catalogs.
*/
-class DropNamespaceSuite extends command.DropNamespaceSuiteBase with
CommandSuiteBase {
- // TODO: Unify the error that throws from v1 and v2 test suite into
`AnalysisException`
- override protected def assertDropFails(): Unit = {
- val e = intercept[SparkException] {
- sql(s"DROP NAMESPACE $catalog.ns")
- }
- assert(e.getMessage.contains("Cannot drop a non-empty namespace: ns"))
- }
-}
+class DropNamespaceSuite extends command.DropNamespaceSuiteBase with
CommandSuiteBase
diff --git
a/sql/hive/src/main/scala/org/apache/spark/sql/hive/HiveExternalCatalog.scala
b/sql/hive/src/main/scala/org/apache/spark/sql/hive/HiveExternalCatalog.scala
index 5fccce2..52b2159 100644
---
a/sql/hive/src/main/scala/org/apache/spark/sql/hive/HiveExternalCatalog.scala
+++
b/sql/hive/src/main/scala/org/apache/spark/sql/hive/HiveExternalCatalog.scala
@@ -41,6 +41,7 @@ import org.apache.spark.sql.catalyst.catalog._
import org.apache.spark.sql.catalyst.catalog.ExternalCatalogUtils._
import org.apache.spark.sql.catalyst.expressions._
import org.apache.spark.sql.catalyst.util.{CaseInsensitiveMap,
CharVarcharUtils}
+import org.apache.spark.sql.errors.QueryCompilationErrors
import org.apache.spark.sql.execution.command.DDLUtils
import org.apache.spark.sql.execution.datasources.{PartitioningUtils,
SourceOptions}
import org.apache.spark.sql.hive.client.HiveClient
@@ -196,7 +197,15 @@ private[spark] class HiveExternalCatalog(conf: SparkConf,
hadoopConf: Configurat
db: String,
ignoreIfNotExists: Boolean,
cascade: Boolean): Unit = withClient {
- client.dropDatabase(db, ignoreIfNotExists, cascade)
+ try {
+ client.dropDatabase(db, ignoreIfNotExists, cascade)
+ } catch {
+ case NonFatal(exception) =>
+ if
(exception.getClass.getName.equals("org.apache.hadoop.hive.ql.metadata.HiveException")
+ && exception.getMessage.contains(s"Database $db is not empty.")) {
+ throw QueryCompilationErrors.cannotDropNonemptyDatabaseError(db)
+ } else throw exception
+ }
}
/**
diff --git
a/sql/hive/src/test/scala/org/apache/spark/sql/hive/execution/HiveDDLSuite.scala
b/sql/hive/src/test/scala/org/apache/spark/sql/hive/execution/HiveDDLSuite.scala
index 3bf3ee5..014feb3 100644
---
a/sql/hive/src/test/scala/org/apache/spark/sql/hive/execution/HiveDDLSuite.scala
+++
b/sql/hive/src/test/scala/org/apache/spark/sql/hive/execution/HiveDDLSuite.scala
@@ -1235,7 +1235,7 @@ class HiveDDLSuite
if (tableExists && !cascade) {
assertAnalysisError(
sqlDropDatabase,
- s"Database $dbName is not empty. One or more tables exist.")
+ s"Cannot drop a non-empty database: $dbName.")
// the database directory was not removed
assert(fs.exists(new Path(expectedDBLocation)))
} else {
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]