Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,8 @@

- **[client-v2]** Fixed inconsistent use of `executionTimeout` parameter in `Client` component. The timeout was previously set in milliseconds but mistakenly retrieved and used in seconds in some places. Now it correctly uses milliseconds consistently. (https://github.com/ClickHouse/clickhouse-java/issues/2358)

- **[client-v2]** Fixed container query parameters being sent unquoted, so `Client.query(sql, params, settings)` binding a `List<LocalDate>` (or an array/`Map`) to a placeholder like `{ids:Array(Date)}` was rejected by the server with `CANNOT_PARSE_INPUT_ASSERTION_FAILED`. Parameter values are now formatted by `DataTypeConverter#convertParameterToString(Object)` before being sent: pass the raw Java value and the client renders it into the text the server's `param_<name>` interface expects — a `Collection`, array (object or primitive), or `Map` becomes ClickHouse `Array` (`['2026-05-13']`) / `Map` (`{'k':'v'}`) text with `String`/temporal leaves single-quoted and numeric/boolean leaves left unquoted, while a scalar is passed through unquoted as before. No manual pre-formatting of container parameters is needed. (https://github.com/ClickHouse/clickhouse-java/issues/2897)

## 0.9.8

### Improvements
Expand Down
11 changes: 10 additions & 1 deletion client-v2/src/main/java/com/clickhouse/client/api/Client.java
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
import com.clickhouse.client.api.insert.InsertSettings;
import com.clickhouse.client.api.internal.ClientStatisticsHolder;
import com.clickhouse.client.api.internal.CredentialsManager;
import com.clickhouse.client.api.internal.DataTypeConverter;
import com.clickhouse.client.api.internal.HttpAPIClientHelper;
import com.clickhouse.client.api.internal.MapUtils;
import com.clickhouse.client.api.internal.TableSchemaParser;
Expand Down Expand Up @@ -1715,7 +1716,15 @@ public CompletableFuture<QueryResponse> query(String sqlQuery, Map<String, Objec
clientStats.start(ClientMetrics.OP_DURATION);

if (queryParams != null) {
requestSettings.setOption(HttpAPIClientHelper.KEY_STATEMENT_PARAMS, queryParams);
// Format parameter values here so the transport layer receives ready-to-send text:
// Array/Map values are quoted the way the server's param_<name> parser expects
// (e.g. {dates:Array(Date)} <- List<LocalDate> becomes ['2026-05-13'], not [2026-05-13]).
Map<String, String> formattedParams = new LinkedHashMap<>();
for (Map.Entry<String, Object> param : queryParams.entrySet()) {
formattedParams.put(param.getKey(),
DataTypeConverter.INSTANCE.convertParameterToString(param.getValue()));
}
requestSettings.setOption(HttpAPIClientHelper.KEY_STATEMENT_PARAMS, formattedParams);
}

if (requestSettings.getQueryId() == null && queryIdGenerator != null) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
import com.clickhouse.client.api.data_formats.internal.BinaryStreamReader;
import com.clickhouse.data.ClickHouseColumn;
import com.clickhouse.data.ClickHouseDataType;
import com.clickhouse.data.ClickHouseValues;

import java.io.IOException;
import java.lang.reflect.Array;
Expand All @@ -17,8 +18,12 @@
import java.time.ZonedDateTime;
import java.time.format.DateTimeFormatter;
import java.time.temporal.TemporalAccessor;
import java.util.ArrayDeque;
import java.util.Collection;
import java.util.Date;
import java.util.Deque;
import java.util.List;
import java.util.Map;

/**
* Class designed to convert different data types to Java objects.
Expand Down Expand Up @@ -221,6 +226,127 @@
return arrayToString(value, column);
}

/**
* Converts a query-parameter value into the text form expected by ClickHouse's HTTP
* {@code param_<name>} interface, allowing callers to pass raw Java values - including
* {@link Collection}, array (object or primitive) and {@link Map} values - for
* {@code Array}/{@code Map} placeholders without pre-formatting them.
*
* <p>A top-level scalar is returned in its bare, unquoted text form, which is what the server
* expects for a scalar {@code {name:Type}} placeholder (e.g. a {@code Date} is sent as
* {@code 2026-05-13}, not {@code '2026-05-13'}). A container is rendered as a ClickHouse
* {@code Array} ({@code [..]}) or {@code Map} ({@code {..}}) text literal in which
* {@code String}/temporal leaves are single-quoted (and escaped) while numeric/boolean leaves
* are left unquoted, as required by the server's array/map text parser.</p>
*
* @param value parameter value, may be {@code null}
* @return the formatted {@code param_<name>} value
*/
public String convertParameterToString(Object value) {
if (isParameterContainer(value)) {
return convertParameterContainer(value);
}
// Scalars (and null) are passed through unquoted: the server reads a scalar parameter value
// verbatim, so quoting it here would break parsing (e.g. Date, numbers, Identifier).
return String.valueOf(value);
}

private boolean isParameterContainer(Object value) {
return value instanceof Collection || value instanceof Map
|| (value != null && value.getClass().isArray());
}
Comment thread
chernser marked this conversation as resolved.

/**
* Renders a {@code Collection}/array/{@code Map} parameter value into ClickHouse
* {@code Array} ({@code [e1,e2,...]}) or {@code Map} ({@code {k:v,...}}) text using an explicit
* work stack rather than recursion, so that arbitrarily deep nesting cannot overflow the call
* stack. Work items are pushed in reverse so they pop in left-to-right output order: a container
* expands into its punctuation and child values, while a leaf is formatted with
* {@link ClickHouseValues#convertToSqlExpression(Object)} (String/temporal single-quoted,
* numeric/boolean unquoted, {@code null} -> {@code NULL}) - exactly what the server's array/map
* text parser expects for nested elements.
*/
private String convertParameterContainer(Object value) {
Comment thread
polyglotAI-bot marked this conversation as resolved.
StringBuilder sb = new StringBuilder();
Deque<Object> stack = new ArrayDeque<>();
stack.push(value);
while (!stack.isEmpty()) {
Object item = stack.pop();
if (item instanceof Literal) {
sb.append(((Literal) item).text);
} else if (isParameterContainer(item)) {
pushContainer(stack, item);
} else {
sb.append(ClickHouseValues.convertToSqlExpression(item));
}
}
return sb.toString();
}

/** Expands one container onto the work {@code stack}, pushed in reverse so it pops in output order. */
private void pushContainer(Deque<Object> stack, Object container) {

Check failure on line 287 in client-v2/src/main/java/com/clickhouse/client/api/internal/DataTypeConverter.java

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Refactor this method to reduce its Cognitive Complexity from 18 to the 15 allowed.

See more on https://sonarcloud.io/project/issues?id=ClickHouse_clickhouse-java&issues=AZ9D_Hqy_UG81LbkguPx&open=AZ9D_Hqy_UG81LbkguPx&pullRequest=2898
if (container instanceof Map) {
stack.push(MAP_CLOSE);
Object[] entries = ((Map<?, ?>) container).entrySet().toArray();
for (int i = entries.length - 1; i >= 0; i--) {
Map.Entry<?, ?> entry = (Map.Entry<?, ?>) entries[i];
pushValue(stack, entry.getValue());
stack.push(COLON);
pushValue(stack, entry.getKey());
if (i > 0) {
stack.push(COMMA);
}
}
stack.push(MAP_OPEN);
} else if (container instanceof Collection) {
stack.push(ARRAY_CLOSE);
Object[] elements = ((Collection<?>) container).toArray();
for (int i = elements.length - 1; i >= 0; i--) {
pushValue(stack, elements[i]);
if (i > 0) {
stack.push(COMMA);
}
}
stack.push(ARRAY_OPEN);
} else {
// Reflection handles both Object[] and primitive arrays (int[], long[], ...);
// Array.get autoboxes primitive elements so they render as unquoted numbers/booleans.
stack.push(ARRAY_CLOSE);
for (int i = Array.getLength(container) - 1; i >= 0; i--) {
pushValue(stack, Array.get(container, i));
if (i > 0) {
stack.push(COMMA);
}
}
stack.push(ARRAY_OPEN);
}
}

/**
* Pushes a child value onto the work {@code stack}, substituting {@link #NULL_LITERAL} for a
* {@code null} element because {@link ArrayDeque} does not permit {@code null} entries.
*/
private static void pushValue(Deque<Object> stack, Object value) {
stack.push(value == null ? NULL_LITERAL : value);
}

/** A pre-rendered literal on the work stack: structural punctuation, or the {@code null} leaf. */
private static final class Literal {
final String text;

Literal(String text) {
this.text = text;
}
}

private static final Literal ARRAY_OPEN = new Literal("[");
private static final Literal ARRAY_CLOSE = new Literal("]");
private static final Literal MAP_OPEN = new Literal("{");
private static final Literal MAP_CLOSE = new Literal("}");
private static final Literal COMMA = new Literal(",");
private static final Literal COLON = new Literal(":");
private static final Literal NULL_LITERAL = new Literal(ClickHouseValues.convertToSqlExpression(null));

public String geoToString(Object value, ClickHouseColumn column) {
String geoValue = tryGeoToString(value, column);
return geoValue != null ? geoValue : value.toString();
Expand Down
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
package com.clickhouse.client.api.internal;

import com.clickhouse.data.ClickHouseColumn;
import org.testng.annotations.DataProvider;
import org.testng.annotations.Test;

import java.math.BigDecimal;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.LocalTime;
Expand Down Expand Up @@ -164,4 +166,79 @@
converter.convertToString(new double[][] {{1D, 2D, 3D}}, ClickHouseColumn.of("field", "Dynamic")),
"[[1.0, 2.0, 3.0]]");
}

@DataProvider(name = "queryParameters")
public static Object[][] queryParameters() {
return new Object[][] {
// --- Scalars: bare, UNQUOTED text form. The server reads a scalar {name:Type} value
// verbatim, so quoting it (e.g. '2026-05-13' for a Date) is rejected. ---
{LocalDate.of(2026, 5, 13), "2026-05-13"},

Check warning on line 175 in client-v2/src/test/java/com/clickhouse/client/api/internal/DataTypeConverterTest.java

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Use a "java.time.Month" enum constant instead of this int literal.

See more on https://sonarcloud.io/project/issues?id=ClickHouse_clickhouse-java&issues=AZ8FXGKzw7IBCOp2OOT9&open=AZ8FXGKzw7IBCOp2OOT9&pullRequest=2898
{"hello", "hello"},
{42, "42"},
{new BigDecimal("1.50"), "1.50"},
{null, "null"},

// --- Array/List with String/temporal leaves: single-quoted so the server's array
// text parser accepts them (previously emitted e.g. [2026-05-13] -> HTTP 400). ---
{Arrays.asList(LocalDate.of(2026, 5, 13), LocalDate.of(2026, 5, 14)), "['2026-05-13','2026-05-14']"},

Check warning on line 183 in client-v2/src/test/java/com/clickhouse/client/api/internal/DataTypeConverterTest.java

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Use a "java.time.Month" enum constant instead of this int literal.

See more on https://sonarcloud.io/project/issues?id=ClickHouse_clickhouse-java&issues=AZ8FXGKzw7IBCOp2OOT_&open=AZ8FXGKzw7IBCOp2OOT_&pullRequest=2898

Check warning on line 183 in client-v2/src/test/java/com/clickhouse/client/api/internal/DataTypeConverterTest.java

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Use a "java.time.Month" enum constant instead of this int literal.

See more on https://sonarcloud.io/project/issues?id=ClickHouse_clickhouse-java&issues=AZ8FXGKzw7IBCOp2OOT-&open=AZ8FXGKzw7IBCOp2OOT-&pullRequest=2898
{Arrays.asList("a", "b"), "['a','b']"},
{Collections.singletonList(LocalDateTime.of(2026, 5, 13, 16, 10, 0)), "['2026-05-13 16:10:00']"},

Check warning on line 185 in client-v2/src/test/java/com/clickhouse/client/api/internal/DataTypeConverterTest.java

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Use a "java.time.Month" enum constant instead of this int literal.

See more on https://sonarcloud.io/project/issues?id=ClickHouse_clickhouse-java&issues=AZ8FXGKzw7IBCOp2OOUA&open=AZ8FXGKzw7IBCOp2OOUA&pullRequest=2898
{new LocalDate[] {LocalDate.of(2026, 5, 13)}, "['2026-05-13']"},

Check warning on line 186 in client-v2/src/test/java/com/clickhouse/client/api/internal/DataTypeConverterTest.java

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Use a "java.time.Month" enum constant instead of this int literal.

See more on https://sonarcloud.io/project/issues?id=ClickHouse_clickhouse-java&issues=AZ8FXGKzw7IBCOp2OOUB&open=AZ8FXGKzw7IBCOp2OOUB&pullRequest=2898

// --- Primitive arrays are detected via getClass().isArray() and iterated reflectively
// (Array.get autoboxes), so they are no longer mis-rendered as a scalar "[I@..". ---
{new int[] {1, 2, 3}, "[1,2,3]"},
{new double[] {1.0d, 2.5d}, "[1.0,2.5]"},
{new boolean[] {true, false}, "[true,false]"},
// byte[] has no declared type here, so it is treated as a numeric array (Array(Int8)).
{new byte[] {1, 2, 3}, "[1,2,3]"},

// --- Nested containers, including a nested primitive array (List<int[]>). ---
{Collections.singletonList(Collections.singletonList(LocalDate.of(2026, 5, 13))), "[['2026-05-13']]"},

Check warning on line 197 in client-v2/src/test/java/com/clickhouse/client/api/internal/DataTypeConverterTest.java

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Use a "java.time.Month" enum constant instead of this int literal.

See more on https://sonarcloud.io/project/issues?id=ClickHouse_clickhouse-java&issues=AZ8FXGKzw7IBCOp2OOUC&open=AZ8FXGKzw7IBCOp2OOUC&pullRequest=2898
{Collections.singletonList(new int[] {1, 2}), "[[1,2]]"},

// --- Map: {k:v} (no spaces), keys/values formatted like array leaves. ---
{Collections.singletonMap("k", LocalDate.of(2026, 5, 13)), "{'k':'2026-05-13'}"},

Check warning on line 201 in client-v2/src/test/java/com/clickhouse/client/api/internal/DataTypeConverterTest.java

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Use a "java.time.Month" enum constant instead of this int literal.

See more on https://sonarcloud.io/project/issues?id=ClickHouse_clickhouse-java&issues=AZ8FXGKzw7IBCOp2OOUD&open=AZ8FXGKzw7IBCOp2OOUD&pullRequest=2898

// --- Escaping and null leaves. ---
{Collections.singletonList("a'b"), "['a\\'b']"},
{Arrays.asList(LocalDate.of(2026, 5, 13), null), "['2026-05-13',NULL]"},

Check warning on line 205 in client-v2/src/test/java/com/clickhouse/client/api/internal/DataTypeConverterTest.java

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Use a "java.time.Month" enum constant instead of this int literal.

See more on https://sonarcloud.io/project/issues?id=ClickHouse_clickhouse-java&issues=AZ8FXGKzw7IBCOp2OOUE&open=AZ8FXGKzw7IBCOp2OOUE&pullRequest=2898

// --- Contrast: numeric containers must stay UNQUOTED (quoting an Array(Int32)/
// Array(Decimal) element causes the server to reject it with CANNOT_READ_ARRAY_FROM_TEXT). ---
{Arrays.asList(1, 2, 3), "[1,2,3]"},
{Collections.singletonList(new BigDecimal("1.50")), "[1.50]"},

// --- Boundary: empty containers. ---
{Collections.emptyList(), "[]"},
{Collections.emptyMap(), "{}"},
};
}

@Test(dataProvider = "queryParameters")
public void testConvertParameterToString(Object value, String expected) {
assertEquals(new DataTypeConverter().convertParameterToString(value), expected);
}

@Test
public void testConvertDeeplyNestedParameterDoesNotOverflow() {
// convertParameterContainer uses an explicit work stack (not recursion), so a deeply nested
// container must format correctly without a StackOverflowError. Recursion overflowed here.
int depth = 20_000;
Object nested = LocalDate.of(2026, 5, 13);

Check warning on line 228 in client-v2/src/test/java/com/clickhouse/client/api/internal/DataTypeConverterTest.java

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Use a "java.time.Month" enum constant instead of this int literal.

See more on https://sonarcloud.io/project/issues?id=ClickHouse_clickhouse-java&issues=AZ9D_Ho0_UG81LbkguPw&open=AZ9D_Ho0_UG81LbkguPw&pullRequest=2898
for (int i = 0; i < depth; i++) {
nested = Collections.singletonList(nested);
}

StringBuilder expected = new StringBuilder(depth * 2 + 12);
for (int i = 0; i < depth; i++) {
expected.append('[');
}
expected.append("'2026-05-13'");
for (int i = 0; i < depth; i++) {
expected.append(']');
}

assertEquals(new DataTypeConverter().convertParameterToString(nested), expected.toString());
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,7 @@
import java.net.InetAddress;
import java.nio.ByteBuffer;
import java.nio.charset.StandardCharsets;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.time.ZonedDateTime;
Expand Down Expand Up @@ -1660,6 +1661,37 @@
Assert.assertEquals(records.get(1).getString("name"), "ENGINES");
}

@DataProvider(name = "containerQueryParameters")
Object[][] containerQueryParameters() {
// {clickHouseType, value, expected} - add a row to extend coverage to another container/type.
return new Object[][]{
// String and temporal elements must be single-quoted so the server's param parser accepts them.
{"Array(Date)", Arrays.asList(LocalDate.of(2026, 5, 13), LocalDate.of(2026, 5, 14)), "['2026-05-13','2026-05-14']"},

Check warning on line 1669 in client-v2/src/test/java/com/clickhouse/client/query/QueryTests.java

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Use a "java.time.Month" enum constant instead of this int literal.

See more on https://sonarcloud.io/project/issues?id=ClickHouse_clickhouse-java&issues=AZ9DypNZR51oomk0lMeW&open=AZ9DypNZR51oomk0lMeW&pullRequest=2898

Check warning on line 1669 in client-v2/src/test/java/com/clickhouse/client/query/QueryTests.java

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Use a "java.time.Month" enum constant instead of this int literal.

See more on https://sonarcloud.io/project/issues?id=ClickHouse_clickhouse-java&issues=AZ9DypNZR51oomk0lMeV&open=AZ9DypNZR51oomk0lMeV&pullRequest=2898
{"Array(DateTime)", Arrays.asList(LocalDateTime.of(2026, 5, 13, 1, 2, 3)), "['2026-05-13 01:02:03']"},

Check warning on line 1670 in client-v2/src/test/java/com/clickhouse/client/query/QueryTests.java

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Use a "java.time.Month" enum constant instead of this int literal.

See more on https://sonarcloud.io/project/issues?id=ClickHouse_clickhouse-java&issues=AZ8E20qMI9QKIFBcMBx2&open=AZ8E20qMI9QKIFBcMBx2&pullRequest=2898
{"Array(String)", Arrays.asList("a", "b"), "['a','b']"},
{"Map(String, Date)", Collections.singletonMap("k", LocalDate.of(2026, 5, 13)), "{'k':'2026-05-13'}"},

Check warning on line 1672 in client-v2/src/test/java/com/clickhouse/client/query/QueryTests.java

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Use a "java.time.Month" enum constant instead of this int literal.

See more on https://sonarcloud.io/project/issues?id=ClickHouse_clickhouse-java&issues=AZ9DypNZR51oomk0lMeX&open=AZ9DypNZR51oomk0lMeX&pullRequest=2898
// Contrast: numeric elements must stay unquoted (quoting an Array(Int*/Float*) triggers CANNOT_READ_ARRAY_FROM_TEXT).
{"Array(Int32)", Arrays.asList(1, 2, 3), "[1,2,3]"},
{"Array(Float64)", Arrays.asList(1.5, 2.5), "[1.5,2.5]"},
// Object arrays, primitive arrays and nested containers must round-trip too, not just List.
{"Array(Date)", new LocalDate[]{LocalDate.of(2026, 5, 13)}, "['2026-05-13']"},

Check warning on line 1677 in client-v2/src/test/java/com/clickhouse/client/query/QueryTests.java

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Use a "java.time.Month" enum constant instead of this int literal.

See more on https://sonarcloud.io/project/issues?id=ClickHouse_clickhouse-java&issues=AZ9DypNZR51oomk0lMeY&open=AZ9DypNZR51oomk0lMeY&pullRequest=2898
{"Array(Int32)", new int[]{4, 5, 6}, "[4,5,6]"},
{"Array(Array(Int32))", Arrays.asList(Arrays.asList(1, 2), Arrays.asList(3, 4)), "[[1,2],[3,4]]"},
};
}

@Test(groups = {"integration"}, dataProvider = "containerQueryParameters")
public void testContainerQueryParamsQuoteInnerValues(String clickHouseType, Object value, String expected) {
// Regression: Array/Map parameters whose elements were emitted unquoted (e.g. param_p=[2026-05-13])
// were rejected by the server with HTTP 400. Raw List/array/Map values must round-trip without the
// manual DataTypeConverter pre-formatting workaround; the query is built from the parameter's type.
Map<String, Object> params = Collections.singletonMap("p", value);
List<GenericRecord> records = client.queryAll("SELECT toString({p:" + clickHouseType + "}) AS v", params);

Assert.assertEquals(records.size(), 1);
Assert.assertEquals(records.get(0).getString("v"), expected);
}

@Test(groups = {"integration"})
public void testExecuteQueryParam() throws ExecutionException, InterruptedException, TimeoutException {

Expand Down Expand Up @@ -2218,9 +2250,9 @@

@Test(groups = {"integration"})
public void testSettingsNotChanged() throws Exception{
final QuerySettings settings = Mockito.spy(new QuerySettings());

Check warning on line 2253 in client-v2/src/test/java/com/clickhouse/client/query/QueryTests.java

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Use a static import for "spy".

See more on https://sonarcloud.io/project/issues?id=ClickHouse_clickhouse-java&issues=AZ9DypNZR51oomk0lMeZ&open=AZ9DypNZR51oomk0lMeZ&pullRequest=2898
try (QueryResponse response = client.query("select 1 FORMAT JSONEachRow", settings).get()) {
Mockito.verify(settings, Mockito.times(1)).getAllSettings();

Check warning on line 2255 in client-v2/src/test/java/com/clickhouse/client/query/QueryTests.java

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Use a static import for "times".

See more on https://sonarcloud.io/project/issues?id=ClickHouse_clickhouse-java&issues=AZ9DypNZR51oomk0lMeb&open=AZ9DypNZR51oomk0lMeb&pullRequest=2898

Check warning on line 2255 in client-v2/src/test/java/com/clickhouse/client/query/QueryTests.java

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Use a static import for "verify".

See more on https://sonarcloud.io/project/issues?id=ClickHouse_clickhouse-java&issues=AZ9DypNZR51oomk0lMea&open=AZ9DypNZR51oomk0lMea&pullRequest=2898
Mockito.verifyNoMoreInteractions(settings);
Assert.assertNull(settings.getFormat());
Assert.assertEquals(response.getFormat(), ClickHouseFormat.JSONEachRow);
Expand Down
Loading