Skip to content

Commit 35f0b31

Browse files
committed
Fixed dynamic primitives. Dates left
1 parent beae9f4 commit 35f0b31

File tree

8 files changed

+188
-71
lines changed

8 files changed

+188
-71
lines changed

clickhouse-data/src/main/java/com/clickhouse/data/ClickHouseColumn.java

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -642,6 +642,11 @@ public static List<ClickHouseColumn> parse(String args) {
642642

643643
public ClickHouseColumn(ClickHouseDataType dataType, String columnName, String originalTypeName, boolean nullable,
644644
boolean lowCardinality, List<String> parameters, List<ClickHouseColumn> nestedColumns) {
645+
this(dataType, columnName, originalTypeName, nullable, lowCardinality, parameters, nestedColumns, ClickHouseEnum.EMPTY);
646+
}
647+
648+
public ClickHouseColumn(ClickHouseDataType dataType, String columnName, String originalTypeName, boolean nullable,
649+
boolean lowCardinality, List<String> parameters, List<ClickHouseColumn> nestedColumns, ClickHouseEnum enumConstants) {
645650
this.aggFuncType = null;
646651
this.dataType = ClickHouseChecker.nonNull(dataType, "dataType");
647652

@@ -671,6 +676,7 @@ public ClickHouseColumn(ClickHouseDataType dataType, String columnName, String o
671676

672677
this.fixedByteLength = false;
673678
this.estimatedByteLength = 0;
679+
this.enumConstants = enumConstants;
674680
}
675681

676682
/**

clickhouse-data/src/main/java/com/clickhouse/data/ClickHouseDataType.java

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -213,6 +213,19 @@ static Map<ClickHouseDataType, Set<Class<?>>> dataTypeClassMap() {
213213
map.put(Enum8, setOf(java.lang.String.class,byte.class, Byte.class, short.class, Short.class, int.class, Integer.class, long.class, Long.class));
214214
map.put(Enum16, setOf(java.lang.String.class,byte.class, Byte.class, short.class, Short.class, int.class, Integer.class, long.class, Long.class));
215215
map.put(Array, setOf(List.class, Object[].class, byte[].class, short[].class, int[].class, long[].class, boolean[].class));
216+
217+
map.put(IntervalYear, setOfAllNumberClasses);
218+
map.put(IntervalQuarter, setOfAllNumberClasses);
219+
map.put(IntervalMonth, setOfAllNumberClasses);
220+
map.put(IntervalWeek, setOfAllNumberClasses);
221+
map.put(IntervalDay, setOfAllNumberClasses);
222+
map.put(IntervalHour, setOfAllNumberClasses);
223+
map.put(IntervalMinute, setOfAllNumberClasses);
224+
map.put(IntervalSecond, setOfAllNumberClasses);
225+
map.put(IntervalMillisecond, setOfAllNumberClasses);
226+
map.put(IntervalMicrosecond, setOfAllNumberClasses);
227+
map.put(IntervalNanosecond, setOfAllNumberClasses);
228+
216229
return map;
217230
}
218231

clickhouse-data/src/main/java/com/clickhouse/data/ClickHouseEnum.java

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,7 @@ protected ClickHouseEnum(Collection<String> params) {
5151
}
5252
}
5353

54-
protected ClickHouseEnum(String[] names, int[] values) {
54+
public ClickHouseEnum(String[] names, int[] values) {
5555
if (names == null || values == null) {
5656
throw new IllegalArgumentException("Non-null names and values are required");
5757
} else if (names.length != values.length) {
@@ -135,4 +135,16 @@ public String toSqlException() {
135135
}
136136
return builder.toString();
137137
}
138+
139+
public int size() {
140+
return size;
141+
}
142+
143+
public String[] getNames() {
144+
return names;
145+
}
146+
147+
public int[] getValues() {
148+
return values;
149+
}
138150
}

client-v2/src/main/java/com/clickhouse/client/api/data_formats/internal/AbstractBinaryFormatReader.java

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -291,9 +291,11 @@ public static String readAsString(Object value, ClickHouseColumn column) {
291291
return zdt.format(com.clickhouse.client.api.DataTypeUtils.DATE_FORMATTER).toString();
292292
}
293293
return value.toString();
294+
} else if (value instanceof BinaryStreamReader.EnumValue) {
295+
return ((BinaryStreamReader.EnumValue)value).name;
294296
} else if (value instanceof Number ) {
295297
ClickHouseDataType dataType = column.getDataType();
296-
int num = ((Number)value).intValue();
298+
int num = ((Number) value).intValue();
297299
if (column.getDataType() == ClickHouseDataType.Variant) {
298300
for (ClickHouseColumn c : column.getNestedColumns()) {
299301
// TODO: will work only if single enum listed as variant

client-v2/src/main/java/com/clickhouse/client/api/data_formats/internal/BinaryStreamReader.java

Lines changed: 52 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
import com.clickhouse.client.api.ClientException;
44
import com.clickhouse.data.ClickHouseColumn;
55
import com.clickhouse.data.ClickHouseDataType;
6+
import com.clickhouse.data.ClickHouseEnum;
67
import com.clickhouse.data.value.ClickHouseBitmap;
78
import org.slf4j.Logger;
89
import org.slf4j.helpers.NOPLogger;
@@ -158,9 +159,11 @@ public <T> T readValue(ClickHouseColumn column, Class<?> typeHint) throws IOExce
158159
case Bool:
159160
return (T) Boolean.valueOf(readByteOrEOF(input) == 1);
160161
case Enum8:
161-
return (T) Byte.valueOf((byte) readUnsignedByte());
162+
byte enum8Val = (byte) readUnsignedByte();
163+
return (T) new EnumValue(actualColumn.getEnumConstants().name(enum8Val), enum8Val);
162164
case Enum16:
163-
return (T) Short.valueOf((short) readUnsignedShortLE());
165+
short enum16Val = (short) readUnsignedShortLE();
166+
return (T) new EnumValue(actualColumn.getEnumConstants().name(enum16Val), enum16Val);
164167
case Date:
165168
return convertDateTime(readDate(timezone), typeHint);
166169
case Date32:
@@ -684,6 +687,38 @@ public synchronized <T> List<T> asList() {
684687
}
685688
}
686689

690+
public static class EnumValue extends Number {
691+
692+
public final String name;
693+
694+
public final int value;
695+
696+
public EnumValue(String name, int value) {
697+
this.name = name;
698+
this.value = value;
699+
}
700+
701+
@Override
702+
public int intValue() {
703+
return value;
704+
}
705+
706+
@Override
707+
public long longValue() {
708+
return value;
709+
}
710+
711+
@Override
712+
public float floatValue() {
713+
return value;
714+
}
715+
716+
@Override
717+
public double doubleValue() {
718+
return value;
719+
}
720+
}
721+
687722
/**
688723
* Reads a map.
689724
* @param column - column information
@@ -1033,6 +1068,21 @@ private ClickHouseColumn readDynamicData() throws IOException {
10331068
ClickHouseColumn keyInfo = readDynamicData();
10341069
ClickHouseColumn valueInfo = readDynamicData();
10351070
return ClickHouseColumn.of("v", "Map(" + keyInfo.getOriginalTypeName() + "," + valueInfo.getOriginalTypeName() + ")");
1071+
} else if (tag == ClickHouseDataType.Enum8.getBinTag() || tag == ClickHouseDataType.Enum16.getBinTag()) {
1072+
int constants = readVarInt(input);
1073+
int []values = new int[constants];
1074+
String []names = new String[constants];
1075+
ClickHouseDataType enumType = constants > 127 ? ClickHouseDataType.Enum16 : ClickHouseDataType.Enum8;
1076+
for (int i = 0; i < constants; i++) {
1077+
names[i] = readString(input);
1078+
if (enumType == ClickHouseDataType.Enum8) {
1079+
values[i] = readUnsignedByte();
1080+
} else {
1081+
values[i] = readUnsignedShortLE();
1082+
}
1083+
}
1084+
return new ClickHouseColumn(enumType, "v", enumType.name(), false, false, Collections.emptyList(), Collections.emptyList(),
1085+
new ClickHouseEnum(names, values));
10361086
} else {
10371087
type = ClickHouseDataType.binTag2Type.get(tag);
10381088
if (type == null) {

client-v2/src/main/java/com/clickhouse/client/api/data_formats/internal/SerializerUtils.java

Lines changed: 30 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
import com.clickhouse.data.ClickHouseAggregateFunction;
77
import com.clickhouse.data.ClickHouseColumn;
88
import com.clickhouse.data.ClickHouseDataType;
9+
import com.clickhouse.data.ClickHouseEnum;
910
import com.clickhouse.data.format.BinaryStreamUtils;
1011
import com.clickhouse.data.value.ClickHouseBitmap;
1112
import com.clickhouse.data.value.ClickHouseGeoMultiPolygonValue;
@@ -28,12 +29,10 @@
2829
import java.net.Inet4Address;
2930
import java.net.Inet6Address;
3031
import java.sql.Timestamp;
31-
import java.time.Instant;
3232
import java.time.LocalDate;
3333
import java.time.LocalDateTime;
3434
import java.time.ZoneId;
3535
import java.time.ZonedDateTime;
36-
import java.util.ArrayList;
3736
import java.util.Arrays;
3837
import java.util.Collections;
3938
import java.util.HashMap;
@@ -46,7 +45,6 @@
4645
import java.util.TimeZone;
4746
import java.util.UUID;
4847
import java.util.stream.Collectors;
49-
import java.util.stream.StreamSupport;
5048

5149
import static org.objectweb.asm.Opcodes.ACC_PUBLIC;
5250
import static org.objectweb.asm.Opcodes.ALOAD;
@@ -177,16 +175,16 @@ public static ClickHouseColumn valueToColumnForDynamicType(Object value) {
177175
int scale;
178176
if (d.precision() > ClickHouseDataType.Decimal128.getMaxScale()) {
179177
decType = "Decimal256";
180-
scale = ClickHouseDataType.Decimal128.getMaxScale();
178+
scale = ClickHouseDataType.Decimal256.getMaxScale();
181179
} else if (d.precision() > ClickHouseDataType.Decimal64.getMaxScale()) {
182180
decType = "Decimal128";
183181
scale = ClickHouseDataType.Decimal128.getMaxScale();
184182
} else if (d.precision() > ClickHouseDataType.Decimal32.getMaxScale()) {
185183
decType = "Decimal64";
186-
scale = ClickHouseDataType.Decimal128.getMaxScale();
184+
scale = ClickHouseDataType.Decimal64.getMaxScale();
187185
} else {
188186
decType = "Decimal32";
189-
scale = ClickHouseDataType.Decimal128.getMaxScale();
187+
scale = ClickHouseDataType.Decimal32.getMaxScale();
190188
}
191189

192190
column = ClickHouseColumn.of("v", decType + "(" + scale + ")");
@@ -197,8 +195,10 @@ public static ClickHouseColumn valueToColumnForDynamicType(Object value) {
197195
ClickHouseColumn keyInfo = valueToColumnForDynamicType(entry.getKey());
198196
ClickHouseColumn valueInfo = valueToColumnForDynamicType(entry.getValue());
199197
column = ClickHouseColumn.of("v", "Map(" + keyInfo.getOriginalTypeName() + ", " + valueInfo.getOriginalTypeName() + ")");
198+
} else if (value instanceof Enum<?>) {
199+
column = enumValue2Column((Enum)value);
200200
} else if (value instanceof List<?>) {
201-
column = value2Column(value);
201+
column = listValue2Column(value);
202202
} else if (value == null) {
203203
column = PREDEFINED_TYPE_COLUMNS.get(Void.class);
204204
} else {
@@ -221,7 +221,7 @@ public static ClickHouseColumn valueToColumnForDynamicType(Object value) {
221221
// { 0, 1, 2 }
222222
// In this case we need to find max depth.
223223

224-
private static ClickHouseColumn value2Column(Object value) {
224+
private static ClickHouseColumn listValue2Column(Object value) {
225225
ClickHouseColumn column;
226226
if (value instanceof List<?>) {
227227
List<?> list = (List<?>) value;
@@ -250,6 +250,12 @@ private static ClickHouseColumn value2Column(Object value) {
250250
return column;
251251
}
252252

253+
private static ClickHouseColumn enumValue2Column(Enum<?> enumValue) {
254+
ClickHouseEnum clickHouseEnum= ClickHouseEnum.of(enumValue.getClass());
255+
return new ClickHouseColumn(clickHouseEnum.size() > 127 ? ClickHouseDataType.Enum16 : ClickHouseDataType.Enum8, "v", "Enum16", false, false, Collections.emptyList(), Collections.emptyList(),
256+
clickHouseEnum);
257+
}
258+
253259
public static void writeDynamicTypeTag(OutputStream stream, ClickHouseColumn typeColumn)
254260
throws IOException {
255261

@@ -272,12 +278,20 @@ public static void writeDynamicTypeTag(OutputStream stream, ClickHouseColumn typ
272278
writeVarInt(stream, typeColumn.getEstimatedLength());
273279
break;
274280
case Enum8:
275-
stream.write(binTag);
276-
/// 0x17<var_uint_number_of_elements><var_uint_name_size_1><name_data_1><int8_value_1>...<var_uint_name_size_N><name_data_N><int8_value_N>
277-
break;
278281
case Enum16:
279282
stream.write(binTag);
280-
//0x18<var_uint_number_of_elements><var_uint_name_size_1><name_data_1><int16_little_endian_value_1>...><var_uint_name_size_N><name_data_N><int16_little_endian_value_N>
283+
ClickHouseEnum enumVal = typeColumn.getEnumConstants();
284+
String[] names = enumVal.getNames();
285+
int[] values = enumVal.getValues();
286+
writeVarInt(stream, names.length);
287+
for (int i = 0; i < enumVal.size(); i++ ) {
288+
BinaryStreamUtils.writeString(stream, names[i]);
289+
if (dt == ClickHouseDataType.Enum8) {
290+
BinaryStreamUtils.writeInt8(stream, values[i]);
291+
} else {
292+
BinaryStreamUtils.writeInt16(stream, values[i]);
293+
}
294+
}
281295
break;
282296
case Decimal:
283297
case Decimal32:
@@ -524,6 +538,7 @@ private static void serializePrimitiveData(OutputStream stream, Object value, Cl
524538
serializeJSON(stream, value);
525539
break;
526540
case IntervalNanosecond:
541+
case IntervalMicrosecond:
527542
case IntervalMillisecond:
528543
case IntervalSecond:
529544
case IntervalMinute:
@@ -545,7 +560,9 @@ private static void serializeEnumData(OutputStream stream, ClickHouseColumn colu
545560
if (value instanceof String) {
546561
enumValue = column.getEnumConstants().value((String) value);
547562
} else if (value instanceof Number) {
548-
enumValue = ((Number)value).intValue();
563+
enumValue = ((Number) value).intValue();
564+
} else if (value instanceof Enum<?>) {
565+
enumValue = ((Enum<?>)value).ordinal();
549566
} else {
550567
throw new IllegalArgumentException("Cannot write value of class " + value.getClass() + " into column with Enum type " + column.getOriginalTypeName());
551568
}

0 commit comments

Comments
 (0)