Skip to content

Commit 4fca682

Browse files
committed
debug UInt32 and UInt64 conversion error and add support for not flattened Nested type
1 parent a245c1f commit 4fca682

File tree

3 files changed

+253
-4
lines changed

3 files changed

+253
-4
lines changed

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

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -234,6 +234,8 @@ public <T> T readValue(ClickHouseColumn column, Class<?> typeHint) throws IOExce
234234
return (T) readVariant(actualColumn);
235235
case Dynamic:
236236
return (T) readValue(actualColumn, typeHint);
237+
case Nested:
238+
return convertArray(readNested(actualColumn), typeHint);
237239
default:
238240
throw new IllegalArgumentException("Unsupported data type: " + actualColumn.getDataType());
239241
}
@@ -785,6 +787,33 @@ public Object[] readTuple(ClickHouseColumn column) throws IOException {
785787
return tuple;
786788
}
787789

790+
/**
791+
* Reads a nested into an ArrayValue object.
792+
* @param column - column information
793+
* @return array value
794+
* @throws IOException when IO error occurs
795+
*/
796+
public ArrayValue readNested(ClickHouseColumn column) throws IOException {
797+
int len = readVarInt(input);
798+
if (len == 0) {
799+
return new ArrayValue(Object[].class, 0);
800+
}
801+
802+
ArrayValue array;
803+
array = new ArrayValue(Object[].class, len);
804+
for (int i = 0; i < len; i++) {
805+
int tupleLen = column.getNestedColumns().size();
806+
Object[] tuple = new Object[tupleLen];
807+
for (int j = 0; j < tupleLen; j++) {
808+
tuple[j] = readValue(column.getNestedColumns().get(j));
809+
}
810+
811+
array.set(i, tuple);
812+
}
813+
814+
return array;
815+
}
816+
788817
public Object readVariant(ClickHouseColumn column) throws IOException {
789818
int ordNum = readByte();
790819
return readValue(column.getNestedColumns().get(ordNum));

jdbc-v2/src/main/java/com/clickhouse/jdbc/internal/JdbcUtils.java

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -44,9 +44,8 @@ private static Map<ClickHouseDataType, SQLType> generateTypeMap() {
4444
map.put(ClickHouseDataType.Int16, JDBCType.SMALLINT);
4545
map.put(ClickHouseDataType.UInt16, JDBCType.SMALLINT);
4646
map.put(ClickHouseDataType.Int32, JDBCType.INTEGER);
47-
map.put(ClickHouseDataType.UInt32, JDBCType.INTEGER);
47+
map.put(ClickHouseDataType.UInt32, JDBCType.BIGINT);
4848
map.put(ClickHouseDataType.Int64, JDBCType.BIGINT);
49-
map.put(ClickHouseDataType.UInt64, JDBCType.BIGINT);
5049
map.put(ClickHouseDataType.Float32, JDBCType.FLOAT);
5150
map.put(ClickHouseDataType.Float64, JDBCType.DOUBLE);
5251
map.put(ClickHouseDataType.Bool, JDBCType.BOOLEAN);

jdbc-v2/src/test/java/com/clickhouse/jdbc/DataTypeTests.java

Lines changed: 223 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
import java.net.Inet6Address;
1414
import java.net.InetAddress;
1515
import java.net.UnknownHostException;
16+
import java.sql.Array;
1617
import java.sql.Connection;
1718
import java.sql.Date;
1819
import java.sql.JDBCType;
@@ -21,6 +22,7 @@
2122
import java.sql.SQLException;
2223
import java.sql.Statement;
2324
import java.sql.Timestamp;
25+
import java.text.DecimalFormat;
2426
import java.time.LocalDate;
2527
import java.time.LocalDateTime;
2628
import java.time.OffsetDateTime;
@@ -165,6 +167,57 @@ public void testIntegerTypes() throws SQLException {
165167
}
166168
}
167169
}
170+
171+
// Check the with getObject
172+
try (Connection conn = getConnection()) {
173+
try (Statement stmt = conn.createStatement()) {
174+
try (ResultSet rs = stmt.executeQuery("SELECT * FROM test_integers ORDER BY order")) {
175+
assertTrue(rs.next());
176+
assertEquals(rs.getObject("int8"), -128);
177+
assertEquals(rs.getObject("int16"), -32768);
178+
assertEquals(rs.getObject("int32"), -2147483648);
179+
assertEquals(rs.getObject("int64"), -9223372036854775808L);
180+
assertEquals(rs.getObject("int128"), new BigInteger("-170141183460469231731687303715884105728"));
181+
assertEquals(rs.getObject("int256"), new BigInteger("-57896044618658097711785492504343953926634992332820282019728792003956564819968"));
182+
assertEquals(rs.getObject("uint8"), 0);
183+
assertEquals(rs.getObject("uint16"), 0);
184+
assertEquals(rs.getObject("uint32"), 0L);
185+
assertEquals(rs.getObject("uint64"), new BigInteger("0"));
186+
assertEquals(rs.getObject("uint128"), new BigInteger("0"));
187+
assertEquals(rs.getObject("uint256"), new BigInteger("0"));
188+
189+
assertTrue(rs.next());
190+
assertEquals(rs.getObject("int8"), 127);
191+
assertEquals(rs.getObject("int16"), 32767);
192+
assertEquals(rs.getObject("int32"), 2147483647);
193+
assertEquals(rs.getObject("int64"), 9223372036854775807L);
194+
assertEquals(rs.getObject("int128"), new BigInteger("170141183460469231731687303715884105727"));
195+
assertEquals(rs.getObject("int256"), new BigInteger("57896044618658097711785492504343953926634992332820282019728792003956564819967"));
196+
assertEquals(rs.getObject("uint8"), 255);
197+
assertEquals(rs.getObject("uint16"), 65535);
198+
assertEquals(rs.getObject("uint32"), 4294967295L);
199+
assertEquals(rs.getObject("uint64"), new BigInteger("18446744073709551615"));
200+
assertEquals(rs.getObject("uint128"), new BigInteger("340282366920938463463374607431768211455"));
201+
assertEquals(rs.getObject("uint256"), new BigInteger("115792089237316195423570985008687907853269984665640564039457584007913129639935"));
202+
203+
assertTrue(rs.next());
204+
assertEquals(rs.getObject("int8"), int8);
205+
assertEquals(rs.getObject("int16"), int16);
206+
assertEquals(rs.getObject("int32"), int32);
207+
assertEquals(rs.getObject("int64"), int64);
208+
assertEquals(rs.getObject("int128"), int128);
209+
assertEquals(rs.getObject("int256"), int256);
210+
assertEquals(rs.getObject("uint8"), uint8);
211+
assertEquals(rs.getObject("uint16"), uint16);
212+
assertEquals(rs.getObject("uint32"), uint32);
213+
assertEquals(rs.getObject("uint64"), uint64);
214+
assertEquals(rs.getObject("uint128"), uint128);
215+
assertEquals(rs.getObject("uint256"), uint256);
216+
217+
assertFalse(rs.next());
218+
}
219+
}
220+
}
168221
}
169222

