Skip to content
Open
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
Original file line number Diff line number Diff line change
Expand Up @@ -142,8 +142,10 @@ public static BigDecimal toBigDecimal(Object value) {
return (BigDecimal) value;
} else if (value instanceof BigInteger) {
return new BigDecimal((BigInteger) value);
} else if (value instanceof Byte || value instanceof Short || value instanceof Integer || value instanceof Long) {
return BigDecimal.valueOf(((Number) value).longValue());
} else if (value instanceof Number) {
return BigDecimal.valueOf(((Number) value).doubleValue());
return new BigDecimal(value.toString());
} else if (value instanceof String) {
return new BigDecimal((String) value);
} else if (value instanceof Boolean) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,7 @@
import static org.objectweb.asm.Opcodes.INVOKEVIRTUAL;
import static org.objectweb.asm.Opcodes.RETURN;

@SuppressWarnings("deprecation")
public class SerializerUtils {

public static void serializeData(OutputStream stream, Object value, ClickHouseColumn column) throws IOException {
Expand Down Expand Up @@ -505,10 +506,10 @@ private static void serializePrimitiveData(OutputStream stream, Object value, Cl
BinaryStreamUtils.writeInt64(stream, convertToLong(value));
break;
case Int128:
BinaryStreamUtils.writeInt128(stream, convertToBigInteger(value));
BinaryStreamUtils.writeInt128(stream, NumberConverter.toBigInteger(value));
break;
case Int256:
BinaryStreamUtils.writeInt256(stream, convertToBigInteger(value));
BinaryStreamUtils.writeInt256(stream, NumberConverter.toBigInteger(value));
break;
case UInt8:
BinaryStreamUtils.writeUnsignedInt8(stream, convertToInteger(value));
Expand All @@ -520,13 +521,13 @@ private static void serializePrimitiveData(OutputStream stream, Object value, Cl
BinaryStreamUtils.writeUnsignedInt32(stream, convertToLong(value));
break;
case UInt64:
BinaryStreamUtils.writeUnsignedInt64(stream, convertToLong(value));
BinaryStreamUtils.writeUnsignedInt64(stream, NumberConverter.toBigInteger(value));
break;
case UInt128:
BinaryStreamUtils.writeUnsignedInt128(stream, convertToBigInteger(value));
BinaryStreamUtils.writeUnsignedInt128(stream, NumberConverter.toBigInteger(value));
break;
case UInt256:
BinaryStreamUtils.writeUnsignedInt256(stream, convertToBigInteger(value));
BinaryStreamUtils.writeUnsignedInt256(stream, NumberConverter.toBigInteger(value));
break;
case Float32:
BinaryStreamUtils.writeFloat32(stream, (float) value);
Expand All @@ -539,7 +540,7 @@ private static void serializePrimitiveData(OutputStream stream, Object value, Cl
case Decimal64:
case Decimal128:
case Decimal256:
BinaryStreamUtils.writeDecimal(stream, convertToBigDecimal(value), column.getPrecision(), column.getScale());
BinaryStreamUtils.writeDecimal(stream, NumberConverter.toBigDecimal(value), column.getPrecision(), column.getScale());
break;
case Bool:
BinaryStreamUtils.writeBoolean(stream, (Boolean) value);
Expand Down Expand Up @@ -765,32 +766,6 @@ public static Long convertToLong(Object value) {
}
}

public static BigInteger convertToBigInteger(Object value) {
if (value instanceof BigInteger) {
return (BigInteger) value;
} else if (value instanceof Number) {
return BigInteger.valueOf(((Number) value).longValue());
} else if (value instanceof String) {
return new BigInteger((String) value);
} else {
throw new IllegalArgumentException("Cannot convert " + value + " to BigInteger");
}
}

public static BigDecimal convertToBigDecimal(Object value) {
if (value instanceof BigDecimal) {
return (BigDecimal) value;
} else if (value instanceof BigInteger) {
return new BigDecimal((BigInteger) value);
} else if (value instanceof Number) {
return BigDecimal.valueOf(((Number) value).doubleValue());
} else if (value instanceof String) {
return new BigDecimal((String) value);
} else {
throw new IllegalArgumentException("Cannot convert " + value + " to BigDecimal");
}
}

public static String convertToString(Object value) {
return java.lang.String.valueOf(value);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,13 +6,16 @@
import java.math.BigInteger;
import java.net.MalformedURLException;
import java.net.URL;
import java.sql.Date;
import java.sql.Time;
import java.sql.Timestamp;
import java.util.Collections;
import java.util.Map;
import java.util.function.Function;

/**
* This class should be used to convert non-null value with known type.
* All methods should be kept minimal without null or instanceOf checks.
*/
public final class ValueConverters {


Expand Down Expand Up @@ -210,7 +213,10 @@ public BigInteger convertNumberToBigInteger(Object value) {
}

public BigDecimal convertNumberToBigDecimal(Object value) {
return BigDecimal.valueOf(((Number) value).doubleValue());
if (value instanceof Byte || value instanceof Short || value instanceof Integer || value instanceof Long) {
return BigDecimal.valueOf(((Number)value).longValue());
}
return new BigDecimal(value.toString());
}

// Date & Time converters
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
import java.util.TimeZone;
import java.util.function.Consumer;

@SuppressWarnings("deprecation")
public class ClickHouseBinaryFormatReaderTest {

@Test
Expand Down Expand Up @@ -83,6 +84,66 @@ public void testReadingNumbers() throws IOException {
}
}

@Test
public void testGetBigDecimalForIntegerWidths8To256() throws IOException {
ByteArrayOutputStream out = new ByteArrayOutputStream();

String[] names = new String[] {
"i8", "u8", "i16", "u16", "i32", "u32", "i64", "u64", "i128", "u128", "i256", "u256"
};
String[] types = new String[] {
"Int8", "UInt8", "Int16", "UInt16", "Int32", "UInt32", "Int64", "UInt64",
"Int128", "UInt128", "Int256", "UInt256"
};

BinaryStreamUtils.writeVarInt(out, names.length);
for (String name : names) {
BinaryStreamUtils.writeString(out, name);
}
for (String type : types) {
BinaryStreamUtils.writeString(out, type);
}

BigInteger u64 = new BigInteger("18446744073709551615");
BigInteger i128 = new BigInteger("-170141183460469231731687303715884105728");
BigInteger u128 = new BigInteger("340282366920938463463374607431768211455");
BigInteger i256 = new BigInteger("-57896044618658097711785492504343953926634992332820282019728792003956564819968");
BigInteger u256 = new BigInteger("115792089237316195423570985008687907853269984665640564039457584007913129639935");

BinaryStreamUtils.writeInt8(out, -128);
BinaryStreamUtils.writeUnsignedInt8(out, 255);
BinaryStreamUtils.writeInt16(out, -32768);
BinaryStreamUtils.writeUnsignedInt16(out, 65535);
BinaryStreamUtils.writeInt32(out, Integer.MIN_VALUE);
BinaryStreamUtils.writeUnsignedInt32(out, 4294967295L);
BinaryStreamUtils.writeInt64(out, Long.MAX_VALUE);
BinaryStreamUtils.writeUnsignedInt64(out, u64);
BinaryStreamUtils.writeInt128(out, i128);
BinaryStreamUtils.writeUnsignedInt128(out, u128);
BinaryStreamUtils.writeInt256(out, i256);
BinaryStreamUtils.writeUnsignedInt256(out, u256);

InputStream in = new ByteArrayInputStream(out.toByteArray());
QuerySettings querySettings = new QuerySettings().setUseTimeZone(TimeZone.getTimeZone("UTC").toZoneId().getId());
RowBinaryWithNamesAndTypesFormatReader reader =
new RowBinaryWithNamesAndTypesFormatReader(in, querySettings, new BinaryStreamReader.CachingByteBufferAllocator());

reader.next();

Assert.assertEquals(reader.getBigDecimal("i8"), BigDecimal.valueOf(-128));
Assert.assertEquals(reader.getBigDecimal("u8"), BigDecimal.valueOf(255));
Assert.assertEquals(reader.getBigDecimal("i16"), BigDecimal.valueOf(-32768));
Assert.assertEquals(reader.getBigDecimal("u16"), BigDecimal.valueOf(65535));
Assert.assertEquals(reader.getBigDecimal("i32"), BigDecimal.valueOf(Integer.MIN_VALUE));
Assert.assertEquals(reader.getBigDecimal("u32"), BigDecimal.valueOf(4294967295L));
Assert.assertEquals(reader.getBigDecimal("i64"), BigDecimal.valueOf(Long.MAX_VALUE));
Assert.assertEquals(reader.getBigDecimal("u64"), new BigDecimal(u64));
Assert.assertEquals(reader.getBigDecimal("i128"), new BigDecimal(i128));
Assert.assertEquals(reader.getBigDecimal("u128"), new BigDecimal(u128));
Assert.assertEquals(reader.getBigDecimal("i256"), new BigDecimal(i256));
Assert.assertEquals(reader.getBigDecimal("u256"), new BigDecimal(u256));
}

@Test
public void testReadingNumbersWithOverflow() throws IOException {
ByteArrayOutputStream out = new ByteArrayOutputStream();
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
package com.clickhouse.client.api.data_formats.internal;

import org.testng.Assert;
import org.testng.annotations.Test;

import java.math.BigDecimal;

public class NumberConverterTests {

@Test
public void testToBigDecimalSupportsGenericNumberValues() {
Assert.assertEquals(NumberConverter.toBigDecimal(new CustomNumber("1234567890.123456789")),
new BigDecimal("1234567890.123456789"));
}

@Test
public void testToBigDecimalSupportsStringValues() {
Assert.assertEquals(NumberConverter.toBigDecimal("98765.4321"), new BigDecimal("98765.4321"));
}

@Test
public void testToBigDecimalPreservesFractionalFloatBoundaries() {
Assert.assertEquals(NumberConverter.toBigDecimal(0.0001f).compareTo(new BigDecimal("0.0001")), 0);
Assert.assertEquals(NumberConverter.toBigDecimal(0.0256f).compareTo(new BigDecimal("0.0256")), 0);
Assert.assertEquals(NumberConverter.toBigDecimal(6.5536f).compareTo(new BigDecimal("6.5536")), 0);
Assert.assertEquals(NumberConverter.toBigDecimal(838.8608f).compareTo(new BigDecimal("838.8608")), 0);
}

private static final class CustomNumber extends Number {
private final BigDecimal value;

private CustomNumber(String value) {
this.value = new BigDecimal(value);
}

@Override
public int intValue() {
return value.intValue();
}

@Override
public long longValue() {
return value.longValue();
}

@Override
public float floatValue() {
return value.floatValue();
}

@Override
public double doubleValue() {
return value.doubleValue();
}

@Override
public String toString() {
return value.toPlainString();
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
package com.clickhouse.client.api.data_formats.internal;

import com.clickhouse.client.api.data_formats.RowBinaryWithNamesAndTypesFormatReader;
import com.clickhouse.client.api.query.QuerySettings;
import com.clickhouse.data.ClickHouseColumn;
import com.clickhouse.data.format.BinaryStreamUtils;
import org.testng.Assert;
import org.testng.annotations.Test;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.math.BigDecimal;
import java.util.TimeZone;

public class SerializerUtilsPrimitiveSerializationTests {

@Test
public void testSerializeIntegerTargetFromStringValue() throws IOException {
RowBinaryWithNamesAndTypesFormatReader reader =
serializeSingleValue("Int32", "123456");

reader.next();

Assert.assertEquals(reader.getInteger("value"), Integer.valueOf(123456));
}

@Test
public void testSerializeDecimalTargetFromStringValue() throws IOException {
RowBinaryWithNamesAndTypesFormatReader reader =
serializeSingleValue("Decimal64(3)", "123456.789");

reader.next();

Assert.assertEquals(reader.getBigDecimal("value"), new BigDecimal("123456.789"));
}

@Test
public void testSerializeDecimalTargetFromGenericNumberValue() throws IOException {
RowBinaryWithNamesAndTypesFormatReader reader =
serializeSingleValue("Decimal64(3)", new CustomNumber("987654.321"));

reader.next();

Assert.assertEquals(reader.getBigDecimal("value"), new BigDecimal("987654.321"));
}

private RowBinaryWithNamesAndTypesFormatReader serializeSingleValue(String type, Object value)
throws IOException {
ByteArrayOutputStream out = new ByteArrayOutputStream();
BinaryStreamUtils.writeVarInt(out, 1);

Check warning on line 51 in client-v2/src/test/java/com/clickhouse/client/api/data_formats/internal/SerializerUtilsPrimitiveSerializationTests.java

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Remove this use of "BinaryStreamUtils"; it is deprecated.

See more on https://sonarcloud.io/project/issues?id=ClickHouse_clickhouse-java&issues=AZ1pmzuPMeJ6ckE6NFY2&open=AZ1pmzuPMeJ6ckE6NFY2&pullRequest=2814
BinaryStreamUtils.writeString(out, "value");

Check warning on line 52 in client-v2/src/test/java/com/clickhouse/client/api/data_formats/internal/SerializerUtilsPrimitiveSerializationTests.java

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Remove this use of "BinaryStreamUtils"; it is deprecated.

See more on https://sonarcloud.io/project/issues?id=ClickHouse_clickhouse-java&issues=AZ1pmzuPMeJ6ckE6NFY3&open=AZ1pmzuPMeJ6ckE6NFY3&pullRequest=2814
BinaryStreamUtils.writeString(out, type);

Check warning on line 53 in client-v2/src/test/java/com/clickhouse/client/api/data_formats/internal/SerializerUtilsPrimitiveSerializationTests.java

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Remove this use of "BinaryStreamUtils"; it is deprecated.

See more on https://sonarcloud.io/project/issues?id=ClickHouse_clickhouse-java&issues=AZ1pmzuPMeJ6ckE6NFY4&open=AZ1pmzuPMeJ6ckE6NFY4&pullRequest=2814
SerializerUtils.serializeData(out, value, ClickHouseColumn.of("value", type));

return new RowBinaryWithNamesAndTypesFormatReader(
new ByteArrayInputStream(out.toByteArray()),
new QuerySettings().setUseTimeZone(TimeZone.getTimeZone("UTC").toZoneId().getId()),
new BinaryStreamReader.CachingByteBufferAllocator());
}

private static final class CustomNumber extends Number {
private final BigDecimal value;

private CustomNumber(String value) {
this.value = new BigDecimal(value);
}

@Override
public int intValue() {
return value.intValue();
}

@Override
public long longValue() {
return value.longValue();
}

@Override
public float floatValue() {
return value.floatValue();
}

@Override
public double doubleValue() {
return value.doubleValue();
}

@Override
public String toString() {
return value.toPlainString();
}
}
}
Loading
Loading