Files
gocqlx/batchx_test.go

213 lines
6.1 KiB
Go

// Copyright (C) 2017 ScyllaDB
// Use of this source code is governed by a ALv2-style
// license that can be found in the LICENSE file.
//go:build all || integration
// +build all integration
package gocqlx_test
import (
"reflect"
"testing"
gocql "github.com/apache/cassandra-gocql-driver/v2"
"github.com/google/go-cmp/cmp"
"github.com/scylladb/gocqlx/v3"
"github.com/scylladb/gocqlx/v3/gocqlxtest"
"github.com/scylladb/gocqlx/v3/qb"
)
func TestBatch(t *testing.T) {
t.Parallel()
cluster := gocqlxtest.CreateCluster()
if err := gocqlxtest.CreateKeyspace(cluster, "batch_test"); err != nil {
t.Fatal("create keyspace:", err)
}
session, err := gocqlx.WrapSession(cluster.CreateSession())
if err != nil {
t.Fatal("create session:", err)
}
t.Cleanup(func() {
session.Close()
})
basicCreateAndPopulateKeyspace(t, session, "batch_test")
song := Song{
ID: mustParseUUID("60fc234a-8481-4343-93bb-72ecab404863"),
Title: "La Petite Tonkinoise",
Album: "Bye Bye Blackbird",
Artist: "Joséphine Baker",
Tags: []string{"jazz"},
Data: []byte("music"),
}
playlist := PlaylistItem{
ID: mustParseUUID("6a6255d9-680f-4cb5-b9a2-27cf4a810344"),
Title: "La Petite Tonkinoise",
Album: "Bye Bye Blackbird",
Artist: "Joséphine Baker",
SongID: mustParseUUID("60fc234a-8481-4343-93bb-72ecab404863"),
}
t.Run("batch inserts", func(t *testing.T) {
t.Parallel()
tcases := []struct {
name string
methodSong func(*gocqlx.Batch, *gocqlx.Queryx, Song) error
methodPlaylist func(*gocqlx.Batch, *gocqlx.Queryx, PlaylistItem) error
}{
{
name: "BindStruct",
methodSong: func(b *gocqlx.Batch, q *gocqlx.Queryx, song Song) error {
return b.BindStruct(q, song)
},
methodPlaylist: func(b *gocqlx.Batch, q *gocqlx.Queryx, playlist PlaylistItem) error {
return b.BindStruct(q, playlist)
},
},
{
name: "BindMap",
methodSong: func(b *gocqlx.Batch, q *gocqlx.Queryx, song Song) error {
return b.BindMap(q, map[string]interface{}{
"id": song.ID,
"title": song.Title,
"album": song.Album,
"artist": song.Artist,
"tags": song.Tags,
"data": song.Data,
})
},
methodPlaylist: func(b *gocqlx.Batch, q *gocqlx.Queryx, playlist PlaylistItem) error {
return b.BindMap(q, map[string]interface{}{
"id": playlist.ID,
"title": playlist.Title,
"album": playlist.Album,
"artist": playlist.Artist,
"song_id": playlist.SongID,
})
},
},
{
name: "Bind",
methodSong: func(b *gocqlx.Batch, q *gocqlx.Queryx, song Song) error {
return b.Bind(q, song.ID, song.Title, song.Album, song.Artist, song.Tags, song.Data)
},
methodPlaylist: func(b *gocqlx.Batch, q *gocqlx.Queryx, playlist PlaylistItem) error {
return b.Bind(q, playlist.ID, playlist.Title, playlist.Album, playlist.Artist, playlist.SongID)
},
},
{
name: "BindStructMap",
methodSong: func(b *gocqlx.Batch, q *gocqlx.Queryx, song Song) error {
in := map[string]interface{}{
"title": song.Title,
"album": song.Album,
}
return b.BindStructMap(q, struct {
ID gocql.UUID
Artist string
Tags []string
Data []byte
}{
ID: song.ID,
Artist: song.Artist,
Tags: song.Tags,
Data: song.Data,
}, in)
},
methodPlaylist: func(b *gocqlx.Batch, q *gocqlx.Queryx, playlist PlaylistItem) error {
in := map[string]interface{}{
"title": playlist.Title,
"album": playlist.Album,
}
return b.BindStructMap(q, struct {
ID gocql.UUID
Artist string
SongID gocql.UUID
}{
ID: playlist.ID,
Artist: playlist.Artist,
SongID: playlist.SongID,
},
in,
)
},
},
}
for _, tcase := range tcases {
t.Run(tcase.name, func(t *testing.T) {
insertSong := qb.Insert("batch_test.songs").
Columns("id", "title", "album", "artist", "tags", "data").Query(session)
insertPlaylist := qb.Insert("batch_test.playlists").
Columns("id", "title", "album", "artist", "song_id").Query(session)
selectSong := qb.Select("batch_test.songs").Where(qb.Eq("id")).Query(session)
selectPlaylist := qb.Select("batch_test.playlists").Where(qb.Eq("id")).Query(session)
deleteSong := qb.Delete("batch_test.songs").Where(qb.Eq("id")).Query(session)
deletePlaylist := qb.Delete("batch_test.playlists").Where(qb.Eq("id")).Query(session)
b := session.NewBatch(gocql.LoggedBatch)
if err = tcase.methodSong(b, insertSong, song); err != nil {
t.Fatal("insert song:", err)
}
if err = tcase.methodPlaylist(b, insertPlaylist, playlist); err != nil {
t.Fatal("insert playList:", err)
}
if err := session.ExecuteBatch(b); err != nil {
t.Fatal("batch execution:", err)
}
// verify song was inserted
var gotSong Song
if err := selectSong.BindStruct(song).Get(&gotSong); err != nil {
t.Fatal("select song:", err)
}
if diff := cmp.Diff(gotSong, song); diff != "" {
t.Errorf("expected %v song, got %v, diff: %q", song, gotSong, diff)
}
// verify playlist item was inserted
var gotPlayList PlaylistItem
if err := selectPlaylist.BindStruct(playlist).Get(&gotPlayList); err != nil {
t.Fatal("select playList:", err)
}
if diff := cmp.Diff(gotPlayList, playlist); diff != "" {
t.Errorf("expected %v playList, got %v, diff: %q", playlist, gotPlayList, diff)
}
if err = deletePlaylist.BindStruct(playlist).Exec(); err != nil {
t.Error("delete playlist:", err)
}
if err = deleteSong.BindStruct(song).Exec(); err != nil {
t.Error("delete song:", err)
}
})
}
})
}
func TestBatchAllWrapped(t *testing.T) {
var (
gocqlType = reflect.TypeOf((*gocql.Batch)(nil))
gocqlxType = reflect.TypeOf((*gocqlx.Batch)(nil))
)
for i := 0; i < gocqlType.NumMethod(); i++ {
m, ok := gocqlxType.MethodByName(gocqlType.Method(i).Name)
if !ok {
t.Fatalf("Batch missing method %s", gocqlType.Method(i).Name)
}
for j := 0; j < m.Type.NumOut(); j++ {
if m.Type.Out(j) == gocqlType {
t.Errorf("Batch method %s not wrapped", m.Name)
}
}
}
}