Skip to content

Commit d32a392

Browse files
lukasz-antoniakjoao-r-reis
authored andcommitted
CASSGO-11 Support vector type
Support marshalling and unmarshalling of vector custom type. patched by Lukasz Antoniak; reviewed by João Reis, Stanislav Bychkov, Oleksandr Luzhniy, Mykyta Oleksiienko and Bohdan Siryk for CASSGO-11
1 parent c75ff5f commit d32a392

File tree

12 files changed

+911
-99
lines changed

12 files changed

+911
-99
lines changed

.github/workflows/main.yml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ on:
88
types: [ opened, synchronize, reopened ]
99

1010
env:
11-
CCM_VERSION: "6e71061146f7ae67b84ccd2b1d90d7319b640e4c"
11+
CCM_VERSION: "4621dfee5ad73956b831091a8b863d100d25c610"
1212

1313
jobs:
1414
build:
@@ -35,7 +35,7 @@ jobs:
3535
fail-fast: false
3636
matrix:
3737
go: [ '1.22', '1.23' ]
38-
cassandra_version: [ '4.0.13', '4.1.6' ]
38+
cassandra_version: [ '4.1.6', '5.0.3' ]
3939
auth: [ "false" ]
4040
compressor: [ "no-compression", "snappy", "lz4" ]
4141
tags: [ "cassandra", "integration", "ccm" ]

CHANGELOG.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
99

1010
### Added
1111

