| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426 |
- // +build all integration
- package gocql
- import (
- "fmt"
- "strings"
- "testing"
- "time"
- )
- type position struct {
- Lat int `cql:"lat"`
- Lon int `cql:"lon"`
- Padding string `json:"padding"`
- }
- // NOTE: due to current implementation details it is not currently possible to use
- // a pointer receiver type for the UDTMarshaler interface to handle UDT's
- func (p position) MarshalUDT(name string, info TypeInfo) ([]byte, error) {
- switch name {
- case "lat":
- return Marshal(info, p.Lat)
- case "lon":
- return Marshal(info, p.Lon)
- case "padding":
- return Marshal(info, p.Padding)
- default:
- return nil, fmt.Errorf("unknown column for position: %q", name)
- }
- }
- func (p *position) UnmarshalUDT(name string, info TypeInfo, data []byte) error {
- switch name {
- case "lat":
- return Unmarshal(info, data, &p.Lat)
- case "lon":
- return Unmarshal(info, data, &p.Lon)
- case "padding":
- return Unmarshal(info, data, &p.Padding)
- default:
- return fmt.Errorf("unknown column for position: %q", name)
- }
- }
- func TestUDT_Marshaler(t *testing.T) {
- if *flagProto < protoVersion3 {
- t.Skip("UDT are only available on protocol >= 3")
- }
- session := createSession(t)
- defer session.Close()
- err := createTable(session, `CREATE TYPE gocql_test.position(
- lat int,
- lon int,
- padding text);`)
- if err != nil {
- t.Fatal(err)
- }
- err = createTable(session, `CREATE TABLE gocql_test.houses(
- id int,
- name text,
- loc frozen<position>,
- primary key(id)
- );`)
- if err != nil {
- t.Fatal(err)
- }
- const (
- expLat = -1
- expLon = 2
- )
- pad := strings.Repeat("X", 1000)
- err = session.Query("INSERT INTO houses(id, name, loc) VALUES(?, ?, ?)", 1, "test", &position{expLat, expLon, pad}).Exec()
- if err != nil {
- t.Fatal(err)
- }
- pos := &position{}
- err = session.Query("SELECT loc FROM houses WHERE id = ?", 1).Scan(pos)
- if err != nil {
- t.Fatal(err)
- }
- if pos.Lat != expLat {
- t.Errorf("expeceted lat to be be %d got %d", expLat, pos.Lat)
- }
- if pos.Lon != expLon {
- t.Errorf("expeceted lon to be be %d got %d", expLon, pos.Lon)
- }
- if pos.Padding != pad {
- t.Errorf("expected to get padding %q got %q\n", pad, pos.Padding)
- }
- }
- func TestUDT_Reflect(t *testing.T) {
- if *flagProto < protoVersion3 {
- t.Skip("UDT are only available on protocol >= 3")
- }
- // Uses reflection instead of implementing the marshaling type
- session := createSession(t)
- defer session.Close()
- err := createTable(session, `CREATE TYPE gocql_test.horse(
- name text,
- owner text);`)
- if err != nil {
- t.Fatal(err)
- }
- err = createTable(session, `CREATE TABLE gocql_test.horse_race(
- position int,
- horse frozen<horse>,
- primary key(position)
- );`)
- if err != nil {
- t.Fatal(err)
- }
- type horse struct {
- Name string `cql:"name"`
- Owner string `cql:"owner"`
- }
- insertedHorse := &horse{
- Name: "pony",
- Owner: "jim",
- }
- err = session.Query("INSERT INTO horse_race(position, horse) VALUES(?, ?)", 1, insertedHorse).Exec()
- if err != nil {
- t.Fatal(err)
- }
- retrievedHorse := &horse{}
- err = session.Query("SELECT horse FROM horse_race WHERE position = ?", 1).Scan(retrievedHorse)
- if err != nil {
- t.Fatal(err)
- }
- if *retrievedHorse != *insertedHorse {
- t.Fatal("exepcted to get %+v got %+v", insertedHorse, retrievedHorse)
- }
- }
- func TestUDT_Proto2error(t *testing.T) {
- if *flagProto < protoVersion3 {
- t.Skip("UDT are only available on protocol >= 3")
- }
- cluster := createCluster()
- cluster.ProtoVersion = 2
- cluster.Keyspace = "gocql_test"
- // Uses reflection instead of implementing the marshaling type
- session, err := cluster.CreateSession()
- if err != nil {
- t.Fatal(err)
- }
- defer session.Close()
- err = createTable(session, `CREATE TYPE gocql_test.fish(
- name text,
- owner text);`)
- if err != nil {
- t.Fatal(err)
- }
- err = createTable(session, `CREATE TABLE gocql_test.fish_race(
- position int,
- fish frozen<fish>,
- primary key(position)
- );`)
- if err != nil {
- t.Fatal(err)
- }
- type fish struct {
- Name string `cql:"name"`
- Owner string `cql:"owner"`
- }
- insertedFish := &fish{
- Name: "pony",
- Owner: "jim",
- }
- err = session.Query("INSERT INTO fish_race(position, fish) VALUES(?, ?)", 1, insertedFish).Exec()
- if err != ErrorUDTUnavailable {
- t.Fatalf("expected to get %v got %v", ErrorUDTUnavailable, err)
- }
- }
- func TestUDT_NullObject(t *testing.T) {
- if *flagProto < protoVersion3 {
- t.Skip("UDT are only available on protocol >= 3")
- }
- session := createSession(t)
- defer session.Close()
- err := createTable(session, `CREATE TYPE gocql_test.udt_null_type(
- name text,
- owner text);`)
- if err != nil {
- t.Fatal(err)
- }
- err = createTable(session, `CREATE TABLE gocql_test.udt_null_table(
- id uuid,
- udt_col frozen<udt_null_type>,
- primary key(id)
- );`)
- if err != nil {
- t.Fatal(err)
- }
- type col struct {
- Name string `cql:"name"`
- Owner string `cql:"owner"`
- }
- id := TimeUUID()
- err = session.Query("INSERT INTO udt_null_table(id) VALUES(?)", id).Exec()
- if err != nil {
- t.Fatal(err)
- }
- readCol := &col{
- Name: "temp",
- Owner: "temp",
- }
- err = session.Query("SELECT udt_col FROM udt_null_table WHERE id = ?", id).Scan(readCol)
- if err != nil {
- t.Fatal(err)
- }
- if readCol.Name != "" {
- t.Errorf("expected empty string to be returned for null udt: got %q", readCol.Name)
- }
- if readCol.Owner != "" {
- t.Errorf("expected empty string to be returned for null udt: got %q", readCol.Owner)
- }
- }
- func TestMapScanUDT(t *testing.T) {
- if *flagProto < protoVersion3 {
- t.Skip("UDT are only available on protocol >= 3")
- }
- session := createSession(t)
- defer session.Close()
- err := createTable(session, `CREATE TYPE gocql_test.log_entry (
- created_timestamp timestamp,
- message text
- );`)
- if err != nil {
- t.Fatal(err)
- }
- err = createTable(session, `CREATE TABLE gocql_test.requests_by_id (
- id uuid PRIMARY KEY,
- type int,
- log_entries list<frozen <log_entry>>
- );`)
- if err != nil {
- t.Fatal(err)
- }
- entry := []struct {
- CreatedTimestamp time.Time `cql:"created_timestamp"`
- Message string `cql:"message"`
- }{
- {
- CreatedTimestamp: time.Now().Truncate(time.Millisecond),
- Message: "test time now",
- },
- }
- id, _ := RandomUUID()
- const typ = 1
- err = session.Query("INSERT INTO requests_by_id(id, type, log_entries) VALUES (?, ?, ?)", id, typ, entry).Exec()
- if err != nil {
- t.Fatal(err)
- }
- rawResult := map[string]interface{}{}
- err = session.Query(`SELECT * FROM requests_by_id WHERE id = ?`, id).MapScan(rawResult)
- if err != nil {
- t.Fatal(err)
- }
- logEntries, ok := rawResult["log_entries"].([]map[string]interface{})
- if !ok {
- t.Fatal("log_entries not in scanned map")
- }
- if len(logEntries) != 1 {
- t.Fatalf("expected to get 1 log_entry got %d", len(logEntries))
- }
- logEntry := logEntries[0]
- timestamp, ok := logEntry["created_timestamp"]
- if !ok {
- t.Error("created_timestamp not unmarshalled into map")
- } else {
- if ts, ok := timestamp.(time.Time); ok {
- if !ts.In(time.UTC).Equal(entry[0].CreatedTimestamp.In(time.UTC)) {
- t.Errorf("created_timestamp not equal to stored: got %v expected %v", ts.In(time.UTC), entry[0].CreatedTimestamp.In(time.UTC))
- }
- } else {
- t.Errorf("created_timestamp was not time.Time got: %T", timestamp)
- }
- }
- message, ok := logEntry["message"]
- if !ok {
- t.Error("message not unmarshalled into map")
- } else {
- if ts, ok := message.(string); ok {
- if ts != message {
- t.Errorf("message not equal to stored: got %v expected %v", ts, entry[0].Message)
- }
- } else {
- t.Errorf("message was not string got: %T", message)
- }
- }
- }
- func TestUDT_MissingField(t *testing.T) {
- if *flagProto < protoVersion3 {
- t.Skip("UDT are only available on protocol >= 3")
- }
- session := createSession(t)
- defer session.Close()
- err := createTable(session, `CREATE TYPE gocql_test.missing_field(
- name text,
- owner text);`)
- if err != nil {
- t.Fatal(err)
- }
- err = createTable(session, `CREATE TABLE gocql_test.missing_field(
- id uuid,
- udt_col frozen<udt_null_type>,
- primary key(id)
- );`)
- if err != nil {
- t.Fatal(err)
- }
- type col struct {
- Name string `cql:"name"`
- }
- writeCol := &col{
- Name: "test",
- }
- id := TimeUUID()
- err = session.Query("INSERT INTO missing_field(id, udt_col) VALUES(?, ?)", id, writeCol).Exec()
- if err != nil {
- t.Fatal(err)
- }
- readCol := &col{}
- err = session.Query("SELECT udt_col FROM missing_field WHERE id = ?", id).Scan(readCol)
- if err != nil {
- t.Fatal(err)
- }
- if readCol.Name != writeCol.Name {
- t.Errorf("expected %q: got %q", writeCol.Name, readCol.Name)
- }
- }
- func TestUDT_EmptyCollections(t *testing.T) {
- if *flagProto < protoVersion3 {
- t.Skip("UDT are only available on protocol >= 3")
- }
- session := createSession(t)
- defer session.Close()
- err := createTable(session, `CREATE TYPE gocql_test.nil_collections(
- a list<text>,
- b map<text, text>,
- c set<text>
- );`)
- if err != nil {
- t.Fatal(err)
- }
- err = createTable(session, `CREATE TABLE gocql_test.nil_collections(
- id uuid,
- udt_col frozen<nil_collections>,
- primary key(id)
- );`)
- if err != nil {
- t.Fatal(err)
- }
- id := TimeUUID()
- err = session.Query("INSERT INTO nil_collections(id, udt_col) VALUES(?, ?)", id, &struct{}{}).Exec()
- if err != nil {
- t.Fatal(err)
- }
- }
|