170223
@Test(groups = { "integration" })
@@ -233,6 +286,36 @@ public void testDecimalTypes() throws SQLException {
233286
}
234287
}
235288
}
289+
290+
// Check the results with getObject
291+
try (Connection conn = getConnection()) {
292+
try (Statement stmt = conn.createStatement()) {
293+
try (ResultSet rs = stmt.executeQuery("SELECT * FROM test_decimals ORDER BY order")) {
294+
assertTrue(rs.next());
295+
assertEquals(rs.getObject("dec"), new BigDecimal("-9999999.99"));
296+
assertEquals(rs.getObject("dec32"), new BigDecimal("-99999.9999"));
297+
assertEquals(rs.getObject("dec64"), new BigDecimal("-9999999999.99999999"));
298+
assertEquals(rs.getObject("dec128"), new BigDecimal("-99999999999999999999.999999999999999999"));
299+
assertEquals(rs.getObject("dec256"), new BigDecimal("-9999999999999999999999999999999999999999999999999999999999.999999999999999999"));
300+
301+
assertTrue(rs.next());
302+
assertEquals(rs.getObject("dec"), new BigDecimal("9999999.99"));
303+
assertEquals(rs.getObject("dec32"), new BigDecimal("99999.9999"));
304+
assertEquals(rs.getObject("dec64"), new BigDecimal("9999999999.99999999"));
305+
assertEquals(rs.getObject("dec128"), new BigDecimal("99999999999999999999.999999999999999999"));
306+
assertEquals(rs.getObject("dec256"), new BigDecimal("9999999999999999999999999999999999999999999999999999999999.999999999999999999"));
307+
308+
assertTrue(rs.next());
309+
assertEquals(rs.getObject("dec"), dec);
310+
assertEquals(rs.getObject("dec32"), dec32);
311+
assertEquals(rs.getObject("dec64"), dec64);
312+
assertEquals(rs.getObject("dec128"), dec128);
313+
assertEquals(rs.getObject("dec256"), dec256);
314+
315+
assertFalse(rs.next());
316+
}
317+
}
318+
}
236319
}
237320

