Search before asking
Paimon version
master
Compute Engine
Any — InternalRowUtils.equals is shared plumbing.
Minimal reproduce step
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);
BinaryMap binary = /* the same single entry, built with BinaryArrayWriter */;
InternalRowUtils.equals(binary, generic, mapType); // true
InternalRowUtils.equals(generic, binary, mapType); // ClassCastException
java.lang.ClassCastException: class org.apache.paimon.data.BinaryMap
cannot be cast to class org.apache.paimon.data.GenericMap
What doesn't meet your expectations?
equals picks the GenericMap fast path by testing data1, then casts data2 with no test of its own:
if (data1 instanceof GenericMap) {
map1 = (GenericMap) data1;
map2 = (GenericMap) data2; // no guard
} else {
map1 = copyToGenericMap((InternalMap) data1, ...);
map2 = copyToGenericMap((InternalMap) data2, ...);
}
The result is asymmetric: one argument order works, the other throws.
Two things make this look unintended rather than a deliberate restriction:
-
The else branch exists precisely because the representation varies. One MapType is carried by GenericMap, BinaryMap or ColumnarMap interchangeably — the conversion is there to normalise exactly that. The operand-1 gate contradicts the branch it guards.
-
InternalRowUtils.hash in the same class already treats them as interchangeable, returning an identical value for a GenericMap and a BinaryMap holding the same entries. So the class says "these are equal" by hash and throws when asked directly.
For contrast, the other casts in the method — (InternalRow) data2, (InternalArray) data2 — are interface casts and are fine, since every representation implements them. The map branch is the only one casting to a concrete class.
Anything else?
Related history in this area: #8535 / #8536 fixed map equality for binary keys.
Are you willing to submit a PR?
Search before asking
Paimon version
master
Compute Engine
Any —
InternalRowUtils.equalsis shared plumbing.Minimal reproduce step
What doesn't meet your expectations?
equalspicks the GenericMap fast path by testing data1, then casts data2 with no test of its own:The result is asymmetric: one argument order works, the other throws.
Two things make this look unintended rather than a deliberate restriction:
The
elsebranch exists precisely because the representation varies. OneMapTypeis carried byGenericMap,BinaryMaporColumnarMapinterchangeably — the conversion is there to normalise exactly that. The operand-1 gate contradicts the branch it guards.InternalRowUtils.hashin the same class already treats them as interchangeable, returning an identical value for aGenericMapand aBinaryMapholding the same entries. So the class says "these are equal" by hash and throws when asked directly.For contrast, the other casts in the method —
(InternalRow) data2,(InternalArray) data2— are interface casts and are fine, since every representation implements them. The map branch is the only one casting to a concrete class.Anything else?
Related history in this area: #8535 / #8536 fixed map equality for binary keys.
Are you willing to submit a PR?