Skip to content

[Bug] (bitmap) Support SET type (Flag=5) deserialization in FE BitmapValue #68309

Description

@iyils

Search before asking

  • I had searched in the issues and found no similar issues.

Version

master, commit_id:6b3ea1eb56dcf57c5f2dd5abb9f170e0fbcf1907

What's Wrong?

FE BitmapValue.java does not handle BitmapTypeCode.SET (Flag = 5) in its deserialize() method. When BE has enable_set_in_bitmap_value=true, or after #65421 merges wider SET adoption, the FE throws RuntimeException: unknown bitmap type 5 when reading such bitmaps. This causes failures in Spark Load, Hive Catalog bitmap import (bitmap_from_base64), and any path that routes a BE-serialized bitmap through FE.

What You Expected?

FE should be able to deserialize all valid bitmap binary formats produced by BE,
including SET type (Flag=5), without throwing an exception.

The deserialized bitmap should contain the same set of values as the original bitmap
serialized by BE.

How to Reproduce?

Prerequisites:

Step 1: Export a SET-format bitmap from BE

On BE, a bitmap with 1–32 elements is serialized as SET type (Flag=5).
Use bitmap_to_base64 to export the binary:

SELECT bitmap_to_base64(bitmap_from_array([1, 3, 5]));
-- Result: BQMBAAAAAAAAAAMAAAAAAAAABQAAAAAAAAA=

The decoded bytes start with 0x05 (Flag=5 = SET type).

Step 2: Try to parse the exported binary in FE
The current BitmapValue.java#deserialize() (line 131–154) only handles EMPTY / SINGLE32 / SINGLE64 / BITMAP32 / BITMAP64, and throws on anything else:

// fe/fe-common/src/main/java/org/apache/doris/common/io/BitmapValue.java L131-154
public void deserialize(DataInput input) throws IOException {
    clear();
    int bitmapType = input.readByte();
    switch (bitmapType) {
        case EMPTY:
            break;
        case SINGLE32:
            singleValue = Util.toUnsignedLong(Integer.reverseBytes(input.readInt()));
            this.bitmapType = SINGLE_VALUE;
            break;
        case SINGLE64:
            singleValue = Long.reverseBytes(input.readLong());
            this.bitmapType = SINGLE_VALUE;
            break;
        case BITMAP32:
        case BITMAP64:
            bitmap = bitmap == null ? new Roaring64Map() : bitmap;
            bitmap.deserialize(input, bitmapType);
            this.bitmapType = BITMAP_VALUE;
            break;
        default:
            throw new RuntimeException(String.format("unknown bitmap type %s ", bitmapType));
    }
}

Feeding the base64 output from Step 1 into this method triggers the default branch:

byte[] bytes = Base64.getDecoder().decode("BQMBAAAAAAAAAAMAAAAAAAAABQAAAAAAAAA=");
DataInput input = new DataInputStream(new ByteArrayInputStream(bytes));

BitmapValue bitmap = new BitmapValue();
bitmap.deserialize(input);  // throws RuntimeException: unknown bitmap type 5

Root Cause:
deserialize() has no case for SET (Flag=5) or SET_V2 (Flag=10). Since BE defaults enable_set_in_bitmap_value=true (since #35730), any bitmap with ≤32 elements is serialized as SET, making this a regression on all FE read paths (Hive Catalog, Spark Load, etc.).

Anything Else?

No response

Are you willing to submit PR?

  • Yes I am willing to submit a PR!

Code of Conduct

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

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