// Licensed to the Apache Software Foundation (ASF) under one // or more contributor license agreements. See the NOTICE file // distributed with this work for additional information // regarding copyright ownership. The ASF licenses this file // to you under the Apache License, Version 2.0 (the // "License"); you may not use this file except in compliance // with the License. You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, // software distributed under the License is distributed on an // "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY // KIND, either express or implied. See the License for the // specific language governing permissions and limitations // under the License. import org.roaringbitmap.RoaringBitmap; import org.roaringbitmap.longlong.Roaring64NavigableMap; import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.io.DataInputStream; import java.io.DataOutputStream; import java.nio.ByteBuffer; import java.nio.ByteOrder; import java.sql.Connection; import java.sql.DriverManager; import java.sql.ResultSet; import java.sql.Statement; /** * Prepare the table and data in Doris: * *
 * {@code
 * CREATE TABLE `t_bitmap` (
 *   `rn` int(11) NULL,
 *   `uids` bitmap BITMAP_UNION NULL
 * ) AGGREGATE KEY(`rn`)
 * DISTRIBUTED BY HASH(`rn`) BUCKETS 1
 * PROPERTIES (
 *   "replication_num" = "1"
 * );
 *
 * INSERT INTO t_bitmap VALUES
 * (0, bitmap_empty()),
 * (1, to_bitmap(243)),
 * (2, bitmap_from_array([1,2,3,4,5,434543])),
 * (3, to_bitmap(287667876573)),
 * (4, bitmap_from_array([487667876573, 387627876573, 987567876573, 187667876573]));
 * }
 * 
* * The pom.xml dependency: *
 * {@code
 * 
 *    mysql
 *    mysql-connector-java
 *    8.0.28
 * 
 * 
 *    org.roaringbitmap
 *    RoaringBitmap
 *    0.9.39
 * 
 * }
 * 
*/ public class ReadBitmap { public static void main(String[] args) throws Exception { try (Connection conn = DriverManager.getConnection("jdbc:mysql://127.0.0.1:9030/test?user=root"); Statement stmt = conn.createStatement() ) { stmt.execute("set return_object_data_as_binary=true"); // IMPORTANT!!! ResultSet rs = stmt.executeQuery("select uids from t_bitmap"); while (rs.next()) { byte[] bytes = rs.getBytes(1); RoaringBitmap bitmap32 = new RoaringBitmap(); // Only Roaring64NavigableMap can work, Roaring64Bitmap can't work!!! Roaring64NavigableMap bitmap64 = new Roaring64NavigableMap(); switch (bytes[0]) { case 0: // for empty bitmap break; case 1: // for only 1 element in bitmap32 bitmap32.add(ByteBuffer.wrap(bytes, 1, bytes.length - 1) .order(ByteOrder.LITTLE_ENDIAN) .getInt()); break; case 2: // for more than 1 elements in bitmap32 bitmap32.deserialize(ByteBuffer.wrap(bytes, 1, bytes.length - 1)); break; case 3: // for only 1 element in bitmap64 bitmap64.add(ByteBuffer.wrap(bytes, 1, bytes.length - 1) .order(ByteOrder.LITTLE_ENDIAN) .getLong()); break; case 4: // for more than 1 elements in bitmap64 Object[] tuple2 = decodeVarint64(bytes); int offset = (int) tuple2[1]; int newLen = 8 + bytes.length - offset; try (ByteArrayOutputStream baos = new ByteArrayOutputStream(newLen); DataOutputStream dos = new DataOutputStream(baos)) { dos.write((byte[]) tuple2[0]); dos.write(bytes, offset, bytes.length - offset); dos.flush(); try (DataInputStream dis = new DataInputStream( new ByteArrayInputStream(baos.toByteArray()))) { bitmap64.deserializePortable(dis); } } break; } System.out.println(bytes[0] <= 2 ? bitmap32 : bitmap64); } } } static Object[] decodeVarint64(byte[] bt) { // nolint long result = 0; int shift = 0; short B = 128; int idx = 1; for (; ; ) { short readByte = bt[idx]; idx++; boolean isEnd = (readByte & B) == 0; result |= (long) (readByte & (B - 1)) << (shift * 7); if (isEnd) { break; } shift++; } byte[] bytes = new byte[8]; for (int i = 0; i < bytes.length; i++) { // LITTLE_ENDIAN bytes[i] = (byte) (result >> 8 * i); } return new Object[]{bytes, idx}; } }