@@ -31,6 +31,7 @@ import (
31
31
"io"
32
32
"io/ioutil"
33
33
"net"
34
+ "reflect"
34
35
"runtime"
35
36
"strings"
36
37
"time"
@@ -869,68 +870,98 @@ func (w *writePrepareFrame) buildFrame(f *framer, streamID int) error {
869
870
return f .finish ()
870
871
}
871
872
872
- func (f * framer ) readTypeInfo () TypeInfo {
873
- // TODO: factor this out so the same code paths can be used to parse custom
874
- // types and other types, as much of the logic will be duplicated.
875
- id := f .readShort ()
876
-
877
- simple := NativeType {
878
- proto : f .proto ,
879
- typ : Type (id ),
880
- }
881
-
882
- if simple .typ == TypeCustom {
883
- simple .custom = f .readString ()
884
- if cassType := getApacheCassandraType (simple .custom ); cassType != TypeCustom {
885
- simple .typ = cassType
886
- }
887
- }
873
+ var (
874
+ typeInfoType = reflect .TypeOf ((* TypeInfo )(nil )).Elem ()
875
+ typeType = reflect .TypeOf (Type (0 ))
876
+ typeInfoListType = reflect .TypeOf ([]TypeInfo (nil ))
877
+ stringListType = reflect .TypeOf ([]string (nil ))
878
+ udtFieldListType = reflect .TypeOf ([]UDTField (nil ))
879
+ stringType = reflect .TypeOf ("" )
880
+ shortType = reflect .TypeOf (uint16 (0 ))
881
+ byteType = reflect .TypeOf (byte (0 ))
882
+ intType = reflect .TypeOf (int (0 ))
883
+ )
888
884
889
- switch simple .typ {
890
- case TypeTuple :
885
+ func (f * framer ) readForType (typ reflect.Type ) interface {} {
886
+ // check simple equality first
887
+ switch typ {
888
+ case stringType :
889
+ return f .readString ()
890
+ case shortType :
891
+ return f .readShort ()
892
+ case byteType :
893
+ return f .readByte ()
894
+ case intType :
895
+ return f .readInt ()
896
+ case stringListType :
897
+ return f .readStringList ()
898
+ case udtFieldListType :
891
899
n := f .readShort ()
892
- tuple := TupleTypeInfo {
893
- NativeType : simple ,
894
- Elems : make ([]TypeInfo , n ),
895
- }
896
-
900
+ fields := make ([]UDTField , n )
897
901
for i := 0 ; i < int (n ); i ++ {
898
- tuple .Elems [i ] = f .readTypeInfo ()
899
- }
900
-
901
- return tuple
902
-
903
- case TypeUDT :
904
- udt := UDTTypeInfo {
905
- NativeType : simple ,
902
+ fields [i ] = UDTField {
903
+ Name : f .readString (),
904
+ Type : f .readTypeInfo (),
905
+ }
906
906
}
907
- udt .KeySpace = f .readString ()
908
- udt .Name = f .readString ()
909
-
907
+ return fields
908
+ case typeInfoType :
909
+ return f .readTypeInfo ()
910
+ case typeType :
911
+ return Type (f .readShort ())
912
+ case typeInfoListType :
910
913
n := f .readShort ()
911
- udt . Elements = make ([]UDTField , n )
914
+ types : = make ([]TypeInfo , n )
912
915
for i := 0 ; i < int (n ); i ++ {
913
- field := & udt .Elements [i ]
914
- field .Name = f .readString ()
915
- field .Type = f .readTypeInfo ()
916
+ types [i ] = f .readTypeInfo ()
916
917
}
918
+ return types
919
+ }
917
920
918
- return udt
919
- case TypeMap , TypeList , TypeSet :
920
- collection := CollectionType {
921
- NativeType : simple ,
921
+ // then check the kind and try to convert
922
+ switch typ .Kind () {
923
+ case reflect .String :
924
+ return reflect .ValueOf (f .readString ()).Convert (typ ).Interface ()
925
+ case reflect .Int :
926
+ return reflect .ValueOf (f .readInt ()).Convert (typ ).Interface ()
927
+ case reflect .Slice :
928
+ n := f .readShort ()
929
+ slice := reflect .MakeSlice (typ , int (n ), int (n ))
930
+ for i := 0 ; i < int (n ); i ++ {
931
+ slice .Index (i ).Set (reflect .ValueOf (f .readForType (typ .Elem ())))
922
932
}
933
+ return slice .Interface ()
934
+ }
935
+ panic (fmt .Errorf ("unsupported type for reading from frame: %s" , typ .String ()))
936
+ }
923
937
924
- if simple .typ == TypeMap {
925
- collection .Key = f .readTypeInfo ()
938
+ func (f * framer ) readTypeInfo () TypeInfo {
939
+ typ := Type (f .readShort ())
940
+
941
+ cqlct , ok := registeredCompositeTypes [typ ]
942
+ if ok {
943
+ paramsTypes := cqlct .Params (int (f .proto ))
944
+ var params []interface {}
945
+ if len (paramsTypes ) > 0 {
946
+ params = make ([]interface {}, len (paramsTypes ))
947
+ for i , paramType := range paramsTypes {
948
+ params [i ] = f .readForType (paramType )
949
+ }
926
950
}
951
+ return cqlct .TypeInfoParams (int (f .proto ), params )
952
+ }
927
953
928
- collection .Elem = f .readTypeInfo ()
929
-
930
- return collection
954
+ // custom is a special case, we need to read the name then get the type info
955
+ if typ == TypeCustom {
956
+ name := f .readString ()
957
+ return (customCQLType {}).TypeInfoParams (int (f .proto ), []interface {}{name })
931
958
}
932
959
933
- return simple
960
+ cqlt , ok := registeredTypes [typ ]
961
+ if ! ok {
962
+ panic (fmt .Errorf ("unknown type id: %d" , typ ))
963
+ }
964
+ return cqlt .TypeInfo (int (f .proto ))
934
965
}
935
966
936
967
type preparedMetadata struct {
0 commit comments