diff --git a/paimon-core/src/main/java/org/apache/paimon/mergetree/compact/aggregate/BinaryMapKeys.java b/paimon-core/src/main/java/org/apache/paimon/mergetree/compact/aggregate/BinaryMapKeys.java
index 5fc1eb68e4fe..4a2e1df3880e 100644
--- a/paimon-core/src/main/java/org/apache/paimon/mergetree/compact/aggregate/BinaryMapKeys.java
+++ b/paimon-core/src/main/java/org/apache/paimon/mergetree/compact/aggregate/BinaryMapKeys.java
@@ -20,14 +20,15 @@
import org.apache.paimon.data.GenericMap;
import org.apache.paimon.types.DataType;
-import org.apache.paimon.types.DataTypeFamily;
+import org.apache.paimon.types.DataTypeRoot;
import org.apache.paimon.utils.ByteArrayKey;
import java.util.HashMap;
import java.util.Map;
/**
- * Value semantics for map keys of type {@code BINARY} or {@code VARBINARY}.
+ * Value semantics for map keys of type {@code BINARY}, {@code VARBINARY}, {@code GEOMETRY} or
+ * {@code GEOGRAPHY}.
*
*
Such a key arrives as a {@code byte[]}, which inherits identity equality from {@link Object}.
* Used directly as a hash key, two keys with the same content occupy two entries, a lookup never
@@ -39,8 +40,18 @@ final class BinaryMapKeys {
private BinaryMapKeys() {}
- static boolean isBinary(DataType keyType) {
- return keyType.getTypeRoot().getFamilies().contains(DataTypeFamily.BINARY_STRING);
+ /**
+ * Whether values of this type are held as a {@code byte[]}. This is the set of roots that
+ * {@link org.apache.paimon.data.InternalArray#createElementGetter} reads with {@code
+ * getBinary}: {@code BINARY} and {@code VARBINARY}, plus {@code GEOMETRY} and {@code GEOGRAPHY}
+ * whose in-memory value is WKB.
+ */
+ static boolean isBinary(DataType type) {
+ return type.isAnyOf(
+ DataTypeRoot.BINARY,
+ DataTypeRoot.VARBINARY,
+ DataTypeRoot.GEOMETRY,
+ DataTypeRoot.GEOGRAPHY);
}
/** Wrap a key for storage in a hash collection; a no-op for every non-binary key type. */
diff --git a/paimon-core/src/main/java/org/apache/paimon/mergetree/compact/aggregate/FieldCollectAgg.java b/paimon-core/src/main/java/org/apache/paimon/mergetree/compact/aggregate/FieldCollectAgg.java
index 368ae685a960..60f60e82ce93 100644
--- a/paimon-core/src/main/java/org/apache/paimon/mergetree/compact/aggregate/FieldCollectAgg.java
+++ b/paimon-core/src/main/java/org/apache/paimon/mergetree/compact/aggregate/FieldCollectAgg.java
@@ -36,7 +36,6 @@
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
-import java.util.Set;
import java.util.function.BiFunction;
import static org.apache.paimon.codegen.CodeGenUtils.newRecordEqualiser;
@@ -55,7 +54,9 @@ public FieldCollectAgg(String name, ArrayType dataType, boolean distinct) {
this.distinct = distinct;
this.elementGetter = InternalArray.createElementGetter(dataType.getElementType());
- if (distinct && needsEqualiser(dataType.getElementType())) {
+ // The equaliser is built from the element type alone: retract() needs it whether or not
+ // the array is distinct, and agg() gates de-duplication on 'distinct' separately.
+ if (needsEqualiser(dataType.getElementType())) {
DataType elementType = dataType.getElementType();
List fieldTypes =
elementType instanceof RowType
@@ -83,14 +84,13 @@ public FieldCollectAgg(String name, ArrayType dataType, boolean distinct) {
* Whether elements of this type need the generated equaliser rather than {@link Object#equals}.
*
*
Constructed types need it because two rows holding the same values are not necessarily
- * equal objects. Binary types need it for a blunter reason: an element of {@code BINARY} or
- * {@code VARBINARY} is a {@code byte[]}, which inherits identity equality from {@link Object},
- * so two arrays with the same content never compare equal and never share a hash bucket.
+ * equal objects. Binary types need it for a blunter reason: an element of {@code BINARY},
+ * {@code VARBINARY}, {@code GEOMETRY} or {@code GEOGRAPHY} is a {@code byte[]}, which inherits
+ * identity equality from {@link Object}, so two arrays with the same content never compare
+ * equal and never share a hash bucket.
*/
private static boolean needsEqualiser(DataType elementType) {
- Set families = elementType.getTypeRoot().getFamilies();
- return families.contains(DataTypeFamily.CONSTRUCTED)
- || families.contains(DataTypeFamily.BINARY_STRING);
+ return elementType.is(DataTypeFamily.CONSTRUCTED) || BinaryMapKeys.isBinary(elementType);
}
@Override
@@ -111,7 +111,7 @@ public Object agg(Object accumulator, Object inputField) {
return accumulator == null ? inputField : accumulator;
}
- if (equaliser != null) {
+ if (distinct && equaliser != null) {
List