When table is used with SelectBuilder it triggers data race on Where() condition usage. This change copies underlining slices on table creation to allow safe concurrent usage of the table.
280 lines
5.5 KiB
Go
280 lines
5.5 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.
|
|
|
|
package table
|
|
|
|
import (
|
|
"sync"
|
|
"testing"
|
|
|
|
"github.com/google/go-cmp/cmp"
|
|
"github.com/scylladb/gocqlx/qb"
|
|
)
|
|
|
|
func TestTableGet(t *testing.T) {
|
|
table := []struct {
|
|
M Metadata
|
|
C []string
|
|
N []string
|
|
S string
|
|
}{
|
|
{
|
|
M: Metadata{
|
|
Name: "table",
|
|
Columns: []string{"a", "b", "c", "d"},
|
|
PartKey: []string{"a"},
|
|
SortKey: []string{"b"},
|
|
},
|
|
N: []string{"a", "b"},
|
|
S: "SELECT * FROM table WHERE a=? AND b=? ",
|
|
},
|
|
{
|
|
M: Metadata{
|
|
Name: "table",
|
|
Columns: []string{"a", "b", "c", "d"},
|
|
PartKey: []string{"a"},
|
|
},
|
|
N: []string{"a"},
|
|
S: "SELECT * FROM table WHERE a=? ",
|
|
},
|
|
{
|
|
M: Metadata{
|
|
Name: "table",
|
|
Columns: []string{"a", "b", "c", "d"},
|
|
PartKey: []string{"a"},
|
|
},
|
|
C: []string{"d"},
|
|
N: []string{"a"},
|
|
S: "SELECT d FROM table WHERE a=? ",
|
|
},
|
|
}
|
|
|
|
for _, test := range table {
|
|
stmt, names := New(test.M).Get(test.C...)
|
|
if diff := cmp.Diff(test.S, stmt); diff != "" {
|
|
t.Error(diff)
|
|
}
|
|
if diff := cmp.Diff(test.N, names); diff != "" {
|
|
t.Error(diff, names)
|
|
}
|
|
}
|
|
}
|
|
|
|
func TestTableSelect(t *testing.T) {
|
|
table := []struct {
|
|
M Metadata
|
|
C []string
|
|
N []string
|
|
S string
|
|
}{
|
|
{
|
|
M: Metadata{
|
|
Name: "table",
|
|
Columns: []string{"a", "b", "c", "d"},
|
|
PartKey: []string{"a"},
|
|
SortKey: []string{"b"},
|
|
},
|
|
N: []string{"a"},
|
|
S: "SELECT * FROM table WHERE a=? ",
|
|
},
|
|
{
|
|
M: Metadata{
|
|
Name: "table",
|
|
Columns: []string{"a", "b", "c", "d"},
|
|
PartKey: []string{"a"},
|
|
SortKey: []string{"b"},
|
|
},
|
|
C: []string{"d"},
|
|
N: []string{"a"},
|
|
S: "SELECT d FROM table WHERE a=? ",
|
|
},
|
|
}
|
|
|
|
for _, test := range table {
|
|
stmt, names := New(test.M).Select(test.C...)
|
|
if diff := cmp.Diff(test.S, stmt); diff != "" {
|
|
t.Error(diff)
|
|
}
|
|
if diff := cmp.Diff(test.N, names); diff != "" {
|
|
t.Error(diff, names)
|
|
}
|
|
}
|
|
|
|
// run SelectBuilder on the same data set
|
|
for _, test := range table {
|
|
stmt, names := New(test.M).SelectBuilder(test.C...).ToCql()
|
|
if diff := cmp.Diff(test.S, stmt); diff != "" {
|
|
t.Error(diff)
|
|
}
|
|
if diff := cmp.Diff(test.N, names); diff != "" {
|
|
t.Error(diff, names)
|
|
}
|
|
}
|
|
}
|
|
|
|
func TestTableInsert(t *testing.T) {
|
|
table := []struct {
|
|
M Metadata
|
|
N []string
|
|
S string
|
|
}{
|
|
{
|
|
M: Metadata{
|
|
Name: "table",
|
|
Columns: []string{"a", "b", "c", "d"},
|
|
PartKey: []string{"a"},
|
|
SortKey: []string{"b"},
|
|
},
|
|
N: []string{"a", "b", "c", "d"},
|
|
S: "INSERT INTO table (a,b,c,d) VALUES (?,?,?,?) ",
|
|
},
|
|
}
|
|
|
|
for _, test := range table {
|
|
stmt, names := New(test.M).Insert()
|
|
if diff := cmp.Diff(test.S, stmt); diff != "" {
|
|
t.Error(diff)
|
|
}
|
|
if diff := cmp.Diff(test.N, names); diff != "" {
|
|
t.Error(diff, names)
|
|
}
|
|
}
|
|
}
|
|
|
|
func TestTableUpdate(t *testing.T) {
|
|
table := []struct {
|
|
M Metadata
|
|
C []string
|
|
N []string
|
|
S string
|
|
}{
|
|
{
|
|
M: Metadata{
|
|
Name: "table",
|
|
Columns: []string{"a", "b", "c", "d"},
|
|
PartKey: []string{"a"},
|
|
SortKey: []string{"b"},
|
|
},
|
|
C: []string{"d"},
|
|
N: []string{"d", "a", "b"},
|
|
S: "UPDATE table SET d=? WHERE a=? AND b=? ",
|
|
},
|
|
}
|
|
|
|
for _, test := range table {
|
|
stmt, names := New(test.M).Update(test.C...)
|
|
if diff := cmp.Diff(test.S, stmt); diff != "" {
|
|
t.Error(diff)
|
|
}
|
|
if diff := cmp.Diff(test.N, names); diff != "" {
|
|
t.Error(diff, names)
|
|
}
|
|
}
|
|
}
|
|
|
|
func TestTableDelete(t *testing.T) {
|
|
table := []struct {
|
|
M Metadata
|
|
C []string
|
|
N []string
|
|
S string
|
|
}{
|
|
{
|
|
M: Metadata{
|
|
Name: "table",
|
|
Columns: []string{"a", "b", "c", "d"},
|
|
PartKey: []string{"a"},
|
|
SortKey: []string{"b"},
|
|
},
|
|
N: []string{"a", "b"},
|
|
S: "DELETE FROM table WHERE a=? AND b=? ",
|
|
},
|
|
{
|
|
M: Metadata{
|
|
Name: "table",
|
|
Columns: []string{"a", "b", "c", "d"},
|
|
PartKey: []string{"a"},
|
|
},
|
|
N: []string{"a"},
|
|
S: "DELETE FROM table WHERE a=? ",
|
|
},
|
|
{
|
|
M: Metadata{
|
|
Name: "table",
|
|
Columns: []string{"a", "b", "c", "d"},
|
|
PartKey: []string{"a"},
|
|
},
|
|
C: []string{"d"},
|
|
N: []string{"a"},
|
|
S: "DELETE d FROM table WHERE a=? ",
|
|
},
|
|
}
|
|
|
|
for _, test := range table {
|
|
stmt, names := New(test.M).Delete(test.C...)
|
|
if diff := cmp.Diff(test.S, stmt); diff != "" {
|
|
t.Error(diff)
|
|
}
|
|
if diff := cmp.Diff(test.N, names); diff != "" {
|
|
t.Error(diff, names)
|
|
}
|
|
}
|
|
}
|
|
|
|
func TestTableConcurrentUsage(t *testing.T) {
|
|
table := []struct {
|
|
Name string
|
|
M Metadata
|
|
C []string
|
|
N []string
|
|
S string
|
|
}{
|
|
{
|
|
Name: "Full select",
|
|
M: Metadata{
|
|
Name: "table",
|
|
Columns: []string{"a", "b", "c", "d"},
|
|
PartKey: []string{"a"},
|
|
SortKey: []string{"b"},
|
|
},
|
|
N: []string{"a", "b"},
|
|
S: "SELECT * FROM table WHERE a=? AND b=? ",
|
|
},
|
|
{
|
|
Name: "Sub select",
|
|
M: Metadata{
|
|
Name: "table",
|
|
Columns: []string{"a", "b", "c", "d"},
|
|
PartKey: []string{"a"},
|
|
SortKey: []string{"b"},
|
|
},
|
|
C: []string{"d"},
|
|
N: []string{"a", "b"},
|
|
S: "SELECT d FROM table WHERE a=? AND b=? ",
|
|
},
|
|
}
|
|
|
|
parallelCount := 3
|
|
// run SelectBuilder on the data set in parallel
|
|
for _, test := range table {
|
|
var wg sync.WaitGroup
|
|
testTable := New(test.M)
|
|
wg.Add(parallelCount)
|
|
for i := 0; i < parallelCount; i++ {
|
|
go func() {
|
|
defer wg.Done()
|
|
stmt, names := testTable.SelectBuilder(test.C...).
|
|
Where(qb.Eq("b")).ToCql()
|
|
if diff := cmp.Diff(test.S, stmt); diff != "" {
|
|
t.Error(diff)
|
|
}
|
|
if diff := cmp.Diff(test.N, names); diff != "" {
|
|
t.Error(diff, names)
|
|
}
|
|
}()
|
|
}
|
|
wg.Wait()
|
|
}
|
|
}
|