diff --git a/marshal.go b/marshal.go index 0592457fc..fdc6a6b0c 100644 --- a/marshal.go +++ b/marshal.go @@ -1914,8 +1914,9 @@ func unmarshalTuple(info TypeInfo, data []byte, value interface{}) error { for i, elem := range tuple.Elems { // each element inside data is a [bytes] var p []byte - p, data = readBytes(data) - + if len(data) > 4 { + p, data = readBytes(data) + } err := Unmarshal(elem, p, v[i]) if err != nil { return err diff --git a/tuple_test.go b/tuple_test.go index 9a6928875..06117c1f0 100644 --- a/tuple_test.go +++ b/tuple_test.go @@ -89,6 +89,45 @@ func TestTuple_NullTuple(t *testing.T) { } +func TestTuple_TupleNotSet(t *testing.T) { + session := createSession(t) + defer session.Close() + if session.cfg.ProtoVersion < protoVersion3 { + t.Skip("tuple types are only available of proto>=3") + } + + err := createTable(session, `CREATE TABLE gocql_test.tuple_not_set_test( + id int, + coord frozen>, + + primary key(id))`) + if err != nil { + t.Fatal(err) + } + + const id = 1 + + err = session.Query("INSERT INTO tuple_not_set_test(id) VALUES(?)", id).Exec() + if err != nil { + t.Fatal(err) + } + + x := new(int) + y := new(int) + iter := session.Query("SELECT coord FROM tuple_not_set_test WHERE id=?", id) + if err := iter.Scan(&x, &y); err != nil { + t.Fatal(err) + } + + if x != nil { + t.Fatalf("x should be nil got %+#v, value=%d", x, *x) + } + if y != nil { + t.Fatalf("y should be nil got %+#v, value=%d", y, *y) + } + +} + func TestTupleMapScan(t *testing.T) { session := createSession(t) defer session.Close() @@ -114,6 +153,74 @@ func TestTupleMapScan(t *testing.T) { if err != nil { t.Fatal(err) } + if m["val[0]"] != 1 { + t.Fatalf("expacted val[0] to be %d but was %d", 1, m["val[0]"]) + } + if m["val[1]"] != 2 { + t.Fatalf("expacted val[1] to be %d but was %d", 2, m["val[1]"]) + } +} + +func TestTupleMapScanNil(t *testing.T) { + session := createSession(t) + defer session.Close() + if session.cfg.ProtoVersion < protoVersion3 { + t.Skip("tuple types are only available of proto>=3") + } + err := createTable(session, `CREATE TABLE gocql_test.tuple_map_scan_nil( + id int, + val frozen>, + + primary key(id))`) + if err != nil { + t.Fatal(err) + } + if err := session.Query(`INSERT INTO tuple_map_scan_nil (id, val) VALUES (?,(?,?));`, 1, nil, nil).Exec(); err != nil { + t.Fatal(err) + } + + m := make(map[string]interface{}) + err = session.Query(`SELECT * FROM tuple_map_scan_nil`).MapScan(m) + if err != nil { + t.Fatal(err) + } + if m["val[0]"] != 0 { + t.Fatalf("expacted val[0] to be %d but was %d", 0, m["val[0]"]) + } + if m["val[1]"] != 0 { + t.Fatalf("expacted val[1] to be %d but was %d", 0, m["val[1]"]) + } +} + +func TestTupleMapScanNotSet(t *testing.T) { + session := createSession(t) + defer session.Close() + if session.cfg.ProtoVersion < protoVersion3 { + t.Skip("tuple types are only available of proto>=3") + } + err := createTable(session, `CREATE TABLE gocql_test.tuple_map_scan_not_set( + id int, + val frozen>, + + primary key(id))`) + if err != nil { + t.Fatal(err) + } + if err := session.Query(`INSERT INTO tuple_map_scan_not_set (id) VALUES (?);`, 1).Exec(); err != nil { + t.Fatal(err) + } + + m := make(map[string]interface{}) + err = session.Query(`SELECT * FROM tuple_map_scan_not_set`).MapScan(m) + if err != nil { + t.Fatal(err) + } + if m["val[0]"] != 0 { + t.Fatalf("expacted val[0] to be %d but was %d", 0, m["val[0]"]) + } + if m["val[1]"] != 0 { + t.Fatalf("expacted val[1] to be %d but was %d", 0, m["val[1]"]) + } } func TestTuple_NestedCollection(t *testing.T) {