xorm/tests/ydbtest/session_find_test.go

657 lines
15 KiB
Go

package ydb
import (
"database/sql"
"fmt"
"testing"
"time"
"github.com/google/uuid"
"github.com/stretchr/testify/assert"
"xorm.io/builder"
)
func TestFindJoinLimit(t *testing.T) {
type Salary struct {
Uuid int64 `xorm:"pk"`
Lid int64
}
type CheckList struct {
Uuid int64 `xorm:"pk"`
Eid int64
}
type Empsetting struct {
Uuid int64 `xorm:"pk"`
Name string
}
assert.NoError(t, PrepareScheme(&Salary{}, &CheckList{}, &Empsetting{}))
engine, err := enginePool.GetDataQueryEngine()
assert.NoError(t, err)
assert.NotNil(t, engine)
emp := Empsetting{
Uuid: int64(1),
Name: "datbeohbbh",
}
session := engine.NewSession()
defer session.Close()
_, err = session.Insert(&emp)
assert.NoError(t, err)
checklist := CheckList{Uuid: int64(1), Eid: emp.Uuid}
_, err = session.Insert(&checklist)
assert.NoError(t, err)
salary := Salary{Uuid: int64(1), Lid: checklist.Uuid}
_, err = session.Insert(&salary)
assert.NoError(t, err)
var salaries []Salary
err = engine.Table("salary").
Cols("`salary`.`uuid`", "`salary`.`lid`").
Join("INNER", "check_list", "`check_list`.`uuid` = `salary`.`lid`").
Join("LEFT", "empsetting", "`empsetting`.`uuid` = `check_list`.`eid`").
Limit(10, 0).
Find(&salaries)
assert.NoError(t, err)
}
func TestFindCond(t *testing.T) {
assert.NoError(t, PrepareScheme(&Users{}))
engine, err := enginePool.GetDataQueryEngine()
assert.NoError(t, err)
assert.NotNil(t, engine)
usersData := getUsersData()
_, err = engine.Insert(&usersData)
assert.NoError(t, err)
users := make([]Users, 0)
err = engine.Where("user_id > ?", sql.NullInt64{Int64: 5, Valid: true}).Find(&users)
assert.NoError(t, err)
assert.Equal(t, len(usersData)-6, len(users))
users = []Users{}
err = engine.
Where(builder.Between{
Col: "user_id",
LessVal: sql.NullInt64{Int64: 5, Valid: true},
MoreVal: sql.NullInt64{Int64: 15, Valid: true},
}).
Where(builder.Gt{"age": int32(30)}).
Find(&users)
assert.NoError(t, err)
assert.Equal(t, 7, len(users))
}
func TestFindMap(t *testing.T) {
type Salary struct {
Uuid int64 `xorm:"pk"`
Lid int64
}
assert.NoError(t, PrepareScheme(&Salary{}))
engine, err := enginePool.GetDataQueryEngine()
assert.NoError(t, err)
assert.NotNil(t, engine)
salaryData := []Salary{}
for uuid := 0; uuid <= 20; uuid++ {
salaryData = append(salaryData, Salary{
Uuid: int64(uuid),
})
}
_, err = engine.Insert(&salaryData)
assert.NoError(t, err)
salaries := make(map[int64]Salary)
err = engine.Find(&salaries)
assert.NoError(t, err)
assert.Equal(t, len(salaryData), len(salaries))
salariesPtr := map[int64]*Salary{}
err = engine.Cols("lid").Find(&salariesPtr)
assert.NoError(t, err)
assert.Equal(t, len(salaryData), len(salariesPtr))
}
func TestFindDistinct(t *testing.T) {
assert.NoError(t, PrepareScheme(&Users{}))
engine, err := enginePool.GetDataQueryEngine()
assert.NoError(t, err)
assert.NotNil(t, engine)
usersData := getUsersData()
for w, g := len(usersData)/4, 0; g < 4; g++ {
for i := 0; i < w; i++ {
usersData[w*g+i].Age = uint32(22 + g)
}
}
_, err = engine.Insert(&usersData)
assert.NoError(t, err)
users := []Users{}
err = engine.Distinct("age").Find(&users)
assert.NoError(t, err)
assert.Equal(t, 4, len(users))
}
func TestFindOrder(t *testing.T) {
assert.NoError(t, PrepareScheme(&Users{}))
engine, err := enginePool.GetDataQueryEngine()
assert.NoError(t, err)
assert.NotNil(t, engine)
usersData := getUsersData()
_, err = engine.Insert(&usersData)
assert.NoError(t, err)
users := make([]Users, 0)
err = engine.OrderBy("`user_id` desc").Find(&users)
assert.NoError(t, err)
assert.Equal(t, len(usersData), len(users))
for i := len(usersData) - 1; i >= 0; i-- {
assert.Equal(t, usersData[i].UserID, users[len(users)-i-1].UserID)
}
users = []Users{}
err = engine.Asc("user_id").Find(&users)
assert.NoError(t, err)
assert.Equal(t, len(usersData), len(users))
for i := 0; i < len(usersData); i++ {
assert.Equal(t, usersData[i].UserID, users[i].UserID)
}
}
func TestFindGroupBy(t *testing.T) {
assert.NoError(t, PrepareScheme(&Users{}))
engine, err := enginePool.GetDataQueryEngine()
assert.NoError(t, err)
assert.NotNil(t, engine)
usersData := getUsersData()
_, err = engine.Insert(&usersData)
assert.NoError(t, err)
users := make([]Users, 0)
err = engine.GroupBy("`age`, `user_id`, `number`").Find(&users)
assert.NoError(t, err)
assert.Equal(t, len(usersData), len(users))
}
func TestFindHaving(t *testing.T) {
assert.NoError(t, PrepareScheme(&Users{}))
engine, err := enginePool.GetDataQueryEngine()
assert.NoError(t, err)
assert.NotNil(t, engine)
usersData := getUsersData()
_, err = engine.Insert(&usersData)
assert.NoError(t, err)
users := make([]Users, 0)
err = engine.
GroupBy("`age`, `user_id`, `number`").
Having("`user_id` = 0").
Find(&users)
assert.NoError(t, err)
}
func TestFindInt(t *testing.T) {
assert.NoError(t, PrepareScheme(&Users{}))
engine, err := enginePool.GetDataQueryEngine()
assert.NoError(t, err)
assert.NotNil(t, engine)
usersData := getUsersData()
_, err = engine.Insert(&usersData)
assert.NoError(t, err)
age := []uint32{}
err = engine.Table(&Users{}).Cols("age").Asc("age").Find(&age)
assert.NoError(t, err)
assert.Equal(t, len(usersData), len(age))
userIds := []int64{}
err = engine.Table(&Users{}).Cols("user_id").Desc("user_id").Find(&userIds)
assert.NoError(t, err)
assert.Equal(t, len(usersData), len(userIds))
}
func TestFindString(t *testing.T) {
assert.NoError(t, PrepareScheme(&Users{}))
engine, err := enginePool.GetDataQueryEngine()
assert.NoError(t, err)
assert.NotNil(t, engine)
usersData := getUsersData()
_, err = engine.Insert(&usersData)
assert.NoError(t, err)
expectedName := []string{}
for _, user := range usersData {
expectedName = append(expectedName, user.Name)
}
expectedNumber := []string{}
for _, user := range usersData {
expectedNumber = append(expectedNumber, user.Number)
}
names := []string{}
err = engine.Table(&Users{}).Cols("name").Asc("name").Find(&names)
assert.NoError(t, err)
assert.Equal(t, len(usersData), len(names))
assert.ElementsMatch(t, expectedName, names)
numbers := []string{}
err = engine.Table(&Users{}).Cols("number").Find(&numbers)
assert.NoError(t, err)
assert.Equal(t, len(usersData), len(numbers))
assert.ElementsMatch(t, expectedNumber, numbers)
}
func TestFindCustomType(t *testing.T) {
assert.NoError(t, PrepareScheme(&Users{}))
engine, err := enginePool.GetDataQueryEngine()
assert.NoError(t, err)
assert.NotNil(t, engine)
usersData := getUsersData()
_, err = engine.Insert(&usersData)
assert.NoError(t, err)
type cstring string
expectedName := []cstring{}
for _, user := range usersData {
expectedName = append(expectedName, cstring(user.Name))
}
names := []cstring{}
err = engine.Table(&Users{}).Cols("name").Asc("name").Find(&names)
assert.NoError(t, err)
assert.Equal(t, len(usersData), len(names))
assert.ElementsMatch(t, expectedName, names)
}
func TestFindInterface(t *testing.T) {
assert.NoError(t, PrepareScheme(&Users{}))
engine, err := enginePool.GetDataQueryEngine()
assert.NoError(t, err)
assert.NotNil(t, engine)
usersData := getUsersData()
_, err = engine.Insert(&usersData)
assert.NoError(t, err)
age := []interface{}{}
err = engine.Table(&Users{}).Cols("age").Asc("age").Find(&age)
assert.NoError(t, err)
assert.Equal(t, len(usersData), len(age))
for i := 0; i < len(usersData); i++ {
assert.Equal(t, usersData[i].Age, age[i].(uint32))
}
}
func TestFindSliceBytes(t *testing.T) {
assert.NoError(t, PrepareScheme(&Series{}))
engine, err := enginePool.GetDataQueryEngine()
assert.NoError(t, err)
assert.NotNil(t, engine)
seriesData, _, _ := getData()
_, err = engine.Insert(&seriesData)
assert.NoError(t, err)
expectedSeriesId := []string{}
for _, series := range seriesData {
expectedSeriesId = append(expectedSeriesId, string(series.SeriesID))
}
seriesIds := make([]string, 0)
err = engine.Table(&Series{}).Cols("series_id").Find(&seriesIds)
assert.NoError(t, err)
assert.ElementsMatch(t, expectedSeriesId, seriesIds)
}
func TestFindBool(t *testing.T) {
engine, err := enginePool.GetDataQueryEngine()
assert.NoError(t, err)
assert.NotNil(t, engine)
type FindBoolStruct struct {
Uuid int64 `xorm:"pk"`
Msg bool
}
assert.NoError(t, PrepareScheme(&FindBoolStruct{}))
_, err = engine.Insert([]FindBoolStruct{
{
Uuid: int64(1),
Msg: false,
},
{
Uuid: int64(2),
Msg: true,
},
})
assert.NoError(t, err)
results := make([]FindBoolStruct, 0)
err = engine.Asc("uuid").Find(&results)
assert.NoError(t, err)
assert.EqualValues(t, 2, len(results))
assert.False(t, results[0].Msg)
assert.True(t, results[1].Msg)
}
func TestFindAndCount(t *testing.T) {
assert.NoError(t, PrepareScheme(&Users{}))
engine, err := enginePool.GetDataQueryEngine()
assert.NoError(t, err)
assert.NotNil(t, engine)
usersData := getUsersData()
_, err = engine.Insert(&usersData)
assert.NoError(t, err)
users := make([]Users, 0)
cnt, err := engine.FindAndCount(&users)
assert.NoError(t, err)
assert.EqualValues(t, len(usersData), cnt)
users = []Users{}
_, err = engine.Limit(10, 0).FindAndCount(&users)
assert.NoError(t, err)
assert.EqualValues(t, 10, len(users))
}
func TestFindAndCountDistinct(t *testing.T) {
assert.NoError(t, PrepareScheme(&Users{}))
engine, err := enginePool.GetDataQueryEngine()
assert.NoError(t, err)
assert.NotNil(t, engine)
usersData := getUsersData()
for w, g := len(usersData)/4, 0; g < 4; g++ {
for i := 0; i < w; i++ {
usersData[w*g+i].Age = uint32(22 + g)
}
}
_, err = engine.Insert(&usersData)
assert.NoError(t, err)
users := make([]Users, 0)
cnt, err := engine.Distinct("age").FindAndCount(&users)
assert.NoError(t, err)
assert.EqualValues(t, 4, cnt)
assert.EqualValues(t, 4, len(users))
}
func TestFindAndCountGroupBy(t *testing.T) {
assert.NoError(t, PrepareScheme(&Users{}))
engine, err := enginePool.GetDataQueryEngine()
assert.NoError(t, err)
assert.NotNil(t, engine)
usersData := getUsersData()
for w, g := len(usersData)/4, 0; g < 4; g++ {
for i := 0; i < w; i++ {
usersData[w*g+i].Age = uint32(22 + g)
}
}
_, err = engine.Insert(&usersData)
assert.NoError(t, err)
users := make([]Users, 0)
cnt, err := engine.GroupBy("age").FindAndCount(&users)
assert.NoError(t, err)
assert.EqualValues(t, 4, cnt)
assert.EqualValues(t, 4, len(users))
}
func TestFindTime(t *testing.T) {
assert.NoError(t, PrepareScheme(&Users{}))
engine, err := enginePool.GetDataQueryEngine()
assert.NoError(t, err)
assert.NotNil(t, engine)
usersData := getUsersData()
_, err = engine.Insert(&usersData)
assert.NoError(t, err)
createdAt := make([]sql.NullTime, 0)
err = engine.Table(&Users{}).Cols("created_at").Find(&createdAt)
assert.NoError(t, err)
assert.EqualValues(t, len(usersData), len(createdAt))
}
func TestFindStringArray(t *testing.T) {
type TestString struct {
Id string `xorm:"pk VARCHAR"`
Data *[]string `xorm:"TEXT"`
}
assert.NoError(t, PrepareScheme(&TestString{}))
engine, err := enginePool.GetDataQueryEngine()
assert.NoError(t, err)
_, err = engine.Insert(&TestString{
Id: uuid.NewString(),
Data: &[]string{"a", "b", "c"},
})
assert.NoError(t, err)
var ret TestString
has, err := engine.Get(&ret)
assert.NoError(t, err)
assert.True(t, has)
assert.EqualValues(t, []string{"a", "b", "c"}, *(ret.Data))
for i := 0; i < 10; i++ {
_, err = engine.Insert(&TestString{
Id: uuid.NewString(),
Data: &[]string{"a", "b", "c"},
})
assert.NoError(t, err)
}
var arr []TestString
err = engine.Asc("id").Find(&arr)
assert.NoError(t, err)
for _, v := range arr {
res := *(v.Data)
assert.EqualValues(t, []string{"a", "b", "c"}, res)
}
}
func TestFindCustomTypeAllField(t *testing.T) {
type RowID = uint64
type Str = *string
type Double = *float64
type Timestamp = *sql.NullTime
type Row struct {
ID RowID `xorm:"pk 'id'"`
PayloadStr Str `xorm:"'payload_str'"`
PayloadDouble Double `xorm:"'payload_double'"`
PayloadTimestamp Timestamp `xorm:"'payload_timestamp'"`
}
rows := make([]Row, 0)
for i := 0; i < 10; i++ {
rows = append(rows, Row{
ID: RowID(i),
PayloadStr: func(s string) *string { return &s }(fmt.Sprintf("payload#%d", i)),
PayloadDouble: func(f float64) *float64 { return &f }((float64)(i)),
PayloadTimestamp: func(t sql.NullTime) *sql.NullTime { return &t }(sql.NullTime{Time: time.Now(), Valid: true}),
})
}
assert.NoError(t, PrepareScheme(&Row{}))
engine, err := enginePool.GetScriptQueryEngine()
assert.NoError(t, err)
session := engine.NewSession()
defer session.Close()
_, err = session.Insert(&rows)
assert.NoError(t, err)
cnt, err := session.Count(&Row{})
assert.NoError(t, err)
assert.EqualValues(t, 10, cnt)
res := make([]Row, 0)
err = session.Asc("id").Find(&res)
assert.NoError(t, err)
assert.EqualValues(t, len(rows), len(res))
for i, v := range rows {
assert.EqualValues(t, v.ID, res[i].ID)
assert.EqualValues(t, v.PayloadStr, res[i].PayloadStr)
assert.EqualValues(t, v.PayloadDouble, res[i].PayloadDouble)
assert.EqualValues(t, v.PayloadTimestamp.Time.Unix(), res[i].PayloadTimestamp.Time.Unix())
}
}
func TestFindSqlNullable(t *testing.T) {
type SqlNullable struct {
ID sql.NullInt64 `xorm:"pk 'id'"`
Bool *sql.NullBool `xorm:"'bool'"`
Int32 *sql.NullInt32 `xorm:"'int32'"`
String sql.NullString `xorm:"'string'"`
Time *sql.NullTime `xorm:"'time'"`
}
assert.NoError(t, PrepareScheme(&SqlNullable{}))
engine, err := enginePool.GetDataQueryEngine()
assert.NoError(t, err)
oldTzLoc := engine.GetTZLocation()
oldDbLoc := engine.GetTZDatabase()
defer func() {
engine.SetTZLocation(oldTzLoc)
engine.SetTZDatabase(oldDbLoc)
}()
engine.SetTZLocation(time.UTC)
engine.SetTZDatabase(time.UTC)
data := make([]*SqlNullable, 0)
for i := 0; i < 10; i++ {
data = append(data, &SqlNullable{
ID: sql.NullInt64{Int64: int64(i), Valid: true},
Bool: &sql.NullBool{},
Int32: &sql.NullInt32{Int32: int32(i), Valid: true},
String: sql.NullString{String: fmt.Sprintf("data#%d", i), Valid: true},
Time: &sql.NullTime{Time: time.Now().In(time.UTC), Valid: true},
})
}
session := engine.NewSession()
defer session.Close()
_, err = session.Insert(&data)
assert.NoError(t, err)
res := make([]*SqlNullable, 0)
err = session.Table(&SqlNullable{}).OrderBy("id").Find(&res)
assert.NoError(t, err)
for i, v := range data {
assert.EqualValues(t, v.ID, res[i].ID)
assert.Nil(t, res[i].Bool)
assert.EqualValues(t, v.Int32, res[i].Int32)
assert.EqualValues(t, v.String, res[i].String)
assert.EqualValues(t, v.Time.Time.Format(time.RFC3339), res[i].Time.Time.Format(time.RFC3339))
}
}
func TestFindEmptyField(t *testing.T) {
type EmptyField struct {
ID uint64 `xorm:"pk 'id'"`
Bool bool
Int64 int64
Uint64 uint64
Int32 int32
Uint32 uint32
Uint8 uint8
Float float32
Double float64
Utf8 string
Timestamp sql.NullTime
Interval time.Duration
String []byte
}
PrepareScheme(&EmptyField{})
engine, err := enginePool.GetDataQueryEngine()
assert.NoError(t, err)
assert.NotNil(t, engine)
data := make([]EmptyField, 0)
for i := 0; i < 10; i++ {
data = append(data, EmptyField{
ID: uint64(i),
})
data[i].String = []uint8{}
}
_, err = engine.Insert(&data)
assert.NoError(t, err)
res := make([]EmptyField, 0)
err = engine.Asc("id").Find(&res)
assert.NoError(t, err)
assert.Equal(t, data, res)
}