[client-v2] Float NaN and Infinity are silently written into integer columns (NaN -> 0, Inf -> MAX_VALUE), also into Nullable(Int*)
I maintainer di solito rispondono entro 1 giorno
Nessuno ha ancora preso questa issue.
Valutazione
- Difficoltà
- 4/5
- Tempo stimato
- 3-5 giorni
- Idoneità per principianti
- 55/100
Direzione di ricerca
Start with client-v2/src/main/java/com/clickhouse/client/api/data_formats/internal/SerializerUtils.java, especially convertToInteger, convertToLong, and the NumberConverter.toBigInteger path. Trace how integer and Decimal targets handle non-finite Float and Double inputs, then locate or add coverage for the listed scalar and nested types. Done means those inputs fail with a clear client-side error instead of being written as zero or maximum values.
Scritto dal modello di indicizzazione a partire dal testo della issue.
Descrizione
Describe the bug
SerializerUtils.serializePrimitiveData converts a user-supplied Number to an integer column value with plain Java narrowing — convertToInteger / convertToLong call ((Number) value).intValue() / .longValue() (client-v2/src/main/java/com/clickhouse/client/api/data_formats/internal/SerializerUtils.java:1056-1082, used at lines 656-681 and 746).
Java narrowing of a non-finite double produces a legal-looking number instead of failing:
| Written value | Column | Stored value |
|---|---|---|
Double.NaN |
Nullable(Int32) |
0 (not NULL, no error) |
Double.POSITIVE_INFINITY |
Int32 |
2147483647 |
Double.POSITIVE_INFINITY |
Int64 |
9223372036854775807 |
No exception is raised and nothing is logged, so the row is silently corrupted. The server itself rejects both conversions (SELECT toInt32(nan) and SELECT toInt32(inf) fail with code 70, CANNOT_CONVERT_TYPE), so the client is more permissive than the server it writes to.
This is related to #3176 (silent wrapping of out-of-range integers) but is a distinct failure mode: the intValue() vs longValue() comparison suggested there (NumberConverter.toInt) does not catch NaN — both accessors return 0 for it — and does not catch +Inf for Int64 either. A non-finite check is needed on top of the range check.
ClickHouse server version
26.10.3.7 (local server at http://localhost:8123). The test below was run against it.
Reproduction
TestNG test in client-v2:
package com.clickhouse.client.insert;
import com.clickhouse.client.api.Client;
import com.clickhouse.client.api.data_formats.RowBinaryFormatWriter;
import com.clickhouse.client.api.insert.InsertResponse;
import com.clickhouse.client.api.insert.InsertSettings;
import com.clickhouse.client.api.metadata.TableSchema;
import com.clickhouse.client.api.query.GenericRecord;
import com.clickhouse.data.ClickHouseFormat;
import org.testng.annotations.Test;
import java.util.List;
public class NanIntScratchTest {
@Test
public void nanAndInfIntoIntegerColumns() throws Exception {
try (Client client = new Client.Builder()
.addEndpoint("http://localhost:8123")
.setUsername("default").setPassword("")
.compressServerResponse(false).compressClientRequest(false)
.build()) {
client.execute("DROP TABLE IF EXISTS nan_int_test").get();
client.execute("CREATE TABLE nan_int_test (v Nullable(Int32), w Int32, i64 Int64, f Float64) ENGINE Memory").get();
TableSchema schema = client.getTableSchema("nan_int_test");
Object[][] rows = new Object[][]{
{13.0d, 13.0d, 13.0d, 13.0d},
{Double.NaN, Double.POSITIVE_INFINITY, Double.POSITIVE_INFINITY, 1.0d},
};
ClickHouseFormat format = ClickHouseFormat.RowBinary;
try (InsertResponse r = client.insert("nan_int_test", out -> {
RowBinaryFormatWriter w = new RowBinaryFormatWriter(out, schema, format);
for (Object[] row : rows) {
for (int i = 0; i < row.length; i++) {
w.setValue(i + 1, row[i]);
}
w.commitRow();
}
}, format, new InsertSettings()).get()) {
System.out.println("written rows = " + r.getWrittenRows());
}
for (GenericRecord rec : client.queryAll("SELECT v, w, i64, f FROM nan_int_test ORDER BY f")) {
System.out.println("v=" + rec.getObject(1) + " w=" + rec.getInteger(2)
+ " i64=" + rec.getLong(3) + " f=" + rec.getDouble(4));
}
}
}
}
Actual output:
written rows = 2
v=0 w=2147483647 i64=9223372036854775807 f=1.0
v=13 w=13 i64=13 f=13.0
Expected: the insert fails with a clear client-side error for the non-finite values (as the server does), instead of writing 0 / MAX_VALUE.
Suggested fix
In client-v2/src/main/java/com/clickhouse/client/api/data_formats/internal/SerializerUtils.java, reject non-finite values before narrowing — in convertToInteger (line 1056) and convertToLong (line 1070), and in the NumberConverter.toBigInteger path used for UInt64/Int128/Int256, throw when a Float/Double argument is NaN or infinite. The same check is needed for Decimal targets. Nested containers (Array(Nullable(Int*)), Tuple, Map, LowCardinality(Nullable(Int*))) go through the same converters, so one check covers them.
Link
Relayed from the equivalent bug in clickhouse-connect: https://github.com/ClickHouse/clickhouse-connect/issues/1172
- Lingua principale
- Java
- Stelle
- 1.6k
- Fork
- 649
- Merge medio
- 1g 20h
- PR unite (30g)
- 39
Preparare l'ambiente
- Nessun Dockerfile né file Docker Compose
- Ha un modello di pull request
- Leggi la guida per i contributori
Come iniziare
- Leggi tutta la issue e poi la guida ai contributi del progetto.
- Commenta sulla issue per dire che te ne occupi tu — evita che due persone facciano lo stesso lavoro.
- Fai un fork del repository e lavora su un branch.
- Apri una pull request che faccia riferimento al numero della issue.
Altre issue di ClickHouse/clickhouse-java
-
Difficoltà 2/5 1-3 ore Idoneità per principianti 76/100
ClickHouse/clickhouse-java#3349 ·
I maintainer di solito rispondono entro 1 giorno
-
bug jdbc-v2
Difficoltà 2/5 1-3 ore Idoneità per principianti 85/100
ClickHouse/clickhouse-java#3347 ·
I maintainer di solito rispondono entro 1 giorno
-
bug jdbc-v2
Difficoltà 2/5 1-3 ore Idoneità per principianti 82/100
ClickHouse/clickhouse-java#3326 ·
I maintainer di solito rispondono entro 1 giorno
-
[client-v2] Enum8/Enum16 insert accepts a non-member integer and uses Enum.ordinal(), silently storing values that are not enum membersForse già presa @jaya232 l’ha presa 6 giorni fa. Aperta
Difficoltà 2/5 1-3 ore Idoneità per principianti 78/100
ClickHouse/clickhouse-java#3304 · 1 commento ·
I maintainer di solito rispondono entro 1 giorno
-
bug jdbc-v2
Difficoltà 2/5 1-3 ore Idoneità per principianti 70/100
ClickHouse/clickhouse-java#3214 ·
I maintainer di solito rispondono entro 1 giorno
Tutte le issue di ClickHouse/clickhouse-java
Issue simili
-
bug
Difficoltà 2/5 1-3 ore Idoneità per principianti 78/100
I maintainer di solito rispondono entro 1 giorno
-
bug:unconfirmed
Difficoltà 2/5 1-3 ore Idoneità per principianti 68/100
UniversalMediaServer/UniversalMediaServer#6473 ·
I maintainer di solito rispondono entro 1 giorno
-
Difficoltà 1/5 Meno di un'ora Idoneità per principianti 82/100
I maintainer di solito rispondono entro 1 giorno
-
Difficoltà 2/5 1-3 ore Idoneità per principianti 72/100
StarRocks/starrocks#83246 · 1 commento ·
I maintainer di solito rispondono entro 1 giorno
-
Difficoltà 2/5 1-3 ore Idoneità per principianti 76/100
I maintainer di solito rispondono entro 2 giorni