Skip to content

[Bug] InternalRowUtils.equals throws ClassCastException when comparing a GenericMap with a BinaryMap #9210

Description

@PDGGK

Search before asking

  • I searched in the issues and found nothing similar.

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:

  1. 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.

  2. 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?

  • I'm willing to submit a PR!

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions