This is an automated email from the ASF dual-hosted git repository.
dkuzmenko pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/hive.git
The following commit(s) were added to refs/heads/master by this push:
new 12d88d912cb HIVE-29093 : ALTER TABLE ADD PARTITION fails if the
DEFAULT_PARTITION_NAME property is a substring of partition value to be added
(#5977)
12d88d912cb is described below
commit 12d88d912cb04c35d5a872492f5b2d65bb186dbd
Author: Vikram Ahuja <[email protected]>
AuthorDate: Tue Jul 22 12:29:54 2025 +0530
HIVE-29093 : ALTER TABLE ADD PARTITION fails if the DEFAULT_PARTITION_NAME
property is a substring of partition value to be added (#5977)
---
.../ql/ddl/table/partition/PartitionUtils.java | 46 ++++++++++------
.../apache/hadoop/hive/ql/metadata/TestHive.java | 44 +++++++++++++++
.../clientpositive/alter_table_add_partition.q | 17 ++++++
ql/src/test/results/clientnegative/archive5.q.out | 2 +-
.../clientnegative/default_partition_name.q.out | 2 +-
.../llap/alter_table_add_partition.q.out | 62 ++++++++++++++++++++++
6 files changed, 154 insertions(+), 19 deletions(-)
diff --git
a/ql/src/java/org/apache/hadoop/hive/ql/ddl/table/partition/PartitionUtils.java
b/ql/src/java/org/apache/hadoop/hive/ql/ddl/table/partition/PartitionUtils.java
index 3f6181f425f..db7a5dfcd3d 100644
---
a/ql/src/java/org/apache/hadoop/hive/ql/ddl/table/partition/PartitionUtils.java
+++
b/ql/src/java/org/apache/hadoop/hive/ql/ddl/table/partition/PartitionUtils.java
@@ -56,30 +56,42 @@ private PartitionUtils() {
}
/**
- * Certain partition values are are used by hive. e.g. the default partition
in dynamic partitioning and the
+ * Certain partition values are used by hive. e.g. the default partition in
dynamic partitioning and the
* intermediate partition values used in the archiving process. Naturally,
prohibit the user from creating partitions
* with these reserved values. The check that this function is more
restrictive than the actual limitation, but it's
* simpler. Should be okay since the reserved names are fairly long and
uncommon.
*/
- public static void validatePartitions(HiveConf conf, Map<String, String>
partitionSpec) throws SemanticException {
- Set<String> reservedPartitionValues = new HashSet<>();
+ public static void validatePartitions(HiveConf conf, Map<String, String>
partitionSpec) {
// Partition can't have this name
- reservedPartitionValues.add(HiveConf.getVar(conf,
ConfVars.DEFAULT_PARTITION_NAME));
- reservedPartitionValues.add(HiveConf.getVar(conf,
ConfVars.DEFAULT_ZOOKEEPER_PARTITION_NAME));
+ Set<String> reservedPartitionValues =
+ new HashSet<String>() {{
+ add(HiveConf.getVar(conf, ConfVars.DEFAULT_PARTITION_NAME));
+ add(HiveConf.getVar(conf,
ConfVars.DEFAULT_ZOOKEEPER_PARTITION_NAME));
+ }};
+
// Partition value can't end in this suffix
- reservedPartitionValues.add(HiveConf.getVar(conf,
ConfVars.METASTORE_INT_ORIGINAL));
- reservedPartitionValues.add(HiveConf.getVar(conf,
ConfVars.METASTORE_INT_ARCHIVED));
- reservedPartitionValues.add(HiveConf.getVar(conf,
ConfVars.METASTORE_INT_EXTRACTED));
-
- for (Entry<String, String> e : partitionSpec.entrySet()) {
- for (String s : reservedPartitionValues) {
- String value = e.getValue();
- if (value != null && value.contains(s)) {
- throw new SemanticException(ErrorMsg.RESERVED_PART_VAL.getMsg(
- "(User value: " + e.getValue() + " Reserved substring: " + s +
")"));
- }
+ Set<String> reservedPartitionSuffixes =
+ new HashSet<String>() {{
+ add(HiveConf.getVar(conf, ConfVars.METASTORE_INT_ORIGINAL));
+ add(HiveConf.getVar(conf, ConfVars.METASTORE_INT_ARCHIVED));
+ add(HiveConf.getVar(conf, ConfVars.METASTORE_INT_EXTRACTED));
+ }};
+
+ partitionSpec.forEach((key, value) -> {
+ if (value == null) {
+ return;
}
- }
+ reservedPartitionValues.stream().filter(value::equals).findAny()
+ .ifPresent(s -> {
+ throw new RuntimeException(ErrorMsg.RESERVED_PART_VAL.getMsg(
+ "(User value: " + value + " Reserved string: " + s + ")"));
+ });
+ reservedPartitionSuffixes.stream().filter(value::endsWith).findAny()
+ .ifPresent(s -> {
+ throw new RuntimeException(ErrorMsg.RESERVED_PART_VAL.getMsg(
+ "(User value: " + value + " Partition value cannot end with
Reserved substring: " + s + ")"));
+ });
+ });
}
public static ExprNodeGenericFuncDesc makeBinaryPredicate(String fn,
ExprNodeDesc left, ExprNodeDesc right)
diff --git a/ql/src/test/org/apache/hadoop/hive/ql/metadata/TestHive.java
b/ql/src/test/org/apache/hadoop/hive/ql/metadata/TestHive.java
index a55551357d2..4c0ab53ea2d 100755
--- a/ql/src/test/org/apache/hadoop/hive/ql/metadata/TestHive.java
+++ b/ql/src/test/org/apache/hadoop/hive/ql/metadata/TestHive.java
@@ -422,6 +422,50 @@ public void testHiveCloseCurrent() throws Throwable {
assertTrue(hive1 != hive2);
}
+ @Test
+ public void testValidatePartitions() {
+ Map<String, String> partitionSpec = new HashMap<>();
+
+ partitionSpec.put("a", HiveConf.getVar(hiveConf,
ConfVars.DEFAULT_PARTITION_NAME));
+ Assert.assertThrows(RuntimeException.class, () ->
PartitionUtils.validatePartitions(hiveConf, partitionSpec));
+
+ partitionSpec.clear();
+ partitionSpec.put("a", HiveConf.getVar(hiveConf,
ConfVars.DEFAULT_ZOOKEEPER_PARTITION_NAME));
+ Assert.assertThrows(RuntimeException.class, () ->
PartitionUtils.validatePartitions(hiveConf, partitionSpec));
+
+ partitionSpec.clear();
+ partitionSpec.put("a", "random" + HiveConf.getVar(hiveConf,
ConfVars.DEFAULT_PARTITION_NAME) + "partition");
+ PartitionUtils.validatePartitions(hiveConf, partitionSpec);
+
+ partitionSpec.clear();
+ partitionSpec.put("a", "random" + HiveConf.getVar(hiveConf,
ConfVars.DEFAULT_ZOOKEEPER_PARTITION_NAME) + "partition");
+ PartitionUtils.validatePartitions(hiveConf, partitionSpec);
+
+ partitionSpec.clear();
+ partitionSpec.put("a", HiveConf.getVar(hiveConf,
ConfVars.METASTORE_INT_ORIGINAL));
+ Assert.assertThrows(RuntimeException.class, () ->
PartitionUtils.validatePartitions(hiveConf, partitionSpec));
+
+ partitionSpec.clear();
+ partitionSpec.put("a", HiveConf.getVar(hiveConf,
ConfVars.METASTORE_INT_ARCHIVED));
+ Assert.assertThrows(RuntimeException.class, () ->
PartitionUtils.validatePartitions(hiveConf, partitionSpec));
+
+ partitionSpec.clear();
+ partitionSpec.put("a", HiveConf.getVar(hiveConf,
ConfVars.METASTORE_INT_EXTRACTED));
+ Assert.assertThrows(RuntimeException.class, () ->
PartitionUtils.validatePartitions(hiveConf, partitionSpec));
+
+ partitionSpec.clear();
+ partitionSpec.put("a", "random_part" + HiveConf.getVar(hiveConf,
ConfVars.METASTORE_INT_ORIGINAL));
+ Assert.assertThrows(RuntimeException.class, () ->
PartitionUtils.validatePartitions(hiveConf, partitionSpec));
+
+ partitionSpec.clear();
+ partitionSpec.put("a", "random_part" + HiveConf.getVar(hiveConf,
ConfVars.METASTORE_INT_ARCHIVED));
+ Assert.assertThrows(RuntimeException.class, () ->
PartitionUtils.validatePartitions(hiveConf, partitionSpec));
+
+ partitionSpec.clear();
+ partitionSpec.put("a", "random_part" + HiveConf.getVar(hiveConf,
ConfVars.METASTORE_INT_EXTRACTED));
+ Assert.assertThrows(RuntimeException.class, () ->
PartitionUtils.validatePartitions(hiveConf, partitionSpec));
+ }
+
@Test
public void testGetAndDropTables() throws Throwable {
try {
diff --git a/ql/src/test/queries/clientpositive/alter_table_add_partition.q
b/ql/src/test/queries/clientpositive/alter_table_add_partition.q
index 54c839b921f..d8822e445db 100644
--- a/ql/src/test/queries/clientpositive/alter_table_add_partition.q
+++ b/ql/src/test/queries/clientpositive/alter_table_add_partition.q
@@ -11,3 +11,20 @@ insert into mp partition (b=1) values (1);
desc formatted mp;
desc formatted mp partition (b=1);
+
+drop table test_part;
+create table test_part(a int) partitioned by (b string);
+
+alter table test_part add partition(b='one');
+
+set hive.exec.default.partition.name=random;
+
+alter table test_part add partition(b='random_access_memory');
+
+show partitions test_part;
+
+alter table test_part add partition(b='partition_random');
+
+show partitions test_part;
+
+drop table test_part;
diff --git a/ql/src/test/results/clientnegative/archive5.q.out
b/ql/src/test/results/clientnegative/archive5.q.out
index 1b0cafd70ff..58397bea92b 100644
--- a/ql/src/test/results/clientnegative/archive5.q.out
+++ b/ql/src/test/results/clientnegative/archive5.q.out
@@ -1 +1 @@
-FAILED: SemanticException [Error 10111]: Partition value contains a reserved
substring (User value: 14_INTERMEDIATE_ORIGINAL Reserved substring:
_INTERMEDIATE_ORIGINAL)
+FAILED: RuntimeException [Error 10111]: Partition value contains a reserved
substring (User value: 14_INTERMEDIATE_ORIGINAL Partition value cannot end with
Reserved substring: _INTERMEDIATE_ORIGINAL)
diff --git a/ql/src/test/results/clientnegative/default_partition_name.q.out
b/ql/src/test/results/clientnegative/default_partition_name.q.out
index f0add0a8a67..84ee3bd6d4d 100644
--- a/ql/src/test/results/clientnegative/default_partition_name.q.out
+++ b/ql/src/test/results/clientnegative/default_partition_name.q.out
@@ -6,4 +6,4 @@ POSTHOOK: query: create table default_partition_name (key int,
value string) par
POSTHOOK: type: CREATETABLE
POSTHOOK: Output: database:default
POSTHOOK: Output: default@default_partition_name
-FAILED: SemanticException [Error 10111]: Partition value contains a reserved
substring (User value: __HIVE_DEFAULT_PARTITION__ Reserved substring:
__HIVE_DEFAULT_PARTITION__)
+FAILED: RuntimeException [Error 10111]: Partition value contains a reserved
substring (User value: __HIVE_DEFAULT_PARTITION__ Reserved string:
__HIVE_DEFAULT_PARTITION__)
diff --git
a/ql/src/test/results/clientpositive/llap/alter_table_add_partition.q.out
b/ql/src/test/results/clientpositive/llap/alter_table_add_partition.q.out
index e39285901f0..465f5717d6c 100644
--- a/ql/src/test/results/clientpositive/llap/alter_table_add_partition.q.out
+++ b/ql/src/test/results/clientpositive/llap/alter_table_add_partition.q.out
@@ -211,3 +211,65 @@ Bucket Columns: []
Sort Columns: []
Storage Desc Params:
serialization.format 1
+PREHOOK: query: drop table test_part
+PREHOOK: type: DROPTABLE
+PREHOOK: Output: database:default
+POSTHOOK: query: drop table test_part
+POSTHOOK: type: DROPTABLE
+POSTHOOK: Output: database:default
+PREHOOK: query: create table test_part(a int) partitioned by (b string)
+PREHOOK: type: CREATETABLE
+PREHOOK: Output: database:default
+PREHOOK: Output: default@test_part
+POSTHOOK: query: create table test_part(a int) partitioned by (b string)
+POSTHOOK: type: CREATETABLE
+POSTHOOK: Output: database:default
+POSTHOOK: Output: default@test_part
+PREHOOK: query: alter table test_part add partition(b='one')
+PREHOOK: type: ALTERTABLE_ADDPARTS
+PREHOOK: Output: default@test_part
+POSTHOOK: query: alter table test_part add partition(b='one')
+POSTHOOK: type: ALTERTABLE_ADDPARTS
+POSTHOOK: Output: default@test_part
+POSTHOOK: Output: default@test_part@b=one
+PREHOOK: query: alter table test_part add partition(b='random_access_memory')
+PREHOOK: type: ALTERTABLE_ADDPARTS
+PREHOOK: Output: default@test_part
+POSTHOOK: query: alter table test_part add partition(b='random_access_memory')
+POSTHOOK: type: ALTERTABLE_ADDPARTS
+POSTHOOK: Output: default@test_part
+POSTHOOK: Output: default@test_part@b=random_access_memory
+PREHOOK: query: show partitions test_part
+PREHOOK: type: SHOWPARTITIONS
+PREHOOK: Input: default@test_part
+POSTHOOK: query: show partitions test_part
+POSTHOOK: type: SHOWPARTITIONS
+POSTHOOK: Input: default@test_part
+b=one
+b=random_access_memory
+PREHOOK: query: alter table test_part add partition(b='partition_random')
+PREHOOK: type: ALTERTABLE_ADDPARTS
+PREHOOK: Output: default@test_part
+POSTHOOK: query: alter table test_part add partition(b='partition_random')
+POSTHOOK: type: ALTERTABLE_ADDPARTS
+POSTHOOK: Output: default@test_part
+POSTHOOK: Output: default@test_part@b=partition_random
+PREHOOK: query: show partitions test_part
+PREHOOK: type: SHOWPARTITIONS
+PREHOOK: Input: default@test_part
+POSTHOOK: query: show partitions test_part
+POSTHOOK: type: SHOWPARTITIONS
+POSTHOOK: Input: default@test_part
+b=one
+b=partition_random
+b=random_access_memory
+PREHOOK: query: drop table test_part
+PREHOOK: type: DROPTABLE
+PREHOOK: Input: default@test_part
+PREHOOK: Output: database:default
+PREHOOK: Output: default@test_part
+POSTHOOK: query: drop table test_part
+POSTHOOK: type: DROPTABLE
+POSTHOOK: Input: default@test_part
+POSTHOOK: Output: database:default
+POSTHOOK: Output: default@test_part