parent
e266fb7af1
commit
7154d2c42d
|
@ -143,7 +143,6 @@ func (engine *Engine) Quote(value string) string {
|
||||||
|
|
||||||
// QuoteTo quotes string and writes into the buffer
|
// QuoteTo quotes string and writes into the buffer
|
||||||
func (engine *Engine) QuoteTo(buf *bytes.Buffer, value string) {
|
func (engine *Engine) QuoteTo(buf *bytes.Buffer, value string) {
|
||||||
|
|
||||||
if buf == nil {
|
if buf == nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
@ -781,6 +780,12 @@ func (engine *Engine) Having(conditions string) *Session {
|
||||||
return session.Having(conditions)
|
return session.Having(conditions)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (engine *Engine) unMapType(t reflect.Type) {
|
||||||
|
engine.mutex.Lock()
|
||||||
|
defer engine.mutex.Unlock()
|
||||||
|
delete(engine.Tables, t)
|
||||||
|
}
|
||||||
|
|
||||||
func (engine *Engine) autoMapType(v reflect.Value) (*core.Table, error) {
|
func (engine *Engine) autoMapType(v reflect.Value) (*core.Table, error) {
|
||||||
t := v.Type()
|
t := v.Type()
|
||||||
engine.mutex.Lock()
|
engine.mutex.Lock()
|
||||||
|
|
|
@ -5,8 +5,11 @@
|
||||||
package xorm
|
package xorm
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"errors"
|
||||||
|
"fmt"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
|
"github.com/go-xorm/core"
|
||||||
"github.com/stretchr/testify/assert"
|
"github.com/stretchr/testify/assert"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -57,3 +60,407 @@ func TestJoinLimit(t *testing.T) {
|
||||||
Find(&salaries)
|
Find(&salaries)
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func assertSync(t *testing.T, beans ...interface{}) {
|
||||||
|
for _, bean := range beans {
|
||||||
|
assert.NoError(t, testEngine.DropTables(bean))
|
||||||
|
assert.NoError(t, testEngine.Sync(bean))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestWhere(t *testing.T) {
|
||||||
|
assert.NoError(t, prepareEngine())
|
||||||
|
|
||||||
|
assertSync(t, new(Userinfo))
|
||||||
|
|
||||||
|
users := make([]Userinfo, 0)
|
||||||
|
err := testEngine.Where("(id) > ?", 2).Find(&users)
|
||||||
|
if err != nil {
|
||||||
|
t.Error(err)
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
fmt.Println(users)
|
||||||
|
|
||||||
|
err = testEngine.Where("(id) > ?", 2).And("(id) < ?", 10).Find(&users)
|
||||||
|
if err != nil {
|
||||||
|
t.Error(err)
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
fmt.Println(users)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestFind(t *testing.T) {
|
||||||
|
assert.NoError(t, prepareEngine())
|
||||||
|
assertSync(t, new(Userinfo))
|
||||||
|
|
||||||
|
users := make([]Userinfo, 0)
|
||||||
|
|
||||||
|
err := testEngine.Find(&users)
|
||||||
|
if err != nil {
|
||||||
|
t.Error(err)
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
for _, user := range users {
|
||||||
|
fmt.Println(user)
|
||||||
|
}
|
||||||
|
|
||||||
|
users2 := make([]Userinfo, 0)
|
||||||
|
userinfo := testEngine.TableMapper.Obj2Table("Userinfo")
|
||||||
|
err = testEngine.Sql("select * from " + testEngine.Quote(userinfo)).Find(&users2)
|
||||||
|
if err != nil {
|
||||||
|
t.Error(err)
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestFind2(t *testing.T) {
|
||||||
|
assert.NoError(t, prepareEngine())
|
||||||
|
users := make([]*Userinfo, 0)
|
||||||
|
|
||||||
|
assertSync(t, new(Userinfo))
|
||||||
|
|
||||||
|
err := testEngine.Find(&users)
|
||||||
|
if err != nil {
|
||||||
|
t.Error(err)
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
for _, user := range users {
|
||||||
|
fmt.Println(user)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
type Team struct {
|
||||||
|
Id int64
|
||||||
|
}
|
||||||
|
|
||||||
|
type TeamUser struct {
|
||||||
|
OrgId int64
|
||||||
|
Uid int64
|
||||||
|
TeamId int64
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestFind3(t *testing.T) {
|
||||||
|
assert.NoError(t, prepareEngine())
|
||||||
|
err := testEngine.Sync2(new(Team), new(TeamUser))
|
||||||
|
if err != nil {
|
||||||
|
t.Error(err)
|
||||||
|
panic(err.Error())
|
||||||
|
}
|
||||||
|
|
||||||
|
var teams []Team
|
||||||
|
err = testEngine.Cols("`team`.id").
|
||||||
|
Where("`team_user`.org_id=?", 1).
|
||||||
|
And("`team_user`.uid=?", 2).
|
||||||
|
Join("INNER", "`team_user`", "`team_user`.team_id=`team`.id").
|
||||||
|
Find(&teams)
|
||||||
|
if err != nil {
|
||||||
|
t.Error(err)
|
||||||
|
panic(err.Error())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestFindMap(t *testing.T) {
|
||||||
|
assert.NoError(t, prepareEngine())
|
||||||
|
assertSync(t, new(Userinfo))
|
||||||
|
|
||||||
|
users := make(map[int64]Userinfo)
|
||||||
|
err := testEngine.Find(&users)
|
||||||
|
if err != nil {
|
||||||
|
t.Error(err)
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
for _, user := range users {
|
||||||
|
fmt.Println(user)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestFindMap2(t *testing.T) {
|
||||||
|
assert.NoError(t, prepareEngine())
|
||||||
|
assertSync(t, new(Userinfo))
|
||||||
|
|
||||||
|
users := make(map[int64]*Userinfo)
|
||||||
|
err := testEngine.Find(&users)
|
||||||
|
if err != nil {
|
||||||
|
t.Error(err)
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
for id, user := range users {
|
||||||
|
fmt.Println(id, user)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestDistinct(t *testing.T) {
|
||||||
|
assert.NoError(t, prepareEngine())
|
||||||
|
assertSync(t, new(Userinfo))
|
||||||
|
|
||||||
|
_, err := testEngine.Insert(&Userinfo{
|
||||||
|
Username: "lunny",
|
||||||
|
})
|
||||||
|
assert.NoError(t, err)
|
||||||
|
|
||||||
|
users := make([]Userinfo, 0)
|
||||||
|
departname := testEngine.TableMapper.Obj2Table("Departname")
|
||||||
|
err = testEngine.Distinct(departname).Find(&users)
|
||||||
|
if err != nil {
|
||||||
|
t.Error(err)
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
if len(users) != 1 {
|
||||||
|
t.Error(err)
|
||||||
|
panic(errors.New("should be one record"))
|
||||||
|
}
|
||||||
|
|
||||||
|
fmt.Println(users)
|
||||||
|
|
||||||
|
type Depart struct {
|
||||||
|
Departname string
|
||||||
|
}
|
||||||
|
|
||||||
|
users2 := make([]Depart, 0)
|
||||||
|
err = testEngine.Distinct(departname).Table(new(Userinfo)).Find(&users2)
|
||||||
|
if err != nil {
|
||||||
|
t.Error(err)
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
if len(users2) != 1 {
|
||||||
|
t.Error(err)
|
||||||
|
panic(errors.New("should be one record"))
|
||||||
|
}
|
||||||
|
fmt.Println(users2)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestOrder(t *testing.T) {
|
||||||
|
assert.NoError(t, prepareEngine())
|
||||||
|
assertSync(t, new(Userinfo))
|
||||||
|
|
||||||
|
users := make([]Userinfo, 0)
|
||||||
|
err := testEngine.OrderBy("id desc").Find(&users)
|
||||||
|
if err != nil {
|
||||||
|
t.Error(err)
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
fmt.Println(users)
|
||||||
|
|
||||||
|
users2 := make([]Userinfo, 0)
|
||||||
|
err = testEngine.Asc("id", "username").Desc("height").Find(&users2)
|
||||||
|
if err != nil {
|
||||||
|
t.Error(err)
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
fmt.Println(users2)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestHaving(t *testing.T) {
|
||||||
|
assert.NoError(t, prepareEngine())
|
||||||
|
assertSync(t, new(Userinfo))
|
||||||
|
|
||||||
|
users := make([]Userinfo, 0)
|
||||||
|
err := testEngine.GroupBy("username").Having("username='xlw'").Find(&users)
|
||||||
|
if err != nil {
|
||||||
|
t.Error(err)
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
fmt.Println(users)
|
||||||
|
|
||||||
|
/*users = make([]Userinfo, 0)
|
||||||
|
err = testEngine.Cols("id, username").GroupBy("username").Having("username='xlw'").Find(&users)
|
||||||
|
if err != nil {
|
||||||
|
t.Error(err)
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
fmt.Println(users)*/
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestOrderSameMapper(t *testing.T) {
|
||||||
|
assert.NoError(t, prepareEngine())
|
||||||
|
testEngine.unMapType(rValue(new(Userinfo)).Type())
|
||||||
|
|
||||||
|
mapper := testEngine.TableMapper
|
||||||
|
testEngine.SetMapper(core.SameMapper{})
|
||||||
|
|
||||||
|
defer func() {
|
||||||
|
testEngine.unMapType(rValue(new(Userinfo)).Type())
|
||||||
|
testEngine.SetMapper(mapper)
|
||||||
|
}()
|
||||||
|
|
||||||
|
assertSync(t, new(Userinfo))
|
||||||
|
|
||||||
|
users := make([]Userinfo, 0)
|
||||||
|
err := testEngine.OrderBy("(id) desc").Find(&users)
|
||||||
|
if err != nil {
|
||||||
|
t.Error(err)
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
fmt.Println(users)
|
||||||
|
|
||||||
|
users2 := make([]Userinfo, 0)
|
||||||
|
err = testEngine.Asc("(id)", "Username").Desc("Height").Find(&users2)
|
||||||
|
if err != nil {
|
||||||
|
t.Error(err)
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
fmt.Println(users2)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestHavingSameMapper(t *testing.T) {
|
||||||
|
assert.NoError(t, prepareEngine())
|
||||||
|
testEngine.unMapType(rValue(new(Userinfo)).Type())
|
||||||
|
|
||||||
|
mapper := testEngine.TableMapper
|
||||||
|
testEngine.SetMapper(core.SameMapper{})
|
||||||
|
defer func() {
|
||||||
|
testEngine.unMapType(rValue(new(Userinfo)).Type())
|
||||||
|
testEngine.SetMapper(mapper)
|
||||||
|
}()
|
||||||
|
assertSync(t, new(Userinfo))
|
||||||
|
|
||||||
|
users := make([]Userinfo, 0)
|
||||||
|
err := testEngine.GroupBy("`Username`").Having("`Username`='xlw'").Find(&users)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
fmt.Println(users)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestFindInts(t *testing.T) {
|
||||||
|
assert.NoError(t, prepareEngine())
|
||||||
|
assertSync(t, new(Userinfo))
|
||||||
|
|
||||||
|
userinfo := testEngine.TableMapper.Obj2Table("Userinfo")
|
||||||
|
var idsInt64 []int64
|
||||||
|
err := testEngine.Table(userinfo).Cols("id").Desc("id").Find(&idsInt64)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
fmt.Println(idsInt64)
|
||||||
|
|
||||||
|
var idsInt32 []int32
|
||||||
|
err = testEngine.Table(userinfo).Cols("id").Desc("id").Find(&idsInt32)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
fmt.Println(idsInt32)
|
||||||
|
|
||||||
|
var idsInt []int
|
||||||
|
err = testEngine.Table(userinfo).Cols("id").Desc("id").Find(&idsInt)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
fmt.Println(idsInt)
|
||||||
|
|
||||||
|
var idsUint []uint
|
||||||
|
err = testEngine.Table(userinfo).Cols("id").Desc("id").Find(&idsUint)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
fmt.Println(idsUint)
|
||||||
|
|
||||||
|
type MyInt int
|
||||||
|
var idsMyInt []MyInt
|
||||||
|
err = testEngine.Table(userinfo).Cols("id").Desc("id").Find(&idsMyInt)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
fmt.Println(idsMyInt)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestFindStrings(t *testing.T) {
|
||||||
|
assert.NoError(t, prepareEngine())
|
||||||
|
assertSync(t, new(Userinfo))
|
||||||
|
userinfo := testEngine.TableMapper.Obj2Table("Userinfo")
|
||||||
|
username := testEngine.ColumnMapper.Obj2Table("Username")
|
||||||
|
var idsString []string
|
||||||
|
err := testEngine.Table(userinfo).Cols(username).Desc("id").Find(&idsString)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
fmt.Println(idsString)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestFindMyString(t *testing.T) {
|
||||||
|
assert.NoError(t, prepareEngine())
|
||||||
|
assertSync(t, new(Userinfo))
|
||||||
|
userinfo := testEngine.TableMapper.Obj2Table("Userinfo")
|
||||||
|
username := testEngine.ColumnMapper.Obj2Table("Username")
|
||||||
|
|
||||||
|
var idsMyString []MyString
|
||||||
|
err := testEngine.Table(userinfo).Cols(username).Desc("id").Find(&idsMyString)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
fmt.Println(idsMyString)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestFindInterface(t *testing.T) {
|
||||||
|
assert.NoError(t, prepareEngine())
|
||||||
|
assertSync(t, new(Userinfo))
|
||||||
|
|
||||||
|
userinfo := testEngine.TableMapper.Obj2Table("Userinfo")
|
||||||
|
username := testEngine.ColumnMapper.Obj2Table("Username")
|
||||||
|
var idsInterface []interface{}
|
||||||
|
err := testEngine.Table(userinfo).Cols(username).Desc("id").Find(&idsInterface)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
fmt.Println(idsInterface)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestFindSliceBytes(t *testing.T) {
|
||||||
|
assert.NoError(t, prepareEngine())
|
||||||
|
assertSync(t, new(Userinfo))
|
||||||
|
|
||||||
|
userinfo := testEngine.TableMapper.Obj2Table("Userinfo")
|
||||||
|
var ids [][][]byte
|
||||||
|
err := testEngine.Table(userinfo).Desc("id").Find(&ids)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
for _, record := range ids {
|
||||||
|
fmt.Println(record)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestFindSlicePtrString(t *testing.T) {
|
||||||
|
assert.NoError(t, prepareEngine())
|
||||||
|
assertSync(t, new(Userinfo))
|
||||||
|
|
||||||
|
userinfo := testEngine.TableMapper.Obj2Table("Userinfo")
|
||||||
|
var ids [][]*string
|
||||||
|
err := testEngine.Table(userinfo).Desc("id").Find(&ids)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
for _, record := range ids {
|
||||||
|
fmt.Println(record)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestFindMapBytes(t *testing.T) {
|
||||||
|
assert.NoError(t, prepareEngine())
|
||||||
|
assertSync(t, new(Userinfo))
|
||||||
|
|
||||||
|
userinfo := testEngine.TableMapper.Obj2Table("Userinfo")
|
||||||
|
var ids []map[string][]byte
|
||||||
|
err := testEngine.Table(userinfo).Desc("id").Find(&ids)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
for _, record := range ids {
|
||||||
|
fmt.Println(record)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestFindMapPtrString(t *testing.T) {
|
||||||
|
assert.NoError(t, prepareEngine())
|
||||||
|
assertSync(t, new(Userinfo))
|
||||||
|
|
||||||
|
userinfo := testEngine.TableMapper.Obj2Table("Userinfo")
|
||||||
|
var ids []map[string]*string
|
||||||
|
err := testEngine.Table(userinfo).Desc("id").Find(&ids)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
for _, record := range ids {
|
||||||
|
fmt.Println(record)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -5,7 +5,9 @@
|
||||||
package xorm
|
package xorm
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"sync"
|
||||||
"testing"
|
"testing"
|
||||||
|
"time"
|
||||||
|
|
||||||
"github.com/stretchr/testify/assert"
|
"github.com/stretchr/testify/assert"
|
||||||
)
|
)
|
||||||
|
@ -72,3 +74,131 @@ func TestUpdateLimit(t *testing.T) {
|
||||||
assert.EqualValues(t, 35, uts[0].Age)
|
assert.EqualValues(t, 35, uts[0].Age)
|
||||||
assert.EqualValues(t, 30, uts[1].Age)
|
assert.EqualValues(t, 30, uts[1].Age)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type ForUpdate struct {
|
||||||
|
Id int64 `xorm:"pk"`
|
||||||
|
Name string
|
||||||
|
}
|
||||||
|
|
||||||
|
func setupForUpdate(engine *Engine) error {
|
||||||
|
v := new(ForUpdate)
|
||||||
|
err := engine.DropTables(v)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
err = engine.CreateTables(v)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
list := []ForUpdate{
|
||||||
|
{1, "data1"},
|
||||||
|
{2, "data2"},
|
||||||
|
{3, "data3"},
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, f := range list {
|
||||||
|
_, err = engine.Insert(f)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestForUpdate(t *testing.T) {
|
||||||
|
if testEngine.DriverName() != "mysql" && testEngine.DriverName() != "mymysql" {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
err := setupForUpdate(testEngine)
|
||||||
|
if err != nil {
|
||||||
|
t.Error(err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
session1 := testEngine.NewSession()
|
||||||
|
session2 := testEngine.NewSession()
|
||||||
|
session3 := testEngine.NewSession()
|
||||||
|
defer session1.Close()
|
||||||
|
defer session2.Close()
|
||||||
|
defer session3.Close()
|
||||||
|
|
||||||
|
// start transaction
|
||||||
|
err = session1.Begin()
|
||||||
|
if err != nil {
|
||||||
|
t.Error(err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// use lock
|
||||||
|
fList := make([]ForUpdate, 0)
|
||||||
|
session1.ForUpdate()
|
||||||
|
session1.Where("(id) = ?", 1)
|
||||||
|
err = session1.Find(&fList)
|
||||||
|
switch {
|
||||||
|
case err != nil:
|
||||||
|
t.Error(err)
|
||||||
|
return
|
||||||
|
case len(fList) != 1:
|
||||||
|
t.Errorf("find not returned single row")
|
||||||
|
return
|
||||||
|
case fList[0].Name != "data1":
|
||||||
|
t.Errorf("for_update.name must be `data1`")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// wait for lock
|
||||||
|
wg := &sync.WaitGroup{}
|
||||||
|
|
||||||
|
// lock is used
|
||||||
|
wg.Add(1)
|
||||||
|
go func() {
|
||||||
|
f2 := new(ForUpdate)
|
||||||
|
session2.Where("(id) = ?", 1).ForUpdate()
|
||||||
|
has, err := session2.Get(f2) // wait release lock
|
||||||
|
switch {
|
||||||
|
case err != nil:
|
||||||
|
t.Error(err)
|
||||||
|
case !has:
|
||||||
|
t.Errorf("cannot find target row. for_update.id = 1")
|
||||||
|
case f2.Name != "updated by session1":
|
||||||
|
t.Errorf("read lock failed")
|
||||||
|
}
|
||||||
|
wg.Done()
|
||||||
|
}()
|
||||||
|
|
||||||
|
// lock is NOT used
|
||||||
|
wg.Add(1)
|
||||||
|
go func() {
|
||||||
|
f3 := new(ForUpdate)
|
||||||
|
session3.Where("(id) = ?", 1)
|
||||||
|
has, err := session3.Get(f3) // wait release lock
|
||||||
|
switch {
|
||||||
|
case err != nil:
|
||||||
|
t.Error(err)
|
||||||
|
case !has:
|
||||||
|
t.Errorf("cannot find target row. for_update.id = 1")
|
||||||
|
case f3.Name != "data1":
|
||||||
|
t.Errorf("read lock failed")
|
||||||
|
}
|
||||||
|
wg.Done()
|
||||||
|
}()
|
||||||
|
|
||||||
|
// wait for go rountines
|
||||||
|
time.Sleep(50 * time.Millisecond)
|
||||||
|
|
||||||
|
f := new(ForUpdate)
|
||||||
|
f.Name = "updated by session1"
|
||||||
|
session1.Where("(id) = ?", 1)
|
||||||
|
session1.Update(f)
|
||||||
|
|
||||||
|
// release lock
|
||||||
|
err = session1.Commit()
|
||||||
|
if err != nil {
|
||||||
|
t.Error(err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
wg.Wait()
|
||||||
|
}
|
||||||
|
|
|
@ -0,0 +1,524 @@
|
||||||
|
// Copyright 2017 The Xorm Authors. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
package xorm
|
||||||
|
|
||||||
|
import (
|
||||||
|
"errors"
|
||||||
|
"fmt"
|
||||||
|
"testing"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"github.com/stretchr/testify/assert"
|
||||||
|
)
|
||||||
|
|
||||||
|
type tempUser struct {
|
||||||
|
Id int64
|
||||||
|
Username string
|
||||||
|
}
|
||||||
|
|
||||||
|
type tempUser2 struct {
|
||||||
|
TempUser tempUser `xorm:"extends"`
|
||||||
|
Departname string
|
||||||
|
}
|
||||||
|
|
||||||
|
type tempUser3 struct {
|
||||||
|
Temp *tempUser `xorm:"extends"`
|
||||||
|
Departname string
|
||||||
|
}
|
||||||
|
|
||||||
|
type tempUser4 struct {
|
||||||
|
TempUser2 tempUser2 `xorm:"extends"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type Userinfo struct {
|
||||||
|
Uid int64 `xorm:"id pk not null autoincr"`
|
||||||
|
Username string `xorm:"unique"`
|
||||||
|
Departname string
|
||||||
|
Alias string `xorm:"-"`
|
||||||
|
Created time.Time
|
||||||
|
Detail Userdetail `xorm:"detail_id int(11)"`
|
||||||
|
Height float64
|
||||||
|
Avatar []byte
|
||||||
|
IsMan bool
|
||||||
|
}
|
||||||
|
|
||||||
|
type Userdetail struct {
|
||||||
|
Id int64
|
||||||
|
Intro string `xorm:"text"`
|
||||||
|
Profile string `xorm:"varchar(2000)"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type UserAndDetail struct {
|
||||||
|
Userinfo `xorm:"extends"`
|
||||||
|
Userdetail `xorm:"extends"`
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestExtends(t *testing.T) {
|
||||||
|
assert.NoError(t, prepareEngine())
|
||||||
|
|
||||||
|
err := testEngine.DropTables(&tempUser2{})
|
||||||
|
if err != nil {
|
||||||
|
t.Error(err)
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
err = testEngine.CreateTables(&tempUser2{})
|
||||||
|
if err != nil {
|
||||||
|
t.Error(err)
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
tu := &tempUser2{tempUser{0, "extends"}, "dev depart"}
|
||||||
|
_, err = testEngine.Insert(tu)
|
||||||
|
if err != nil {
|
||||||
|
t.Error(err)
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
tu2 := &tempUser2{}
|
||||||
|
_, err = testEngine.Get(tu2)
|
||||||
|
if err != nil {
|
||||||
|
t.Error(err)
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
tu3 := &tempUser2{tempUser{0, "extends update"}, ""}
|
||||||
|
_, err = testEngine.Id(tu2.TempUser.Id).Update(tu3)
|
||||||
|
if err != nil {
|
||||||
|
t.Error(err)
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
err = testEngine.DropTables(&tempUser4{})
|
||||||
|
if err != nil {
|
||||||
|
t.Error(err)
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
err = testEngine.CreateTables(&tempUser4{})
|
||||||
|
if err != nil {
|
||||||
|
t.Error(err)
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
tu8 := &tempUser4{tempUser2{tempUser{0, "extends"}, "dev depart"}}
|
||||||
|
_, err = testEngine.Insert(tu8)
|
||||||
|
if err != nil {
|
||||||
|
t.Error(err)
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
tu9 := &tempUser4{}
|
||||||
|
_, err = testEngine.Get(tu9)
|
||||||
|
if err != nil {
|
||||||
|
t.Error(err)
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
if tu9.TempUser2.TempUser.Username != tu8.TempUser2.TempUser.Username || tu9.TempUser2.Departname != tu8.TempUser2.Departname {
|
||||||
|
err = errors.New(fmt.Sprintln("not equal for", tu8, tu9))
|
||||||
|
t.Error(err)
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
tu10 := &tempUser4{tempUser2{tempUser{0, "extends update"}, ""}}
|
||||||
|
_, err = testEngine.Id(tu9.TempUser2.TempUser.Id).Update(tu10)
|
||||||
|
if err != nil {
|
||||||
|
t.Error(err)
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
err = testEngine.DropTables(&tempUser3{})
|
||||||
|
if err != nil {
|
||||||
|
t.Error(err)
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
err = testEngine.CreateTables(&tempUser3{})
|
||||||
|
if err != nil {
|
||||||
|
t.Error(err)
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
tu4 := &tempUser3{&tempUser{0, "extends"}, "dev depart"}
|
||||||
|
_, err = testEngine.Insert(tu4)
|
||||||
|
if err != nil {
|
||||||
|
t.Error(err)
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
tu5 := &tempUser3{}
|
||||||
|
_, err = testEngine.Get(tu5)
|
||||||
|
if err != nil {
|
||||||
|
t.Error(err)
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
if tu5.Temp == nil {
|
||||||
|
err = errors.New("error get data extends")
|
||||||
|
t.Error(err)
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
if tu5.Temp.Id != 1 || tu5.Temp.Username != "extends" ||
|
||||||
|
tu5.Departname != "dev depart" {
|
||||||
|
err = errors.New("error get data extends")
|
||||||
|
t.Error(err)
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
tu6 := &tempUser3{&tempUser{0, "extends update"}, ""}
|
||||||
|
_, err = testEngine.Id(tu5.Temp.Id).Update(tu6)
|
||||||
|
if err != nil {
|
||||||
|
t.Error(err)
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
users := make([]tempUser3, 0)
|
||||||
|
err = testEngine.Find(&users)
|
||||||
|
if err != nil {
|
||||||
|
t.Error(err)
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
if len(users) != 1 {
|
||||||
|
err = errors.New("error get data not 1")
|
||||||
|
t.Error(err)
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
assertSync(t, new(Userinfo), new(Userdetail))
|
||||||
|
|
||||||
|
detail := Userdetail{
|
||||||
|
Intro: "I'm in China",
|
||||||
|
}
|
||||||
|
_, err = testEngine.Insert(&detail)
|
||||||
|
assert.NoError(t, err)
|
||||||
|
|
||||||
|
_, err = testEngine.Insert(&Userinfo{
|
||||||
|
Username: "lunny",
|
||||||
|
Detail: detail,
|
||||||
|
})
|
||||||
|
assert.NoError(t, err)
|
||||||
|
|
||||||
|
var info UserAndDetail
|
||||||
|
qt := testEngine.Quote
|
||||||
|
ui := testEngine.TableMapper.Obj2Table("Userinfo")
|
||||||
|
ud := testEngine.TableMapper.Obj2Table("Userdetail")
|
||||||
|
uiid := testEngine.TableMapper.Obj2Table("Id")
|
||||||
|
udid := "detail_id"
|
||||||
|
sql := fmt.Sprintf("select * from %s, %s where %s.%s = %s.%s",
|
||||||
|
qt(ui), qt(ud), qt(ui), qt(udid), qt(ud), qt(uiid))
|
||||||
|
b, err := testEngine.Sql(sql).NoCascade().Get(&info)
|
||||||
|
if err != nil {
|
||||||
|
t.Error(err)
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
if !b {
|
||||||
|
err = errors.New("should has lest one record")
|
||||||
|
t.Error(err)
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
fmt.Println(info)
|
||||||
|
if info.Userinfo.Uid == 0 || info.Userdetail.Id == 0 {
|
||||||
|
err = errors.New("all of the id should has value")
|
||||||
|
t.Error(err)
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
fmt.Println("----join--info2")
|
||||||
|
var info2 UserAndDetail
|
||||||
|
b, err = testEngine.Table(&Userinfo{}).
|
||||||
|
Join("LEFT", qt(ud), qt(ui)+"."+qt("detail_id")+" = "+qt(ud)+"."+qt(uiid)).
|
||||||
|
NoCascade().Get(&info2)
|
||||||
|
if err != nil {
|
||||||
|
t.Error(err)
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
if !b {
|
||||||
|
err = errors.New("should has lest one record")
|
||||||
|
t.Error(err)
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
if info2.Userinfo.Uid == 0 || info2.Userdetail.Id == 0 {
|
||||||
|
err = errors.New("all of the id should has value")
|
||||||
|
t.Error(err)
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
fmt.Println(info2)
|
||||||
|
|
||||||
|
fmt.Println("----join--infos2")
|
||||||
|
var infos2 = make([]UserAndDetail, 0)
|
||||||
|
err = testEngine.Table(&Userinfo{}).
|
||||||
|
Join("LEFT", qt(ud), qt(ui)+"."+qt("detail_id")+" = "+qt(ud)+"."+qt(uiid)).
|
||||||
|
NoCascade().
|
||||||
|
Find(&infos2)
|
||||||
|
if err != nil {
|
||||||
|
t.Error(err)
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
fmt.Println(infos2)
|
||||||
|
}
|
||||||
|
|
||||||
|
type MessageBase struct {
|
||||||
|
Id int64 `xorm:"int(11) pk autoincr"`
|
||||||
|
TypeId int64 `xorm:"int(11) notnull"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type Message struct {
|
||||||
|
MessageBase `xorm:"extends"`
|
||||||
|
Title string `xorm:"varchar(100) notnull"`
|
||||||
|
Content string `xorm:"text notnull"`
|
||||||
|
Uid int64 `xorm:"int(11) notnull"`
|
||||||
|
ToUid int64 `xorm:"int(11) notnull"`
|
||||||
|
CreateTime time.Time `xorm:"datetime notnull created"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type MessageUser struct {
|
||||||
|
Id int64
|
||||||
|
Name string
|
||||||
|
}
|
||||||
|
|
||||||
|
type MessageType struct {
|
||||||
|
Id int64
|
||||||
|
Name string
|
||||||
|
}
|
||||||
|
|
||||||
|
type MessageExtend3 struct {
|
||||||
|
Message `xorm:"extends"`
|
||||||
|
Sender MessageUser `xorm:"extends"`
|
||||||
|
Receiver MessageUser `xorm:"extends"`
|
||||||
|
Type MessageType `xorm:"extends"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type MessageExtend4 struct {
|
||||||
|
Message `xorm:"extends"`
|
||||||
|
MessageUser `xorm:"extends"`
|
||||||
|
MessageType `xorm:"extends"`
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestExtends2(t *testing.T) {
|
||||||
|
assert.NoError(t, prepareEngine())
|
||||||
|
|
||||||
|
err := testEngine.DropTables(&Message{}, &MessageUser{}, &MessageType{})
|
||||||
|
if err != nil {
|
||||||
|
t.Error(err)
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
err = testEngine.CreateTables(&Message{}, &MessageUser{}, &MessageType{})
|
||||||
|
if err != nil {
|
||||||
|
t.Error(err)
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
var sender = MessageUser{Name: "sender"}
|
||||||
|
var receiver = MessageUser{Name: "receiver"}
|
||||||
|
var msgtype = MessageType{Name: "type"}
|
||||||
|
_, err = testEngine.Insert(&sender, &receiver, &msgtype)
|
||||||
|
if err != nil {
|
||||||
|
t.Error(err)
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
msg := Message{
|
||||||
|
MessageBase: MessageBase{
|
||||||
|
Id: msgtype.Id,
|
||||||
|
},
|
||||||
|
Title: "test",
|
||||||
|
Content: "test",
|
||||||
|
Uid: sender.Id,
|
||||||
|
ToUid: receiver.Id,
|
||||||
|
}
|
||||||
|
_, err = testEngine.Insert(&msg)
|
||||||
|
if err != nil {
|
||||||
|
t.Error(err)
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
var mapper = testEngine.TableMapper.Obj2Table
|
||||||
|
userTableName := mapper("MessageUser")
|
||||||
|
typeTableName := mapper("MessageType")
|
||||||
|
msgTableName := mapper("Message")
|
||||||
|
|
||||||
|
list := make([]Message, 0)
|
||||||
|
err = testEngine.Table(msgTableName).Join("LEFT", []string{userTableName, "sender"}, "`sender`.`"+mapper("Id")+"`=`"+msgTableName+"`.`"+mapper("Uid")+"`").
|
||||||
|
Join("LEFT", []string{userTableName, "receiver"}, "`receiver`.`"+mapper("Id")+"`=`"+msgTableName+"`.`"+mapper("ToUid")+"`").
|
||||||
|
Join("LEFT", []string{typeTableName, "type"}, "`type`.`"+mapper("Id")+"`=`"+msgTableName+"`.`"+mapper("Id")+"`").
|
||||||
|
Find(&list)
|
||||||
|
if err != nil {
|
||||||
|
t.Error(err)
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(list) != 1 {
|
||||||
|
err = errors.New(fmt.Sprintln("should have 1 message, got", len(list)))
|
||||||
|
t.Error(err)
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if list[0].Id != msg.Id {
|
||||||
|
err = errors.New(fmt.Sprintln("should message equal", list[0], msg))
|
||||||
|
t.Error(err)
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestExtends3(t *testing.T) {
|
||||||
|
assert.NoError(t, prepareEngine())
|
||||||
|
|
||||||
|
err := testEngine.DropTables(&Message{}, &MessageUser{}, &MessageType{})
|
||||||
|
if err != nil {
|
||||||
|
t.Error(err)
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
err = testEngine.CreateTables(&Message{}, &MessageUser{}, &MessageType{})
|
||||||
|
if err != nil {
|
||||||
|
t.Error(err)
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
var sender = MessageUser{Name: "sender"}
|
||||||
|
var receiver = MessageUser{Name: "receiver"}
|
||||||
|
var msgtype = MessageType{Name: "type"}
|
||||||
|
_, err = testEngine.Insert(&sender, &receiver, &msgtype)
|
||||||
|
if err != nil {
|
||||||
|
t.Error(err)
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
msg := Message{
|
||||||
|
MessageBase: MessageBase{
|
||||||
|
Id: msgtype.Id,
|
||||||
|
},
|
||||||
|
Title: "test",
|
||||||
|
Content: "test",
|
||||||
|
Uid: sender.Id,
|
||||||
|
ToUid: receiver.Id,
|
||||||
|
}
|
||||||
|
_, err = testEngine.Insert(&msg)
|
||||||
|
if err != nil {
|
||||||
|
t.Error(err)
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
var mapper = testEngine.TableMapper.Obj2Table
|
||||||
|
userTableName := mapper("MessageUser")
|
||||||
|
typeTableName := mapper("MessageType")
|
||||||
|
msgTableName := mapper("Message")
|
||||||
|
|
||||||
|
list := make([]MessageExtend3, 0)
|
||||||
|
err = testEngine.Table(msgTableName).Join("LEFT", []string{userTableName, "sender"}, "`sender`.`"+mapper("Id")+"`=`"+msgTableName+"`.`"+mapper("Uid")+"`").
|
||||||
|
Join("LEFT", []string{userTableName, "receiver"}, "`receiver`.`"+mapper("Id")+"`=`"+msgTableName+"`.`"+mapper("ToUid")+"`").
|
||||||
|
Join("LEFT", []string{typeTableName, "type"}, "`type`.`"+mapper("Id")+"`=`"+msgTableName+"`.`"+mapper("Id")+"`").
|
||||||
|
Find(&list)
|
||||||
|
if err != nil {
|
||||||
|
t.Error(err)
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(list) != 1 {
|
||||||
|
err = errors.New(fmt.Sprintln("should have 1 message, got", len(list)))
|
||||||
|
t.Error(err)
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if list[0].Message.Id != msg.Id {
|
||||||
|
err = errors.New(fmt.Sprintln("should message equal", list[0].Message, msg))
|
||||||
|
t.Error(err)
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if list[0].Sender.Id != sender.Id || list[0].Sender.Name != sender.Name {
|
||||||
|
err = errors.New(fmt.Sprintln("should sender equal", list[0].Sender, sender))
|
||||||
|
t.Error(err)
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if list[0].Receiver.Id != receiver.Id || list[0].Receiver.Name != receiver.Name {
|
||||||
|
err = errors.New(fmt.Sprintln("should receiver equal", list[0].Receiver, receiver))
|
||||||
|
t.Error(err)
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if list[0].Type.Id != msgtype.Id || list[0].Type.Name != msgtype.Name {
|
||||||
|
err = errors.New(fmt.Sprintln("should msgtype equal", list[0].Type, msgtype))
|
||||||
|
t.Error(err)
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestExtends4(t *testing.T) {
|
||||||
|
assert.NoError(t, prepareEngine())
|
||||||
|
|
||||||
|
err := testEngine.DropTables(&Message{}, &MessageUser{}, &MessageType{})
|
||||||
|
if err != nil {
|
||||||
|
t.Error(err)
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
err = testEngine.CreateTables(&Message{}, &MessageUser{}, &MessageType{})
|
||||||
|
if err != nil {
|
||||||
|
t.Error(err)
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
var sender = MessageUser{Name: "sender"}
|
||||||
|
var msgtype = MessageType{Name: "type"}
|
||||||
|
_, err = testEngine.Insert(&sender, &msgtype)
|
||||||
|
if err != nil {
|
||||||
|
t.Error(err)
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
msg := Message{
|
||||||
|
MessageBase: MessageBase{
|
||||||
|
Id: msgtype.Id,
|
||||||
|
},
|
||||||
|
Title: "test",
|
||||||
|
Content: "test",
|
||||||
|
Uid: sender.Id,
|
||||||
|
}
|
||||||
|
_, err = testEngine.Insert(&msg)
|
||||||
|
if err != nil {
|
||||||
|
t.Error(err)
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
var mapper = testEngine.TableMapper.Obj2Table
|
||||||
|
userTableName := mapper("MessageUser")
|
||||||
|
typeTableName := mapper("MessageType")
|
||||||
|
msgTableName := mapper("Message")
|
||||||
|
|
||||||
|
list := make([]MessageExtend4, 0)
|
||||||
|
err = testEngine.Table(msgTableName).Join("LEFT", userTableName, "`"+userTableName+"`.`"+mapper("Id")+"`=`"+msgTableName+"`.`"+mapper("Uid")+"`").
|
||||||
|
Join("LEFT", typeTableName, "`"+typeTableName+"`.`"+mapper("Id")+"`=`"+msgTableName+"`.`"+mapper("Id")+"`").
|
||||||
|
Find(&list)
|
||||||
|
if err != nil {
|
||||||
|
t.Error(err)
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(list) != 1 {
|
||||||
|
err = errors.New(fmt.Sprintln("should have 1 message, got", len(list)))
|
||||||
|
t.Error(err)
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if list[0].Message.Id != msg.Id {
|
||||||
|
err = errors.New(fmt.Sprintln("should message equal", list[0].Message, msg))
|
||||||
|
t.Error(err)
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if list[0].MessageUser.Id != sender.Id || list[0].MessageUser.Name != sender.Name {
|
||||||
|
err = errors.New(fmt.Sprintln("should sender equal", list[0].MessageUser, sender))
|
||||||
|
t.Error(err)
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if list[0].MessageType.Id != msgtype.Id || list[0].MessageType.Name != msgtype.Name {
|
||||||
|
err = errors.New(fmt.Sprintln("should msgtype equal", list[0].MessageType, msgtype))
|
||||||
|
t.Error(err)
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1 @@
|
||||||
|
go test -db=mysql -conn_str="root:@/xorm_test"
|
|
@ -0,0 +1 @@
|
||||||
|
go test -db=postgres -conn_str="dbname=xorm_test sslmode=disable"
|
|
@ -0,0 +1 @@
|
||||||
|
go test -db=sqlite3 -conn_str="./test.db?cache=shared&mode=rwc"
|
238
types_test.go
238
types_test.go
|
@ -5,8 +5,12 @@
|
||||||
package xorm
|
package xorm
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"encoding/json"
|
||||||
|
"errors"
|
||||||
|
"fmt"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
|
"github.com/go-xorm/core"
|
||||||
"github.com/stretchr/testify/assert"
|
"github.com/stretchr/testify/assert"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -95,3 +99,237 @@ func TestGetBytes(t *testing.T) {
|
||||||
assert.Equal(t, true, has)
|
assert.Equal(t, true, has)
|
||||||
assert.Equal(t, "test", string(b.Data))
|
assert.Equal(t, "test", string(b.Data))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type ConvString string
|
||||||
|
|
||||||
|
func (s *ConvString) FromDB(data []byte) error {
|
||||||
|
*s = ConvString("prefix---" + string(data))
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *ConvString) ToDB() ([]byte, error) {
|
||||||
|
return []byte(string(*s)), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
type ConvConfig struct {
|
||||||
|
Name string
|
||||||
|
Id int64
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *ConvConfig) FromDB(data []byte) error {
|
||||||
|
return json.Unmarshal(data, s)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *ConvConfig) ToDB() ([]byte, error) {
|
||||||
|
return json.Marshal(s)
|
||||||
|
}
|
||||||
|
|
||||||
|
type SliceType []*ConvConfig
|
||||||
|
|
||||||
|
func (s *SliceType) FromDB(data []byte) error {
|
||||||
|
return json.Unmarshal(data, s)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *SliceType) ToDB() ([]byte, error) {
|
||||||
|
return json.Marshal(s)
|
||||||
|
}
|
||||||
|
|
||||||
|
type ConvStruct struct {
|
||||||
|
Conv ConvString
|
||||||
|
Conv2 *ConvString
|
||||||
|
Cfg1 ConvConfig
|
||||||
|
Cfg2 *ConvConfig `xorm:"TEXT"`
|
||||||
|
Cfg3 core.Conversion `xorm:"BLOB"`
|
||||||
|
Slice SliceType
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *ConvStruct) BeforeSet(name string, cell Cell) {
|
||||||
|
if name == "cfg3" || name == "Cfg3" {
|
||||||
|
c.Cfg3 = new(ConvConfig)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestConversion(t *testing.T) {
|
||||||
|
assert.NoError(t, prepareEngine())
|
||||||
|
|
||||||
|
c := new(ConvStruct)
|
||||||
|
assert.NoError(t, testEngine.DropTables(c))
|
||||||
|
assert.NoError(t, testEngine.Sync(c))
|
||||||
|
|
||||||
|
var s ConvString = "sssss"
|
||||||
|
c.Conv = "tttt"
|
||||||
|
c.Conv2 = &s
|
||||||
|
c.Cfg1 = ConvConfig{"mm", 1}
|
||||||
|
c.Cfg2 = &ConvConfig{"xx", 2}
|
||||||
|
c.Cfg3 = &ConvConfig{"zz", 3}
|
||||||
|
c.Slice = []*ConvConfig{{"yy", 4}, {"ff", 5}}
|
||||||
|
|
||||||
|
_, err := testEngine.Insert(c)
|
||||||
|
assert.NoError(t, err)
|
||||||
|
|
||||||
|
c1 := new(ConvStruct)
|
||||||
|
has, err := testEngine.Get(c1)
|
||||||
|
assert.NoError(t, err)
|
||||||
|
assert.True(t, has)
|
||||||
|
assert.EqualValues(t, "prefix---tttt", string(c1.Conv))
|
||||||
|
assert.NotNil(t, c1.Conv2)
|
||||||
|
assert.EqualValues(t, "prefix---"+s, *c1.Conv2)
|
||||||
|
assert.EqualValues(t, c.Cfg1, c1.Cfg1)
|
||||||
|
assert.NotNil(t, c1.Cfg2)
|
||||||
|
assert.EqualValues(t, *c.Cfg2, *c1.Cfg2)
|
||||||
|
assert.NotNil(t, c1.Cfg3)
|
||||||
|
assert.EqualValues(t, *c.Cfg3.(*ConvConfig), *c1.Cfg3.(*ConvConfig))
|
||||||
|
assert.EqualValues(t, 2, len(c1.Slice))
|
||||||
|
assert.EqualValues(t, *c.Slice[0], *c1.Slice[0])
|
||||||
|
assert.EqualValues(t, *c.Slice[1], *c1.Slice[1])
|
||||||
|
}
|
||||||
|
|
||||||
|
type MyInt int
|
||||||
|
type MyUInt uint
|
||||||
|
type MyFloat float64
|
||||||
|
|
||||||
|
type MyStruct struct {
|
||||||
|
Type MyInt
|
||||||
|
U MyUInt
|
||||||
|
F MyFloat
|
||||||
|
S MyString
|
||||||
|
IA []MyInt
|
||||||
|
UA []MyUInt
|
||||||
|
FA []MyFloat
|
||||||
|
SA []MyString
|
||||||
|
NameArray []string
|
||||||
|
Name string
|
||||||
|
UIA []uint
|
||||||
|
UIA8 []uint8
|
||||||
|
UIA16 []uint16
|
||||||
|
UIA32 []uint32
|
||||||
|
UIA64 []uint64
|
||||||
|
UI uint
|
||||||
|
//C64 complex64
|
||||||
|
MSS map[string]string
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestCustomType1(t *testing.T) {
|
||||||
|
assert.NoError(t, prepareEngine())
|
||||||
|
|
||||||
|
err := testEngine.DropTables(&MyStruct{})
|
||||||
|
assert.NoError(t, err)
|
||||||
|
|
||||||
|
err = testEngine.CreateTables(&MyStruct{})
|
||||||
|
assert.NoError(t, err)
|
||||||
|
|
||||||
|
i := MyStruct{Name: "Test", Type: MyInt(1)}
|
||||||
|
i.U = 23
|
||||||
|
i.F = 1.34
|
||||||
|
i.S = "fafdsafdsaf"
|
||||||
|
i.UI = 2
|
||||||
|
i.IA = []MyInt{1, 3, 5}
|
||||||
|
i.UIA = []uint{1, 3}
|
||||||
|
i.UIA16 = []uint16{2}
|
||||||
|
i.UIA32 = []uint32{4, 5}
|
||||||
|
i.UIA64 = []uint64{6, 7, 9}
|
||||||
|
i.UIA8 = []uint8{1, 2, 3, 4}
|
||||||
|
i.NameArray = []string{"ssss", "fsdf", "lllll, ss"}
|
||||||
|
i.MSS = map[string]string{"s": "sfds,ss", "x": "lfjljsl"}
|
||||||
|
|
||||||
|
cnt, err := testEngine.Insert(&i)
|
||||||
|
assert.NoError(t, err)
|
||||||
|
assert.EqualValues(t, 1, cnt)
|
||||||
|
|
||||||
|
fmt.Println(i)
|
||||||
|
i.NameArray = []string{}
|
||||||
|
i.MSS = map[string]string{}
|
||||||
|
i.F = 0
|
||||||
|
has, err := testEngine.Get(&i)
|
||||||
|
assert.NoError(t, err)
|
||||||
|
assert.True(t, has)
|
||||||
|
|
||||||
|
ss := []MyStruct{}
|
||||||
|
err = testEngine.Find(&ss)
|
||||||
|
assert.NoError(t, err)
|
||||||
|
assert.EqualValues(t, 1, len(ss))
|
||||||
|
assert.EqualValues(t, i, ss[0])
|
||||||
|
|
||||||
|
sss := MyStruct{}
|
||||||
|
has, err = testEngine.Get(&sss)
|
||||||
|
assert.NoError(t, err)
|
||||||
|
assert.True(t, has)
|
||||||
|
|
||||||
|
sss.NameArray = []string{}
|
||||||
|
sss.MSS = map[string]string{}
|
||||||
|
cnt, err = testEngine.Delete(&sss)
|
||||||
|
assert.NoError(t, err)
|
||||||
|
assert.EqualValues(t, 1, cnt)
|
||||||
|
}
|
||||||
|
|
||||||
|
type Status struct {
|
||||||
|
Name string
|
||||||
|
Color string
|
||||||
|
}
|
||||||
|
|
||||||
|
var (
|
||||||
|
_ core.Conversion = &Status{}
|
||||||
|
Registed Status = Status{"Registed", "white"}
|
||||||
|
Approved Status = Status{"Approved", "green"}
|
||||||
|
Removed Status = Status{"Removed", "red"}
|
||||||
|
Statuses map[string]Status = map[string]Status{
|
||||||
|
Registed.Name: Registed,
|
||||||
|
Approved.Name: Approved,
|
||||||
|
Removed.Name: Removed,
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
func (s *Status) FromDB(bytes []byte) error {
|
||||||
|
if r, ok := Statuses[string(bytes)]; ok {
|
||||||
|
*s = r
|
||||||
|
return nil
|
||||||
|
} else {
|
||||||
|
return errors.New("no this data")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *Status) ToDB() ([]byte, error) {
|
||||||
|
return []byte(s.Name), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
type UserCus struct {
|
||||||
|
Id int64
|
||||||
|
Name string
|
||||||
|
Status Status `xorm:"varchar(40)"`
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestCustomType2(t *testing.T) {
|
||||||
|
assert.NoError(t, prepareEngine())
|
||||||
|
|
||||||
|
err := testEngine.CreateTables(&UserCus{})
|
||||||
|
assert.NoError(t, err)
|
||||||
|
|
||||||
|
tableName := testEngine.TableMapper.Obj2Table("UserCus")
|
||||||
|
_, err = testEngine.Exec("delete from " + testEngine.Quote(tableName))
|
||||||
|
assert.NoError(t, err)
|
||||||
|
|
||||||
|
if testEngine.Dialect().DBType() == core.MSSQL {
|
||||||
|
return
|
||||||
|
/*_, err = engine.Exec("set IDENTITY_INSERT " + tableName + " on")
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}*/
|
||||||
|
}
|
||||||
|
|
||||||
|
_, err = testEngine.Insert(&UserCus{1, "xlw", Registed})
|
||||||
|
assert.NoError(t, err)
|
||||||
|
|
||||||
|
user := UserCus{}
|
||||||
|
exist, err := testEngine.Id(1).Get(&user)
|
||||||
|
assert.NoError(t, err)
|
||||||
|
assert.True(t, exist)
|
||||||
|
|
||||||
|
fmt.Println(user)
|
||||||
|
|
||||||
|
users := make([]UserCus, 0)
|
||||||
|
err = testEngine.Where("`"+testEngine.ColumnMapper.Obj2Table("Status")+"` = ?", "Registed").Find(&users)
|
||||||
|
assert.NoError(t, err)
|
||||||
|
assert.EqualValues(t, 1, len(users))
|
||||||
|
|
||||||
|
fmt.Println(users)
|
||||||
|
}
|
||||||
|
|
|
@ -58,7 +58,7 @@ func TestMain(m *testing.M) {
|
||||||
dbType = *db
|
dbType = *db
|
||||||
if *db == "sqlite3" {
|
if *db == "sqlite3" {
|
||||||
if ptrConnStr == nil {
|
if ptrConnStr == nil {
|
||||||
connString = "./test.db"
|
connString = "./test.db?cache=shared&mode=rwc"
|
||||||
} else {
|
} else {
|
||||||
connString = *ptrConnStr
|
connString = *ptrConnStr
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue