Skip to content

Commit 8225fae

Browse files
committed
Added support of custom decimals
1 parent 895ae01 commit 8225fae

File tree

1 file changed

+84
-74
lines changed

1 file changed

+84
-74
lines changed

jdbc/src/main/java/tech/ydb/jdbc/impl/YdbTypes.java

Lines changed: 84 additions & 74 deletions
Original file line numberDiff line numberDiff line change
@@ -15,9 +15,6 @@
1515
import java.util.List;
1616
import java.util.Map;
1717

18-
import io.grpc.netty.shaded.io.netty.util.collection.IntObjectHashMap;
19-
import io.grpc.netty.shaded.io.netty.util.collection.IntObjectMap;
20-
2118
import tech.ydb.jdbc.YdbConst;
2219
import tech.ydb.table.values.DecimalType;
2320
import tech.ydb.table.values.DecimalValue;
@@ -29,18 +26,43 @@
2926
public class YdbTypes {
3027
private static final YdbTypes INSTANCE = new YdbTypes();
3128

32-
private final IntObjectMap<Type> typeBySqlType;
29+
private final Map<Integer, Type> typeBySqlType;
3330
private final Map<Class<?>, Type> typeByClass;
3431

35-
private final Map<Type, Integer> sqlTypeByPrimitiveNumId;
36-
3732
private YdbTypes() {
38-
typeBySqlType = new IntObjectHashMap<>(18 + PrimitiveType.values().length);
33+
typeBySqlType = new HashMap<>();
3934

4035
// Store custom type ids to use it for PrepaparedStatement.setObject
41-
for (PrimitiveType type: PrimitiveType.values()) {
42-
typeBySqlType.put(YdbConst.SQL_KIND_PRIMITIVE + type.ordinal(), type);
43-
}
36+
typeBySqlType.put(YdbConst.SQL_KIND_PRIMITIVE + 0, PrimitiveType.Bool);
37+
38+
typeBySqlType.put(YdbConst.SQL_KIND_PRIMITIVE + 1, PrimitiveType.Int8);
39+
typeBySqlType.put(YdbConst.SQL_KIND_PRIMITIVE + 2, PrimitiveType.Uint8);
40+
typeBySqlType.put(YdbConst.SQL_KIND_PRIMITIVE + 3, PrimitiveType.Int16);
41+
typeBySqlType.put(YdbConst.SQL_KIND_PRIMITIVE + 4, PrimitiveType.Uint16);
42+
typeBySqlType.put(YdbConst.SQL_KIND_PRIMITIVE + 5, PrimitiveType.Int32);
43+
typeBySqlType.put(YdbConst.SQL_KIND_PRIMITIVE + 6, PrimitiveType.Uint32);
44+
typeBySqlType.put(YdbConst.SQL_KIND_PRIMITIVE + 7, PrimitiveType.Int64);
45+
typeBySqlType.put(YdbConst.SQL_KIND_PRIMITIVE + 8, PrimitiveType.Uint64);
46+
47+
typeBySqlType.put(YdbConst.SQL_KIND_PRIMITIVE + 9, PrimitiveType.Float);
48+
typeBySqlType.put(YdbConst.SQL_KIND_PRIMITIVE + 10, PrimitiveType.Double);
49+
50+
typeBySqlType.put(YdbConst.SQL_KIND_PRIMITIVE + 11, PrimitiveType.Bytes);
51+
typeBySqlType.put(YdbConst.SQL_KIND_PRIMITIVE + 12, PrimitiveType.Text);
52+
typeBySqlType.put(YdbConst.SQL_KIND_PRIMITIVE + 13, PrimitiveType.Yson);
53+
typeBySqlType.put(YdbConst.SQL_KIND_PRIMITIVE + 14, PrimitiveType.Json);
54+
55+
typeBySqlType.put(YdbConst.SQL_KIND_PRIMITIVE + 15, PrimitiveType.Uuid);
56+
57+
typeBySqlType.put(YdbConst.SQL_KIND_PRIMITIVE + 16, PrimitiveType.Date);
58+
typeBySqlType.put(YdbConst.SQL_KIND_PRIMITIVE + 17, PrimitiveType.Datetime);
59+
typeBySqlType.put(YdbConst.SQL_KIND_PRIMITIVE + 18, PrimitiveType.Timestamp);
60+
typeBySqlType.put(YdbConst.SQL_KIND_PRIMITIVE + 19, PrimitiveType.Interval);
61+
typeBySqlType.put(YdbConst.SQL_KIND_PRIMITIVE + 20, PrimitiveType.TzDate);
62+
typeBySqlType.put(YdbConst.SQL_KIND_PRIMITIVE + 21, PrimitiveType.TzDatetime);
63+
typeBySqlType.put(YdbConst.SQL_KIND_PRIMITIVE + 22, PrimitiveType.TzTimestamp);
64+
65+
typeBySqlType.put(YdbConst.SQL_KIND_PRIMITIVE + 23, PrimitiveType.JsonDocument);
4466

4567
typeBySqlType.put(Types.VARCHAR, PrimitiveType.Text);
4668
typeBySqlType.put(Types.BIGINT, PrimitiveType.Int64);
@@ -104,71 +126,21 @@ private YdbTypes() {
104126
typeByClass.put(DecimalValue.class, DecimalType.getDefault());
105127
typeByClass.put(BigDecimal.class, DecimalType.getDefault());
106128
typeByClass.put(Duration.class, PrimitiveType.Interval);
107-
108-
sqlTypeByPrimitiveNumId = new HashMap<>(PrimitiveType.values().length);
109-
for (PrimitiveType id : PrimitiveType.values()) {
110-
final int sqlType;
111-
switch (id) {
112-
case Text:
113-
case Json:
114-
case JsonDocument:
115-
case Uuid:
116-
sqlType = Types.VARCHAR;
117-
break;
118-
case Bytes:
119-
case Yson:
120-
sqlType = Types.BINARY;
121-
break;
122-
case Bool:
123-
sqlType = Types.BOOLEAN;
124-
break;
125-
case Int8:
126-
case Int16:
127-
sqlType = Types.SMALLINT;
128-
break;
129-
case Uint8:
130-
case Int32:
131-
case Uint16:
132-
sqlType = Types.INTEGER;
133-
break;
134-
case Uint32:
135-
case Int64:
136-
case Uint64:
137-
case Interval:
138-
sqlType = Types.BIGINT;
139-
break;
140-
case Float:
141-
sqlType = Types.FLOAT;
142-
break;
143-
case Double:
144-
sqlType = Types.DOUBLE;
145-
break;
146-
case Date:
147-
sqlType = Types.DATE;
148-
break;
149-
case Datetime:
150-
sqlType = Types.TIMESTAMP;
151-
break;
152-
case Timestamp:
153-
sqlType = Types.TIMESTAMP;
154-
break;
155-
case TzDate:
156-
case TzDatetime:
157-
case TzTimestamp:
158-
sqlType = Types.TIMESTAMP_WITH_TIMEZONE;
159-
break;
160-
default:
161-
sqlType = Types.JAVA_OBJECT;
162-
}
163-
sqlTypeByPrimitiveNumId.put(id, sqlType);
164-
}
165129
}
166130

167131
public static Type findType(Object obj, int sqlType) {
168132
return INSTANCE.findTypeImpl(obj, sqlType);
169133
}
170134

171135
private Type findTypeImpl(Object obj, int sqlType) {
136+
if ((sqlType & YdbConst.SQL_KIND_DECIMAL) != 0) {
137+
int precision = ((sqlType - YdbConst.SQL_KIND_DECIMAL) >> 5);
138+
int scale = ((sqlType - YdbConst.SQL_KIND_DECIMAL) & 0b11111);
139+
if (precision > 0 && precision < 36 && scale >= 0 && scale <= precision) {
140+
return DecimalType.of(precision, scale);
141+
}
142+
}
143+
172144
if (typeBySqlType.containsKey(sqlType)) {
173145
return typeBySqlType.get(sqlType);
174146
}
@@ -196,14 +168,54 @@ public static int toSqlType(Type type) {
196168
private int toSqlTypeImpl(Type type) {
197169
switch (type.getKind()) {
198170
case PRIMITIVE:
199-
if (!sqlTypeByPrimitiveNumId.containsKey(type)) {
200-
throw new RuntimeException("Internal error. Unsupported YDB type: " + type);
171+
switch ((PrimitiveType) type) {
172+
case Text:
173+
case Json:
174+
case JsonDocument:
175+
case Uuid:
176+
return Types.VARCHAR;
177+
case Bytes:
178+
case Yson:
179+
return Types.BINARY;
180+
case Bool:
181+
return Types.BOOLEAN;
182+
case Int8:
183+
case Int16:
184+
return Types.SMALLINT;
185+
case Uint8:
186+
case Int32:
187+
case Uint16:
188+
return Types.INTEGER;
189+
case Uint32:
190+
case Int64:
191+
case Uint64:
192+
case Interval:
193+
return Types.BIGINT;
194+
case Float:
195+
return Types.FLOAT;
196+
case Double:
197+
return Types.DOUBLE;
198+
case Date:
199+
return Types.DATE;
200+
case Datetime:
201+
return Types.TIMESTAMP;
202+
case Timestamp:
203+
return Types.TIMESTAMP;
204+
case TzDate:
205+
case TzDatetime:
206+
case TzTimestamp:
207+
return Types.TIMESTAMP_WITH_TIMEZONE;
208+
default:
209+
return Types.JAVA_OBJECT;
201210
}
202-
return sqlTypeByPrimitiveNumId.get(type);
203211
case OPTIONAL:
204212
return toSqlTypeImpl(type.unwrapOptional());
205213
case DECIMAL:
206-
return Types.DECIMAL;
214+
DecimalType decimal = (DecimalType) type;
215+
if (DecimalType.getDefault().equals(type)) {
216+
return Types.DECIMAL;
217+
}
218+
return YdbConst.SQL_KIND_DECIMAL + decimal.getPrecision() << 5 + decimal.getScale();
207219
case STRUCT:
208220
return Types.STRUCT;
209221
case LIST:
@@ -287,8 +299,6 @@ private List<Type> getAllDatabaseTypesImpl() {
287299
DecimalType.getDefault());
288300
}
289301

290-
//
291-
292302
private int getSqlPrecisionImpl(PrimitiveType type) {
293303
switch (type) {
294304
case Bool:

0 commit comments

Comments
 (0)