[client-v2] A Map/List/array bound to a Tuple query parameter is rendered as a Map/Array literal and fails with code 27
Maintainer thường phản hồi trong vòng 1 ngày
Chưa có ai nhận issue này.
Đánh giá
- Độ khó
- 4/5
- Thời gian dự kiến
- 3-5 ngày
- Mức phù hợp với người mới
- 35/100
Hướng nghiên cứu
Start in client-v2/src/main/java/com/clickhouse/client/api/internal/DataTypeConverter.java, where convertParameterToString is type-blind and convertParameterContainer/pushContainer (around lines 340-396) render Maps and Collections as {...} and [...]. Reproduce with the TestNG snippet in the issue under client-v2/src/test/java/com/clickhouse/client/query/. Done when a Map, List or Object[] bound to {p:Tuple(protocol UInt8, port UInt16)} returns (6,80) and the existing string-binding behaviour is unchanged. The maintainers have not chosen between a type-aware renderer and a tuple-specific overload, so confirm that first.
Do mô hình lập chỉ mục viết ra từ nội dung của issue.
Mô tả
Description
Client.query(String, Map<String, Object>, QuerySettings) renders every parameter value through
DataTypeConverter.convertParameterToString, which is type-blind: it never sees the {name:Type}
placeholder's declared type. convertParameterContainer/pushContainer
(client-v2/src/main/java/com/clickhouse/client/api/internal/DataTypeConverter.java:340-396) therefore
renders:
- any
java.util.Mapas a ClickHouse Map literal —{'protocol':6,'port':80} - any
Collectionor array as a ClickHouse Array literal —[6,80]
The server's param_<name> reader parses a Tuple(...) value with the tuple text parser, which requires
a leading (. Both renderings are rejected:
Code: 27. DB::Exception: Cannot parse input: expected '(' before: '{\'protocol\':6,\'port\':80}':
value {'protocol':6,'port':80} cannot be parsed as Tuple(protocol UInt8, port UInt16)
for query parameter 'p'. (CANNOT_PARSE_INPUT_ASSERTION_FAILED)
Net effect: there is no natural Java value that can be bound to a Tuple(...) query parameter.
The only thing that works is hand-formatting the literal yourself as a String ("(6,80)"), which
relies on the caller doing the quoting/escaping that the converter exists to do, and which is unsafe
for Tuple(String, ...) elements.
This is the Java-side equivalent of clickhouse-connect issue #1148 (there a dict bound to a named
Tuple is formatted as JSON or as a map literal and hits the same code 27).
ClickHouse server version
26.10.3.7 (official build), reached over HTTP at localhost:8123.
Reproduction
TestNG test placed in client-v2/src/test/java/com/clickhouse/client/query/:
package com.clickhouse.client.query;
import com.clickhouse.client.api.Client;
import com.clickhouse.client.api.query.QueryResponse;
import com.clickhouse.client.api.query.QuerySettings;
import com.clickhouse.data.ClickHouseFormat;
import org.testng.annotations.Test;
import java.io.InputStream;
import java.util.Arrays;
import java.util.LinkedHashMap;
import java.util.Map;
public class TupleParamTest {
@Test
public void tupleParameterBinding() throws Exception {
try (Client client = new Client.Builder()
.addEndpoint("http://localhost:8123")
.setUsername("default")
.setPassword("")
.build()) {
Map<String, Object> named = new LinkedHashMap<>();
named.put("protocol", 6);
named.put("port", 80);
run(client, "Map -> named Tuple", named);
run(client, "List -> named Tuple", Arrays.asList(6, 80));
run(client, "Object[] -> named Tuple", new Object[]{6, 80});
run(client, "String \"(6,80)\" -> named Tuple", "(6,80)");
}
}
private static void run(Client client, String label, Object value) {
Map<String, Object> params = new LinkedHashMap<>();
params.put("p", value);
try (QueryResponse resp = client.query(
"SELECT {p:Tuple(protocol UInt8, port UInt16)} AS t",
params,
new QuerySettings().setFormat(ClickHouseFormat.TabSeparated)).get()) {
InputStream in = resp.getInputStream();
byte[] buf = new byte[256];
int n = in.read(buf);
System.out.println("RESULT " + label + " -> OK: " + new String(buf, 0, Math.max(n, 0)).trim());
} catch (Exception e) {
Throwable t = e.getCause() == null ? e : e.getCause();
String m = t.getMessage();
System.out.println("RESULT " + label + " -> FAIL: " + (m == null ? t.toString() : m.split("\n")[0]));
}
}
}
mvn -pl client-v2 test -Dtest=TupleParamTest
Expected — a Map keyed by the tuple element names, and an ordered List/array, bind the same way
the hand-written (6,80) literal does:
RESULT Map -> named Tuple -> OK: (6,80)
RESULT List -> named Tuple -> OK: (6,80)
RESULT Object[] -> named Tuple -> OK: (6,80)
RESULT String "(6,80)" -> named Tuple -> OK: (6,80)
Actual:
RESULT Map -> named Tuple -> FAIL: Code: 27. DB::Exception: Cannot parse input: expected '(' before: '{\'protocol\':6,\'port\':80}': value {'protocol':6,'port':80} cannot be parsed as Tuple(protocol UInt8, port UInt16) for query parameter 'p'. (CANNOT_PARSE_INPUT_ASSERTION_FAILED)
RESULT List -> named Tuple -> FAIL: Code: 27. DB::Exception: Cannot parse input: expected '(' before: '[6,80]': value [6,80] cannot be parsed as Tuple(protocol UInt8, port UInt16) for query parameter 'p'. (CANNOT_PARSE_INPUT_ASSERTION_FAILED)
RESULT Object[] -> named Tuple -> FAIL: Code: 27. DB::Exception: Cannot parse input: expected '(' before: '[6,80]': value [6,80] cannot be parsed as Tuple(protocol UInt8, port UInt16) for query parameter 'p'. (CANNOT_PARSE_INPUT_ASSERTION_FAILED)
RESULT String "(6,80)" -> named Tuple -> OK: (6,80)
Only the pre-formatted string works.
Suggested fix
In client-v2/src/main/java/com/clickhouse/client/api/internal/DataTypeConverter.java, the parameter
renderer has no notion of a tuple. Two parts:
- The
param_<name>placeholder type is already present in the SQL text ({p:Tuple(...)}). If the
converter were given the declared type (asarrayToString(Object, String columnDef)already is), a
Tuple(...)placeholder could render aCollection/array as(e1,e2,...)and aMapby ordering
its entries against the declared element names. - Failing that, a dedicated marker/overload for tuple-shaped values would at least give callers a safe
path that still applies the element quoting/escaping rules inconvertParameterContainer.
Note pushContainer would also need the parenthesised form for a tuple nested inside an
Array(Tuple(...)) parameter, which has the same problem today.
Link
Upstream client report: https://github.com/ClickHouse/clickhouse-connect/issues/1148
- Ngôn ngữ chính
- Java
- Star
- 1.6k
- Fork
- 649
- Merge trung bình
- 1 ngày 20 giờ
- Pull request đã merge (30 ngày)
- 39
Chuẩn bị môi trường
- Không có Dockerfile hay tệp Docker Compose
- Có mẫu pull request
- Đọc hướng dẫn đóng góp
Bắt đầu từ đâu
- Đọc hết issue, rồi đọc hướng dẫn đóng góp của dự án.
- Bình luận trên issue rằng bạn sẽ nhận — tránh hai người làm cùng một việc.
- Fork repository và làm thay đổi trên một nhánh.
- Mở pull request có tham chiếu số hiệu của issue.
Issue khác của ClickHouse/clickhouse-java
-
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 76/100
ClickHouse/clickhouse-java#3349 ·
Maintainer thường phản hồi trong vòng 1 ngày
-
bug jdbc-v2
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 85/100
ClickHouse/clickhouse-java#3347 ·
Maintainer thường phản hồi trong vòng 1 ngày
-
bug jdbc-v2
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 82/100
ClickHouse/clickhouse-java#3326 ·
Maintainer thường phản hồi trong vòng 1 ngày
-
[client-v2] Enum8/Enum16 insert accepts a non-member integer and uses Enum.ordinal(), silently storing values that are not enum membersCó thể đã có người làm @jaya232 đã nhận 6 ngày trước. Đang mở
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 78/100
ClickHouse/clickhouse-java#3304 · 1 bình luận ·
Maintainer thường phản hồi trong vòng 1 ngày
-
bug jdbc-v2
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 70/100
ClickHouse/clickhouse-java#3214 ·
Maintainer thường phản hồi trong vòng 1 ngày
Tất cả issue của ClickHouse/clickhouse-java
Issue tương tự
-
bug
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 78/100
Maintainer thường phản hồi trong vòng 1 ngày
-
bug:unconfirmed
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 68/100
UniversalMediaServer/UniversalMediaServer#6473 ·
Maintainer thường phản hồi trong vòng 1 ngày
-
Độ khó 1/5 Dưới một giờ Mức phù hợp với người mới 82/100
Maintainer thường phản hồi trong vòng 1 ngày
-
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 72/100
StarRocks/starrocks#83246 · 1 bình luận ·
Maintainer thường phản hồi trong vòng 1 ngày
-
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 76/100
Maintainer thường phản hồi trong vòng 2 ngày