@@ -389,7 +389,7 @@ func compileMetadata(
389389 col .Order = DESC
390390 }
391391 } else {
392- validatorParsed := parseType (col .Validator , logger )
392+ validatorParsed := parseType (col .Validator , byte ( protoVersion ), logger )
393393 col .Type = validatorParsed .types [0 ]
394394 col .Order = ASC
395395 if validatorParsed .reversed [0 ] {
@@ -411,9 +411,9 @@ func compileMetadata(
411411 }
412412
413413 if protoVersion == protoVersion1 {
414- compileV1Metadata (tables , logger )
414+ compileV1Metadata (tables , protoVersion , logger )
415415 } else {
416- compileV2Metadata (tables , logger )
416+ compileV2Metadata (tables , protoVersion , logger )
417417 }
418418}
419419
@@ -422,14 +422,14 @@ func compileMetadata(
422422// column metadata as V2+ (because V1 doesn't support the "type" column in the
423423// system.schema_columns table) so determining PartitionKey and ClusterColumns
424424// is more complex.
425- func compileV1Metadata (tables []TableMetadata , logger StdLogger ) {
425+ func compileV1Metadata (tables []TableMetadata , protoVer int , logger StdLogger ) {
426426 for i := range tables {
427427 table := & tables [i ]
428428
429429 // decode the key validator
430- keyValidatorParsed := parseType (table .KeyValidator , logger )
430+ keyValidatorParsed := parseType (table .KeyValidator , byte ( protoVer ), logger )
431431 // decode the comparator
432- comparatorParsed := parseType (table .Comparator , logger )
432+ comparatorParsed := parseType (table .Comparator , byte ( protoVer ), logger )
433433
434434 // the partition key length is the same as the number of types in the
435435 // key validator
@@ -515,7 +515,7 @@ func compileV1Metadata(tables []TableMetadata, logger StdLogger) {
515515 alias = table .ValueAlias
516516 }
517517 // decode the default validator
518- defaultValidatorParsed := parseType (table .DefaultValidator , logger )
518+ defaultValidatorParsed := parseType (table .DefaultValidator , byte ( protoVer ), logger )
519519 column := & ColumnMetadata {
520520 Keyspace : table .Keyspace ,
521521 Table : table .Name ,
@@ -529,15 +529,15 @@ func compileV1Metadata(tables []TableMetadata, logger StdLogger) {
529529}
530530
531531// The simpler compile case for V2+ protocol
532- func compileV2Metadata (tables []TableMetadata , logger StdLogger ) {
532+ func compileV2Metadata (tables []TableMetadata , protoVer int , logger StdLogger ) {
533533 for i := range tables {
534534 table := & tables [i ]
535535
536536 clusteringColumnCount := componentColumnCountOfType (table .Columns , ColumnClusteringKey )
537537 table .ClusteringColumns = make ([]* ColumnMetadata , clusteringColumnCount )
538538
539539 if table .KeyValidator != "" {
540- keyValidatorParsed := parseType (table .KeyValidator , logger )
540+ keyValidatorParsed := parseType (table .KeyValidator , byte ( protoVer ), logger )
541541 table .PartitionKey = make ([]* ColumnMetadata , len (keyValidatorParsed .types ))
542542 } else { // Cassandra 3.x+
543543 partitionKeyCount := componentColumnCountOfType (table .Columns , ColumnPartitionKey )
@@ -1186,6 +1186,7 @@ type typeParser struct {
11861186 input string
11871187 index int
11881188 logger StdLogger
1189+ proto byte
11891190}
11901191
11911192// the type definition parser result
@@ -1197,8 +1198,8 @@ type typeParserResult struct {
11971198}
11981199
11991200// Parse the type definition used for validator and comparator schema data
1200- func parseType (def string , logger StdLogger ) typeParserResult {
1201- parser := & typeParser {input : def , logger : logger }
1201+ func parseType (def string , protoVer byte , logger StdLogger ) typeParserResult {
1202+ parser := & typeParser {input : def , proto : protoVer , logger : logger }
12021203 return parser .parse ()
12031204}
12041205
@@ -1209,6 +1210,7 @@ const (
12091210 LIST_TYPE = "org.apache.cassandra.db.marshal.ListType"
12101211 SET_TYPE = "org.apache.cassandra.db.marshal.SetType"
12111212 MAP_TYPE = "org.apache.cassandra.db.marshal.MapType"
1213+ UDT_TYPE = "org.apache.cassandra.db.marshal.UserType"
12121214 VECTOR_TYPE = "org.apache.cassandra.db.marshal.VectorType"
12131215)
12141216
@@ -1218,6 +1220,7 @@ type typeParserClassNode struct {
12181220 params []typeParserParamNode
12191221 // this is the segment of the input string that defined this node
12201222 input string
1223+ proto byte
12211224}
12221225
12231226// represents a class parameter in the type def AST
@@ -1237,6 +1240,7 @@ func (t *typeParser) parse() typeParserResult {
12371240 NativeType {
12381241 typ : TypeCustom ,
12391242 custom : t .input ,
1243+ proto : t .proto ,
12401244 },
12411245 },
12421246 reversed : []bool {false },
@@ -1292,6 +1296,26 @@ func (t *typeParser) parse() typeParserResult {
12921296 reversed : reversed ,
12931297 collections : collections ,
12941298 }
1299+ } else if strings .HasPrefix (ast .name , VECTOR_TYPE ) {
1300+ count := len (ast .params )
1301+
1302+ types := make ([]TypeInfo , count )
1303+ reversed := make ([]bool , count )
1304+
1305+ for i , param := range ast .params [:count ] {
1306+ class := param .class
1307+ reversed [i ] = strings .HasPrefix (class .name , REVERSED_TYPE )
1308+ if reversed [i ] {
1309+ class = class .params [0 ].class
1310+ }
1311+ types [i ] = class .asTypeInfo ()
1312+ }
1313+
1314+ return typeParserResult {
1315+ isComposite : true ,
1316+ types : types ,
1317+ reversed : reversed ,
1318+ }
12951319 } else {
12961320 // not composite, so one type
12971321 class := * ast
@@ -1314,7 +1338,8 @@ func (class *typeParserClassNode) asTypeInfo() TypeInfo {
13141338 elem := class .params [0 ].class .asTypeInfo ()
13151339 return CollectionType {
13161340 NativeType : NativeType {
1317- typ : TypeList ,
1341+ typ : TypeList ,
1342+ proto : class .proto ,
13181343 },
13191344 Elem : elem ,
13201345 }
@@ -1323,7 +1348,8 @@ func (class *typeParserClassNode) asTypeInfo() TypeInfo {
13231348 elem := class .params [0 ].class .asTypeInfo ()
13241349 return CollectionType {
13251350 NativeType : NativeType {
1326- typ : TypeSet ,
1351+ typ : TypeSet ,
1352+ proto : class .proto ,
13271353 },
13281354 Elem : elem ,
13291355 }
@@ -1333,15 +1359,47 @@ func (class *typeParserClassNode) asTypeInfo() TypeInfo {
13331359 elem := class .params [1 ].class .asTypeInfo ()
13341360 return CollectionType {
13351361 NativeType : NativeType {
1336- typ : TypeMap ,
1362+ typ : TypeMap ,
1363+ proto : class .proto ,
13371364 },
13381365 Key : key ,
13391366 Elem : elem ,
13401367 }
13411368 }
1369+ if strings .HasPrefix (class .name , UDT_TYPE ) {
1370+ udtName , _ := hex .DecodeString (class .params [1 ].class .name )
1371+ fields := make ([]UDTField , len (class .params )- 2 )
1372+ for i := 2 ; i < len (class .params ); i ++ {
1373+ fieldName , _ := hex .DecodeString (* class .params [i ].name )
1374+ fields [i - 2 ] = UDTField {
1375+ Name : string (fieldName ),
1376+ Type : class .params [i ].class .asTypeInfo (),
1377+ }
1378+ }
1379+ return UDTTypeInfo {
1380+ NativeType : NativeType {
1381+ typ : TypeUDT ,
1382+ proto : class .proto ,
1383+ },
1384+ KeySpace : class .params [0 ].class .name ,
1385+ Name : string (udtName ),
1386+ Elements : fields ,
1387+ }
1388+ }
1389+ if strings .HasPrefix (class .name , VECTOR_TYPE ) {
1390+ dim , _ := strconv .Atoi (class .params [1 ].class .name )
1391+ return VectorType {
1392+ NativeType : NativeType {
1393+ typ : TypeCustom ,
1394+ proto : class .proto ,
1395+ },
1396+ SubType : class .params [0 ].class .asTypeInfo (),
1397+ Dimensions : dim ,
1398+ }
1399+ }
13421400
13431401 // must be a simple type or custom type
1344- info := NativeType {typ : getApacheCassandraType (class .name )}
1402+ info := NativeType {typ : getApacheCassandraType (class .name ), proto : class . proto }
13451403 if info .typ == TypeCustom {
13461404 // add the entire class definition
13471405 info .custom = class .input
@@ -1371,6 +1429,7 @@ func (t *typeParser) parseClassNode() (node *typeParserClassNode, ok bool) {
13711429 name : name ,
13721430 params : params ,
13731431 input : t .input [startIndex :endIndex ],
1432+ proto : t .proto ,
13741433 }
13751434 return node , true
13761435}
0 commit comments