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

Reply via email to