blob: b94a3ca9c8a26beeecf8a1a07521d0d9626347ec [file] [log] [blame]
// 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:
*
* <pre>
* {@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]));
* }
* </pre>
*
* The pom.xml dependency:
* <pre>
* {@code
* <dependency>
* <groupId>mysql</groupId>
* <artifactId>mysql-connector-java</artifactId>
* <version>8.0.28</version>
* </dependency>
* <dependency>
* <groupId>org.roaringbitmap</groupId>
* <artifactId>RoaringBitmap</artifactId>
* <version>0.9.39</version>
* </dependency>
* }
* </pre>
*/
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};
}
}