@@ -331,6 +331,35 @@ public void testValidateCaseInsensitive() {
331331 checkValidationFails (pinotSchema , true );
332332 }
333333
334+ /**
335+ * Case-only column collisions (e.g. memberId / MemberID) are rejected when case-insensitive mode is on.
336+ * Cluster default is enable.case.insensitive=true, so new schemas on default clusters are already protected.
337+ * When case-insensitive mode is off, collisions are allowed (always-on rejection needs validation levels #6645).
338+ */
339+ @ Test
340+ public void testValidateCaseOnlyColumnCollision () {
341+ Schema collidingSchema = new Schema .SchemaBuilder ().setSchemaName (TABLE_NAME )
342+ .addSingleValueDimension ("memberId" , DataType .STRING )
343+ .addSingleValueDimension ("MemberID" , DataType .STRING )
344+ .addDateTime (TIME_COLUMN , DataType .LONG , "1:MILLISECONDS:EPOCH" , "1:MILLISECONDS" )
345+ .build ();
346+
347+ // Default cluster path: enable.case.insensitive=true rejects case-only collisions
348+ checkValidationFails (collidingSchema , true );
349+
350+ // Case-sensitive mode still allows collisions (compat; do not force always-on without #6645)
351+ SchemaUtils .validate (collidingSchema , false );
352+
353+ // Distinct after lowercasing is fine even when case-insensitive
354+ Schema distinctSchema = new Schema .SchemaBuilder ().setSchemaName (TABLE_NAME )
355+ .addSingleValueDimension ("memberId" , DataType .STRING )
356+ .addSingleValueDimension ("memberName" , DataType .STRING )
357+ .addDateTime (TIME_COLUMN , DataType .LONG , "1:MILLISECONDS:EPOCH" , "1:MILLISECONDS" )
358+ .build ();
359+ SchemaUtils .validate (distinctSchema , true );
360+ SchemaUtils .validate (distinctSchema , false );
361+ }
362+
334363 @ Test
335364 public void testValidatePrimaryKeyColumns () {
336365 Schema pinotSchema ;
0 commit comments