|
1 | 1 | package com.clickhouse.data; |
2 | 2 |
|
| 3 | +import java.lang.reflect.Array; |
3 | 4 | import java.math.BigDecimal; |
4 | 5 | import java.math.BigInteger; |
5 | 6 | import java.net.Inet4Address; |
6 | 7 | import java.net.Inet6Address; |
7 | 8 | import java.time.LocalDate; |
8 | 9 | import java.time.LocalDateTime; |
| 10 | +import java.time.ZonedDateTime; |
| 11 | +import java.util.ArrayList; |
9 | 12 | import java.util.Arrays; |
| 13 | +import java.util.Collection; |
10 | 14 | import java.util.Collections; |
| 15 | +import java.util.Comparator; |
| 16 | +import java.util.EnumSet; |
11 | 17 | import java.util.HashMap; |
| 18 | +import java.util.HashSet; |
12 | 19 | import java.util.LinkedList; |
13 | 20 | import java.util.List; |
14 | 21 | import java.util.Locale; |
15 | 22 | import java.util.Map; |
16 | 23 | import java.util.Set; |
| 24 | +import java.util.TreeMap; |
17 | 25 | import java.util.TreeSet; |
18 | 26 | import java.util.UUID; |
| 27 | +import java.util.stream.Collectors; |
19 | 28 |
|
| 29 | +import com.clickhouse.data.value.ClickHouseGeoMultiPolygonValue; |
| 30 | +import com.clickhouse.data.value.ClickHouseGeoPointValue; |
| 31 | +import com.clickhouse.data.value.ClickHouseGeoPolygonValue; |
| 32 | +import com.clickhouse.data.value.ClickHouseGeoRingValue; |
20 | 33 | import com.clickhouse.data.value.UnsignedByte; |
21 | 34 | import com.clickhouse.data.value.UnsignedInteger; |
22 | 35 | import com.clickhouse.data.value.UnsignedLong; |
@@ -101,7 +114,111 @@ public enum ClickHouseDataType { |
101 | 114 | Nothing(Object.class, false, true, false, 0, 0, 0, 0, 0, true), |
102 | 115 | SimpleAggregateFunction(String.class, true, true, false, 0, 0, 0, 0, 0, false), |
103 | 116 | // implementation-defined intermediate state |
104 | | - AggregateFunction(String.class, true, true, false, 0, 0, 0, 0, 0, true); |
| 117 | + AggregateFunction(String.class, true, true, false, 0, 0, 0, 0, 0, true), |
| 118 | + Variant(List.class, true, true, false, 0, 0, 0, 0, 0, true), |
| 119 | + |
| 120 | + ; |
| 121 | + |
| 122 | + public static final List<ClickHouseDataType> ORDERED_BY_RANGE_INT_TYPES = |
| 123 | + Collections.unmodifiableList(Arrays.asList( |
| 124 | + Int8, UInt8, Int16, UInt16, Int32, UInt32, Int64, UInt64, Int128, UInt128, Int256, UInt256 |
| 125 | + )); |
| 126 | + |
| 127 | + public static final List<ClickHouseDataType> ORDERED_BY_RANGE_DECIMAL_TYPES = |
| 128 | + Collections.unmodifiableList(Arrays.asList( |
| 129 | + Float32, Float64, Decimal32, Decimal64, Decimal128, Decimal256, Decimal |
| 130 | + )); |
| 131 | + |
| 132 | + public static Map<Class<?>, Integer> buildVariantMapping(List<ClickHouseDataType> variantDataTypes) { |
| 133 | + Map<Class<?>, Integer> variantMapping = new HashMap<>(); |
| 134 | + |
| 135 | + TreeMap<ClickHouseDataType, Integer> intTypesMappings = new TreeMap<>(Comparator.comparingInt(ORDERED_BY_RANGE_INT_TYPES::indexOf)); |
| 136 | + TreeMap<ClickHouseDataType, Integer> decTypesMappings = new TreeMap<>(Comparator.comparingInt(ORDERED_BY_RANGE_DECIMAL_TYPES::indexOf)); |
| 137 | + |
| 138 | + for (int ordNum = 0; ordNum < variantDataTypes.size(); ordNum++) { |
| 139 | + ClickHouseDataType dataType = variantDataTypes.get(ordNum); |
| 140 | + Set<Class<?>> classSet = DATA_TYPE_TO_CLASS.get(dataType); |
| 141 | + |
| 142 | + final int finalOrdNum = ordNum; |
| 143 | + if (classSet != null) { |
| 144 | + if (ORDERED_BY_RANGE_INT_TYPES.contains(dataType)) { |
| 145 | + intTypesMappings.put(dataType, ordNum); |
| 146 | + } else if (ORDERED_BY_RANGE_DECIMAL_TYPES.contains(dataType)) { |
| 147 | + decTypesMappings.put(dataType, ordNum); |
| 148 | + } else { |
| 149 | + classSet.forEach(c -> variantMapping.put(c, finalOrdNum)); |
| 150 | + } |
| 151 | + } |
| 152 | + } |
| 153 | + |
| 154 | + // add integers |
| 155 | + for (java.util.Map.Entry<ClickHouseDataType, Integer> entry : intTypesMappings.entrySet()) { |
| 156 | + DATA_TYPE_TO_CLASS.get(entry.getKey()).forEach(c -> variantMapping.put(c, entry.getValue())); |
| 157 | + } |
| 158 | + // add decimals |
| 159 | + for (java.util.Map.Entry<ClickHouseDataType, Integer> entry : decTypesMappings.entrySet()) { |
| 160 | + DATA_TYPE_TO_CLASS.get(entry.getKey()).forEach(c -> variantMapping.put(c, entry.getValue())); |
| 161 | + } |
| 162 | + |
| 163 | + return variantMapping; |
| 164 | + } |
| 165 | + |
| 166 | + static final Map<ClickHouseDataType, Set<Class<?>>> DATA_TYPE_TO_CLASS = dataTypeClassMap(); |
| 167 | + static Map<ClickHouseDataType, Set<Class<?>>> dataTypeClassMap() { |
| 168 | + Map<ClickHouseDataType, Set<Class<?>>> map = new HashMap<>(); |
| 169 | + |
| 170 | + // We allow to write short to UInt8 even it may not fit. It is done because we have to allow users to utilize UInt* data types. |
| 171 | + List<Class<?>> allNumberClassesOrderedBySize = Arrays.asList(byte.class, Byte.class, short.class, Short.class, int.class, Integer.class, long.class, Long.class, BigInteger.class); |
| 172 | + Set<Class<?>> setOfAllNumberClasses = Collections.unmodifiableSet(new HashSet<>(allNumberClassesOrderedBySize)); |
| 173 | + map.put(UInt256, setOfAllNumberClasses); |
| 174 | + map.put(Int256, setOfAllNumberClasses); |
| 175 | + map.put(UInt128, setOfAllNumberClasses); |
| 176 | + map.put(Int128, setOfAllNumberClasses); |
| 177 | + map.put(UInt64, setOfAllNumberClasses); |
| 178 | + |
| 179 | + map.put(Int64, setOf(byte.class, Byte.class, short.class, Short.class, int.class, Integer.class, long.class, Long.class)); |
| 180 | + map.put(UInt32, setOf(byte.class, Byte.class, short.class, Short.class, int.class, Integer.class, long.class, Long.class )); |
| 181 | + map.put(Int32, setOf(byte.class, Byte.class, short.class, Short.class, int.class, Integer.class)); |
| 182 | + map.put(UInt16, setOf(byte.class, Byte.class, short.class, Short.class, int.class, Integer.class)); |
| 183 | + map.put(Int16, setOf(byte.class, Byte.class, short.class, Short.class)); |
| 184 | + map.put(UInt8, setOf(byte.class, Byte.class, short.class, Short.class)); |
| 185 | + map.put(Int8, setOf(byte.class, Byte.class)); |
| 186 | + |
| 187 | + map.put(Bool, setOf(boolean.class, Boolean.class)); |
| 188 | + map.put(String, setOf(String.class)); |
| 189 | + map.put(Float64, setOf(float.class, Float.class, double.class, Double.class)); |
| 190 | + map.put(Float32, setOf(float.class, Float.class)); |
| 191 | + map.put(Decimal, setOf(float.class, Float.class, double.class, Double.class, BigDecimal.class)); |
| 192 | + map.put(Decimal256, setOf(float.class, Float.class, double.class, Double.class, BigDecimal.class)); |
| 193 | + map.put(Decimal128, setOf(float.class, Float.class, double.class, Double.class, BigDecimal.class)); |
| 194 | + map.put(Decimal64, setOf(float.class, Float.class, double.class, Double.class)); |
| 195 | + map.put(Decimal32, setOf(float.class, Float.class)); |
| 196 | + |
| 197 | + map.put(IPv4, setOf(Inet4Address.class)); |
| 198 | + map.put(IPv6, setOf(Inet6Address.class)); |
| 199 | + map.put(UUID, setOf(java.util.UUID.class)); |
| 200 | + |
| 201 | + map.put(Point, setOf(double[].class, ClickHouseGeoPointValue.class)); |
| 202 | + map.put(Ring, setOf(double[][].class, ClickHouseGeoRingValue.class)); |
| 203 | + map.put(Polygon, setOf(double[][][].class, ClickHouseGeoPolygonValue.class)); |
| 204 | + map.put(MultiPolygon, setOf(double[][][][].class, ClickHouseGeoMultiPolygonValue.class)); |
| 205 | + |
| 206 | + map.put(Date, setOf(LocalDateTime.class, LocalDate.class, ZonedDateTime.class)); |
| 207 | + map.put(Date32, setOf(LocalDateTime.class, LocalDate.class, ZonedDateTime.class)); |
| 208 | + map.put(DateTime64, setOf(LocalDateTime.class, ZonedDateTime.class)); |
| 209 | + map.put(DateTime32, setOf(LocalDateTime.class, ZonedDateTime.class)); |
| 210 | + map.put(DateTime, setOf(LocalDateTime.class, ZonedDateTime.class)); |
| 211 | + |
| 212 | + map.put(Enum8, setOf(java.lang.String.class,byte.class, Byte.class, short.class, Short.class, int.class, Integer.class, long.class, Long.class)); |
| 213 | + map.put(Enum16, setOf(java.lang.String.class,byte.class, Byte.class, short.class, Short.class, int.class, Integer.class, long.class, Long.class)); |
| 214 | + map.put(Array, setOf(List.class, Object[].class, byte[].class, short[].class, int[].class, long[].class, boolean[].class)); |
| 215 | + return map; |
| 216 | + } |
| 217 | + |
| 218 | + private static Set<Class<?>> setOf(Class<?>... args) { |
| 219 | + return Collections.unmodifiableSet(new HashSet<>(Arrays.stream(args).collect(Collectors.toList()))); |
| 220 | + } |
| 221 | + |
105 | 222 |
|
106 | 223 | /** |
107 | 224 | * Immutable set(sorted) for all aliases. |
|
0 commit comments