Skip to content

Commit 860ed34

Browse files
committed
Added more tests and fixed issue
1 parent 95face3 commit 860ed34

4 files changed

Lines changed: 152 additions & 2 deletions

File tree

client-v2/src/main/java/com/clickhouse/client/api/data_formats/internal/SerializerUtils.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -521,7 +521,7 @@ private static void serializePrimitiveData(OutputStream stream, Object value, Cl
521521
BinaryStreamUtils.writeUnsignedInt32(stream, convertToLong(value));
522522
break;
523523
case UInt64:
524-
BinaryStreamUtils.writeUnsignedInt64(stream, convertToLong(value));
524+
BinaryStreamUtils.writeUnsignedInt64(stream, NumberConverter.toBigInteger(value));
525525
break;
526526
case UInt128:
527527
BinaryStreamUtils.writeUnsignedInt128(stream, NumberConverter.toBigInteger(value));

client-v2/src/test/java/com/clickhouse/client/datatypes/DataTypeTests.java

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -313,6 +313,24 @@ public void testVariantWithDecimals() throws Exception {
313313
});
314314
}
315315

316+
@Test(groups = {"integration"})
317+
public void testGetBigDecimalDoesNotTruncateLargeIntegers() throws Exception {
318+
BigDecimal expectedInt64 = BigDecimal.valueOf(Long.MAX_VALUE);
319+
BigDecimal expectedUInt64 = new BigDecimal("18446744073709551615");
320+
321+
String sql = "SELECT toInt64(" + Long.MAX_VALUE + ") AS i64, "
322+
+ "toUInt64('" + expectedUInt64.toPlainString() + "') AS u64";
323+
324+
try (QueryResponse response = client.query(sql).get(3, TimeUnit.SECONDS)) {
325+
ClickHouseBinaryFormatReader reader = client.newBinaryFormatReader(response);
326+
327+
Assert.assertNotNull(reader.next());
328+
Assert.assertEquals(reader.getBigDecimal("i64"), expectedInt64);
329+
Assert.assertEquals(reader.getBigDecimal("u64"), expectedUInt64);
330+
Assert.assertFalse(reader.hasNext());
331+
}
332+
}
333+
316334
@Test(groups = {"integration"})
317335
public void testVariantWithArrays() throws Exception {
318336
testVariantWith("arrays", new String[]{"field Variant(String, Array(String))"},

client-v2/src/test/java/com/clickhouse/client/internal/SerializerUtilsTests.java

Lines changed: 122 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,22 @@
11
package com.clickhouse.client.internal;
22

3+
import com.clickhouse.client.api.data_formats.RowBinaryWithNamesAndTypesFormatReader;
4+
import com.clickhouse.client.api.data_formats.internal.BinaryStreamReader;
35
import com.clickhouse.client.api.data_formats.internal.SerializerUtils;
6+
import com.clickhouse.client.api.query.QuerySettings;
7+
import com.clickhouse.data.ClickHouseColumn;
8+
import com.clickhouse.data.format.BinaryStreamUtils;
49
import org.testng.annotations.Test;
510

611
import org.testng.Assert;
712

13+
import java.io.ByteArrayInputStream;
14+
import java.io.ByteArrayOutputStream;
15+
import java.io.IOException;
16+
import java.math.BigDecimal;
17+
import java.math.BigInteger;
18+
import java.util.TimeZone;
19+
820
public class SerializerUtilsTests {
921

1022
@Test
@@ -13,4 +25,114 @@ public void testConvertToInteger() {
1325
Assert.assertEquals(SerializerUtils.convertToInteger("1640995199").intValue(), expected);
1426
Assert.assertEquals(SerializerUtils.convertToInteger(false).intValue(), 0);
1527
}
28+
29+
@Test
30+
public void testSerializeNumbersRoundTrip() throws IOException {
31+
String[] names = new String[]{"a", "b", "c", "d", "e", "f", "g", "h", "i", "j", "k", "l", "m", "n", "o",
32+
"p", "q", "r"};
33+
String[] types = new String[]{"Int8", "Int16", "Int32", "Int64", "UInt8", "UInt16", "UInt32", "UInt64",
34+
"Int128", "Int256", "UInt128", "UInt256", "Float32", "Float64", "Decimal32(3)", "Decimal64(3)",
35+
"Decimal128(4)", "Decimal256(4)"};
36+
Object[] values = new Object[]{
37+
(byte) 120,
38+
(short) 120,
39+
120,
40+
120L,
41+
120,
42+
120,
43+
120L,
44+
BigInteger.valueOf(120),
45+
BigInteger.valueOf(120),
46+
BigInteger.valueOf(120),
47+
BigInteger.valueOf(120),
48+
BigInteger.valueOf(120),
49+
120.0f,
50+
120.0d,
51+
BigDecimal.valueOf(120),
52+
BigDecimal.valueOf(120),
53+
BigDecimal.valueOf(120),
54+
BigDecimal.valueOf(120)
55+
};
56+
57+
RowBinaryWithNamesAndTypesFormatReader reader = serializeRow(names, types, values);
58+
reader.next();
59+
60+
for (String name : names) {
61+
Assert.assertTrue(reader.getBigDecimal(name).compareTo(BigDecimal.valueOf(120)) == 0);
62+
}
63+
}
64+
65+
@Test
66+
public void testSerializeIntegerWidths8To256RoundTripAsBigDecimal() throws IOException {
67+
String[] names = new String[]{
68+
"i8", "u8", "i16", "u16", "i32", "u32", "i64", "u64", "i128", "u128", "i256", "u256"
69+
};
70+
String[] types = new String[]{
71+
"Int8", "UInt8", "Int16", "UInt16", "Int32", "UInt32", "Int64", "UInt64",
72+
"Int128", "UInt128", "Int256", "UInt256"
73+
};
74+
75+
BigInteger u64 = new BigInteger("18446744073709551615");
76+
BigInteger i128 = new BigInteger("-170141183460469231731687303715884105728");
77+
BigInteger u128 = new BigInteger("340282366920938463463374607431768211455");
78+
BigInteger i256 = new BigInteger("-57896044618658097711785492504343953926634992332820282019728792003956564819968");
79+
BigInteger u256 = new BigInteger("115792089237316195423570985008687907853269984665640564039457584007913129639935");
80+
81+
Object[] values = new Object[]{
82+
-128,
83+
255,
84+
-32768,
85+
65535,
86+
Integer.MIN_VALUE,
87+
4294967295L,
88+
Long.MAX_VALUE,
89+
u64,
90+
i128,
91+
u128,
92+
i256,
93+
u256
94+
};
95+
96+
BigDecimal[] expected = new BigDecimal[]{
97+
BigDecimal.valueOf(-128),
98+
BigDecimal.valueOf(255),
99+
BigDecimal.valueOf(-32768),
100+
BigDecimal.valueOf(65535),
101+
BigDecimal.valueOf(Integer.MIN_VALUE),
102+
BigDecimal.valueOf(4294967295L),
103+
BigDecimal.valueOf(Long.MAX_VALUE),
104+
new BigDecimal(u64),
105+
new BigDecimal(i128),
106+
new BigDecimal(u128),
107+
new BigDecimal(i256),
108+
new BigDecimal(u256)
109+
};
110+
111+
RowBinaryWithNamesAndTypesFormatReader reader = serializeRow(names, types, values);
112+
reader.next();
113+
114+
for (int i = 0; i < names.length; i++) {
115+
Assert.assertEquals(reader.getBigDecimal(names[i]), expected[i]);
116+
}
117+
}
118+
119+
private RowBinaryWithNamesAndTypesFormatReader serializeRow(String[] names, String[] types, Object[] values)
120+
throws IOException {
121+
ByteArrayOutputStream out = new ByteArrayOutputStream();
122+
BinaryStreamUtils.writeVarInt(out, names.length);
123+
for (String name : names) {
124+
BinaryStreamUtils.writeString(out, name);
125+
}
126+
for (String type : types) {
127+
BinaryStreamUtils.writeString(out, type);
128+
}
129+
for (int i = 0; i < names.length; i++) {
130+
SerializerUtils.serializeData(out, values[i], ClickHouseColumn.of(names[i], types[i]));
131+
}
132+
133+
return new RowBinaryWithNamesAndTypesFormatReader(
134+
new ByteArrayInputStream(out.toByteArray()),
135+
new QuerySettings().setUseTimeZone(TimeZone.getTimeZone("UTC").toZoneId().getId()),
136+
new BinaryStreamReader.CachingByteBufferAllocator());
137+
}
16138
}

jdbc-v2/src/test/java/com/clickhouse/jdbc/types/ArrayResultSetTest.java

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -185,7 +185,7 @@ void testPrimitiveValues(Object array, ClickHouseColumn column) throws SQLExcept
185185
assertEquals(rs.getLong(valueColumn), number.longValue());
186186
assertEquals(rs.getFloat(valueColumn), number.floatValue());
187187
assertEquals(rs.getDouble(valueColumn), number.doubleValue());
188-
assertEquals(rs.getBigDecimal(valueColumn), BigDecimal.valueOf(number.doubleValue()));
188+
assertEquals(rs.getBigDecimal(valueColumn), expectedBigDecimal(number));
189189
} else if (itemClass == Boolean.class || itemClass == boolean.class) {
190190
Number number = ((Boolean) value) ? 1 : 0;
191191
assertEquals(rs.getBoolean(valueColumn), ((Boolean) value));
@@ -207,6 +207,16 @@ void testPrimitiveValues(Object array, ClickHouseColumn column) throws SQLExcept
207207
}
208208
}
209209

210+
private static BigDecimal expectedBigDecimal(Number number) {
211+
if (number instanceof Byte || number instanceof Short || number instanceof Integer || number instanceof Long) {
212+
return BigDecimal.valueOf(number.longValue());
213+
} else if (number instanceof Float || number instanceof Double) {
214+
return BigDecimal.valueOf(number.doubleValue());
215+
}
216+
217+
return new BigDecimal(number.toString());
218+
}
219+
210220
@DataProvider
211221
static Object[][] testPrimitiveValues() {
212222
return new Object[][]{

0 commit comments

Comments
 (0)