Skip to content

Commit 549a62f

Browse files
authored
Merge pull request #601 from zhicwu/prepare-release
Prepare 0.3.0 release
2 parents cc6be0b + 4932653 commit 549a62f

File tree

5 files changed

+106
-53
lines changed

5 files changed

+106
-53
lines changed

CHANGELOG

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,16 @@
1+
0.3.0
2+
* BREAKING CHANGE - dropped JDK 7 support
3+
* BREAKING CHANGE - removed Guava dependency(and so is UnsignedLong)
4+
* JDBC 4.2 support
5+
* add connection setting client_name for load-balancing and troubleshooting
6+
* add writeBytes & writeUUIDArray and remove UnsignedLong related methods in ClickHouseRowBinaryStream
7+
* support more data types: IPv4, IPv6, Int128, UInt128, Int256, UInt256, Decimal256, DateTime*, and Map
8+
* support ORC/Parquet streaming
9+
* support read/write Bitmap from/into AggregateFunction(groupBitmap, UInt[8-64]) column
10+
* throw SQLException instead of RuntimeException when instantiating ClickHouseConnectionImpl
11+
* fix error when using ClickHouseCompression.none against 19.16
12+
* fix NegativeArraySizeException when dealing with large array
13+
* fix datetime/date display issue caused by timezone differences(between client and column/server)
114
0.2.6
215
* add new feature for sending compressed files/streams
316
* introduce an experimental SQL parser to fix parsing related issues - set connection setting use_new_parser to false to disable

