WARNING: THIS SITE IS A MIRROR OF GITHUB.COM / IT CANNOT LOGIN OR REGISTER ACCOUNTS / THE CONTENTS ARE PROVIDED AS-IS / THIS SITE ASSUMES NO RESPONSIBILITY FOR ANY DISPLAYED CONTENT OR LINKS / IF YOU FOUND SOMETHING MAY NOT GOOD FOR EVERYONE, CONTACT ADMIN AT ilovescratch@foxmail.com
Skip to content

Commit 32bbfc8

Browse files
committed
added lazy init of conversion map to make logic more coherent
1 parent 23d1f94 commit 32bbfc8

File tree

2 files changed

+67
-39
lines changed

2 files changed

+67
-39
lines changed

jdbc-v2/src/main/java/com/clickhouse/jdbc/types/ArrayResultSet.java

Lines changed: 43 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,6 @@
1010
import java.io.InputStream;
1111
import java.io.Reader;
1212
import java.math.BigDecimal;
13-
import java.math.RoundingMode;
1413
import java.net.MalformedURLException;
1514
import java.net.URL;
1615
import java.sql.Array;
@@ -30,7 +29,6 @@
3029
import java.sql.Statement;
3130
import java.sql.Time;
3231
import java.sql.Timestamp;
33-
import java.time.ZonedDateTime;
3432
import java.util.Arrays;
3533
import java.util.Calendar;
3634
import java.util.List;
@@ -52,7 +50,7 @@ public class ArrayResultSet implements ResultSet {
5250
private int fetchDirection = ResultSet.FETCH_FORWARD;
5351
private int fetchSize = 0;
5452
private boolean wasNull = false;
55-
private final Map<Class<?>, Function<Object, Object>> converterMap;
53+
private Map<Class<?>, Function<Object, Object>> converterMap;
5654
private final Map<Class<?>, Function<Object, Object>> indexConverterMap;
5755
private final ClickHouseDataType componentDataType;
5856
private final Class<?> defaultClass;
@@ -74,16 +72,6 @@ public ArrayResultSet(Object array, ClickHouseColumn column) {
7472
this.componentDataType = valueColumn.getDataType();
7573
this.defaultClass = JdbcUtils.DATA_TYPE_CLASS_MAP.get(componentDataType);
7674
indexConverterMap = defaultValueConverters.getConvertersForType(Integer.class);
77-
if (this.length > 0) {
78-
Class<?> itemClass = array.getClass().getComponentType();
79-
if (itemClass == null) {
80-
itemClass = java.lang.reflect.Array.get(array, 0).getClass();
81-
}
82-
converterMap = defaultValueConverters.getConvertersForType(itemClass);
83-
} else {
84-
// empty array - no values to convert
85-
converterMap = null;
86-
}
8775
}
8876

8977
@Override
@@ -107,39 +95,58 @@ private void checkRowPosition() throws SQLException {
10795
}
10896
}
10997

