This is an automated email from the ASF dual-hosted git repository.

Jackie-Jiang pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/pinot.git


The following commit(s) were added to refs/heads/master by this push:
     new 7ecf65743e6 Harden schema case-collision validation with Locale.ROOT 
(#19089)
7ecf65743e6 is described below

commit 7ecf65743e676497d4fad4de0a0fd6098715764c
Author: deepinsight coder <[email protected]>
AuthorDate: Tue Jul 28 14:30:24 2026 -0700

    Harden schema case-collision validation with Locale.ROOT (#19089)
---
 .../apache/pinot/core/util/SchemaUtilsTest.java    | 29 ++++++++++++++++++++++
 .../pinot/segment/local/utils/SchemaUtils.java     |  8 +++---
 2 files changed, 34 insertions(+), 3 deletions(-)

diff --git 
a/pinot-core/src/test/java/org/apache/pinot/core/util/SchemaUtilsTest.java 
b/pinot-core/src/test/java/org/apache/pinot/core/util/SchemaUtilsTest.java
index a335a66fe36..f2d4f07df81 100644
--- a/pinot-core/src/test/java/org/apache/pinot/core/util/SchemaUtilsTest.java
+++ b/pinot-core/src/test/java/org/apache/pinot/core/util/SchemaUtilsTest.java
@@ -331,6 +331,35 @@ public class SchemaUtilsTest {
     checkValidationFails(pinotSchema, true);
   }
 
+  /**
+   * Case-only column collisions (e.g. memberId / MemberID) are rejected when 
case-insensitive mode is on.
+   * Cluster default is enable.case.insensitive=true, so new schemas on 
default clusters are already protected.
+   * When case-insensitive mode is off, collisions are allowed (always-on 
rejection needs validation levels #6645).
+   */
+  @Test
+  public void testValidateCaseOnlyColumnCollision() {
+    Schema collidingSchema = new 
Schema.SchemaBuilder().setSchemaName(TABLE_NAME)
+        .addSingleValueDimension("memberId", DataType.STRING)
+        .addSingleValueDimension("MemberID", DataType.STRING)
+        .addDateTime(TIME_COLUMN, DataType.LONG, "1:MILLISECONDS:EPOCH", 
"1:MILLISECONDS")
+        .build();
+
+    // Default cluster path: enable.case.insensitive=true rejects case-only 
collisions
+    checkValidationFails(collidingSchema, true);
+
+    // Case-sensitive mode still allows collisions (compat; do not force 
always-on without #6645)
+    SchemaUtils.validate(collidingSchema, false);
+
+    // Distinct after lowercasing is fine even when case-insensitive
+    Schema distinctSchema = new 
Schema.SchemaBuilder().setSchemaName(TABLE_NAME)
+        .addSingleValueDimension("memberId", DataType.STRING)
+        .addSingleValueDimension("memberName", DataType.STRING)
+        .addDateTime(TIME_COLUMN, DataType.LONG, "1:MILLISECONDS:EPOCH", 
"1:MILLISECONDS")
+        .build();
+    SchemaUtils.validate(distinctSchema, true);
+    SchemaUtils.validate(distinctSchema, false);
+  }
+
   @Test
   public void testValidatePrimaryKeyColumns() {
     Schema pinotSchema;
diff --git 
a/pinot-segment-local/src/main/java/org/apache/pinot/segment/local/utils/SchemaUtils.java
 
b/pinot-segment-local/src/main/java/org/apache/pinot/segment/local/utils/SchemaUtils.java
index 7bcfbc053b6..99ec4d9ddc2 100644
--- 
a/pinot-segment-local/src/main/java/org/apache/pinot/segment/local/utils/SchemaUtils.java
+++ 
b/pinot-segment-local/src/main/java/org/apache/pinot/segment/local/utils/SchemaUtils.java
@@ -23,6 +23,7 @@ import java.util.Collections;
 import java.util.HashMap;
 import java.util.HashSet;
 import java.util.List;
+import java.util.Locale;
 import java.util.Map;
 import java.util.Set;
 import org.apache.commons.lang3.StringUtils;
@@ -121,9 +122,10 @@ public class SchemaUtils {
     if (isIgnoreCase) {
       Set<String> lowerCaseColumnNames = new HashSet<>();
       for (String column : schema.getColumnNames()) {
-        
Preconditions.checkState(lowerCaseColumnNames.add(column.toLowerCase()),
-            "When enable case insensitive, you can't use the same lowercase 
column name: %s",
-            column.toLowerCase());
+        // Locale.ROOT avoids locale-dependent lowercasing (e.g. Turkish 
dotted/dotless I)
+        String lowerCaseColumn = column.toLowerCase(Locale.ROOT);
+        Preconditions.checkState(lowerCaseColumnNames.add(lowerCaseColumn),
+            "When enable case insensitive, you can't use the same lowercase 
column name: %s", lowerCaseColumn);
       }
     }
     Set<String> transformedColumns = new HashSet<>();


---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to