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

JingsongLi pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/paimon.git


The following commit(s) were added to refs/heads/master by this push:
     new 8f46a6285f [common] Compare maps of different representations without 
throwing (#9211)
8f46a6285f is described below

commit 8f46a6285ff8a8550aec8ef2fc552c1c350d25f9
Author: ZIHAN DAI <[email protected]>
AuthorDate: Sat Aug 15 16:34:33 2026 +1000

    [common] Compare maps of different representations without throwing (#9211)
---
 .../org/apache/paimon/utils/InternalRowUtils.java  | 29 ++++++++----------
 .../apache/paimon/utils/InternalRowUtilsTest.java  | 34 ++++++++++++++++++++++
 2 files changed, 46 insertions(+), 17 deletions(-)

diff --git 
a/paimon-common/src/main/java/org/apache/paimon/utils/InternalRowUtils.java 
b/paimon-common/src/main/java/org/apache/paimon/utils/InternalRowUtils.java
index 4c329797f3..8fb0b8f805 100644
--- a/paimon-common/src/main/java/org/apache/paimon/utils/InternalRowUtils.java
+++ b/paimon-common/src/main/java/org/apache/paimon/utils/InternalRowUtils.java
@@ -91,23 +91,12 @@ public class InternalRowUtils {
                     return false;
                 }
                 MapType mapType = (MapType) dataType;
-                GenericMap map1;
-                GenericMap map2;
-                if (data1 instanceof GenericMap) {
-                    map1 = (GenericMap) data1;
-                    map2 = (GenericMap) data2;
-                } else {
-                    map1 =
-                            copyToGenericMap(
-                                    (InternalMap) data1,
-                                    mapType.getKeyType(),
-                                    mapType.getValueType());
-                    map2 =
-                            copyToGenericMap(
-                                    (InternalMap) data2,
-                                    mapType.getKeyType(),
-                                    mapType.getValueType());
-                }
+                // Decide per operand. One MapType is represented by 
GenericMap, BinaryMap or
+                // ColumnarMap interchangeably -- which is why the conversion 
below exists at all --
+                // so gating data2's cast on data1's concrete class threw 
ClassCastException
+                // whenever the two sides happened to use different 
representations.
+                GenericMap map1 = toGenericMap((InternalMap) data1, mapType);
+                GenericMap map2 = toGenericMap((InternalMap) data2, mapType);
                 InternalArray keyArray1 = map1.keyArray();
                 InternalArray keyArray2 = map2.keyArray();
                 InternalArray valueArray1 = map1.valueArray();
@@ -284,6 +273,12 @@ public class InternalRowUtils {
         return copyToGenericMap(map, keyType, valueType);
     }
 
+    private static GenericMap toGenericMap(InternalMap map, MapType mapType) {
+        return map instanceof GenericMap
+                ? (GenericMap) map
+                : copyToGenericMap(map, mapType.getKeyType(), 
mapType.getValueType());
+    }
+
     private static GenericMap copyToGenericMap(
             InternalMap map, DataType keyType, DataType valueType) {
         Map<Object, Object> javaMap = new HashMap<>();
diff --git 
a/paimon-common/src/test/java/org/apache/paimon/utils/InternalRowUtilsTest.java 
b/paimon-common/src/test/java/org/apache/paimon/utils/InternalRowUtilsTest.java
index dec1ab4ad6..fb14c024ac 100644
--- 
a/paimon-common/src/test/java/org/apache/paimon/utils/InternalRowUtilsTest.java
+++ 
b/paimon-common/src/test/java/org/apache/paimon/utils/InternalRowUtilsTest.java
@@ -18,6 +18,9 @@
 
 package org.apache.paimon.utils;
 
+import org.apache.paimon.data.BinaryArray;
+import org.apache.paimon.data.BinaryArrayWriter;
+import org.apache.paimon.data.BinaryMap;
 import org.apache.paimon.data.BinaryRow;
 import org.apache.paimon.data.BinaryString;
 import org.apache.paimon.data.BinaryVector;
@@ -33,6 +36,7 @@ import org.apache.paimon.datagen.DataGenerator;
 import org.apache.paimon.datagen.RandomGeneratorVisitor;
 import org.apache.paimon.datagen.RowDataGenerator;
 import org.apache.paimon.options.Options;
+import org.apache.paimon.types.DataType;
 import org.apache.paimon.types.DataTypeRoot;
 import org.apache.paimon.types.DataTypes;
 import org.apache.paimon.types.RowType;
@@ -299,4 +303,34 @@ public class InternalRowUtilsTest {
         rowWithMap2.setField(0, new GenericMap(map2));
         assertThat(InternalRowUtils.equals(rowWithMap1, rowWithMap2, 
rowType2)).isFalse();
     }
+
+    @Test
+    public void testEqualsAcrossMapImplementations() {
+        DataType mapType = DataTypes.MAP(DataTypes.STRING(), DataTypes.INT());
+
+        Map<Object, Object> entries = new HashMap<>();
+        entries.put(BinaryString.fromString("a"), 1);
+        GenericMap generic = new GenericMap(entries);
+
+        BinaryArray keys = new BinaryArray();
+        BinaryArrayWriter keyWriter = new BinaryArrayWriter(keys, 1, 8);
+        keyWriter.writeString(0, BinaryString.fromString("a"));
+        keyWriter.complete();
+        BinaryArray values = new BinaryArray();
+        BinaryArrayWriter valueWriter = new BinaryArrayWriter(values, 1, 4);
+        valueWriter.writeInt(0, 1);
+        valueWriter.complete();
+        BinaryMap binary = BinaryMap.valueOf(keys, values);
+
+        // hash() already treats the two representations as interchangeable, 
so equals() throwing
+        // for one ordering is the inconsistency being fixed here.
+        assertThat(InternalRowUtils.hash(generic, mapType))
+                .isEqualTo(InternalRowUtils.hash(binary, mapType));
+
+        // Both orderings must agree. Only the generic-first one changes: it 
used to pick the
+        // GenericMap fast path off data1 and then cast data2 to GenericMap 
unconditionally,
+        // throwing ClassCastException for a BinaryMap.
+        assertThat(InternalRowUtils.equals(generic, binary, mapType)).isTrue();
+        assertThat(InternalRowUtils.equals(binary, generic, mapType)).isTrue();
+    }
 }

Reply via email to