238321
@Test(groups = { "integration" })
@@ -315,6 +398,42 @@ public void testDateTypes() throws SQLException {
315398
}
316399
}
317400
}
401+
402+
// Check the results
403+
try (Connection conn = getConnection()) {
404+
try (Statement stmt = conn.createStatement()) {
405+
try (ResultSet rs = stmt.executeQuery("SELECT * FROM test_dates ORDER BY order")) {
406+
assertTrue(rs.next());
407+
assertEquals(rs.getObject("date"), Date.valueOf("1970-01-01"));
408+
assertEquals(rs.getObject("date32"), Date.valueOf("1970-01-01"));
409+
assertEquals(rs.getObject("dateTime").toString(), "1970-01-01 00:00:00.0");
410+
assertEquals(rs.getObject("dateTime32").toString(), "1970-01-01 00:00:00.0");
411+
assertEquals(rs.getObject("dateTime643").toString(), "1970-01-01 00:00:00.0");
412+
assertEquals(rs.getObject("dateTime646").toString(), "1970-01-01 00:00:00.0");
413+
assertEquals(rs.getObject("dateTime649").toString(), "1970-01-01 00:00:00.0");
414+
415+
assertTrue(rs.next());
416+
assertEquals(rs.getObject("date"), Date.valueOf("2149-06-06"));
417+
assertEquals(rs.getObject("date32"), Date.valueOf("2299-12-31"));
418+
assertEquals(rs.getObject("dateTime").toString(), "2106-02-07 06:28:15.0");
419+
assertEquals(rs.getObject("dateTime32").toString(), "2106-02-07 06:28:15.0");
420+
assertEquals(rs.getObject("dateTime643").toString(), "2261-12-31 23:59:59.999");
421+
assertEquals(rs.getObject("dateTime646").toString(), "2261-12-31 23:59:59.999999");
422+
assertEquals(rs.getObject("dateTime649").toString(), "2261-12-31 23:59:59.999999999");
423+
424+
assertTrue(rs.next());
425+
assertEquals(rs.getObject("date").toString(), date.toString());
426+
assertEquals(rs.getObject("date32").toString(), date32.toString());
427+
assertEquals(rs.getObject("dateTime").toString(), dateTime.toString());
428+
assertEquals(rs.getObject("dateTime32").toString(), dateTime32.toString());
429+
assertEquals(rs.getObject("dateTime643").toString(), dateTime643.toString());
430+
assertEquals(rs.getObject("dateTime646").toString(), dateTime646.toString());
431+
assertEquals(rs.getObject("dateTime649").toString(), dateTime649.toString());
432+
433+
assertFalse(rs.next());
434+
}
435+
}
436+
}
318437
}
319438

