mirror of
https://github.com/asdine/storm.git
synced 2025-10-04 06:26:30 +08:00
895 lines
20 KiB
Go
895 lines
20 KiB
Go
package storm
|
|
|
|
import (
|
|
"fmt"
|
|
"io/ioutil"
|
|
"os"
|
|
"path/filepath"
|
|
"testing"
|
|
"time"
|
|
|
|
"github.com/asdine/storm/codec/json"
|
|
"github.com/asdine/storm/q"
|
|
"github.com/boltdb/bolt"
|
|
"github.com/stretchr/testify/assert"
|
|
"github.com/stretchr/testify/require"
|
|
)
|
|
|
|
func TestFind(t *testing.T) {
|
|
db, cleanup := createDB(t)
|
|
defer cleanup()
|
|
|
|
for i := 0; i < 100; i++ {
|
|
w := User{Name: "John", ID: i + 1, Slug: fmt.Sprintf("John%d", i+1)}
|
|
|
|
if i%2 == 0 {
|
|
w.Group = "staff"
|
|
} else {
|
|
w.Group = "normal"
|
|
}
|
|
|
|
err := db.Save(&w)
|
|
assert.NoError(t, err)
|
|
}
|
|
|
|
err := db.Find("Name", "John", &User{})
|
|
assert.Error(t, err)
|
|
assert.Equal(t, ErrSlicePtrNeeded, err)
|
|
|
|
err = db.Find("Name", "John", &[]struct {
|
|
Name string
|
|
ID int
|
|
}{})
|
|
assert.Error(t, err)
|
|
assert.Equal(t, ErrNoName, err)
|
|
|
|
notTheRightUsers := []UniqueNameUser{}
|
|
|
|
err = db.Find("Name", "John", ¬TheRightUsers)
|
|
assert.Error(t, err)
|
|
assert.EqualError(t, err, "not found")
|
|
|
|
users := []User{}
|
|
|
|
err = db.Find("unexportedField", "John", &users)
|
|
assert.Error(t, err)
|
|
assert.EqualError(t, err, "field unexportedField not found")
|
|
|
|
err = db.Find("DateOfBirth", "John", &users)
|
|
assert.Error(t, err)
|
|
assert.True(t, ErrNotFound == err)
|
|
|
|
err = db.Find("Group", "staff", &users)
|
|
assert.NoError(t, err)
|
|
assert.Len(t, users, 50)
|
|
assert.Equal(t, 1, users[0].ID)
|
|
assert.Equal(t, 99, users[49].ID)
|
|
|
|
err = db.Find("Group", "staff", &users, Reverse())
|
|
assert.NoError(t, err)
|
|
assert.Len(t, users, 50)
|
|
assert.Equal(t, 99, users[0].ID)
|
|
assert.Equal(t, 1, users[49].ID)
|
|
|
|
err = db.Find("Group", "admin", &users)
|
|
assert.Error(t, err)
|
|
assert.True(t, ErrNotFound == err)
|
|
|
|
err = db.Find("Name", "John", users)
|
|
assert.Error(t, err)
|
|
assert.Equal(t, ErrSlicePtrNeeded, err)
|
|
|
|
err = db.Find("Name", "John", &users)
|
|
assert.NoError(t, err)
|
|
assert.Len(t, users, 100)
|
|
assert.Equal(t, 1, users[0].ID)
|
|
assert.Equal(t, 100, users[99].ID)
|
|
|
|
err = db.Find("Name", "John", &users, Reverse())
|
|
assert.NoError(t, err)
|
|
assert.Len(t, users, 100)
|
|
assert.Equal(t, 100, users[0].ID)
|
|
assert.Equal(t, 1, users[99].ID)
|
|
|
|
users = []User{}
|
|
err = db.Find("Slug", "John10", &users)
|
|
assert.NoError(t, err)
|
|
assert.Len(t, users, 1)
|
|
assert.Equal(t, 10, users[0].ID)
|
|
|
|
users = []User{}
|
|
err = db.Find("Name", nil, &users)
|
|
assert.Error(t, err)
|
|
assert.True(t, ErrNotFound == err)
|
|
|
|
err = db.Find("Name", "John", &users, Limit(10), Skip(20))
|
|
assert.NoError(t, err)
|
|
assert.Len(t, users, 10)
|
|
assert.Equal(t, 21, users[0].ID)
|
|
assert.Equal(t, 30, users[9].ID)
|
|
|
|
// err = db.Find("Age", 10, &users)
|
|
// assert.NoError(t, err)
|
|
|
|
}
|
|
|
|
func TestFindIntIndex(t *testing.T) {
|
|
db, cleanup := createDB(t, AutoIncrement())
|
|
defer cleanup()
|
|
|
|
type Score struct {
|
|
ID int
|
|
Score uint64 `storm:"index"`
|
|
}
|
|
|
|
for i := 0; i < 10; i++ {
|
|
w := Score{Score: uint64(i % 3)}
|
|
err := db.Save(&w)
|
|
require.NoError(t, err)
|
|
}
|
|
|
|
var scores []Score
|
|
err := db.Find("Score", 2, &scores)
|
|
require.NoError(t, err)
|
|
require.Len(t, scores, 3)
|
|
require.Equal(t, []Score{
|
|
{ID: 3, Score: 2},
|
|
{ID: 6, Score: 2},
|
|
{ID: 9, Score: 2},
|
|
}, scores)
|
|
}
|
|
|
|
func TestAllByIndex(t *testing.T) {
|
|
db, cleanup := createDB(t)
|
|
defer cleanup()
|
|
|
|
for i := 0; i < 100; i++ {
|
|
w := User{Name: "John", ID: i + 1, Slug: fmt.Sprintf("John%d", i+1), DateOfBirth: time.Now().Add(-time.Duration(i*10) * time.Minute)}
|
|
err := db.Save(&w)
|
|
assert.NoError(t, err)
|
|
}
|
|
|
|
err := db.AllByIndex("", nil)
|
|
assert.Error(t, err)
|
|
assert.Equal(t, ErrSlicePtrNeeded, err)
|
|
|
|
var users []User
|
|
|
|
err = db.AllByIndex("Unknown field", &users)
|
|
assert.Error(t, err)
|
|
assert.Equal(t, ErrNotFound, err)
|
|
|
|
err = db.AllByIndex("DateOfBirth", &users)
|
|
assert.NoError(t, err)
|
|
assert.Len(t, users, 100)
|
|
assert.Equal(t, 100, users[0].ID)
|
|
assert.Equal(t, 1, users[99].ID)
|
|
|
|
err = db.AllByIndex("Name", &users)
|
|
assert.NoError(t, err)
|
|
assert.Len(t, users, 100)
|
|
assert.Equal(t, 1, users[0].ID)
|
|
assert.Equal(t, 100, users[99].ID)
|
|
|
|
y := UniqueNameUser{Name: "Jake", ID: 200}
|
|
err = db.Save(&y)
|
|
assert.NoError(t, err)
|
|
|
|
var y2 []UniqueNameUser
|
|
err = db.AllByIndex("ID", &y2)
|
|
assert.NoError(t, err)
|
|
assert.Len(t, y2, 1)
|
|
|
|
n := NestedID{}
|
|
n.ID = "100"
|
|
n.Name = "John"
|
|
|
|
err = db.Save(&n)
|
|
assert.NoError(t, err)
|
|
|
|
var n2 []NestedID
|
|
err = db.AllByIndex("ID", &n2)
|
|
assert.NoError(t, err)
|
|
assert.Len(t, n2, 1)
|
|
|
|
err = db.AllByIndex("Name", &users, Limit(10))
|
|
assert.NoError(t, err)
|
|
assert.Len(t, users, 10)
|
|
assert.Equal(t, 1, users[0].ID)
|
|
assert.Equal(t, 10, users[9].ID)
|
|
|
|
err = db.AllByIndex("Name", &users, Limit(200))
|
|
assert.NoError(t, err)
|
|
assert.Len(t, users, 100)
|
|
assert.Equal(t, 1, users[0].ID)
|
|
assert.Equal(t, 100, users[99].ID)
|
|
|
|
err = db.AllByIndex("Name", &users, Limit(-10))
|
|
assert.NoError(t, err)
|
|
assert.Len(t, users, 100)
|
|
assert.Equal(t, 1, users[0].ID)
|
|
assert.Equal(t, 100, users[99].ID)
|
|
|
|
err = db.AllByIndex("Name", &users, Skip(200))
|
|
assert.NoError(t, err)
|
|
assert.Len(t, users, 0)
|
|
|
|
err = db.AllByIndex("Name", &users, Skip(-10))
|
|
assert.NoError(t, err)
|
|
assert.Len(t, users, 100)
|
|
assert.Equal(t, 1, users[0].ID)
|
|
assert.Equal(t, 100, users[99].ID)
|
|
|
|
err = db.AllByIndex("ID", &users)
|
|
assert.NoError(t, err)
|
|
assert.Len(t, users, 100)
|
|
assert.Equal(t, 1, users[0].ID)
|
|
assert.Equal(t, 100, users[99].ID)
|
|
|
|
err = db.AllByIndex("ID", &users, Limit(10))
|
|
assert.NoError(t, err)
|
|
assert.Len(t, users, 10)
|
|
assert.Equal(t, 1, users[0].ID)
|
|
assert.Equal(t, 10, users[9].ID)
|
|
|
|
err = db.AllByIndex("ID", &users, Skip(10))
|
|
assert.NoError(t, err)
|
|
assert.Len(t, users, 90)
|
|
assert.Equal(t, 11, users[0].ID)
|
|
assert.Equal(t, 100, users[89].ID)
|
|
|
|
err = db.AllByIndex("Name", &users, Limit(10), Skip(10))
|
|
assert.NoError(t, err)
|
|
assert.Len(t, users, 10)
|
|
assert.Equal(t, 11, users[0].ID)
|
|
assert.Equal(t, 20, users[9].ID)
|
|
|
|
err = db.AllByIndex("Name", &users, Limit(10), Skip(10), Reverse())
|
|
assert.NoError(t, err)
|
|
assert.Len(t, users, 10)
|
|
assert.Equal(t, 90, users[0].ID)
|
|
assert.Equal(t, 81, users[9].ID)
|
|
}
|
|
|
|
func TestAll(t *testing.T) {
|
|
db, cleanup := createDB(t)
|
|
defer cleanup()
|
|
|
|
for i := 0; i < 100; i++ {
|
|
w := User{Name: "John", ID: i + 1, Slug: fmt.Sprintf("John%d", i+1), DateOfBirth: time.Now().Add(-time.Duration(i*10) * time.Minute)}
|
|
err := db.Save(&w)
|
|
assert.NoError(t, err)
|
|
}
|
|
|
|
var users []User
|
|
|
|
err := db.All(&users)
|
|
assert.NoError(t, err)
|
|
assert.Len(t, users, 100)
|
|
assert.Equal(t, 1, users[0].ID)
|
|
assert.Equal(t, 100, users[99].ID)
|
|
|
|
err = db.All(&users, Reverse())
|
|
assert.NoError(t, err)
|
|
assert.Len(t, users, 100)
|
|
assert.Equal(t, 100, users[0].ID)
|
|
assert.Equal(t, 1, users[99].ID)
|
|
|
|
var users2 []*User
|
|
|
|
err = db.All(&users2)
|
|
assert.NoError(t, err)
|
|
assert.Len(t, users2, 100)
|
|
assert.Equal(t, 1, users2[0].ID)
|
|
assert.Equal(t, 100, users2[99].ID)
|
|
|
|
err = db.Save(&NestedID{
|
|
ToEmbed: ToEmbed{ID: "id1"},
|
|
Name: "John",
|
|
})
|
|
assert.NoError(t, err)
|
|
|
|
err = db.Save(&NestedID{
|
|
ToEmbed: ToEmbed{ID: "id2"},
|
|
Name: "Mike",
|
|
})
|
|
assert.NoError(t, err)
|
|
|
|
db.Save(&NestedID{
|
|
ToEmbed: ToEmbed{ID: "id3"},
|
|
Name: "Steve",
|
|
})
|
|
assert.NoError(t, err)
|
|
|
|
var nested []NestedID
|
|
err = db.All(&nested)
|
|
assert.NoError(t, err)
|
|
assert.Len(t, nested, 3)
|
|
|
|
err = db.All(&users, Limit(10), Skip(10))
|
|
assert.NoError(t, err)
|
|
assert.Len(t, users, 10)
|
|
assert.Equal(t, 11, users[0].ID)
|
|
assert.Equal(t, 20, users[9].ID)
|
|
|
|
err = db.All(&users, Limit(0), Skip(0))
|
|
assert.NoError(t, err)
|
|
assert.Len(t, users, 0)
|
|
}
|
|
|
|
func TestCount(t *testing.T) {
|
|
db, cleanup := createDB(t)
|
|
defer cleanup()
|
|
|
|
for i := 0; i < 100; i++ {
|
|
w := User{Name: "John", ID: i + 1, Slug: fmt.Sprintf("John%d", i+1), DateOfBirth: time.Now().Add(-time.Duration(i*10) * time.Minute)}
|
|
err := db.Save(&w)
|
|
assert.NoError(t, err)
|
|
}
|
|
|
|
count, err := db.Count(&User{})
|
|
assert.NoError(t, err)
|
|
assert.Equal(t, 100, count)
|
|
|
|
w := User{Name: "John", ID: 101, Slug: fmt.Sprintf("John%d", 101), DateOfBirth: time.Now().Add(-time.Duration(101*10) * time.Minute)}
|
|
err = db.Save(&w)
|
|
assert.NoError(t, err)
|
|
|
|
count, err = db.Count(&User{})
|
|
assert.NoError(t, err)
|
|
assert.Equal(t, 101, count)
|
|
|
|
tx, err := db.Begin(true)
|
|
assert.NoError(t, err)
|
|
|
|
count, err = tx.Count(User{})
|
|
assert.Equal(t, ErrStructPtrNeeded, err)
|
|
|
|
count, err = tx.Count(&User{})
|
|
assert.NoError(t, err)
|
|
assert.Equal(t, 101, count)
|
|
|
|
w = User{Name: "John", ID: 102, Slug: fmt.Sprintf("John%d", 102), DateOfBirth: time.Now().Add(-time.Duration(101*10) * time.Minute)}
|
|
err = tx.Save(&w)
|
|
assert.NoError(t, err)
|
|
|
|
count, err = tx.Count(&User{})
|
|
assert.NoError(t, err)
|
|
assert.Equal(t, 102, count)
|
|
|
|
tx.Commit()
|
|
}
|
|
|
|
func TestOne(t *testing.T) {
|
|
db, cleanup := createDB(t)
|
|
defer cleanup()
|
|
|
|
u := UniqueNameUser{Name: "John", ID: 10}
|
|
err := db.Save(&u)
|
|
assert.NoError(t, err)
|
|
|
|
v := UniqueNameUser{}
|
|
err = db.One("Name", "John", &v)
|
|
assert.NoError(t, err)
|
|
assert.Equal(t, u, v)
|
|
|
|
for i := 0; i < 10; i++ {
|
|
w := IndexedNameUser{Name: "John", ID: i + 1, Group: "staff"}
|
|
err = db.Save(&w)
|
|
assert.NoError(t, err)
|
|
}
|
|
|
|
x := IndexedNameUser{}
|
|
err = db.One("Name", "John", &x)
|
|
assert.NoError(t, err)
|
|
assert.Equal(t, "John", x.Name)
|
|
assert.Equal(t, 1, x.ID)
|
|
assert.Zero(t, x.age)
|
|
assert.True(t, x.DateOfBirth.IsZero())
|
|
|
|
err = db.One("Name", "Mike", &x)
|
|
assert.Error(t, err)
|
|
assert.Equal(t, ErrNotFound, err)
|
|
|
|
err = db.One("", nil, &x)
|
|
assert.Error(t, err)
|
|
assert.True(t, ErrNotFound == err)
|
|
|
|
err = db.One("", "Mike", nil)
|
|
assert.Error(t, err)
|
|
assert.Equal(t, ErrStructPtrNeeded, err)
|
|
|
|
err = db.One("", nil, nil)
|
|
assert.Error(t, err)
|
|
assert.Equal(t, ErrStructPtrNeeded, err)
|
|
|
|
err = db.One("Group", "staff", &x)
|
|
assert.NoError(t, err)
|
|
assert.Equal(t, 1, x.ID)
|
|
|
|
err = db.One("Group", "admin", &x)
|
|
assert.Error(t, err)
|
|
assert.Equal(t, ErrNotFound, err)
|
|
|
|
y := UniqueNameUser{Name: "Jake", ID: 200}
|
|
err = db.Save(&y)
|
|
assert.NoError(t, err)
|
|
|
|
var y2 UniqueNameUser
|
|
err = db.One("ID", 200, &y2)
|
|
assert.NoError(t, err)
|
|
assert.Equal(t, y, y2)
|
|
|
|
n := NestedID{}
|
|
n.ID = "100"
|
|
n.Name = "John"
|
|
|
|
err = db.Save(&n)
|
|
assert.NoError(t, err)
|
|
|
|
var n2 NestedID
|
|
err = db.One("ID", "100", &n2)
|
|
assert.NoError(t, err)
|
|
assert.Equal(t, n, n2)
|
|
}
|
|
|
|
func TestOneNotWritable(t *testing.T) {
|
|
dir, _ := ioutil.TempDir(os.TempDir(), "storm")
|
|
defer os.RemoveAll(dir)
|
|
db, _ := Open(filepath.Join(dir, "storm.db"))
|
|
|
|
err := db.Save(&User{ID: 10, Name: "John"})
|
|
assert.NoError(t, err)
|
|
|
|
db.Close()
|
|
|
|
db, _ = Open(filepath.Join(dir, "storm.db"), BoltOptions(0660, &bolt.Options{
|
|
ReadOnly: true,
|
|
}))
|
|
defer db.Close()
|
|
|
|
err = db.Save(&User{ID: 20, Name: "John"})
|
|
assert.Error(t, err)
|
|
|
|
var u User
|
|
err = db.One("ID", 10, &u)
|
|
assert.NoError(t, err)
|
|
assert.Equal(t, 10, u.ID)
|
|
assert.Equal(t, "John", u.Name)
|
|
|
|
err = db.One("Name", "John", &u)
|
|
assert.NoError(t, err)
|
|
assert.Equal(t, 10, u.ID)
|
|
assert.Equal(t, "John", u.Name)
|
|
}
|
|
|
|
func TestRange(t *testing.T) {
|
|
db, cleanup := createDB(t)
|
|
defer cleanup()
|
|
|
|
for i := 0; i < 100; i++ {
|
|
w := User{
|
|
Name: "John",
|
|
ID: i + 1,
|
|
Slug: fmt.Sprintf("John%03d", i+1),
|
|
DateOfBirth: time.Now().Add(-time.Duration(i) * time.Hour),
|
|
Group: fmt.Sprintf("Group%03d", i%5),
|
|
}
|
|
err := db.Save(&w)
|
|
assert.NoError(t, err)
|
|
z := User{Name: fmt.Sprintf("Zach%03d", i+1), ID: i + 101, Slug: fmt.Sprintf("Zach%03d", i+1)}
|
|
err = db.Save(&z)
|
|
assert.NoError(t, err)
|
|
}
|
|
|
|
min := "John010"
|
|
max := "John020"
|
|
var users []User
|
|
|
|
err := db.Range("Slug", min, max, users)
|
|
assert.Equal(t, ErrSlicePtrNeeded, err)
|
|
|
|
err = db.Range("Slug", min, max, &users)
|
|
assert.NoError(t, err)
|
|
assert.Len(t, users, 11)
|
|
assert.Equal(t, "John010", users[0].Slug)
|
|
assert.Equal(t, "John020", users[10].Slug)
|
|
|
|
err = db.Range("Slug", min, max, &users, Reverse())
|
|
assert.NoError(t, err)
|
|
assert.Len(t, users, 11)
|
|
assert.Equal(t, "John020", users[0].Slug)
|
|
assert.Equal(t, "John010", users[10].Slug)
|
|
|
|
min = "Zach010"
|
|
max = "Zach020"
|
|
users = nil
|
|
err = db.Range("Name", min, max, &users)
|
|
assert.NoError(t, err)
|
|
assert.Len(t, users, 11)
|
|
assert.Equal(t, "Zach010", users[0].Name)
|
|
assert.Equal(t, "Zach020", users[10].Name)
|
|
|
|
err = db.Range("Name", min, max, &users, Reverse())
|
|
assert.NoError(t, err)
|
|
assert.Len(t, users, 11)
|
|
assert.Equal(t, "Zach020", users[0].Name)
|
|
assert.Equal(t, "Zach010", users[10].Name)
|
|
|
|
err = db.Range("Name", min, max, &User{})
|
|
assert.Error(t, err)
|
|
assert.Equal(t, ErrSlicePtrNeeded, err)
|
|
|
|
notTheRightUsers := []UniqueNameUser{}
|
|
|
|
err = db.Range("Name", min, max, ¬TheRightUsers)
|
|
assert.NoError(t, err)
|
|
assert.Equal(t, 0, len(notTheRightUsers))
|
|
|
|
users = nil
|
|
|
|
err = db.Range("Age", min, max, &users)
|
|
assert.Error(t, err)
|
|
assert.EqualError(t, err, "not found")
|
|
|
|
dateMin := time.Now().Add(-time.Duration(50) * time.Hour)
|
|
dateMax := dateMin.Add(time.Duration(3) * time.Hour)
|
|
err = db.Range("DateOfBirth", dateMin, dateMax, &users)
|
|
assert.NoError(t, err)
|
|
assert.Len(t, users, 3)
|
|
assert.Equal(t, "John050", users[0].Slug)
|
|
assert.Equal(t, "John048", users[2].Slug)
|
|
|
|
err = db.Range("Slug", "John010", "John040", &users, Limit(10), Skip(20))
|
|
assert.NoError(t, err)
|
|
assert.Len(t, users, 10)
|
|
assert.Equal(t, 30, users[0].ID)
|
|
assert.Equal(t, 39, users[9].ID)
|
|
|
|
err = db.Range("Slug", "John010", "John040", &users, Limit(10), Skip(20), Reverse())
|
|
assert.NoError(t, err)
|
|
assert.Len(t, users, 10)
|
|
assert.Equal(t, 20, users[0].ID)
|
|
assert.Equal(t, 11, users[9].ID)
|
|
|
|
err = db.Range("Group", "Group002", "Group004", &users)
|
|
assert.NoError(t, err)
|
|
assert.Len(t, users, 60)
|
|
}
|
|
|
|
type Score struct {
|
|
ID int
|
|
Value int
|
|
}
|
|
|
|
func prepareScoreDB(t *testing.T) (*DB, func()) {
|
|
db, cleanup := createDB(t, AutoIncrement())
|
|
|
|
for i := 0; i < 20; i++ {
|
|
err := db.Save(&Score{
|
|
Value: i,
|
|
})
|
|
assert.NoError(t, err)
|
|
}
|
|
|
|
return db, cleanup
|
|
}
|
|
|
|
func TestSelectFind(t *testing.T) {
|
|
db, cleanup := prepareScoreDB(t)
|
|
defer cleanup()
|
|
|
|
var scores []Score
|
|
var scoresPtr []*Score
|
|
|
|
err := db.Select(q.Eq("Value", 5)).Find(&scores)
|
|
assert.NoError(t, err)
|
|
assert.Len(t, scores, 1)
|
|
assert.Equal(t, 5, scores[0].Value)
|
|
|
|
err = db.Select(q.Eq("Value", 5)).Find(&scoresPtr)
|
|
assert.NoError(t, err)
|
|
assert.Len(t, scoresPtr, 1)
|
|
assert.Equal(t, 5, scoresPtr[0].Value)
|
|
|
|
err = db.Select(
|
|
q.Or(
|
|
q.Eq("Value", 5),
|
|
q.Eq("Value", 6),
|
|
),
|
|
).Find(&scores)
|
|
assert.NoError(t, err)
|
|
assert.Len(t, scores, 2)
|
|
assert.Equal(t, 5, scores[0].Value)
|
|
assert.Equal(t, 6, scores[1].Value)
|
|
|
|
err = db.Select(q.Or(
|
|
q.Eq("Value", 5),
|
|
q.Or(
|
|
q.Lte("Value", 2),
|
|
q.Gte("Value", 18),
|
|
),
|
|
)).Find(&scores)
|
|
assert.NoError(t, err)
|
|
assert.Len(t, scores, 6)
|
|
assert.Equal(t, 0, scores[0].Value)
|
|
assert.Equal(t, 1, scores[1].Value)
|
|
assert.Equal(t, 2, scores[2].Value)
|
|
assert.Equal(t, 5, scores[3].Value)
|
|
assert.Equal(t, 18, scores[4].Value)
|
|
assert.Equal(t, 19, scores[5].Value)
|
|
|
|
err = db.Select(q.Or(
|
|
q.Eq("Value", 5),
|
|
q.Or(
|
|
q.Lte("Value", 2),
|
|
q.Gte("Value", 18),
|
|
),
|
|
)).Reverse().Find(&scores)
|
|
assert.NoError(t, err)
|
|
assert.Len(t, scores, 6)
|
|
assert.Equal(t, 19, scores[0].Value)
|
|
assert.Equal(t, 18, scores[1].Value)
|
|
assert.Equal(t, 5, scores[2].Value)
|
|
assert.Equal(t, 2, scores[3].Value)
|
|
assert.Equal(t, 1, scores[4].Value)
|
|
assert.Equal(t, 0, scores[5].Value)
|
|
}
|
|
|
|
func TestSelectFindSkip(t *testing.T) {
|
|
db, cleanup := prepareScoreDB(t)
|
|
defer cleanup()
|
|
|
|
var scores []Score
|
|
|
|
err := db.Select(q.Or(
|
|
q.Eq("Value", 5),
|
|
q.Or(
|
|
q.Lte("Value", 2),
|
|
q.Gte("Value", 18),
|
|
),
|
|
)).Skip(4).Find(&scores)
|
|
assert.NoError(t, err)
|
|
assert.Len(t, scores, 2)
|
|
assert.Equal(t, 18, scores[0].Value)
|
|
assert.Equal(t, 19, scores[1].Value)
|
|
|
|
err = db.Select(q.Or(
|
|
q.Eq("Value", 5),
|
|
q.Or(
|
|
q.Lte("Value", 2),
|
|
q.Gte("Value", 18),
|
|
),
|
|
)).Skip(-10).Find(&scores)
|
|
assert.NoError(t, err)
|
|
assert.Len(t, scores, 6)
|
|
assert.Equal(t, 0, scores[0].Value)
|
|
|
|
scores = nil
|
|
err = db.Select(q.Or(
|
|
q.Eq("Value", 5),
|
|
q.Or(
|
|
q.Lte("Value", 2),
|
|
q.Gte("Value", 18),
|
|
),
|
|
)).Skip(1000).Find(&scores)
|
|
assert.Error(t, err)
|
|
assert.True(t, ErrNotFound == err)
|
|
assert.Len(t, scores, 0)
|
|
}
|
|
|
|
func TestSelectFindLimit(t *testing.T) {
|
|
db, cleanup := prepareScoreDB(t)
|
|
defer cleanup()
|
|
var scores []Score
|
|
|
|
err := db.Select(q.Or(
|
|
q.Eq("Value", 5),
|
|
q.Or(
|
|
q.Lte("Value", 2),
|
|
q.Gte("Value", 18),
|
|
),
|
|
)).Limit(2).Find(&scores)
|
|
assert.NoError(t, err)
|
|
assert.Len(t, scores, 2)
|
|
assert.Equal(t, 0, scores[0].Value)
|
|
assert.Equal(t, 1, scores[1].Value)
|
|
|
|
err = db.Select(q.Or(
|
|
q.Eq("Value", 5),
|
|
q.Or(
|
|
q.Lte("Value", 2),
|
|
q.Gte("Value", 18),
|
|
),
|
|
)).Limit(-10).Find(&scores)
|
|
assert.NoError(t, err)
|
|
assert.Len(t, scores, 6)
|
|
assert.Equal(t, 0, scores[0].Value)
|
|
|
|
scores = nil
|
|
err = db.Select(q.Or(
|
|
q.Eq("Value", 5),
|
|
q.Or(
|
|
q.Lte("Value", 2),
|
|
q.Gte("Value", 18),
|
|
),
|
|
)).Limit(0).Find(&scores)
|
|
assert.Error(t, err)
|
|
assert.True(t, ErrNotFound == err)
|
|
assert.Len(t, scores, 0)
|
|
}
|
|
|
|
func TestSelectFindLimitSkip(t *testing.T) {
|
|
db, cleanup := prepareScoreDB(t)
|
|
defer cleanup()
|
|
|
|
var scores []Score
|
|
|
|
err := db.Select(q.Or(
|
|
q.Eq("Value", 5),
|
|
q.Or(
|
|
q.Lte("Value", 2),
|
|
q.Gte("Value", 18),
|
|
),
|
|
)).Limit(2).Skip(2).Find(&scores)
|
|
assert.NoError(t, err)
|
|
assert.Len(t, scores, 2)
|
|
assert.Equal(t, 2, scores[0].Value)
|
|
assert.Equal(t, 5, scores[1].Value)
|
|
|
|
err = db.Select(q.Or(
|
|
q.Eq("Value", 5),
|
|
q.Or(
|
|
q.Lte("Value", 2),
|
|
q.Gte("Value", 18),
|
|
),
|
|
)).Limit(2).Skip(5).Find(&scores)
|
|
assert.NoError(t, err)
|
|
assert.Len(t, scores, 1)
|
|
assert.Equal(t, 19, scores[0].Value)
|
|
}
|
|
|
|
func TestSelectFirst(t *testing.T) {
|
|
db, cleanup := prepareScoreDB(t)
|
|
defer cleanup()
|
|
|
|
var score Score
|
|
|
|
err := db.Select(q.Or(
|
|
q.Eq("Value", 5),
|
|
q.Or(
|
|
q.Lte("Value", 2),
|
|
q.Gte("Value", 18),
|
|
),
|
|
)).Skip(2).First(&score)
|
|
assert.NoError(t, err)
|
|
assert.Equal(t, 2, score.Value)
|
|
|
|
err = db.Select(q.Or(
|
|
q.Eq("Value", 5),
|
|
q.Or(
|
|
q.Lte("Value", 2),
|
|
q.Gte("Value", 18),
|
|
),
|
|
)).Skip(1).Reverse().First(&score)
|
|
assert.NoError(t, err)
|
|
assert.Equal(t, 18, score.Value)
|
|
}
|
|
|
|
func TestSelectRemove(t *testing.T) {
|
|
db, cleanup := prepareScoreDB(t)
|
|
defer cleanup()
|
|
|
|
err := db.Select(q.Or(
|
|
q.Eq("Value", 5),
|
|
q.Or(
|
|
q.Lte("Value", 2),
|
|
q.Gte("Value", 18),
|
|
),
|
|
)).Skip(2).Delete(&Score{})
|
|
assert.NoError(t, err)
|
|
|
|
var scores []Score
|
|
err = db.Select(q.Or(
|
|
q.Eq("Value", 5),
|
|
q.Or(
|
|
q.Lte("Value", 2),
|
|
q.Gte("Value", 18),
|
|
),
|
|
)).Find(&scores)
|
|
assert.NoError(t, err)
|
|
assert.Len(t, scores, 2)
|
|
assert.Equal(t, 0, scores[0].Value)
|
|
assert.Equal(t, 1, scores[1].Value)
|
|
|
|
for i := 0; i < 10; i++ {
|
|
w := User{ID: i + 1, Name: fmt.Sprintf("John%d", i+1)}
|
|
err = db.Save(&w)
|
|
assert.NoError(t, err)
|
|
}
|
|
|
|
err = db.Select(q.Gte("ID", 5)).Delete(&User{})
|
|
assert.NoError(t, err)
|
|
|
|
var user User
|
|
err = db.One("Name", "John6", &user)
|
|
assert.Error(t, err)
|
|
assert.Equal(t, ErrNotFound, err)
|
|
|
|
err = db.One("Name", "John4", &user)
|
|
assert.NoError(t, err)
|
|
}
|
|
|
|
func TestSelectCount(t *testing.T) {
|
|
db, cleanup := prepareScoreDB(t)
|
|
defer cleanup()
|
|
|
|
total, err := db.Select(q.Or(
|
|
q.Eq("Value", 5),
|
|
q.Or(
|
|
q.Lte("Value", 2),
|
|
q.Gte("Value", 18),
|
|
),
|
|
)).Count(&Score{})
|
|
assert.NoError(t, err)
|
|
assert.Equal(t, 6, total)
|
|
|
|
total, err = db.Select(q.Or(
|
|
q.Eq("Value", 5),
|
|
q.Or(
|
|
q.Lte("Value", 2),
|
|
q.Gte("Value", 18),
|
|
),
|
|
)).Skip(2).Count(&Score{})
|
|
assert.NoError(t, err)
|
|
assert.Equal(t, 4, total)
|
|
|
|
total, err = db.Select(q.Or(
|
|
q.Eq("Value", 5),
|
|
q.Or(
|
|
q.Lte("Value", 2),
|
|
q.Gte("Value", 18),
|
|
),
|
|
)).Skip(2).Limit(2).Count(&Score{})
|
|
assert.NoError(t, err)
|
|
assert.Equal(t, 2, total)
|
|
|
|
total, err = db.Select(q.Or(
|
|
q.Eq("Value", 5),
|
|
q.Or(
|
|
q.Lte("Value", 2),
|
|
q.Gte("Value", 18),
|
|
),
|
|
)).Skip(5).Limit(2).Count(&Score{})
|
|
assert.NoError(t, err)
|
|
assert.Equal(t, 1, total)
|
|
}
|
|
|
|
func TestSelectRaw(t *testing.T) {
|
|
db, cleanup := createDB(t, AutoIncrement(), Codec(json.Codec))
|
|
defer cleanup()
|
|
|
|
for i := 0; i < 20; i++ {
|
|
err := db.Save(&Score{
|
|
Value: i,
|
|
})
|
|
assert.NoError(t, err)
|
|
}
|
|
|
|
list, err := db.Select().Bucket("Score").Raw()
|
|
assert.NoError(t, err)
|
|
assert.Len(t, list, 20)
|
|
|
|
list, err = db.Select().Bucket("Score").Skip(18).Limit(5).Raw()
|
|
assert.NoError(t, err)
|
|
assert.Len(t, list, 2)
|
|
|
|
i := 0
|
|
err = db.Select().Bucket("Score").Skip(18).Limit(5).RawEach(func(k []byte, v []byte) error {
|
|
i++
|
|
return nil
|
|
})
|
|
assert.NoError(t, err)
|
|
assert.Equal(t, i, 2)
|
|
}
|