316 lines
7.3 KiB
Go
316 lines
7.3 KiB
Go
|
package ydb
|
||
|
|
||
|
import (
|
||
|
"database/sql"
|
||
|
"fmt"
|
||
|
"testing"
|
||
|
"time"
|
||
|
|
||
|
"github.com/google/uuid"
|
||
|
"github.com/stretchr/testify/assert"
|
||
|
)
|
||
|
|
||
|
func TestInsertOne(t *testing.T) {
|
||
|
assert.NoError(t, PrepareScheme(&Users{}))
|
||
|
|
||
|
engine, err := enginePool.GetDataQueryEngine()
|
||
|
assert.NoError(t, err)
|
||
|
assert.NotNil(t, engine)
|
||
|
|
||
|
user := Users{
|
||
|
Name: "Dat",
|
||
|
Age: 21,
|
||
|
Account: Account{
|
||
|
UserID: sql.NullInt64{Int64: 1234, Valid: true},
|
||
|
Number: "56789",
|
||
|
},
|
||
|
}
|
||
|
|
||
|
_, err = engine.InsertOne(&user)
|
||
|
assert.NoError(t, err)
|
||
|
|
||
|
has, err := engine.Exist(&user)
|
||
|
assert.NoError(t, err)
|
||
|
assert.True(t, has)
|
||
|
}
|
||
|
|
||
|
func TestInsertMultiStruct(t *testing.T) {
|
||
|
assert.NoError(t, PrepareScheme(&Users{}))
|
||
|
|
||
|
engine, err := enginePool.GetDataQueryEngine()
|
||
|
assert.NoError(t, err)
|
||
|
assert.NotNil(t, engine)
|
||
|
|
||
|
users := getUsersData()
|
||
|
|
||
|
_, err = engine.Insert(&users)
|
||
|
assert.NoError(t, err)
|
||
|
|
||
|
cnt, err := engine.Count(&Users{})
|
||
|
assert.NoError(t, err)
|
||
|
assert.Equal(t, int64(len(users)), cnt)
|
||
|
}
|
||
|
|
||
|
func TestInsertCreated(t *testing.T) {
|
||
|
assert.NoError(t, PrepareScheme(&Users{}))
|
||
|
|
||
|
engine, err := enginePool.GetDataQueryEngine()
|
||
|
assert.NoError(t, err)
|
||
|
assert.NotNil(t, engine)
|
||
|
|
||
|
curTime := time.Now()
|
||
|
users := getUsersData()
|
||
|
|
||
|
_, err = engine.Insert(&users)
|
||
|
assert.NoError(t, err)
|
||
|
|
||
|
err = engine.Table(&Users{}).Cols("created_at").Find(&users)
|
||
|
assert.NoError(t, err)
|
||
|
|
||
|
loc := engine.GetTZLocation()
|
||
|
for _, user := range users {
|
||
|
layout := "2006-01-02 15:04:05"
|
||
|
assert.EqualValues(t, curTime.In(loc).Format(layout), user.Created.In(loc).Format(layout))
|
||
|
}
|
||
|
}
|
||
|
|
||
|
func TestInsertMapInterface(t *testing.T) {
|
||
|
assert.NoError(t, PrepareScheme(&Users{}))
|
||
|
engine, err := enginePool.GetDataQueryEngine()
|
||
|
assert.NoError(t, err)
|
||
|
assert.NotNil(t, engine)
|
||
|
|
||
|
user := map[string]interface{}{
|
||
|
"name": "Dat",
|
||
|
"age": uint32(22),
|
||
|
"user_id": sql.NullInt64{Int64: int64(1), Valid: true},
|
||
|
"number": uuid.NewString(),
|
||
|
}
|
||
|
|
||
|
_, err = engine.Table("users").Insert(user)
|
||
|
assert.NoError(t, err)
|
||
|
|
||
|
res := Users{
|
||
|
Account: Account{
|
||
|
UserID: user["user_id"].(sql.NullInt64),
|
||
|
Number: user["number"].(string),
|
||
|
},
|
||
|
}
|
||
|
has, err := engine.Get(&res)
|
||
|
assert.NoError(t, err)
|
||
|
assert.True(t, has)
|
||
|
|
||
|
assert.Equal(t, res.Name, user["name"])
|
||
|
assert.Equal(t, res.Age, user["age"])
|
||
|
assert.Equal(t, res.UserID, user["user_id"])
|
||
|
assert.Equal(t, res.Number, user["number"])
|
||
|
}
|
||
|
|
||
|
func TestInsertMultiMapInterface(t *testing.T) {
|
||
|
assert.NoError(t, PrepareScheme(&Users{}))
|
||
|
engine, err := enginePool.GetDataQueryEngine()
|
||
|
assert.NoError(t, err)
|
||
|
assert.NotNil(t, engine)
|
||
|
|
||
|
users := []map[string]interface{}{}
|
||
|
|
||
|
for i := 0; i < 20; i++ {
|
||
|
users = append(users, map[string]interface{}{
|
||
|
"name": fmt.Sprintf("Dat - %d", i),
|
||
|
"age": uint32(22 + i),
|
||
|
"user_id": sql.NullInt64{Int64: int64(i + 1), Valid: true},
|
||
|
"number": uuid.NewString(),
|
||
|
})
|
||
|
}
|
||
|
|
||
|
_, err = engine.Table("users").Insert(users)
|
||
|
assert.NoError(t, err)
|
||
|
|
||
|
cnt, err := engine.Table("users").Count()
|
||
|
assert.NoError(t, err)
|
||
|
assert.Equal(t, int64(len(users)), cnt)
|
||
|
}
|
||
|
|
||
|
func TestInsertCustomType(t *testing.T) {
|
||
|
type RowID = uint64
|
||
|
|
||
|
type Row struct {
|
||
|
ID RowID `xorm:"pk 'id'"`
|
||
|
PayloadStr *string `xorm:"'payload_str'"`
|
||
|
PayloadDouble *float64 `xorm:"'payload_double'"`
|
||
|
PayloadTimestamp *time.Time `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 time.Time) *time.Time { return &t }(time.Now()),
|
||
|
})
|
||
|
}
|
||
|
|
||
|
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)
|
||
|
}
|
||
|
|
||
|
func TestInsertWithTableParams(t *testing.T) {
|
||
|
engine, err := enginePool.GetScriptQueryEngine()
|
||
|
assert.NoError(t, err)
|
||
|
assert.NotNil(t, engine)
|
||
|
|
||
|
type SeriesTableWithParams struct {
|
||
|
Hash uint64 `xorm:"pk hash"`
|
||
|
Series *Series `xorm:"extends"`
|
||
|
}
|
||
|
|
||
|
tableParams := map[string]string{
|
||
|
"AUTO_PARTITIONING_BY_SIZE": "ENABLED",
|
||
|
"AUTO_PARTITIONING_BY_LOAD": "ENABLED",
|
||
|
"AUTO_PARTITIONING_PARTITION_SIZE_MB": "1",
|
||
|
"AUTO_PARTITIONING_MIN_PARTITIONS_COUNT": "6",
|
||
|
"AUTO_PARTITIONING_MAX_PARTITIONS_COUNT": "1000",
|
||
|
"UNIFORM_PARTITIONS": "6",
|
||
|
}
|
||
|
|
||
|
engine.Dialect().SetParams(tableParams)
|
||
|
|
||
|
session := engine.NewSession()
|
||
|
defer session.Close()
|
||
|
defer session.Engine().Dialect().SetParams(nil)
|
||
|
|
||
|
err = session.DropTable(&SeriesTableWithParams{})
|
||
|
assert.NoError(t, err)
|
||
|
|
||
|
err = session.CreateTable(&SeriesTableWithParams{})
|
||
|
assert.NoError(t, err)
|
||
|
|
||
|
t.Run("check-YQL-script", func(t *testing.T) {
|
||
|
createTableYQL, _ := session.LastSQL()
|
||
|
for params, value := range tableParams {
|
||
|
pattern := params + `\s*=\s*` + value
|
||
|
assert.Regexp(t, pattern, createTableYQL)
|
||
|
}
|
||
|
})
|
||
|
|
||
|
computeHash := func(bean interface{}) {
|
||
|
data := bean.(*SeriesTableWithParams)
|
||
|
err := session.
|
||
|
DB().
|
||
|
QueryRow(fmt.Sprintf("SELECT Digest::IntHash64(%d)", data.Hash)).
|
||
|
Scan(&data.Hash)
|
||
|
assert.NoError(t, err)
|
||
|
t.Log(data.Hash)
|
||
|
}
|
||
|
|
||
|
for i := uint64(1); i < 100; i++ {
|
||
|
_, err = session.
|
||
|
Before(computeHash).
|
||
|
Insert(&SeriesTableWithParams{
|
||
|
Hash: i,
|
||
|
Series: &Series{
|
||
|
SeriesID: []byte(uuid.New().String()),
|
||
|
ReleaseDate: time.Now(),
|
||
|
},
|
||
|
})
|
||
|
assert.NoError(t, err)
|
||
|
}
|
||
|
}
|
||
|
|
||
|
func TestInsertWithTableParams2(t *testing.T) {
|
||
|
engine, err := enginePool.GetScriptQueryEngine()
|
||
|
assert.NoError(t, err)
|
||
|
assert.NotNil(t, engine)
|
||
|
|
||
|
tableParams := map[string]string{
|
||
|
"AUTO_PARTITIONING_BY_SIZE": "ENABLED",
|
||
|
"AUTO_PARTITIONING_BY_LOAD": "ENABLED",
|
||
|
"AUTO_PARTITIONING_PARTITION_SIZE_MB": "1",
|
||
|
"AUTO_PARTITIONING_MIN_PARTITIONS_COUNT": "3",
|
||
|
"AUTO_PARTITIONING_MAX_PARTITIONS_COUNT": "5",
|
||
|
}
|
||
|
|
||
|
engine.Dialect().SetParams(tableParams)
|
||
|
|
||
|
session := engine.NewSession()
|
||
|
defer session.Close()
|
||
|
defer session.Engine().Dialect().SetParams(nil)
|
||
|
|
||
|
err = session.DropTable(&Series{})
|
||
|
assert.NoError(t, err)
|
||
|
|
||
|
err = session.CreateTable(&Series{})
|
||
|
assert.NoError(t, err)
|
||
|
|
||
|
t.Run("check-YQL-script", func(t *testing.T) {
|
||
|
createTableYQL, _ := session.LastSQL()
|
||
|
for params, value := range tableParams {
|
||
|
pattern := params + `\s*=\s*` + value
|
||
|
assert.Regexp(t, pattern, createTableYQL)
|
||
|
}
|
||
|
})
|
||
|
|
||
|
for i := uint64(1); i < 100; i++ {
|
||
|
s := &Series{
|
||
|
SeriesID: []byte(uuid.New().String()),
|
||
|
Title: fmt.Sprintf("series#%d", i),
|
||
|
SeriesInfo: fmt.Sprintf("series_info#%d", i),
|
||
|
Comment: fmt.Sprintf("comment#%d", i),
|
||
|
}
|
||
|
_, err = session.Insert(s)
|
||
|
assert.NoError(t, err)
|
||
|
}
|
||
|
}
|
||
|
|
||
|
func TestInsertEmptyField(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 time.Time
|
||
|
|
||
|
Interval time.Duration
|
||
|
|
||
|
String []byte
|
||
|
}
|
||
|
|
||
|
PrepareScheme(&EmptyField{})
|
||
|
|
||
|
engine, err := enginePool.GetDataQueryEngine()
|
||
|
assert.NoError(t, err)
|
||
|
assert.NotNil(t, engine)
|
||
|
|
||
|
for i := 0; i < 10; i++ {
|
||
|
_, err = engine.Insert(&EmptyField{
|
||
|
ID: uint64(i),
|
||
|
})
|
||
|
assert.NoError(t, err)
|
||
|
}
|
||
|
}
|