From 55b71cb1ce60321adedf85a38ee4e8767fce03d1 Mon Sep 17 00:00:00 2001 From: Zhichun Wu Date: Mon, 14 Mar 2022 14:34:09 +0800 Subject: [PATCH 1/2] Bump version --- README.md | 4 ++-- clickhouse-benchmark/pom.xml | 2 +- clickhouse-client/README.md | 2 +- clickhouse-jdbc/README.md | 2 +- examples/grpc/pom.xml | 2 +- examples/jdbc/pom.xml | 2 +- 6 files changed, 7 insertions(+), 7 deletions(-) diff --git a/README.md b/README.md index 42a25c761..624d65165 100644 --- a/README.md +++ b/README.md @@ -112,7 +112,7 @@ Note: in general, the new driver(v0.3.2) is a few times faster with less memory com.clickhouse clickhouse-http-client - 0.3.2-patch6 + 0.3.2-patch7 ``` @@ -148,7 +148,7 @@ try (ClickHouseClient client = ClickHouseClient.newInstance(preferredProtocol); com.clickhouse clickhouse-jdbc - 0.3.2-patch6 + 0.3.2-patch7 http diff --git a/clickhouse-benchmark/pom.xml b/clickhouse-benchmark/pom.xml index 47d4c64eb..4406f3c21 100644 --- a/clickhouse-benchmark/pom.xml +++ b/clickhouse-benchmark/pom.xml @@ -18,7 +18,7 @@ 0.3.1-patch 1.4.4 - 2.6.4 + 2.6.5 UTF-8 1.34 benchmarks diff --git a/clickhouse-client/README.md b/clickhouse-client/README.md index 788f47fde..97cfe422c 100644 --- a/clickhouse-client/README.md +++ b/clickhouse-client/README.md @@ -9,7 +9,7 @@ Async Java client for ClickHouse. `clickhouse-client` is an abstract module, so com.clickhouse clickhouse-http-client - 0.3.2-patch6 + 0.3.2-patch7 ``` diff --git a/clickhouse-jdbc/README.md b/clickhouse-jdbc/README.md index c1493b4cf..234c78a45 100644 --- a/clickhouse-jdbc/README.md +++ b/clickhouse-jdbc/README.md @@ -11,7 +11,7 @@ Keep in mind that `clickhouse-jdbc` is synchronous, and in general it has more o com.clickhouse clickhouse-jdbc - 0.3.2-patch6 + 0.3.2-patch7 ``` diff --git a/examples/grpc/pom.xml b/examples/grpc/pom.xml index 951981096..4e59ff9f4 100644 --- a/examples/grpc/pom.xml +++ b/examples/grpc/pom.xml @@ -56,7 +56,7 @@ UTF-8 UTF-8 - 0.3.2-patch6 + 0.3.2-patch7 3.8.1 diff --git a/examples/jdbc/pom.xml b/examples/jdbc/pom.xml index 279b157bd..ce0845643 100644 --- a/examples/jdbc/pom.xml +++ b/examples/jdbc/pom.xml @@ -56,7 +56,7 @@ UTF-8 UTF-8 - 0.3.2-patch6 + 0.3.2-patch7 3.8.1 From 6977c179a2c93123fac175002dac51c8157386ab Mon Sep 17 00:00:00 2001 From: Zhichun Wu Date: Mon, 14 Mar 2022 19:52:30 +0800 Subject: [PATCH 2/2] Merge a few more changes from 0.3.3 branch --- .../com/clickhouse/client/AbstractClient.java | 1 - .../clickhouse/client/ClickHouseClient.java | 66 ++++++++++++---- .../clickhouse/client/ClickHouseColumn.java | 78 +++++++++++++++++-- .../clickhouse/client/ClickHouseRequest.java | 26 ++++++- .../client/ClickHouseColumnTest.java | 30 +++++++ .../jdbc/ClickHouseStatementTest.java | 20 +++++ 6 files changed, 194 insertions(+), 27 deletions(-) diff --git a/clickhouse-client/src/main/java/com/clickhouse/client/AbstractClient.java b/clickhouse-client/src/main/java/com/clickhouse/client/AbstractClient.java index cf3c49d5b..51077b20f 100644 --- a/clickhouse-client/src/main/java/com/clickhouse/client/AbstractClient.java +++ b/clickhouse-client/src/main/java/com/clickhouse/client/AbstractClient.java @@ -3,7 +3,6 @@ import java.util.concurrent.CompletableFuture; import java.util.concurrent.CompletionException; import java.util.concurrent.ExecutorService; -import java.util.concurrent.TimeUnit; import java.util.concurrent.locks.ReadWriteLock; import java.util.concurrent.locks.ReentrantReadWriteLock; diff --git a/clickhouse-client/src/main/java/com/clickhouse/client/ClickHouseClient.java b/clickhouse-client/src/main/java/com/clickhouse/client/ClickHouseClient.java index 322ed6e50..03a297232 100644 --- a/clickhouse-client/src/main/java/com/clickhouse/client/ClickHouseClient.java +++ b/clickhouse-client/src/main/java/com/clickhouse/client/ClickHouseClient.java @@ -4,6 +4,7 @@ import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; +import java.io.UncheckedIOException; import java.util.ArrayList; import java.util.LinkedList; import java.util.List; @@ -49,13 +50,12 @@ static ClickHouseClientBuilder builder() { /** * Gets default {@link java.util.concurrent.ExecutorService} for static methods - * like {@code dump()}, {@code load()}, {@code send()}, and {@code submit()} - * when {@link com.clickhouse.client.config.ClickHouseDefaults#ASYNC} is - * {@code true}. It will be shared among all client instances when + * like {@code dump()}, {@code load()}, {@code send()}, and {@code submit()}. It + * will be shared among all client instances when * {@link com.clickhouse.client.config.ClickHouseClientOption#MAX_THREADS_PER_CLIENT} * is less than or equals to zero. * - * @return default executor service + * @return non-null default executor service */ static ExecutorService getExecutorService() { return ClickHouseClientBuilder.defaultExecutor; @@ -68,7 +68,7 @@ static ExecutorService getExecutorService() { * * @param return type of the task * @param task non-null task - * @return future object to get result + * @return non-null future object to get result * @throws CompletionException when failed to complete the task */ static CompletableFuture submit(Callable task) { @@ -114,7 +114,7 @@ static CompletableFuture submit(Callable task) { * @param format output format to use * @param compression compression algorithm to use * @param file output file - * @return future object to get result + * @return non-null future object to get result * @throws IllegalArgumentException if any of server, tableOrQuery, and output * is null * @throws CompletionException when error occurred during execution @@ -592,7 +592,8 @@ default boolean accept(ClickHouseProtocol protocol) { * invoked(usually triggered by {@code request.execute()}). * * @param nodeFunc function to get a {@link ClickHouseNode} to connect to - * @return request object holding references to this client and node provider + * @return non-null request object holding references to this client and node + * provider */ default ClickHouseRequest connect(Function nodeFunc) { return new ClickHouseRequest<>(this, ClickHouseChecker.nonNull(nodeFunc, "nodeFunc"), false); @@ -609,17 +610,47 @@ default ClickHouseRequest connect(Function execute(ClickHouseRequest request); + /** + * Synchronous version of {@link #execute(ClickHouseRequest)}. + * + * @param request request object which will be sealed(immutable copy) upon + * execution + * @return non-null response + * @throws ClickHouseException when error occurred during execution + */ + default ClickHouseResponse executeAndWait(ClickHouseRequest request) throws ClickHouseException { + final ClickHouseRequest sealedRequest = request.seal(); + + try { + return execute(sealedRequest).get(); + } catch (InterruptedException e) { + Thread.currentThread().interrupt(); + throw ClickHouseException.forCancellation(e, sealedRequest.getServer()); + } catch (CancellationException e) { + throw ClickHouseException.forCancellation(e, sealedRequest.getServer()); + } catch (CompletionException | ExecutionException | UncheckedIOException e) { + Throwable cause = e.getCause(); + if (cause == null) { + cause = e; + } + throw cause instanceof ClickHouseException ? (ClickHouseException) cause + : ClickHouseException.of(cause, sealedRequest.getServer()); + } catch (RuntimeException e) { // unexpected + throw ClickHouseException.of(e, sealedRequest.getServer()); + } + } + /** * Gets the immutable configuration associated with this client. In most cases * it's the exact same one passed to {@link #init(ClickHouseConfig)} method for * initialization. * - * @return configuration associated with this client + * @return non-null configuration associated with this client */ ClickHouseConfig getConfig(); @@ -650,25 +681,26 @@ default void init(ClickHouseConfig config) { } /** - * Tests if the given server is alive or not. Pay attention that it's a - * synchronous call with minimum overhead(e.g. tiny buffer, no compression and - * no deserialization etc). + * Tests if the given server is alive or not. It always returns {@code false} + * when server is {@code null} or timeout is less than one. Pay attention that + * it's a synchronous call with minimum overhead(e.g. tiny buffer, no + * compression and no deserialization etc). * - * @param server server to test - * @param timeout timeout in millisecond + * @param server non-null server to test + * @param timeout timeout in millisecond, should be greater than zero * @return true if the server is alive; false otherwise */ default boolean ping(ClickHouseNode server, int timeout) { - if (server != null) { + if (server != null && timeout > 0) { server = ClickHouseCluster.probe(server, timeout); - try (ClickHouseResponse resp = connect(server) // create request .option(ClickHouseClientOption.ASYNC, false) // use current thread .option(ClickHouseClientOption.CONNECTION_TIMEOUT, timeout) .option(ClickHouseClientOption.SOCKET_TIMEOUT, timeout) .option(ClickHouseClientOption.MAX_BUFFER_SIZE, 8) // actually 4 bytes should be enough .option(ClickHouseClientOption.MAX_QUEUED_BUFFERS, 1) // enough with only one buffer - .format(ClickHouseFormat.TabSeparated).query("SELECT 1").execute() + .format(ClickHouseFormat.TabSeparated) + .query("SELECT 1 FORMAT TabSeparated").execute() .get(timeout, TimeUnit.MILLISECONDS)) { return true; } catch (Exception e) { diff --git a/clickhouse-client/src/main/java/com/clickhouse/client/ClickHouseColumn.java b/clickhouse-client/src/main/java/com/clickhouse/client/ClickHouseColumn.java index ec0d27899..4714c1535 100644 --- a/clickhouse-client/src/main/java/com/clickhouse/client/ClickHouseColumn.java +++ b/clickhouse-client/src/main/java/com/clickhouse/client/ClickHouseColumn.java @@ -42,6 +42,9 @@ public final class ClickHouseColumn implements Serializable { private int arrayLevel; private ClickHouseColumn arrayBaseColumn; + private boolean fixedByteLength; + private int estimatedByteLength; + private static ClickHouseColumn update(ClickHouseColumn column) { column.enumConstants = ClickHouseEnum.EMPTY; int size = column.parameters.size(); @@ -70,11 +73,17 @@ private static ClickHouseColumn update(ClickHouseColumn column) { if (size >= 2) { // same as DateTime64 column.scale = Integer.parseInt(column.parameters.get(0)); column.timeZone = TimeZone.getTimeZone(column.parameters.get(1).replace("'", "")); + if (!column.nullable) { + column.estimatedByteLength += ClickHouseDataType.DateTime64.getByteLength(); + } } else if (size == 1) { // same as DateTime32 // unfortunately this will fall back to GMT if the time zone // cannot be resolved TimeZone tz = TimeZone.getTimeZone(column.parameters.get(0).replace("'", "")); column.timeZone = tz; + if (!column.nullable) { + column.estimatedByteLength += ClickHouseDataType.DateTime32.getByteLength(); + } } break; case DateTime32: @@ -97,6 +106,18 @@ private static ClickHouseColumn update(ClickHouseColumn column) { if (size >= 2) { column.precision = Integer.parseInt(column.parameters.get(0)); column.scale = Integer.parseInt(column.parameters.get(1)); + + if (!column.nullable) { + if (column.precision > ClickHouseDataType.Decimal128.getMaxScale()) { + column.estimatedByteLength += ClickHouseDataType.Decimal256.getByteLength(); + } else if (column.precision > ClickHouseDataType.Decimal64.getMaxScale()) { + column.estimatedByteLength += ClickHouseDataType.Decimal128.getByteLength(); + } else if (column.precision > ClickHouseDataType.Decimal32.getMaxScale()) { + column.estimatedByteLength += ClickHouseDataType.Decimal64.getByteLength(); + } else { + column.estimatedByteLength += ClickHouseDataType.Decimal32.getByteLength(); + } + } } break; case Decimal32: @@ -110,6 +131,15 @@ private static ClickHouseColumn update(ClickHouseColumn column) { case FixedString: if (size > 0) { column.precision = Integer.parseInt(column.parameters.get(0)); + if (!column.nullable) { + column.estimatedByteLength += column.precision; + } + } + break; + case String: + column.fixedByteLength = false; + if (!column.nullable) { + column.estimatedByteLength += 1; } break; default: @@ -129,6 +159,9 @@ protected static int readColumn(String args, int startIndex, int len, String nam boolean lowCardinality = false; int i = startIndex; + boolean fixedLength = true; + int estimatedLength = 0; + if (args.startsWith(KEYWORD_LOW_CARDINALITY, i)) { lowCardinality = true; int index = args.indexOf('(', i + KEYWORD_LOW_CARDINALITY.length()); @@ -173,6 +206,8 @@ protected static int readColumn(String args, int startIndex, int len, String nam column = new ClickHouseColumn(ClickHouseDataType.valueOf(matchedKeyword), name, args.substring(startIndex, i), nullable, lowCardinality, params, nestedColumns); column.aggFuncType = aggFunc; + fixedLength = false; + estimatedLength++; } else if (args.startsWith(KEYWORD_ARRAY, i)) { int index = args.indexOf('(', i + KEYWORD_ARRAY.length()); if (index < i) { @@ -188,6 +223,8 @@ protected static int readColumn(String args, int startIndex, int len, String nam column = new ClickHouseColumn(ClickHouseDataType.Array, name, args.substring(startIndex, endIndex), nullable, lowCardinality, null, nestedColumns); i = endIndex; + fixedLength = false; + estimatedLength++; } else if (args.startsWith(KEYWORD_MAP, i)) { int index = args.indexOf('(', i + KEYWORD_MAP.length()); if (index < i) { @@ -210,6 +247,8 @@ protected static int readColumn(String args, int startIndex, int len, String nam column = new ClickHouseColumn(ClickHouseDataType.Map, name, args.substring(startIndex, endIndex), nullable, lowCardinality, null, nestedColumns); i = endIndex; + fixedLength = false; + estimatedLength++; } else if (args.startsWith(KEYWORD_NESTED, i)) { int index = args.indexOf('(', i + KEYWORD_NESTED.length()); if (index < i) { @@ -223,6 +262,8 @@ protected static int readColumn(String args, int startIndex, int len, String nam } column = new ClickHouseColumn(ClickHouseDataType.Nested, name, originalTypeName, nullable, lowCardinality, null, nestedColumns); + fixedLength = false; + estimatedLength++; } else if (args.startsWith(KEYWORD_TUPLE, i)) { int index = args.indexOf('(', i + KEYWORD_TUPLE.length()); if (index < i) { @@ -243,6 +284,12 @@ protected static int readColumn(String args, int startIndex, int len, String nam } column = new ClickHouseColumn(ClickHouseDataType.Tuple, name, args.substring(startIndex, endIndex), nullable, lowCardinality, null, nestedColumns); + for (ClickHouseColumn n : nestedColumns) { + estimatedLength += n.estimatedByteLength; + if (!n.fixedByteLength) { + fixedLength = false; + } + } } if (column == null) { @@ -298,6 +345,16 @@ protected static int readColumn(String args, int startIndex, int len, String nam builder.setLength(0); } + if (nullable) { + fixedLength = false; + estimatedLength++; + } else if (column.dataType.getByteLength() == 0) { + fixedLength = false; + } else { + estimatedLength += column.dataType.getByteLength(); + } + column.fixedByteLength = fixedLength; + column.estimatedByteLength = estimatedLength; list.add(update(column)); return i; @@ -373,11 +430,6 @@ public static List parse(String args) { return Collections.unmodifiableList(c); } - private ClickHouseColumn(String originalTypeName, String columnName) { - this.originalTypeName = originalTypeName; - this.columnName = columnName; - } - private ClickHouseColumn(ClickHouseDataType dataType, String columnName, String originalTypeName, boolean nullable, boolean lowCardinality, List parameters, List nestedColumns) { this.aggFuncType = null; @@ -403,6 +455,9 @@ private ClickHouseColumn(ClickHouseDataType dataType, String columnName, String list.addAll(nestedColumns); this.nested = Collections.unmodifiableList(list); } + + this.fixedByteLength = false; + this.estimatedByteLength = 0; } public boolean isAggregateFunction() { @@ -420,6 +475,10 @@ public boolean isEnum() { || dataType == ClickHouseDataType.Enum16; } + public boolean isFixedLength() { + return fixedByteLength; + } + public boolean isMap() { return dataType == ClickHouseDataType.Map; } @@ -448,6 +507,10 @@ public ClickHouseEnum getEnumConstants() { return enumConstants; } + public int getEstimatedLength() { + return estimatedByteLength; + } + public String getOriginalTypeName() { return originalTypeName; } @@ -541,6 +604,8 @@ public int hashCode() { result = prime * result + precision; result = prime * result + scale; result = prime * result + ((timeZone == null) ? 0 : timeZone.hashCode()); + result = prime * result + (fixedByteLength ? 1231 : 1237); + result = prime * result + estimatedByteLength; return result; } @@ -561,7 +626,8 @@ public boolean equals(Object obj) { && Objects.equals(nested, other.nested) && nullable == other.nullable && Objects.equals(originalTypeName, other.originalTypeName) && Objects.equals(parameters, other.parameters) && precision == other.precision && scale == other.scale - && Objects.equals(timeZone, other.timeZone); + && Objects.equals(timeZone, other.timeZone) && fixedByteLength == other.fixedByteLength + && estimatedByteLength == other.estimatedByteLength; } @Override diff --git a/clickhouse-client/src/main/java/com/clickhouse/client/ClickHouseRequest.java b/clickhouse-client/src/main/java/com/clickhouse/client/ClickHouseRequest.java index 6ab9cb3da..7191de6f1 100644 --- a/clickhouse-client/src/main/java/com/clickhouse/client/ClickHouseRequest.java +++ b/clickhouse-client/src/main/java/com/clickhouse/client/ClickHouseRequest.java @@ -124,11 +124,21 @@ public Mutation data(InputStream input) { * Sends mutation requets for execution. Same as * {@code client.execute(request.seal())}. * - * @return future to get response + * @return non-null future to get response * @throws CompletionException when error occurred */ public CompletableFuture send() { - return getClient().execute(isSealed() ? this : seal()); + return execute(); + } + + /** + * Synchronous version of {@link #send()}. + * + * @return non-null response + * @throws ClickHouseException when error occurred during execution + */ + public ClickHouseResponse sendAndWait() throws ClickHouseException { + return executeAndWait(); } @Override @@ -1368,10 +1378,20 @@ public Mutation write() { /** * Executes the request. Same as {@code client.execute(request.seal())}. * - * @return future to get response + * @return non-null future to get response * @throws CompletionException when error occurred during execution */ public CompletableFuture execute() { return getClient().execute(isSealed() ? this : seal()); } + + /** + * Synchronous version of {@link #execute()}. + * + * @return non-null response + * @throws ClickHouseException when error occurred during execution + */ + public ClickHouseResponse executeAndWait() throws ClickHouseException { + return getClient().executeAndWait(isSealed() ? this : seal()); + } } diff --git a/clickhouse-client/src/test/java/com/clickhouse/client/ClickHouseColumnTest.java b/clickhouse-client/src/test/java/com/clickhouse/client/ClickHouseColumnTest.java index 44e59286a..e0974cc0e 100644 --- a/clickhouse-client/src/test/java/com/clickhouse/client/ClickHouseColumnTest.java +++ b/clickhouse-client/src/test/java/com/clickhouse/client/ClickHouseColumnTest.java @@ -20,6 +20,8 @@ public void testReadColumn() { List list = new LinkedList<>(); Assert.assertEquals(ClickHouseColumn.readColumn(args, 0, args.length(), null, list), args.indexOf("cc") - 2); Assert.assertEquals(list.size(), 1); + Assert.assertFalse(list.get(0).isFixedLength(), "Should not have fixed length in byte"); + Assert.assertEquals(list.get(0).getEstimatedLength(), 1); list.clear(); Assert.assertEquals(ClickHouseColumn.readColumn(args, args.indexOf("cc") + 3, args.length(), null, list), args.lastIndexOf(',')); @@ -32,6 +34,8 @@ public void testReadColumn() { Assert.assertFalse(column.isLowCardinality()); Assert.assertTrue(column.isNullable()); Assert.assertEquals(column.getDataType(), ClickHouseDataType.UInt8); + Assert.assertFalse(column.isFixedLength(), "Should not have fixed length in byte"); + Assert.assertEquals(column.getEstimatedLength(), 1); list.clear(); args = "INT1 unsigned not null, b DateTime64(3) NULL"; @@ -40,6 +44,8 @@ public void testReadColumn() { column = list.get(0); Assert.assertFalse(column.isNullable()); Assert.assertEquals(column.getDataType(), ClickHouseDataType.UInt8); + Assert.assertTrue(column.isFixedLength(), "Should have fixed length in byte"); + Assert.assertEquals(column.getEstimatedLength(), 1); list.clear(); Assert.assertEquals(ClickHouseColumn.readColumn(args, args.indexOf('D'), args.length(), null, list), @@ -48,6 +54,8 @@ public void testReadColumn() { column = list.get(0); Assert.assertTrue(column.isNullable()); Assert.assertEquals(column.getDataType(), ClickHouseDataType.DateTime64); + Assert.assertFalse(column.isFixedLength(), "Should not have fixed length in byte"); + Assert.assertEquals(column.getEstimatedLength(), 1); } @Test(groups = { "unit" }) @@ -59,6 +67,8 @@ public void testReadNestedColumn() { ClickHouseColumn column = list.get(0); Assert.assertEquals(column.getNestedColumns().size(), 1); Assert.assertEquals(column.getNestedColumns().get(0).getNestedColumns().size(), 1); + Assert.assertFalse(column.isFixedLength(), "Should not have fixed length in byte"); + Assert.assertEquals(column.getEstimatedLength(), 1); list.clear(); args = " Tuple(Nullable(FixedString(3)), Array(UInt8),String not null) "; @@ -66,6 +76,8 @@ public void testReadNestedColumn() { Assert.assertEquals(list.size(), 1); column = list.get(0); Assert.assertEquals(column.getOriginalTypeName(), args.trim()); + Assert.assertFalse(column.isFixedLength(), "Should not have fixed length in byte"); + Assert.assertEquals(column.getEstimatedLength(), 3); list.clear(); args = "Map(UInt8 , UInt8)"; @@ -73,6 +85,8 @@ public void testReadNestedColumn() { Assert.assertEquals(list.size(), 1); column = list.get(0); Assert.assertEquals(column.getOriginalTypeName(), args); + Assert.assertFalse(column.isFixedLength(), "Should not have fixed length in byte"); + Assert.assertEquals(column.getEstimatedLength(), 1); list.clear(); args = "Map(String, FixedString(233))"; @@ -80,6 +94,8 @@ public void testReadNestedColumn() { Assert.assertEquals(list.size(), 1); column = list.get(0); Assert.assertEquals(column.getOriginalTypeName(), args); + Assert.assertFalse(column.isFixedLength(), "Should not have fixed length in byte"); + Assert.assertEquals(column.getEstimatedLength(), 1); list.clear(); args = "Map(String, Tuple(UInt8, Nullable(String), UInt16 null))"; @@ -91,6 +107,8 @@ public void testReadNestedColumn() { Assert.assertEquals(column.getKeyInfo().getOriginalTypeName(), "String"); Assert.assertEquals(column.getValueInfo().getOriginalTypeName(), "Tuple(UInt8, Nullable(String), UInt16 null)"); Assert.assertEquals(column.getValueInfo().getNestedColumns().size(), 3); + Assert.assertFalse(column.isFixedLength(), "Should not have fixed length in byte"); + Assert.assertEquals(column.getEstimatedLength(), 1); list.clear(); args = "Nested(\na Array(Nullable(UInt8)), `b b` LowCardinality(Nullable(DateTime64(3))))"; @@ -98,6 +116,8 @@ public void testReadNestedColumn() { Assert.assertEquals(list.size(), 1); column = list.get(0); Assert.assertEquals(column.getOriginalTypeName(), args); + Assert.assertFalse(column.isFixedLength(), "Should not have fixed length in byte"); + Assert.assertEquals(column.getEstimatedLength(), 1); } @Test(groups = { "unit" }) @@ -123,6 +143,8 @@ public void testAggregationFunction() throws Exception { Assert.assertEquals(column.getAggregateFunction(), ClickHouseAggregateFunction.groupBitmap); Assert.assertEquals(column.getFunction(), "groupBitmap"); Assert.assertEquals(column.getNestedColumns(), Collections.singletonList(ClickHouseColumn.of("", "UInt32"))); + Assert.assertFalse(column.isFixedLength(), "Should not have fixed length in byte"); + Assert.assertEquals(column.getEstimatedLength(), 1); column = ClickHouseColumn.of("aggFunc", "AggregateFunction(quantiles(0.5, 0.9), Nullable(UInt64))"); Assert.assertTrue(column.isAggregateFunction()); @@ -131,6 +153,8 @@ public void testAggregationFunction() throws Exception { Assert.assertEquals(column.getFunction(), "quantiles(0.5,0.9)"); Assert.assertEquals(column.getNestedColumns(), Collections.singletonList(ClickHouseColumn.of("", "Nullable(UInt64)"))); + Assert.assertFalse(column.isFixedLength(), "Should not have fixed length in byte"); + Assert.assertEquals(column.getEstimatedLength(), 1); } @Test(groups = { "unit" }) @@ -146,6 +170,8 @@ public void testArray() throws Exception { Assert.assertEquals(column.getArrayBaseColumn().getArrayNestedLevel(), 0); Assert.assertEquals(column.getArrayBaseColumn().getArrayBaseColumn(), null); + Assert.assertFalse(column.isFixedLength(), "Should not have fixed length in byte"); + Assert.assertEquals(column.getEstimatedLength(), 1); ClickHouseColumn c = ClickHouseColumn.of("arr", "Array(LowCardinality(Nullable(String)))"); Assert.assertTrue(c.isArray()); @@ -153,6 +179,8 @@ public void testArray() throws Exception { Assert.assertEquals(c.getArrayNestedLevel(), 1); Assert.assertEquals(c.getArrayBaseColumn().getOriginalTypeName(), "LowCardinality(Nullable(String))"); Assert.assertFalse(c.getArrayBaseColumn().isArray()); + Assert.assertFalse(column.isFixedLength(), "Should not have fixed length in byte"); + Assert.assertEquals(column.getEstimatedLength(), 1); } @Test(dataProvider = "enumTypesProvider", groups = { "unit" }) @@ -169,5 +197,7 @@ public void testEnum(String typeName) throws Exception { Assert.assertEquals(column.getEnumConstants().name(10), "Query'Finish"); Assert.assertEquals(column.getEnumConstants().value("Query'Start"), 1); Assert.assertEquals(column.getEnumConstants().value("Query'Finish"), 10); + Assert.assertTrue(column.isFixedLength(), "Should have fixed length in byte"); + Assert.assertEquals(column.getEstimatedLength(), column.getDataType().getByteLength()); } } diff --git a/clickhouse-jdbc/src/test/java/com/clickhouse/jdbc/ClickHouseStatementTest.java b/clickhouse-jdbc/src/test/java/com/clickhouse/jdbc/ClickHouseStatementTest.java index 13c235827..177270ad8 100644 --- a/clickhouse-jdbc/src/test/java/com/clickhouse/jdbc/ClickHouseStatementTest.java +++ b/clickhouse-jdbc/src/test/java/com/clickhouse/jdbc/ClickHouseStatementTest.java @@ -112,6 +112,26 @@ public void testLogComment() throws SQLException { } } + @Test(groups = "integration") + public void testMaxFloatValues() throws SQLException { + Properties props = new Properties(); + try (ClickHouseConnection conn = newConnection(props); + ClickHouseStatement s = conn.createStatement()) { + s.execute("drop table if exists test_float_values; " + + "create table test_float_values(f1 Nullable(Float64), f2 Nullable(Float64))engine=Memory"); + try (PreparedStatement ps = conn.prepareStatement("insert into test_float_values values(?, ?)")) { + ps.setObject(1, Float.MAX_VALUE); + ps.setObject(2, Double.MAX_VALUE); + ps.executeUpdate(); + } + ResultSet rs = s.executeQuery("select * from test_float_values"); + Assert.assertTrue(rs.next()); + Assert.assertEquals(rs.getFloat(1), Float.MAX_VALUE); + Assert.assertEquals(rs.getDouble(2), Double.MAX_VALUE); + Assert.assertFalse(rs.next()); + } + } + @Test(groups = "integration") public void testMutation() throws SQLException { Properties props = new Properties();