clickhouse-jdbc/src/main/java/ru/yandex/clickhouse/domain/ClickHouseFormat.java

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,11 @@ public enum ClickHouseFormat {
2424
Vertical,
2525
JSON,
2626
JSONCompact,
27+
JSONCompactString,
2728
JSONEachRow,
29+
JSONStringEachRow,
30+
JSONCompactEachRow,
31+
JSONCompactStringEachRow,
2832
TSKV,
2933
TSV,
3034
Pretty,

clickhouse-jdbc/src/main/java/ru/yandex/clickhouse/util/ClickHouseBitmap.java

Lines changed: 77 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
package ru.yandex.clickhouse.util;
22

3+
import java.io.ByteArrayInputStream;
34
import java.io.ByteArrayOutputStream;
45
import java.io.DataInputStream;
56
import java.io.DataOutput;
@@ -9,13 +10,11 @@
910
import java.nio.ByteBuffer;
1011
import java.nio.ByteOrder;
1112
import java.util.Objects;
12-
1313
import org.roaringbitmap.RoaringBitmap;
1414
import org.roaringbitmap.buffer.ImmutableRoaringBitmap;
1515
import org.roaringbitmap.buffer.MutableRoaringBitmap;
1616
import org.roaringbitmap.longlong.Roaring64Bitmap;
1717
import org.roaringbitmap.longlong.Roaring64NavigableMap;
18-
1918
import ru.yandex.clickhouse.domain.ClickHouseDataType;
2019

2120
public abstract class ClickHouseBitmap {
@@ -131,16 +130,24 @@ public long getLongCardinality() {
131130
@Override
132131
public void serialize(ByteBuffer buffer) {
133132
int size = serializedSizeInBytes();
133+
// TODO use custom data output so that we can handle large byte array
134134
try (ByteArrayOutputStream bas = new ByteArrayOutputStream(size)) {
135135
DataOutput out = new DataOutputStream(bas);
136136
try {
137+
// https://github.com/RoaringBitmap/RoaringBitmap/blob/0.9.9/RoaringBitmap/src/main/java/org/roaringbitmap/longlong/Roaring64NavigableMap.java#L1105
137138
rb.serialize(out);
138139
} catch (IOException e) {
139140
throw new IllegalArgumentException("Failed to serialize given bitmap", e);
140141
}
141-
buffer.put(bas.toByteArray(), 5, size - 5);
142+
143+
byte[] bytes = bas.toByteArray();
144+
for (int i = 4; i > 0; i--) {
145+
buffer.put(bytes[i]);
146+
}
147+
buffer.putInt(0);
148+
buffer.put(bytes, 5, size - 5);
142149
} catch (IOException e) {
143-
throw new IllegalArgumentException("Failed to serialize given bitmap", e);
150+
throw new IllegalStateException("Failed to serialize given bitmap", e);
144151
}
145152
}
146153

@@ -253,6 +260,8 @@ public static ClickHouseBitmap wrap(Object bitmap, ClickHouseDataType innerType)
253260
}
254261

255262
public static ClickHouseBitmap deserialize(DataInputStream in, ClickHouseDataType innerType) throws IOException {
263+
final ClickHouseBitmap rb;
264+
256265
int byteLen = byteLength(innerType);
257266
int flag = in.readUnsignedByte();
258267
if (flag == 0) {
@@ -262,20 +271,36 @@ public static ClickHouseBitmap deserialize(DataInputStream in, ClickHouseDataTyp
262271
bytes[1] = cardinality;
263272
in.read(bytes, 2, bytes.length - 2);
264273

265-
return ClickHouseBitmap.deserialize(bytes, innerType);
266-
} else if (byteLen <= 4) {
274+
rb = ClickHouseBitmap.deserialize(bytes, innerType);
275+
} else {
267276
int len = Utils.readVarInt(in);
268277
byte[] bytes = new byte[len];
269-
Utils.readFully(in, bytes);
270-
RoaringBitmap b = new RoaringBitmap();
271-
b.deserialize(flip(newBuffer(len).put(bytes)));
272-
return ClickHouseBitmap.wrap(b, innerType);
273-
} else {
274-
// why? when serializing Roaring64NavigableMap, the initial 5 bytes were removed
275-
// with 8 unknown bytes appended
276-
throw new UnsupportedOperationException(
277-
"Deserializing Roaring64NavigableMap with cardinality larger than 32 is currently not supported.");
278+
279+
if (byteLen <= 4) {
280+
Utils.readFully(in, bytes);
281+
RoaringBitmap b = new RoaringBitmap();
282+
b.deserialize(flip(newBuffer(len).put(bytes)));
283+
rb = ClickHouseBitmap.wrap(b, innerType);
284+
} else {
285+
// TODO implement a wrapper of DataInput to get rid of byte array here
286+
bytes[0] = (byte) 0; // always unsigned
287+
// read map size in big-endian byte order
288+
for (int i = 4; i > 0; i--) {
289+
bytes[i] = in.readByte();
290+
}
291+
if (in.readByte() != 0 || in.readByte() != 0 || in.readByte() != 0 || in.readByte() != 0) {
292+
throw new IllegalStateException(
293+
"Not able to deserialize ClickHouseBitmap for too many bitmaps(>" + 0xFFFFFFFFL + ")!");
294+
}
295+
// read the rest
296+
Utils.readFully(in, bytes, 5, len - 5);
297+
Roaring64NavigableMap b = new Roaring64NavigableMap();
298+
b.deserialize(new DataInputStream(new ByteArrayInputStream(bytes)));
299+
rb = ClickHouseBitmap.wrap(b, innerType);
300+
}
278301
}
302+
303+
return rb;
279304
}
280305

281306
public static ClickHouseBitmap deserialize(byte[] bytes, ClickHouseDataType innerType) throws IOException {
@@ -287,10 +312,7 @@ public static ClickHouseBitmap deserialize(byte[] bytes, ClickHouseDataType inne
287312
}
288313

289314
int byteLen = byteLength(innerType);
290-
ByteBuffer buffer = ByteBuffer.allocate(bytes.length);
291-
if (buffer.order() != ByteOrder.LITTLE_ENDIAN) {
292-
buffer = buffer.slice().order(ByteOrder.LITTLE_ENDIAN);
293-
}
315+
ByteBuffer buffer = newBuffer(bytes.length);
294316
buffer = (ByteBuffer) ((Buffer) buffer.put(bytes)).flip();
295317

296318
if (buffer.get() == (byte) 0) { // small set
@@ -331,10 +353,29 @@ public static ClickHouseBitmap deserialize(byte[] bytes, ClickHouseDataType inne
331353
b.deserialize(buffer);
332354
rb = ClickHouseBitmap.wrap(b, innerType);
333355
} else {
334-
// why? when serializing Roaring64NavigableMap, the initial 5 bytes were removed
335-
// with 8 unknown bytes appended
336-
throw new UnsupportedOperationException(
337-
"Deserializing Roaring64NavigableMap with cardinality larger than 32 is currently not supported.");
356+
// consume map size(long in little-endian byte order)
357+
byte[] bitmaps = new byte[4];
358+
buffer.get(bitmaps);
359+
if (buffer.get() != 0 || buffer.get() != 0 || buffer.get() != 0 || buffer.get() != 0) {
360+
throw new IllegalStateException(
361+
"Not able to deserialize ClickHouseBitmap for too many bitmaps(>" + 0xFFFFFFFFL + ")!");
362+
}
363+
// replace the last 5 bytes to flag(boolean for signed/unsigned) and map
364+
// size(integer)
365+
buffer.position(buffer.position() - 5);
366+
// always unsigned due to limit of CRoaring
367+
buffer.put((byte) 0);
368+
// big-endian -> little-endian
369+
for (int i = 3; i >= 0; i--) {
370+
buffer.put(bitmaps[i]);
371+
}
372+
373+
buffer.position(buffer.position() - 5);
374+
bitmaps = new byte[buffer.remaining()];
375+
buffer.get(bitmaps);
376+
Roaring64NavigableMap b = new Roaring64NavigableMap();
377+
b.deserialize(new DataInputStream(new ByteArrayInputStream(bitmaps)));
378+
rb = ClickHouseBitmap.wrap(b, innerType);
338379
}
339380
}
340381

@@ -436,15 +477,17 @@ public long[] toLongArray() {
436477
return longs;
437478
}
438479

480+
/**
481+
* Serialize the bitmap into a flipped ByteBuffer.
482+
*
483+
* @return flipped byte buffer
484+
*/
439485
public ByteBuffer toByteBuffer() {
440486
ByteBuffer buf;
441487

442488
int cardinality = getCardinality();
443489
if (cardinality <= 32) {
444-
buf = ByteBuffer.allocate(2 + byteLen * cardinality);
445-
if (buf.order() != ByteOrder.LITTLE_ENDIAN) {
446-
buf = buf.slice().order(ByteOrder.LITTLE_ENDIAN);
447-
}
490+
buf = newBuffer(2 + byteLen * cardinality);
448491
buf.put((byte) 0);
449492
buf.put((byte) cardinality);
450493
if (byteLen == 1) {
@@ -468,28 +511,23 @@ public ByteBuffer toByteBuffer() {
468511
int size = serializedSizeInBytes();
469512
int varIntSize = Utils.getVarIntSize(size);
470513

471-
buf = ByteBuffer.allocate(1 + varIntSize + size);
472-
if (buf.order() != ByteOrder.LITTLE_ENDIAN) {
473-
buf = buf.slice().order(ByteOrder.LITTLE_ENDIAN);
474-
}
514+
buf = newBuffer(1 + varIntSize + size);
475515
buf.put((byte) 1);
476516
Utils.writeVarInt(size, buf);
477517
serialize(buf);
478518
} else { // 64
479-
// 1) exclude the leading 5 bytes - boolean flag + map size, see below:
519+
// 1) deduct one to exclude the leading byte - boolean flag, see below:
480520
// https://github.com/RoaringBitmap/RoaringBitmap/blob/0.9.9/RoaringBitmap/src/main/java/org/roaringbitmap/longlong/Roaring64NavigableMap.java#L1107
481-
// 2) not sure what's the extra 8 bytes?
482-
long size = serializedSizeInBytesAsLong() - 5 + 8;
521+
// 2) add 4 bytes because CRoaring uses long to store count of 32-bit bitmaps,
522+
// while Java uses int - see
523+
// https://github.com/RoaringBitmap/CRoaring/blob/v0.2.66/cpp/roaring64map.hh#L597
524+
long size = serializedSizeInBytesAsLong() - 1 + 4;
483525
int varIntSize = Utils.getVarLongSize(size);
484526
// TODO add serialize(DataOutput) to handle more
485527
int intSize = (int) size;
486-
buf = ByteBuffer.allocate(1 + varIntSize + intSize);
487-
if (buf.order() != ByteOrder.LITTLE_ENDIAN) {
488-
buf = buf.slice().order(ByteOrder.LITTLE_ENDIAN);
489-
}
528+
buf = newBuffer(1 + varIntSize + intSize);
490529
buf.put((byte) 1);
491530
Utils.writeVarInt(intSize, buf);
492-
buf.putLong(1L); // what's this?
493531
serialize(buf);
494532
}
495533

clickhouse-jdbc/src/test/java/ru/yandex/clickhouse/integration/RowBinaryStreamTest.java

Lines changed: 9 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -152,11 +152,11 @@ private int[] genRoaringBitmapValues(int length, ClickHouseDataType innerType) {
152152
return values;
153153
}
154154

155-
private long[] genRoaring64BitmapValues(int length) {
155+
private long[] gen64BitmapValues(int length, long base, long step) {
156156
long[] values = new long[length];
157157

158158
for (int i = 0; i < length; i++) {
159-
values[i] = 100000L + i;
159+
values[i] = base + i * step;
160160
}
161161

162162
return values;
@@ -219,11 +219,11 @@ public void writeTo(ClickHouseRowBinaryStream stream) throws IOException {
219219
}
220220
}
221221

222-
private void testBitmap64(int valueLength) throws Exception {
222+
private void testBitmap64(int valueLength, long base, long step) throws Exception {
223223
ClickHouseDataType innerType = ClickHouseDataType.UInt64;
224224
try (ClickHouseStatement statement = connection.createStatement()) {
225225
String tableName = createtestBitmapTable(innerType);
226-
long[] values = genRoaring64BitmapValues(valueLength);
226+
long[] values = gen64BitmapValues(valueLength, base, step);
227227
statement.sendRowBinaryStream("insert into table " + tableName, new ClickHouseStreamCallback() {
228228
@Override
229229
public void writeTo(ClickHouseRowBinaryStream stream) throws IOException {
@@ -247,11 +247,7 @@ public void writeTo(ClickHouseRowBinaryStream stream) throws IOException {
247247

248248
sql = "select b from " + tableName + " order by i";
249249
try (ClickHouseRowBinaryInputStream in = statement.executeQueryClickhouseRowBinaryStream(sql)) {
250-
if (valueLength <= 32) {
251-
assertEquals(in.readBitmap(innerType), ClickHouseBitmap.wrap(Roaring64NavigableMap.bitmapOf(values), innerType));
252-
} else {
253-
assertThrows(UnsupportedOperationException.class, () -> in.readBitmap(innerType));
254-
}
250+
assertEquals(in.readBitmap(innerType), ClickHouseBitmap.wrap(Roaring64NavigableMap.bitmapOf(values), innerType));
255251
}
256252

257253
statement.execute("drop table if exists " + tableName);
@@ -268,13 +264,15 @@ public void testBitmap() throws Exception {
268264
testBitmap(ClickHouseDataType.UInt32, 32);
269265
testBitmap(ClickHouseDataType.UInt32, 65537);
270266

271-
testBitmap64(32);
267+
testBitmap64(32, 0L, 1L);
268+
testBitmap64(32, Long.MAX_VALUE, -1L);
272269

273270
String versionNumber = connection.getServerVersion();
274271
int majorVersion = ClickHouseVersionNumberUtil.getMajorVersion(versionNumber);
275272
int minorVersion = ClickHouseVersionNumberUtil.getMinorVersion(versionNumber);
276273
if (majorVersion > 20 || (majorVersion == 20 && minorVersion > 8)) {
277-
testBitmap64(65537);
274+
testBitmap64(65537, 100000L, 1L); // highToBitmap.size() == 1
275+
testBitmap64(65537, 9223372036854775807L, -1000000000L); // highToBitmap.size() > 1
278276
}
279277
}
280278

pom.xml

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -65,11 +65,11 @@
6565
<distributionManagement>
6666
<snapshotRepository>
6767
<id>ossrh</id>
68-
<url>https://oss.sonatype.org/content/repositories/snapshots</url>
68+
<url>https://s01.oss.sonatype.org/content/repositories/snapshots</url>
6969
</snapshotRepository>
7070
<repository>
7171
<id>ossrh</id>
72-
<url>https://oss.sonatype.org/service/local/staging/deploy/maven2/</url>
72+
<url>https://s01.oss.sonatype.org/service/local/staging/deploy/maven2/</url>
7373
</repository>
7474
</distributionManagement>
7575

@@ -394,7 +394,7 @@
394394
</executions>
395395
<configuration>
396396
<serverId>ossrh</serverId>
397-
<nexusUrl>https://oss.sonatype.org/</nexusUrl>
397+
<nexusUrl>https://s01.oss.sonatype.org/</nexusUrl>
398398
</configuration>
399399
</plugin>
400400
</plugins>

0 commit comments

Comments
 (0)