1111import java .time .Instant ;
1212import java .time .LocalDate ;
1313import java .time .LocalDateTime ;
14+ import java .time .ZoneId ;
1415import java .time .ZoneOffset ;
1516import java .time .ZonedDateTime ;
17+ import java .util .HashMap ;
18+ import java .util .Map ;
1619import java .util .Objects ;
20+ import java .util .UUID ;
1721import java .util .concurrent .TimeUnit ;
22+ import java .util .function .Function ;
1823
1924import tech .ydb .jdbc .YdbConst ;
20- import tech .ydb .jdbc .impl .YdbTypesImpl ;
25+ import tech .ydb .jdbc .impl .YdbTypes ;
2126import tech .ydb .table .result .PrimitiveReader ;
2227import tech .ydb .table .result .ValueReader ;
2328import tech .ydb .table .values .DecimalValue ;
5459public class MappingGetters {
5560 private MappingGetters () { }
5661
62+ @ SuppressWarnings ("Convert2Lambda" )
5763 static Getters buildGetters (Type type ) {
5864 Type .Kind kind = type .getKind ();
5965 String clazz = kind .toString ();
@@ -71,6 +77,7 @@ static Getters buildGetters(Type type) {
7177 valueToDouble (id ),
7278 valueToBytes (id ),
7379 valueToObject (id ),
80+ valueToClass (id ),
7481 valueToInstant (id ),
7582 valueToNString (id ),
7683 valueToURL (id ),
@@ -89,6 +96,7 @@ static Getters buildGetters(Type type) {
8996 value -> value .getDecimal ().toBigDecimal ().doubleValue (),
9097 castToBytesNotSupported (clazz ),
9198 PrimitiveReader ::getDecimal ,
99+ castToClassNotSupported (clazz ),
92100 castToInstantNotSupported (clazz ),
93101 castToNStringNotSupported (clazz ),
94102 castToUrlNotSupported (clazz ),
@@ -108,6 +116,12 @@ static Getters buildGetters(Type type) {
108116 value -> 0 ,
109117 value -> null ,
110118 value -> null ,
119+ new ValueToClass () {
120+ @ Override
121+ public <T > T fromValue (ValueReader reader , Class <T > clazz ) throws SQLException {
122+ return null ;
123+ }
124+ },
111125 value -> Instant .ofEpochSecond (0 ),
112126 value -> null ,
113127 value -> null ,
@@ -126,6 +140,7 @@ static Getters buildGetters(Type type) {
126140 castToDoubleNotSupported (clazz ),
127141 castToBytesNotSupported (clazz ),
128142 ValueReader ::getValue ,
143+ castToClassNotSupported (clazz ),
129144 castToInstantNotSupported (clazz ),
130145 castToNStringNotSupported (clazz ),
131146 castToUrlNotSupported (clazz ),
@@ -356,6 +371,8 @@ private static ValueToInt valueToInt(PrimitiveType id) {
356371 return value -> checkIntValue (id , value .getUint32 ());
357372 case Uint64 :
358373 return value -> checkIntValue (id , value .getUint64 ());
374+ case Date :
375+ return value -> checkIntValue (id , value .getDate ().toEpochDay ());
359376 default :
360377 return castToIntNotSupported (id .name ());
361378 }
@@ -382,6 +399,7 @@ private static ValueToLong valueToLong(PrimitiveType id) {
382399 case Uint64 :
383400 return PrimitiveReader ::getUint64 ;
384401 case Date :
402+ return value -> value .getDate ().toEpochDay ();
385403 case Datetime :
386404 case TzDate :
387405 case TzDatetime :
@@ -622,7 +640,7 @@ private static SqlType buildPrimitiveType(int sqlType, PrimitiveType id) {
622640
623641 static SqlType buildDataType (Type type ) {
624642 // All types must be the same as for #valueToObject
625- int sqlType = YdbTypesImpl . getInstance () .toSqlType (type );
643+ int sqlType = YdbTypes .toSqlType (type );
626644
627645 switch (type .getKind ()) {
628646 case PRIMITIVE :
@@ -692,6 +710,177 @@ private static ValueToObject valueToObject(PrimitiveType id) {
692710 }
693711 }
694712
713+ private static class ValueToClassBuilder {
714+ private final Type type ;
715+ private final Map <Class <?>, Function <ValueReader , ?>> map = new HashMap <>();
716+
717+ ValueToClassBuilder (Type type ) {
718+ this .type = type ;
719+ }
720+
721+ public <T > ValueToClassBuilder register (Class <T > clazz , Function <ValueReader , T > func ) {
722+ map .put (clazz , func );
723+ return this ;
724+ }
725+
726+ @ SuppressWarnings ("Convert2Lambda" )
727+ public ValueToClass build () {
728+ return new ValueToClass () {
729+ @ Override
730+ @ SuppressWarnings ("unchecked" )
731+ public <T > T fromValue (ValueReader reader , Class <T > clazz ) throws SQLException {
732+ Function <ValueReader , ?> f = map .get (clazz );
733+ if (f != null ) {
734+ return (T ) f .apply (reader );
735+ }
736+ throw new SQLException (String .format (YdbConst .UNABLE_TO_CAST_TO_CLASS , type , clazz ));
737+ }
738+ };
739+ }
740+ }
741+
742+
743+ private static ValueToClass valueToClass (PrimitiveType id ) {
744+ ValueToClassBuilder builder = new ValueToClassBuilder (id );
745+ switch (id ) {
746+ case Bytes :
747+ return builder
748+ .register (byte [].class , ValueReader ::getBytes )
749+ .build ();
750+ case Text :
751+ return builder
752+ .register (String .class , ValueReader ::getText )
753+ .build ();
754+ case Json :
755+ return builder
756+ .register (String .class , ValueReader ::getJson )
757+ .build ();
758+ case JsonDocument :
759+ return builder
760+ .register (String .class , ValueReader ::getJsonDocument )
761+ .build ();
762+ case Yson :
763+ return builder
764+ .register (byte [].class , ValueReader ::getYson )
765+ .build ();
766+ case Uuid :
767+ return builder
768+ .register (UUID .class , ValueReader ::getUuid )
769+ .build ();
770+ case Bool :
771+ return builder
772+ .register (boolean .class , ValueReader ::getBool )
773+ .register (Boolean .class , ValueReader ::getBool )
774+ .build ();
775+ case Int8 :
776+ return builder
777+ .register (byte .class , ValueReader ::getInt8 )
778+ .register (Byte .class , ValueReader ::getInt8 )
779+ .build ();
780+ case Uint8 :
781+ return builder
782+ .register (int .class , ValueReader ::getUint8 )
783+ .register (Integer .class , ValueReader ::getUint8 )
784+ .build ();
785+ case Int16 :
786+ return builder
787+ .register (short .class , ValueReader ::getInt16 )
788+ .register (Short .class , ValueReader ::getInt16 )
789+ .build ();
790+ case Uint16 :
791+ return builder
792+ .register (int .class , ValueReader ::getUint16 )
793+ .register (Integer .class , ValueReader ::getUint16 )
794+ .build ();
795+ case Int32 :
796+ return builder
797+ .register (int .class , ValueReader ::getInt32 )
798+ .register (Integer .class , ValueReader ::getInt32 )
799+ .build ();
800+ case Uint32 :
801+ return builder
802+ .register (long .class , ValueReader ::getUint32 )
803+ .register (Long .class , ValueReader ::getUint32 )
804+ .build ();
805+ case Int64 :
806+ return builder
807+ .register (long .class , ValueReader ::getInt64 )
808+ .register (Long .class , ValueReader ::getInt64 )
809+ .build ();
810+ case Uint64 :
811+ return builder
812+ .register (long .class , ValueReader ::getUint64 )
813+ .register (Long .class , ValueReader ::getUint64 )
814+ .build ();
815+ case Float :
816+ return builder
817+ .register (float .class , ValueReader ::getFloat )
818+ .register (Float .class , ValueReader ::getFloat )
819+ .build ();
820+ case Double :
821+ return builder
822+ .register (double .class , ValueReader ::getDouble )
823+ .register (Double .class , ValueReader ::getDouble )
824+ .build ();
825+ case Date :
826+ return builder
827+ .register (long .class , v -> v .getDate ().toEpochDay ())
828+ .register (Long .class , v -> v .getDate ().toEpochDay ())
829+ .register (LocalDate .class , ValueReader ::getDate )
830+ .register (LocalDateTime .class , v -> v .getDate ().atStartOfDay ())
831+ .register (java .sql .Date .class , v -> java .sql .Date .valueOf (v .getDate ()))
832+ .register (java .sql .Timestamp .class , v -> java .sql .Timestamp .valueOf (v .getDate ().atStartOfDay ()))
833+ .register (Instant .class , v -> v .getDate ().atStartOfDay (ZoneId .systemDefault ()).toInstant ())
834+ .register (java .util .Date .class , v -> java .util .Date .from (
835+ v .getDate ().atStartOfDay (ZoneId .systemDefault ()).toInstant ()))
836+ .build ();
837+ case Datetime :
838+ return builder
839+ .register (long .class , v -> v .getDatetime ().toEpochSecond (ZoneOffset .UTC ))
840+ .register (Long .class , v -> v .getDatetime ().toEpochSecond (ZoneOffset .UTC ))
841+ .register (LocalDate .class , v -> v .getDatetime ().toLocalDate ())
842+ .register (LocalDateTime .class , ValueReader ::getDatetime )
843+ .register (java .sql .Date .class , v -> java .sql .Date .valueOf (v .getDatetime ().toLocalDate ()))
844+ .register (java .sql .Timestamp .class , v -> java .sql .Timestamp .valueOf (v .getDatetime ()))
845+ .register (Instant .class , v -> v .getDatetime ().atZone (ZoneId .systemDefault ()).toInstant ())
846+ .register (java .util .Date .class , v -> java .util .Date .from (
847+ v .getDatetime ().atZone (ZoneId .systemDefault ()).toInstant ()))
848+ .build ();
849+ case Timestamp :
850+ return builder
851+ .register (long .class , v -> v .getTimestamp ().toEpochMilli ())
852+ .register (Long .class , v -> v .getTimestamp ().toEpochMilli ())
853+ .register (LocalDate .class , v -> v .getTimestamp ().atZone (ZoneId .systemDefault ()).toLocalDate ())
854+ .register (LocalDateTime .class , v -> v .getTimestamp ()
855+ .atZone (ZoneId .systemDefault ()).toLocalDateTime ())
856+ .register (java .sql .Date .class , v -> java .sql .Date
857+ .valueOf (v .getTimestamp ().atZone (ZoneId .systemDefault ()).toLocalDate ()))
858+ .register (java .sql .Timestamp .class , v -> java .sql .Timestamp
859+ .valueOf (v .getTimestamp ().atZone (ZoneId .systemDefault ()).toLocalDateTime ()))
860+ .register (Instant .class , ValueReader ::getTimestamp )
861+ .register (java .util .Date .class , v -> java .util .Date .from (v .getTimestamp ()))
862+ .build ();
863+ case Interval :
864+ return builder
865+ .register (Duration .class , ValueReader ::getInterval )
866+ .build ();
867+ case TzDate :
868+ return builder
869+ .register (ZonedDateTime .class , ValueReader ::getTzDate )
870+ .build ();
871+ case TzDatetime :
872+ return builder
873+ .register (ZonedDateTime .class , ValueReader ::getTzDatetime )
874+ .build ();
875+ case TzTimestamp :
876+ return builder
877+ .register (ZonedDateTime .class , ValueReader ::getTzTimestamp )
878+ .build ();
879+ default :
880+ return castToClassNotSupported (id .toString ());
881+ }
882+ }
883+
695884 private static SQLException cannotConvert (PrimitiveType type , Class <?> javaType , Object value ) {
696885 return new SQLException (String .format (YdbConst .UNABLE_TO_CONVERT , type , value , javaType ));
697886 }
@@ -778,6 +967,16 @@ private static ValueToReader castToReaderNotSupported(String type) {
778967 };
779968 }
780969
970+ @ SuppressWarnings ("Convert2Lambda" )
971+ private static ValueToClass castToClassNotSupported (String type ) {
972+ return new ValueToClass () {
973+ @ Override
974+ public <T > T fromValue (ValueReader reader , Class <T > clazz ) throws SQLException {
975+ throw new SQLException (String .format (YdbConst .UNABLE_TO_CAST_TO_CLASS , type , clazz ));
976+ }
977+ };
978+ }
979+
781980 public static class Getters {
782981 private final ValueToString toString ;
783982 private final ValueToBoolean toBoolean ;
@@ -789,6 +988,7 @@ public static class Getters {
789988 private final ValueToDouble toDouble ;
790989 private final ValueToBytes toBytes ;
791990 private final ValueToObject toObject ;
991+ private final ValueToClass toClass ;
792992 private final ValueToInstant toInstant ;
793993 private final ValueToNString toNString ;
794994 private final ValueToURL toURL ;
@@ -806,6 +1006,7 @@ public static class Getters {
8061006 ValueToDouble toDouble ,
8071007 ValueToBytes toBytes ,
8081008 ValueToObject toObject ,
1009+ ValueToClass toClass ,
8091010 ValueToInstant toInstant ,
8101011 ValueToNString toNString ,
8111012 ValueToURL toURL ,
@@ -821,6 +1022,7 @@ public static class Getters {
8211022 this .toDouble = toDouble ;
8221023 this .toBytes = toBytes ;
8231024 this .toObject = toObject ;
1025+ this .toClass = toClass ;
8241026 this .toInstant = toInstant ;
8251027 this .toNString = toNString ;
8261028 this .toURL = toURL ;
@@ -868,6 +1070,10 @@ public Object readObject(ValueReader reader) throws SQLException {
8681070 return toObject .fromValue (reader );
8691071 }
8701072
1073+ public <T > T readClass (ValueReader reader , Class <T > clazz ) throws SQLException {
1074+ return toClass .fromValue (reader , clazz );
1075+ }
1076+
8711077 public Instant readInstant (ValueReader reader ) throws SQLException {
8721078 return toInstant .fromValue (reader );
8731079 }
@@ -929,6 +1135,10 @@ private interface ValueToObject {
9291135 Object fromValue (ValueReader reader ) throws SQLException ;
9301136 }
9311137
1138+ private interface ValueToClass {
1139+ <T > T fromValue (ValueReader reader , Class <T > clazz ) throws SQLException ;
1140+ }
1141+
9321142 private interface ValueToInstant {
9331143 Instant fromValue (ValueReader reader ) throws SQLException ;
9341144 }
0 commit comments