Skip to content

Commit cdd1752

Browse files
MaxGekkdongjoon-hyun
authored andcommitted
[SPARK-33862][SQL] Throw PartitionAlreadyExistsException if the target partition exists while renaming
### What changes were proposed in this pull request? Throw `PartitionAlreadyExistsException` from `ALTER TABLE .. RENAME TO PARTITION` for a table from Hive V1 External Catalog in the case when the target partition already exists. ### Why are the changes needed? 1. To have the same behavior of V1 In-Memory and Hive External Catalog. 2. To not propagate internal Hive's exceptions to users. ### Does this PR introduce _any_ user-facing change? Yes. After the changes, the partition renaming command throws `PartitionAlreadyExistsException` for tables from the Hive catalog. ### How was this patch tested? Added new UT: ``` $ build/sbt -Phive-2.3 -Phive-thriftserver "test:testOnly *HiveCatalogedDDLSuite" ``` Closes apache#30866 from MaxGekk/throw-PartitionAlreadyExistsException. Authored-by: Max Gekk <[email protected]> Signed-off-by: Dongjoon Hyun <[email protected]>
1 parent f4e1069 commit cdd1752

File tree

2 files changed

+11
-2
lines changed

2 files changed

+11
-2
lines changed

sql/core/src/test/scala/org/apache/spark/sql/execution/command/DDLSuite.scala

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ import org.apache.spark.internal.config
2929
import org.apache.spark.internal.config.RDD_PARALLEL_LISTING_THRESHOLD
3030
import org.apache.spark.sql.{AnalysisException, QueryTest, Row, SaveMode}
3131
import org.apache.spark.sql.catalyst.{FunctionIdentifier, QualifiedTableName, TableIdentifier}
32-
import org.apache.spark.sql.catalyst.analysis.{FunctionRegistry, NoSuchDatabaseException, NoSuchFunctionException, NoSuchPartitionException, TempTableAlreadyExistsException}
32+
import org.apache.spark.sql.catalyst.analysis.{FunctionRegistry, NoSuchDatabaseException, NoSuchFunctionException, NoSuchPartitionException, PartitionAlreadyExistsException, TempTableAlreadyExistsException}
3333
import org.apache.spark.sql.catalyst.catalog._
3434
import org.apache.spark.sql.catalyst.catalog.CatalogTypes.TablePartitionSpec
3535
import org.apache.spark.sql.connector.catalog.SupportsNamespaces.PROP_OWNER
@@ -1635,6 +1635,12 @@ abstract class DDLSuite extends QueryTest with SQLTestUtils {
16351635
sql("ALTER TABLE tab1 PARTITION (A='10', B='p') RENAME TO PARTITION (A='1', B='p')")
16361636
assert(catalog.listPartitions(tableIdent).map(_.spec).toSet ==
16371637
Set(Map("a" -> "1", "b" -> "p"), Map("a" -> "20", "b" -> "c"), Map("a" -> "3", "b" -> "p")))
1638+
1639+
// target partition already exists
1640+
val errMsg = intercept[PartitionAlreadyExistsException] {
1641+
sql("ALTER TABLE tab1 PARTITION (a='1', b='p') RENAME TO PARTITION (a='20', b='c')")
1642+
}.getMessage
1643+
assert(errMsg.contains("Partition already exists"))
16381644
}
16391645

16401646
protected def testChangeColumn(isDatasourceTable: Boolean): Unit = {

sql/hive/src/main/scala/org/apache/spark/sql/hive/client/HiveClientImpl.scala

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,7 @@ import org.apache.spark.internal.Logging
4949
import org.apache.spark.metrics.source.HiveCatalogMetrics
5050
import org.apache.spark.sql.AnalysisException
5151
import org.apache.spark.sql.catalyst.TableIdentifier
52-
import org.apache.spark.sql.catalyst.analysis.{NoSuchDatabaseException, NoSuchPartitionException, NoSuchPartitionsException, PartitionsAlreadyExistException}
52+
import org.apache.spark.sql.catalyst.analysis.{NoSuchDatabaseException, NoSuchPartitionException, NoSuchPartitionsException, PartitionAlreadyExistsException, PartitionsAlreadyExistException}
5353
import org.apache.spark.sql.catalyst.catalog._
5454
import org.apache.spark.sql.catalyst.catalog.CatalogTypes.TablePartitionSpec
5555
import org.apache.spark.sql.catalyst.expressions.Expression
@@ -665,6 +665,9 @@ private[hive] class HiveClientImpl(
665665
val catalogTable = getTable(db, table)
666666
val hiveTable = toHiveTable(catalogTable, Some(userName))
667667
specs.zip(newSpecs).foreach { case (oldSpec, newSpec) =>
668+
if (client.getPartition(hiveTable, newSpec.asJava, false) != null) {
669+
throw new PartitionAlreadyExistsException(db, table, newSpec)
670+
}
668671
val hivePart = getPartitionOption(catalogTable, oldSpec)
669672
.map { p => toHivePartition(p.copy(spec = newSpec), hiveTable) }
670673
.getOrElse { throw new NoSuchPartitionException(db, table, oldSpec) }

0 commit comments

Comments
 (0)