98+
private Map<Class<?>, Function<Object, Object>> initValueConverterMapIfNeeded(Object nonNullValue) {
99+
if (converterMap == null) {
100+
if (array.getClass().getComponentType() == Object.class) {
101+
converterMap = defaultValueConverters.getConvertersForType(nonNullValue.getClass());
102+
} else {
103+
converterMap = defaultValueConverters.getConvertersForType(array.getClass().getComponentType());
104+
}
105+
}
106+
return converterMap;
107+
}
108+
109+
private Object convertValue(Object value, Class<?> targetType, Map<Class<?>, Function<Object, Object>> valueConverterMap) throws SQLException {
110+
if (value == null || targetType == value.getClass() || targetType == Object.class) {
111+
return value;
112+
}
113+
114+
Function<Object, Object> converter = valueConverterMap.get(targetType);
115+
if (converter != null) {
116+
try {
117+
return converter.apply(value);
118+
} catch (Exception e) {
119+
throw new SQLException("Failed to convert value of " + value.getClass() + " to " + targetType,
120+
ExceptionUtils.SQL_STATE_DATA_EXCEPTION, e);
121+
}
122+
} else {
123+
throw new SQLException("Value of " + value.getClass() + " cannot be converted to " + targetType);
124+
}
125+
}
126+
110127
private Object getValueAsObject(int columnIndex, Class<?> type, Object defaultValue) throws SQLException {
111128
checkColumnIndex(columnIndex);
112129
checkRowPosition();
113130

114-
Object value;
115-
Map<Class<?>, Function<Object, Object>> valueConverterMap;
116131
if (columnIndex == 1) {
117-
value = pos + 1;
118-
valueConverterMap = indexConverterMap;
132+
Integer value = pos + 1;
133+
return convertValue(value, type, indexConverterMap);
119134
} else {
120-
value = java.lang.reflect.Array.get(array, pos);
121-
valueConverterMap = converterMap;
122-
}
135+
Object value = java.lang.reflect.Array.get(array, pos);
136+
wasNull = value == null;
137+
if (value == null) {
138+
return defaultValue;
139+
}
123140

124-
if (columnIndex != 1 && value != null && type == Array.class) {
125-
ClickHouseColumn nestedColumn = column.getArrayNestedLevel() == 1 ? column.getArrayBaseColumn() : column.getNestedColumns().get(0);
126-
return new com.clickhouse.jdbc.types.Array(nestedColumn, JdbcUtils.arrayToObjectArray(value));
127-
} else if (value != null && type != Object.class) {
128-
// if there is something to convert. type == Object.class means no conversion
129-
Function<Object, Object> converter = valueConverterMap.get(type);
130-
if (converter != null) {
131-
try {
132-
value = converter.apply(value);
133-
} catch (Exception e) {
134-
throw new SQLException("Failed to convert value of " + value.getClass() + " to " + type,
135-
ExceptionUtils.SQL_STATE_DATA_EXCEPTION, e);
136-
}
141+
if (type == Array.class) {
142+
ClickHouseColumn nestedColumn =
143+
column.getArrayNestedLevel() == 1 ? column.getArrayBaseColumn() : column.getNestedColumns().get(0);
144+
return new com.clickhouse.jdbc.types.Array(nestedColumn, JdbcUtils.arrayToObjectArray(value));
137145
} else {
138-
throw new SQLException("Value of " + value.getClass() + " cannot be converted to " + type);
146+
Map<Class<?>, Function<Object, Object>> valueConverterMap = initValueConverterMapIfNeeded(value);
147+
return convertValue(value, type, valueConverterMap);
139148
}
140149
}
141-
wasNull = value == null;
142-
return value == null ? defaultValue : value;
143150
}
144151

145152
private void throwReadOnlyException() throws SQLException {

jdbc-v2/src/test/java/com/clickhouse/jdbc/types/ArrayResultSetTest.java

Lines changed: 24 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -134,12 +134,17 @@ void testCursorNavigation() throws SQLException {
134134

135135
@Test
136136
void testNullValues() throws SQLException {
137-
Integer[] array = {1, null, 3, 4, 5};
137+
Integer[] array = {null, 1, null, 3, 4, 5};
138138
ArrayResultSet rs = new ArrayResultSet(array, ClickHouseColumn.parse("v Array(Int32)").get(0));
139139

140140
rs.next();
141-
assertFalse(rs.wasNull());
142-
assertEquals(rs.getInt(2), array[0]);
141+
assertEquals(rs.getInt(2), 0);
142+
assertTrue(rs.wasNull());
143+
assertTrue(rs.wasNull());
144+
145+
rs.next();
146+
assertTrue(rs.wasNull());
147+
assertEquals(rs.getInt(2), array[1]);
143148
assertFalse(rs.wasNull());
144149
assertFalse(rs.wasNull());
145150

@@ -537,4 +542,20 @@ void testInvalidStringConverts() throws Exception {
537542
Assert.assertThrows(SQLException.class, () -> rs.getFloat(stringColumn));
538543
Assert.assertThrows(SQLException.class, () -> rs.getDouble(stringColumn));
539544
}
545+
546+
@Test
547+
void testArrayOfObjects() throws Exception {
548+
Object[] array = {null, 2, 3};
549+
ArrayResultSet rs = new ArrayResultSet(array, ClickHouseColumn.parse("v Array(Nullable(UInt32))").get(0));
550+
551+
final String valueColumn = rs.getMetaData().getColumnName(2);
552+
rs.next();
553+
assertEquals(rs.getObject(valueColumn), null);
554+
assertTrue(rs.wasNull());
555+
556+
rs.next();
557+
assertEquals(rs.getInt(valueColumn), 2);
558+
assertEquals(rs.getObject(valueColumn, String.class), "2");
559+
assertEquals(rs.getString(valueColumn), rs.getObject(valueColumn, String.class));
560+
}
540561
}

0 commit comments

Comments
 (0)