12+
- Support vector type [CASSGO-11](https://issues.apache.org/jira/browse/CASSGO-11)
13+
1214
- Allow SERIAL and LOCAL_SERIAL on SELECT statements [CASSGO-26](https://issues.apache.org/jira/browse/CASSGO-26)
1315

1416
- Support of sending queries to the specific node with Query.SetHostID() (CASSGO-4)

cassandra_test.go

Lines changed: 30 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -481,15 +481,15 @@ func TestCAS(t *testing.T) {
481481
}
482482

483483
insertBatch := session.Batch(LoggedBatch)
484-
insertBatch.Query("INSERT INTO cas_table (title, revid, last_modified) VALUES ('_foo', 2c3af400-73a4-11e5-9381-29463d90c3f0, DATEOF(NOW()))")
485-
insertBatch.Query("INSERT INTO cas_table (title, revid, last_modified) VALUES ('_foo', 3e4ad2f1-73a4-11e5-9381-29463d90c3f0, DATEOF(NOW()))")
484+
insertBatch.Query("INSERT INTO cas_table (title, revid, last_modified) VALUES ('_foo', 2c3af400-73a4-11e5-9381-29463d90c3f0, TOTIMESTAMP(NOW()))")
485+
insertBatch.Query("INSERT INTO cas_table (title, revid, last_modified) VALUES ('_foo', 3e4ad2f1-73a4-11e5-9381-29463d90c3f0, TOTIMESTAMP(NOW()))")
486486
if err := session.ExecuteBatch(insertBatch); err != nil {
487487
t.Fatal("insert:", err)
488488
}
489489

490490
failBatch = session.Batch(LoggedBatch)
491-
failBatch.Query("UPDATE cas_table SET last_modified = DATEOF(NOW()) WHERE title='_foo' AND revid=2c3af400-73a4-11e5-9381-29463d90c3f0 IF last_modified=DATEOF(NOW());")
492-
failBatch.Query("UPDATE cas_table SET last_modified = DATEOF(NOW()) WHERE title='_foo' AND revid=3e4ad2f1-73a4-11e5-9381-29463d90c3f0 IF last_modified=DATEOF(NOW());")
491+
failBatch.Query("UPDATE cas_table SET last_modified = TOTIMESTAMP(NOW()) WHERE title='_foo' AND revid=2c3af400-73a4-11e5-9381-29463d90c3f0 IF last_modified=TOTIMESTAMP(NOW());")
492+
failBatch.Query("UPDATE cas_table SET last_modified = TOTIMESTAMP(NOW()) WHERE title='_foo' AND revid=3e4ad2f1-73a4-11e5-9381-29463d90c3f0 IF last_modified=TOTIMESTAMP(NOW());")
493493
if applied, iter, err := session.ExecuteBatchCAS(failBatch, &titleCAS, &revidCAS, &modifiedCAS); err != nil {
494494
t.Fatal("insert:", err)
495495
} else if applied {
@@ -533,21 +533,21 @@ func TestCAS(t *testing.T) {
533533
}
534534

535535
failBatch = session.Batch(LoggedBatch)
536-
failBatch.Query("UPDATE cas_table SET last_modified = DATEOF(NOW()) WHERE title='_foo' AND revid=3e4ad2f1-73a4-11e5-9381-29463d90c3f0 IF last_modified = ?", modified)
536+
failBatch.Query("UPDATE cas_table SET last_modified = TOTIMESTAMP(NOW()) WHERE title='_foo' AND revid=3e4ad2f1-73a4-11e5-9381-29463d90c3f0 IF last_modified = ?", modified)
537537
if _, _, err := session.ExecuteBatchCAS(failBatch, new(bool)); err == nil {
538538
t.Fatal("update should have errored")
539539
}
540540
// make sure MapScanCAS does not panic when MapScan fails
541541
casMap = make(map[string]interface{})
542542
casMap["last_modified"] = false
543-
if _, err := session.Query(`UPDATE cas_table SET last_modified = DATEOF(NOW()) WHERE title='_foo' AND revid=3e4ad2f1-73a4-11e5-9381-29463d90c3f0 IF last_modified = ?`,
543+
if _, err := session.Query(`UPDATE cas_table SET last_modified = TOTIMESTAMP(NOW()) WHERE title='_foo' AND revid=3e4ad2f1-73a4-11e5-9381-29463d90c3f0 IF last_modified = ?`,
544544
modified).MapScanCAS(casMap); err == nil {
545545
t.Fatal("update should hvae errored", err)
546546
}
547547

548548
// make sure MapExecuteBatchCAS does not panic when MapScan fails
549549
failBatch = session.Batch(LoggedBatch)
550-
failBatch.Query("UPDATE cas_table SET last_modified = DATEOF(NOW()) WHERE title='_foo' AND revid=3e4ad2f1-73a4-11e5-9381-29463d90c3f0 IF last_modified = ?", modified)
550+
failBatch.Query("UPDATE cas_table SET last_modified = TOTIMESTAMP(NOW()) WHERE title='_foo' AND revid=3e4ad2f1-73a4-11e5-9381-29463d90c3f0 IF last_modified = ?", modified)
551551
casMap = make(map[string]interface{})
552552
casMap["last_modified"] = false
553553
if _, _, err := session.MapExecuteBatchCAS(failBatch, casMap); err == nil {
@@ -2516,18 +2516,19 @@ func TestAggregateMetadata(t *testing.T) {
25162516
t.Fatal("expected two aggregates")
25172517
}
25182518

2519+
protoVer := byte(session.cfg.ProtoVersion)
25192520
expectedAggregrate := AggregateMetadata{
25202521
Keyspace: "gocql_test",
25212522
Name: "average",
2522-
ArgumentTypes: []TypeInfo{NativeType{typ: TypeInt}},
2523+
ArgumentTypes: []TypeInfo{NativeType{typ: TypeInt, proto: protoVer}},
25232524
InitCond: "(0, 0)",
2524-
ReturnType: NativeType{typ: TypeDouble},
2525+
ReturnType: NativeType{typ: TypeDouble, proto: protoVer},
25252526
StateType: TupleTypeInfo{
2526-
NativeType: NativeType{typ: TypeTuple},
2527+
NativeType: NativeType{typ: TypeTuple, proto: protoVer},
25272528

25282529
Elems: []TypeInfo{
2529-
NativeType{typ: TypeInt},
2530-
NativeType{typ: TypeBigInt},
2530+
NativeType{typ: TypeInt, proto: protoVer},
2531+
NativeType{typ: TypeBigInt, proto: protoVer},
25312532
},
25322533
},
25332534
stateFunc: "avgstate",
@@ -2566,28 +2567,29 @@ func TestFunctionMetadata(t *testing.T) {
25662567
avgState := functions[1]
25672568
avgFinal := functions[0]
25682569

2570+
protoVer := byte(session.cfg.ProtoVersion)
25692571
avgStateBody := "if (val !=null) {state.setInt(0, state.getInt(0)+1); state.setLong(1, state.getLong(1)+val.intValue());}return state;"
25702572
expectedAvgState := FunctionMetadata{
25712573
Keyspace: "gocql_test",
25722574
Name: "avgstate",
25732575
ArgumentTypes: []TypeInfo{
25742576
TupleTypeInfo{
2575-
NativeType: NativeType{typ: TypeTuple},
2577+
NativeType: NativeType{typ: TypeTuple, proto: protoVer},
25762578

25772579
Elems: []TypeInfo{
2578-
NativeType{typ: TypeInt},
2579-
NativeType{typ: TypeBigInt},
2580+
NativeType{typ: TypeInt, proto: protoVer},
2581+
NativeType{typ: TypeBigInt, proto: protoVer},
25802582
},
25812583
},
2582-
NativeType{typ: TypeInt},
2584+
NativeType{typ: TypeInt, proto: protoVer},
25832585
},
25842586
ArgumentNames: []string{"state", "val"},
25852587
ReturnType: TupleTypeInfo{
2586-
NativeType: NativeType{typ: TypeTuple},
2588+
NativeType: NativeType{typ: TypeTuple, proto: protoVer},
25872589

25882590
Elems: []TypeInfo{
2589-
NativeType{typ: TypeInt},
2590-
NativeType{typ: TypeBigInt},
2591+
NativeType{typ: TypeInt, proto: protoVer},
2592+
NativeType{typ: TypeBigInt, proto: protoVer},
25912593
},
25922594
},
25932595
CalledOnNullInput: true,
@@ -2604,16 +2606,16 @@ func TestFunctionMetadata(t *testing.T) {
26042606
Name: "avgfinal",
26052607
ArgumentTypes: []TypeInfo{
26062608
TupleTypeInfo{
2607-
NativeType: NativeType{typ: TypeTuple},
2609+
NativeType: NativeType{typ: TypeTuple, proto: protoVer},
26082610

26092611
Elems: []TypeInfo{
2610-
NativeType{typ: TypeInt},
2611-
NativeType{typ: TypeBigInt},
2612+
NativeType{typ: TypeInt, proto: protoVer},
2613+
NativeType{typ: TypeBigInt, proto: protoVer},
26122614
},
26132615
},
26142616
},
26152617
ArgumentNames: []string{"state"},
2616-
ReturnType: NativeType{typ: TypeDouble},
2618+
ReturnType: NativeType{typ: TypeDouble, proto: protoVer},
26172619
CalledOnNullInput: true,
26182620
Language: "java",
26192621
Body: finalStateBody,
@@ -2717,15 +2719,16 @@ func TestKeyspaceMetadata(t *testing.T) {
27172719
if flagCassVersion.Before(3, 0, 0) {
27182720
textType = TypeVarchar
27192721
}
2722+
protoVer := byte(session.cfg.ProtoVersion)
27202723
expectedType := UserTypeMetadata{
27212724
Keyspace: "gocql_test",
27222725
Name: "basicview",
27232726
FieldNames: []string{"birthday", "nationality", "weight", "height"},
27242727
FieldTypes: []TypeInfo{
2725-
NativeType{typ: TypeTimestamp},
2726-
NativeType{typ: textType},
2727-
NativeType{typ: textType},
2728-
NativeType{typ: textType},
2728+
NativeType{typ: TypeTimestamp, proto: protoVer},
2729+
NativeType{typ: textType, proto: protoVer},
2730+
NativeType{typ: textType, proto: protoVer},
2731+
NativeType{typ: textType, proto: protoVer},
27292732
},
27302733
}
27312734
if !reflect.DeepEqual(*keyspaceMetadata.UserTypes["basicview"], expectedType) {

common_test.go

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ import (
2828
"flag"
2929
"fmt"
3030
"log"
31+
"math/rand"
3132
"net"
3233
"reflect"
3334
"strings"
@@ -54,6 +55,10 @@ var (
5455
flagCassVersion cassVersion
5556
)
5657

58+
var seededRand *rand.Rand = rand.New(rand.NewSource(time.Now().UnixNano()))
59+
60+
const randCharset = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"
61+
5762
func init() {
5863
flag.Var(&flagCassVersion, "gocql.cversion", "the cassandra version being tested against")
5964

@@ -281,6 +286,14 @@ func assertTrue(t *testing.T, description string, value bool) {
281286
}
282287
}
283288

289+
func randomText(size int) string {
290+
result := make([]byte, size)
291+
for i := range result {
292+
result[i] = randCharset[rand.Intn(len(randCharset))]
293+
}
294+
return string(result)
295+
}
296+
284297
func assertEqual(t *testing.T, description string, expected, actual interface{}) {
285298
t.Helper()
286299
if expected != actual {

frame.go

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@ import (
3434
"io/ioutil"
3535
"net"
3636
"runtime"
37+
"strconv"
3738
"strings"
3839
"time"
3940
)
@@ -905,6 +906,22 @@ func (f *framer) readTypeInfo() TypeInfo {
905906
collection.Elem = f.readTypeInfo()
906907

907908
return collection
909+
case TypeCustom:
910+
if strings.HasPrefix(simple.custom, VECTOR_TYPE) {
911+
spec := strings.TrimPrefix(simple.custom, VECTOR_TYPE)
912+
spec = spec[1 : len(spec)-1] // remove parenthesis
913+
idx := strings.LastIndex(spec, ",")
914+
typeStr := spec[:idx]
915+
dimStr := spec[idx+1:]
916+
subType := getCassandraLongType(strings.TrimSpace(typeStr), f.proto, nopLogger{})
917+
dim, _ := strconv.Atoi(strings.TrimSpace(dimStr))
918+
vector := VectorType{
919+
NativeType: simple,
920+
SubType: subType,
921+
Dimensions: dim,
922+
}
923+
return vector
924+
}
908925
}
909926

910927
return simple

0 commit comments

Comments
 (0)