320439
@Test(groups = { "integration" })
@@ -368,6 +487,23 @@ public void testStringTypes() throws SQLException {
368487
}
369488
}
370489
}
490+
491+
// Check the results with getObject
492+
try (Connection conn = getConnection()) {
493+
try (Statement stmt = conn.createStatement()) {
494+
try (ResultSet rs = stmt.executeQuery("SELECT * FROM test_strings ORDER BY order")) {
495+
assertTrue(rs.next());
496+
assertEquals(rs.getObject("str"), str);
497+
assertEquals(rs.getObject("fixed"), fixed);
498+
assertEquals(rs.getObject("enum"), "a");
499+
assertEquals(rs.getObject("enum8"), "a");
500+
assertEquals(rs.getObject("enum16"), "b");
501+
assertEquals(rs.getObject("uuid"), UUID.fromString(uuid));
502+
assertEquals(rs.getObject("escaped"), escaped);
503+
assertFalse(rs.next());
504+
}
505+
}
506+
}
371507
}
372508

373509
@Test(groups = { "integration" })
@@ -457,6 +593,29 @@ public void testFloatTypes() throws SQLException {
457593
}
458594
}
459595
}
596+
597+
// Check the results with getObject
598+
try (Connection conn = getConnection()) {
599+
try (Statement stmt = conn.createStatement()) {
600+
try (ResultSet rs = stmt.executeQuery("SELECT * FROM test_floats ORDER BY order")) {
601+
assertTrue(rs.next());
602+
assertEquals(rs.getObject("float32"), -3.402823E38d);
603+
assertEquals(rs.getObject("float64"), Double.valueOf(-1.7976931348623157E308));
604+
605+
assertTrue(rs.next());
606+
assertEquals(rs.getObject("float32"), 3.402823E38d);
607+
assertEquals(rs.getObject("float64"), Double.valueOf(1.7976931348623157E308));
608+
609+
assertTrue(rs.next());
610+
611+
DecimalFormat df = new DecimalFormat("#.########");
612+
assertEquals(df.format(rs.getObject("float32")), df.format(float32));
613+
assertEquals(rs.getObject("float64"), float64);
614+
615+
assertFalse(rs.next());
616+
}
617+
}
618+
}
460619
}
461620

462621
@Test(groups = { "integration" })
@@ -490,6 +649,18 @@ public void testBooleanTypes() throws SQLException {
490649
}
491650
}
492651
}
652+
653+
// Check the results with getObject
654+
try (Connection conn = getConnection()) {
655+
try (Statement stmt = conn.createStatement()) {
656+
try (ResultSet rs = stmt.executeQuery("SELECT * FROM test_booleans ORDER BY order")) {
657+
assertTrue(rs.next());
658+
assertEquals(rs.getObject("bool"), bool);
659+
660+
assertFalse(rs.next());
661+
}
662+
}
663+
}
493664
}
494665

495666
@Test(groups = { "integration" })
@@ -556,6 +727,35 @@ public void testArrayTypes() throws SQLException {
556727
}
557728
}
558729
}
730+
731+
// Check the results with getObject
732+
try (Connection conn = getConnection()) {
733+
try (Statement stmt = conn.createStatement()) {
734+
try (ResultSet rs = stmt.executeQuery("SELECT * FROM test_arrays ORDER BY order")) {
735+
assertTrue(rs.next());
736+
Object[] arrayResult = (Object[]) ((Array) rs.getObject("array")).getArray();
737+
assertEquals(arrayResult.length, array.length);
738+
for (int i = 0; i < array.length; i++) {
739+
assertEquals(String.valueOf(arrayResult[i]), String.valueOf(array[i]));
740+
}
741+
742+
Object[] arraystrResult = (Object[]) ((Array) rs.getObject("arraystr")).getArray();
743+
assertEquals(arraystrResult.length, arraystr.length);
744+
for (int i = 0; i < arraystr.length; i++) {
745+
assertEquals(arraystrResult[i], arraystr[i]);
746+
}
747+
Object[] arraytupleResult = (Object[]) ((Array) rs.getObject("arraytuple")).getArray();
748+
assertEquals(arraytupleResult.length, arraytuple.length);
749+
for (int i = 0; i < arraytuple.length; i++) {
750+
Tuple tuple = arraytuple[i];
751+
Tuple tupleResult = new Tuple(((Object[]) arraytupleResult[i]));
752+
assertEquals(String.valueOf(tupleResult.getValue(0)), String.valueOf(tuple.getValue(0)));
753+
assertEquals(String.valueOf(tupleResult.getValue(1)), String.valueOf(tuple.getValue(1)));
754+
}
755+
assertFalse(rs.next());
756+
}
757+
}
758+
}
559759
}
560760

