Skip to content
Open
Show file tree
Hide file tree
Changes from 13 commits
Commits
Show all changes
18 commits
Select commit Hold shift + click to select a range
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
@@ -0,0 +1,251 @@
package com.clickhouse.client.api.data_formats.internal;

import com.google.common.collect.ImmutableMap;

import java.math.BigDecimal;
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;

public final class ValueConverters {


// <source type, <target type, converter>>
private final Map<Class<?>, Map<Class<?>, Function<Object, Object>>> classConverters;

// <target type, converter>
private final ImmutableMap<Class<?>, Function<Object, Object>> numberConverters;

public ValueConverters() {


ImmutableMap.Builder<Class<?>, Function<Object, Object>> numberConvertersBuilder = ImmutableMap.builder();
numberConvertersBuilder.put(String.class, this::convertNumberToString);
numberConvertersBuilder.put(Boolean.class, this::convertNumberToBoolean);
numberConvertersBuilder.put(byte.class, this::convertNumberToByte);
numberConvertersBuilder.put(short.class, this::convertNumberToShort);
numberConvertersBuilder.put(int.class, this::convertNumberToInt);
numberConvertersBuilder.put(long.class, this::convertNumberToLong);
numberConvertersBuilder.put(float.class, this::convertNumberToFloat);
numberConvertersBuilder.put(double.class, this::convertNumberToDouble);
numberConvertersBuilder.put(Byte.class, this::convertNumberToByte);
numberConvertersBuilder.put(Short.class, this::convertNumberToShort);
numberConvertersBuilder.put(Integer.class, this::convertNumberToInt);
numberConvertersBuilder.put(Long.class, this::convertNumberToLong);
numberConvertersBuilder.put(Float.class, this::convertNumberToFloat);
numberConvertersBuilder.put(Double.class, this::convertNumberToDouble);
numberConvertersBuilder.put(BigInteger.class, this::convertNumberToBigInteger);
numberConvertersBuilder.put(BigDecimal.class, this::convertNumberToBigDecimal);

numberConverters = numberConvertersBuilder.build();


ImmutableMap.Builder<Class<?>, Map<Class<?>, Function<Object, Object>>> mapBuilder = ImmutableMap.builder();

mapBuilder.put(byte.class, numberConverters);
mapBuilder.put(short.class, numberConverters);
mapBuilder.put(int.class, numberConverters);
mapBuilder.put(long.class, numberConverters);
mapBuilder.put(float.class, numberConverters);
mapBuilder.put(double.class, numberConverters);
mapBuilder.put(Byte.class, numberConverters);
mapBuilder.put(Short.class, numberConverters);
mapBuilder.put(Integer.class, numberConverters);
mapBuilder.put(Long.class, numberConverters);
mapBuilder.put(Float.class, numberConverters);
mapBuilder.put(Double.class, numberConverters);
mapBuilder.put(BigInteger.class, numberConverters);
mapBuilder.put(BigDecimal.class, numberConverters);

ImmutableMap.Builder<Class<?>, Function<Object, Object>> booleanMapBuilder = ImmutableMap.builder();
booleanMapBuilder.put(byte.class, this::convertBooleanToNumber);
booleanMapBuilder.put(short.class, this::convertBooleanToNumber);
booleanMapBuilder.put(int.class, this::convertBooleanToNumber);
booleanMapBuilder.put(long.class, this::convertBooleanToNumber);
booleanMapBuilder.put(float.class, this::convertBooleanToNumber);
booleanMapBuilder.put(double.class, this::convertBooleanToNumber);
booleanMapBuilder.put(Byte.class, this::convertBooleanToNumber);
booleanMapBuilder.put(Short.class, this::convertBooleanToNumber);
booleanMapBuilder.put(Integer.class, this::convertBooleanToNumber);
booleanMapBuilder.put(Long.class, this::convertBooleanToNumber);
booleanMapBuilder.put(Float.class, this::convertBooleanToNumber);
booleanMapBuilder.put(Double.class, this::convertBooleanToNumber);
booleanMapBuilder.put(BigInteger.class, this::convertBooleanToNumber);
booleanMapBuilder.put(BigDecimal.class, this::convertBooleanToNumber);
booleanMapBuilder.put(String.class, this::convertBooleanToString);
booleanMapBuilder.put(Boolean.class, this::convertBooleanToBoolean);
booleanMapBuilder.put(boolean.class, this::convertBooleanToBoolean);

mapBuilder.put(Boolean.class, booleanMapBuilder.build());
mapBuilder.put(boolean.class, booleanMapBuilder.build());

ImmutableMap.Builder<Class<?>, Function<Object, Object>> stringMapBuilder = ImmutableMap.builder();
stringMapBuilder.put(byte.class, this::convertStringToByte);
stringMapBuilder.put(short.class, this::convertStringToShort);
stringMapBuilder.put(int.class, this::convertStringToInt);
stringMapBuilder.put(long.class, this::convertStringToLong);
stringMapBuilder.put(float.class, this::convertStringToFloat);
stringMapBuilder.put(double.class, this::convertStringToDouble);
stringMapBuilder.put(Byte.class, this::convertStringToByte);
stringMapBuilder.put(Short.class, this::convertStringToShort);
stringMapBuilder.put(Integer.class, this::convertStringToInt);
stringMapBuilder.put(Long.class, this::convertStringToLong);
stringMapBuilder.put(Float.class, this::convertStringToFloat);
stringMapBuilder.put(Double.class, this::convertStringToDouble);
stringMapBuilder.put(Boolean.class, this::convertStringToBoolean);
stringMapBuilder.put(String.class, this::convertStringToString);
stringMapBuilder.put(byte[].class, this::convertStringToBytes);
stringMapBuilder.put(URL.class, this::convertStringToURL);
mapBuilder.put(String.class, stringMapBuilder.build());

mapBuilder.put(java.sql.Date.class, ImmutableMap.of(java.sql.Date.class, this::convertSqlDateToSqlDate,
String.class, this::convertDateToString));
mapBuilder.put(Time.class, ImmutableMap.of(Time.class, this::convertSqlTimeToSqlTime,
String.class, this::convertTimeToString));
mapBuilder.put(Timestamp.class, ImmutableMap.of(Timestamp.class, this::convertSqlTimestampToSqlTimestamp,
String.class, this::convertTimestampToString));

classConverters = mapBuilder.build();
}

// Boolean to any
public Boolean convertBooleanToBoolean(Object value) {
return (Boolean) value;
}

public Number convertBooleanToNumber(Object value) {
return ((Number) (((Boolean)value) ? 1 : 0)).longValue();

Check warning on line 123 in client-v2/src/main/java/com/clickhouse/client/api/data_formats/internal/ValueConverters.java

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Use a primitive boolean expression here.

See more on https://sonarcloud.io/project/issues?id=ClickHouse_clickhouse-java&issues=AZrr6QT0EAUtN0e-6mGn&open=AZrr6QT0EAUtN0e-6mGn&pullRequest=2668
}

public String convertBooleanToString(Object value) {
return String.valueOf(value);
}

// String to any
public String convertStringToString(Object value) {
return (String) value;
}

public byte[] convertStringToBytes(Object value) {
return ((String) value).getBytes();
}

public boolean convertStringToBoolean(Object value) {
return Boolean.parseBoolean((String) value);
}

public byte convertStringToByte(Object value) {
return Byte.parseByte((String) value);
}

public short convertStringToShort(Object value) {
return Short.parseShort((String) value);
}

public int convertStringToInt(Object value) {
return Integer.parseInt((String) value);
}

public long convertStringToLong(Object value) {
return Long.parseLong((String) value);
}

public float convertStringToFloat(Object value) {
return Float.parseFloat((String) value);
}

public double convertStringToDouble(Object value) {
return Double.parseDouble((String) value);
}

public URL convertStringToURL(Object value) {
try {
return new URL((String) value);
} catch (MalformedURLException e) {
throw new RuntimeException(e);

Check warning on line 171 in client-v2/src/main/java/com/clickhouse/client/api/data_formats/internal/ValueConverters.java

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Replace generic exceptions with specific library exceptions or a custom exception.

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

// Number to any
public String convertNumberToString(Object value) {
return String.valueOf(value);
}

public boolean convertNumberToBoolean(Object value) {
return ((Number) value).floatValue() != 0.0f;
}

public byte convertNumberToByte(Object value) {
return ((Number) value).byteValue();
}

public short convertNumberToShort(Object value) {
return ((Number) value).shortValue();
}

public int convertNumberToInt(Object value) {
return ((Number) value).intValue();
}

public long convertNumberToLong(Object value) {
return ((Number) value).longValue();
}

public float convertNumberToFloat(Object value) {
return ((Number) value).floatValue();
}

public double convertNumberToDouble(Object value) {
return ((Number) value).doubleValue();
}

public BigInteger convertNumberToBigInteger(Object value) {
return BigInteger.valueOf(((Number) value).longValue());
}

public BigDecimal convertNumberToBigDecimal(Object value) {
return BigDecimal.valueOf(((Number) value).doubleValue());
}

// Date & Time converters
public java.sql.Date convertSqlDateToSqlDate(Object value) {
return (java.sql.Date) value;
}

public Time convertSqlTimeToSqlTime(Object value) {
return (Time) value;
}

public Timestamp convertSqlTimestampToSqlTimestamp(Object value) {
return (Timestamp) value;
}

public String convertDateToString(Object value) {
return ((Date)value).toString();
}

public String convertTimeToString(Object value) {
return ((Time) value).toString();
}

public String convertTimestampToString(Object value) {
return ((Timestamp) value).toString();
}

/**
* Returns the converter map for the given source type.
* Map contains target type and converter function. For example, if source type is boolean then map will contain all
* converters that support converting boolean to target type.
* @param type - source type
* @return - map of target type and converter function
*/
public Map<Class<?>, Function<Object, Object>> getConvertersForType(Class<?> type) {
return classConverters.getOrDefault(type, Collections.emptyMap());
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,8 @@
map.put(ClickHouseDataType.DateTime, JDBCType.TIMESTAMP);
map.put(ClickHouseDataType.DateTime32, JDBCType.TIMESTAMP);
map.put(ClickHouseDataType.DateTime64, JDBCType.TIMESTAMP);
map.put(ClickHouseDataType.Time, JDBCType.TIME);
map.put(ClickHouseDataType.Time64, JDBCType.TIME);
map.put(ClickHouseDataType.Array, JDBCType.ARRAY);
map.put(ClickHouseDataType.Nested, JDBCType.ARRAY);
map.put(ClickHouseDataType.Map, JDBCType.JAVA_OBJECT);
Expand Down Expand Up @@ -106,7 +108,7 @@
map.put(JDBCType.INTEGER, Integer.class);
map.put(JDBCType.BIGINT, Long.class);
map.put(JDBCType.REAL, Float.class);
map.put(JDBCType.FLOAT, Double.class);
map.put(JDBCType.FLOAT, Float.class);
map.put(JDBCType.DOUBLE, Double.class);
map.put(JDBCType.BINARY, byte[].class);
map.put(JDBCType.VARBINARY, byte[].class);
Expand Down Expand Up @@ -457,7 +459,7 @@
}
}

private static Object[] arrayToObjectArray(Object array) {
public static Object[] arrayToObjectArray(Object array) {

Check failure on line 462 in jdbc-v2/src/main/java/com/clickhouse/jdbc/internal/JdbcUtils.java

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

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

See more on https://sonarcloud.io/project/issues?id=ClickHouse_clickhouse-java&issues=AZrxWsjGFDjduF-g7WLA&open=AZrxWsjGFDjduF-g7WLA&pullRequest=2668
if (array == null) {
return null;
}
Expand Down
12 changes: 9 additions & 3 deletions jdbc-v2/src/main/java/com/clickhouse/jdbc/types/Array.java
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ public class Array implements java.sql.Array {
private final String elementTypeName;
private boolean valid;
private final ClickHouseDataType baseDataType;
private ArrayResultSet arrayResultSet;

public Array(ClickHouseColumn column, Object[] elements) throws SQLException {
this.column = column;
Expand Down Expand Up @@ -88,8 +89,12 @@ public Object getArray(long index, int count, Map<String, Class<?>> map) throws
}

@Override
public ResultSet getResultSet() throws SQLException {
throw new SQLFeatureNotSupportedException("getResultSet() is not supported", ExceptionUtils.SQL_STATE_FEATURE_NOT_SUPPORTED);
public synchronized ResultSet getResultSet() throws SQLException {
ensureValid();
if (arrayResultSet == null) {
arrayResultSet = new ArrayResultSet(array, column);
}
return arrayResultSet;
}

@Override
Expand All @@ -99,7 +104,8 @@ public ResultSet getResultSet(Map<String, Class<?>> map) throws SQLException {

@Override
public ResultSet getResultSet(long index, int count) throws SQLException {
throw new SQLFeatureNotSupportedException("getResultSet(long, int) is not supported", ExceptionUtils.SQL_STATE_FEATURE_NOT_SUPPORTED);
ensureValid();
return new ArrayResultSet(getArray(index, count), column);
}

@Override
Expand Down
Loading
Loading