561761
@Test(groups = { "integration" })
@@ -669,7 +869,7 @@ public void testLowCardinalityTypeSimpleStatement() throws SQLException {
669869
try (ResultSet rs = stmt.executeQuery("SELECT * FROM test_low_cardinality ORDER BY order")) {
670870
assertTrue(rs.next());
671871
assertEquals(rs.getString("lowcardinality"), lowcardinality);
672-
872+
assertEquals(rs.getObject("lowcardinality"), lowcardinality);
673873
assertFalse(rs.next());
674874
}
675875
}
@@ -700,6 +900,7 @@ public void testSimpleAggregateFunction() throws SQLException {
700900
try (ResultSet rs = stmt.executeQuery("SELECT sum(int8) FROM test_aggregate")) {
701901
assertTrue(rs.next());
702902
assertEquals(rs.getInt(1), int8 * 3);
903+
assertEquals(rs.getObject(1), (long) (int8 * 3));
703904
}
704905
try (ResultSet rs = stmt.executeQuery("SELECT any(val) FROM test_aggregate")) {
705906
assertTrue(rs.next());
@@ -715,7 +916,9 @@ public void testNestedTypeSimpleStatement() throws SQLException {
715916
runQuery("CREATE TABLE test_nested (order Int8, "
716917
+ "nested Nested (int8 Int8, int16 Int16, int32 Int32, int64 Int64, int128 Int128, int256 Int256)"
717918
+ ") ENGINE = MergeTree ORDER BY ()");
718-
919+
runQuery("CREATE TABLE test_nested_not_flatten (order Int8, "
920+
+ "nested Nested (int8 Int8, int16 Int16, int32 Int32, int64 Int64, int128 Int128, int256 Int256)"
921+
+ ") ENGINE = MergeTree ORDER BY () SETTINGS flatten_nested = 0");
719922
// Insert random (valid) values
720923
long seed = System.currentTimeMillis();
721924
Random rand = new Random(seed);
@@ -733,6 +936,11 @@ public void testNestedTypeSimpleStatement() throws SQLException {
733936
log.info("SQL: {}", sql);
734937
insertData(sql);
735938

939+
String nsql = String.format("INSERT INTO test_nested_not_flatten VALUES ( 1, [(%s,%s,%s,%s,%s,%s)])",
940+
int8, int16, int32, int64, int128, int256);
941+
log.info("SQL: {}", nsql);
942+
insertData(nsql);
943+
736944
// Check the results
737945
try (Connection conn = getConnection()) {
738946
try (Statement stmt = conn.createStatement()) {
@@ -749,6 +957,19 @@ public void testNestedTypeSimpleStatement() throws SQLException {
749957
}
750958
}
751959
}
960+
961+
// Check the results
962+
try (Connection conn = getConnection()) {
963+
try (Statement stmt = conn.createStatement()) {
964+
try (ResultSet rs = stmt.executeQuery("SELECT * FROM test_nested_not_flatten ORDER BY order")) {
965+
assertTrue(rs.next());
966+
assertEquals((Object[])((Object[])((java.sql.Array) rs.getObject("nested")).getArray())[0],
967+
new Object[] {(byte) int8, (short) int16, int32, int64, int128, int256});
968+
969+
assertFalse(rs.next());
970+
}
971+
}
972+
}
752973
}
753974

754975
@Test(groups = { "integration" })

0 commit comments

Comments
 (0)