v0.1.2 Insert function now supports both struct and slice pointer parameters, batch inserting and auto transaction

This commit is contained in:
Lunny Xiao 2013-05-12 21:37:10 +08:00
parent 8c81e70188
commit a2ebf21969
6 changed files with 204 additions and 79 deletions

View File

@ -16,6 +16,7 @@ Drivers for Go's sql package which currently support database/sql includes:
## Changelog ## Changelog
* **v0.1.2** : Insert function now supports both struct and slice pointer parameters, batch inserting and auto transaction
* **v0.1.1** : Add Id, In functions and improved README * **v0.1.1** : Add Id, In functions and improved README
* **v0.1.0** : Inital release. * **v0.1.0** : Inital release.
@ -39,7 +40,7 @@ Drivers for Go's sql package which currently support database/sql includes:
1.Create a database engine just like sql.Open, commonly you just need create once. 1.Create a database engine just like sql.Open, commonly you just need create once.
``` ```Go
import ( import (
_ "github.com/Go-SQL-Driver/MySQL" _ "github.com/Go-SQL-Driver/MySQL"
"github.com/lunny/xorm" "github.com/lunny/xorm"
@ -49,7 +50,7 @@ engine := xorm.Create("mysql", "root:123@/test?charset=utf8")
or or
``` ```Go
import ( import (
_ "github.com/mattn/go-sqlite3" _ "github.com/mattn/go-sqlite3"
"github.com/lunny/xorm" "github.com/lunny/xorm"
@ -59,13 +60,13 @@ engine = xorm.Create("sqlite3", "./test.db")
1.1.If you want to show all generated SQL 1.1.If you want to show all generated SQL
``` ```Go
engine.ShowSQL = true engine.ShowSQL = true
``` ```
2.Define a struct 2.Define a struct
``` ```Go
type User struct { type User struct {
Id int Id int
Name string Name string
@ -77,7 +78,7 @@ type User struct {
3.When you set up your program, you can use CreateTables to create database tables. 3.When you set up your program, you can use CreateTables to create database tables.
``` ```Go
err := engine.CreateTables(&User{}) err := engine.CreateTables(&User{})
// or err := engine.Map(&User{}, &Article{}) // or err := engine.Map(&User{}, &Article{})
// err = engine.CreateAll() // err = engine.CreateAll()
@ -85,13 +86,13 @@ err := engine.CreateTables(&User{})
4.then, insert an struct to table 4.then, insert an struct to table
``` ```Go
id, err := engine.Insert(&User{Name:"lunny"}) id, err := engine.Insert(&User{Name:"lunny"})
``` ```
or if you want to update records or if you want to update records
``` ```Go
user := User{Name:"xlw"} user := User{Name:"xlw"}
rows, err := engine.Update(&user, &User{Id:1}) rows, err := engine.Update(&user, &User{Id:1})
// or rows, err := engine.Where("id = ?", 1).Update(&user) // or rows, err := engine.Where("id = ?", 1).Update(&user)
@ -100,7 +101,7 @@ rows, err := engine.Update(&user, &User{Id:1})
5.Fetch a single object by user 5.Fetch a single object by user
``` ```Go
var user = User{Id:27} var user = User{Id:27}
err := engine.Get(&user) err := engine.Get(&user)
// or err := engine.Id(27).Get(&user) // or err := engine.Id(27).Get(&user)
@ -111,42 +112,42 @@ err := engine.Get(&user)
6.Fetch multipe objects, use Find 6.Fetch multipe objects, use Find
``` ```Go
var everyone []Userinfo var everyone []Userinfo
err := engine.Find(&everyone) err := engine.Find(&everyone)
``` ```
6.1 also you can use Where, Limit 6.1 also you can use Where, Limit
``` ```Go
var allusers []Userinfo var allusers []Userinfo
err := engine.Where("id > ?", "3").Limit(10,20).Find(&allusers) //Get id>3 limit 10 offset 20 err := engine.Where("id > ?", "3").Limit(10,20).Find(&allusers) //Get id>3 limit 10 offset 20
``` ```
6.2 or you can use a struct query 6.2 or you can use a struct query
``` ```Go
var tenusers []Userinfo var tenusers []Userinfo
err := engine.Limit(10).Find(&tenusers, &Userinfo{Name:"xlw"}) //Get All Name="xlw" limit 10 offset 0 err := engine.Limit(10).Find(&tenusers, &Userinfo{Name:"xlw"}) //Get All Name="xlw" limit 10 offset 0
``` ```
6.3 or In function 6.3 or In function
``` ```Go
var tenusers []Userinfo var tenusers []Userinfo
err := engine.In("id", 1, 3, 5).Find(&tenusers) //Get All id in (1, 3, 5) err := engine.In("id", 1, 3, 5).Find(&tenusers) //Get All id in (1, 3, 5)
``` ```
7.Delete 7.Delete
``` ```Go
err := engine.Delete(&User{Id:1}) err := engine.Delete(&User{Id:1})
// or err := engine.Id(1).Delete(&User{}) // or err := engine.Id(1).Delete(&User{})
``` ```
8.Count 8.Count
``` ```Go
total, err := engine.Count(&User{Name:"xlw"}) total, err := engine.Count(&User{Name:"xlw"})
``` ```
@ -155,14 +156,14 @@ Of course, SQL execution is also provided.
1.if select then use Query 1.if select then use Query
``` ```Go
sql := "select * from userinfo" sql := "select * from userinfo"
results, err := engine.Query(sql) results, err := engine.Query(sql)
``` ```
2.if insert, update or delete then use Exec 2.if insert, update or delete then use Exec
``` ```Go
sql = "update userinfo set username=? where id=?" sql = "update userinfo set username=? where id=?"
res, err := engine.Exec(sql, "xiaolun", 1) res, err := engine.Exec(sql, "xiaolun", 1)
``` ```
@ -170,7 +171,7 @@ res, err := engine.Exec(sql, "xiaolun", 1)
##Advanced Usage ##Advanced Usage
for deep usage, you should create a session, this func will create a database connection immediatelly for deep usage, you should create a session, this func will create a database connection immediatelly
``` ```Go
session, err := engine.MakeSession() session, err := engine.MakeSession()
defer session.Close() defer session.Close()
if err != nil { if err != nil {
@ -180,7 +181,7 @@ if err != nil {
1.Fetch a single object by where 1.Fetch a single object by where
``` ```Go
var user Userinfo var user Userinfo
session.Where("id=?", 27).Get(&user) session.Where("id=?", 27).Get(&user)
@ -193,7 +194,7 @@ session.Where("name = ? and age < ?", "john", 88).Get(&user4) // even more compl
2.Fetch multiple objects 2.Fetch multiple objects
``` ```Go
var allusers []Userinfo var allusers []Userinfo
err := session.Where("id > ?", "3").Limit(10,20).Find(&allusers) //Get id>3 limit 10 offset 20 err := session.Where("id > ?", "3").Limit(10,20).Find(&allusers) //Get id>3 limit 10 offset 20
@ -206,7 +207,7 @@ err := session.Find(&everyone)
3.Transaction 3.Transaction
``` ```Go
// add Begin() before any action // add Begin() before any action
session.Begin() session.Begin()
user1 := Userinfo{Username: "xiaoxiao", Departname: "dev", Alias: "lunny", Created: time.Now()} user1 := Userinfo{Username: "xiaoxiao", Departname: "dev", Alias: "lunny", Created: time.Now()}
@ -237,7 +238,7 @@ if err != nil {
4.Mixed Transaction 4.Mixed Transaction
``` ```Go
// add Begin() before any action // add Begin() before any action
session.Begin() session.Begin()
user1 := Userinfo{Username: "xiaoxiao", Departname: "dev", Alias: "lunny", Created: time.Now()} user1 := Userinfo{Username: "xiaoxiao", Departname: "dev", Alias: "lunny", Created: time.Now()}
@ -304,7 +305,7 @@ Another is use field tag, field tag support the below keywords which split with
For Example For Example
``` ```Go
type Userinfo struct { type Userinfo struct {
Uid int `xorm:"id pk not null autoincr"` Uid int `xorm:"id pk not null autoincr"`
Username string Username string
@ -321,7 +322,7 @@ Please visit [GoWalker](http://gowalker.org/github.com/lunny/xorm)
Use space. Use space.
``` ```Go
type User struct { type User struct {
Name string `json:"name" xorm:"name"` Name string `json:"name" xorm:"name"`
} }

View File

@ -14,6 +14,7 @@ xorm是一个Go语言的ORM库. 通过它可以使数据库操作非常简便。
## 更新日志 ## 更新日志
* **v0.1.2** : Insert函数支持混合struct和slice指针传入并根据数据库类型自动批量插入同时自动添加事务
* **v0.1.1** : 添加 Id, In 函数,改善 README 文档 * **v0.1.1** : 添加 Id, In 函数,改善 README 文档
* **v0.1.0** : 初始化工程 * **v0.1.0** : 初始化工程
@ -36,7 +37,7 @@ xorm是一个Go语言的ORM库. 通过它可以使数据库操作非常简便。
1.创建数据库引擎这个函数的参数和sql.Open相同但不会立即创建连接 (例如: mysql) 1.创建数据库引擎这个函数的参数和sql.Open相同但不会立即创建连接 (例如: mysql)
``` ```Go
import ( import (
_ "github.com/Go-SQL-Driver/MySQL" _ "github.com/Go-SQL-Driver/MySQL"
"github.com/lunny/xorm" "github.com/lunny/xorm"
@ -46,7 +47,7 @@ engine := xorm.Create("mysql", "root:123@/test?charset=utf8")
or or
``` ```Go
import ( import (
_ "github.com/mattn/go-sqlite3" _ "github.com/mattn/go-sqlite3"
"github.com/lunny/xorm" "github.com/lunny/xorm"
@ -56,13 +57,13 @@ engine = xorm.Create("sqlite3", "./test.db")
1.1.默认将不会显示自动生成的SQL语句如果要显示则需要设置 1.1.默认将不会显示自动生成的SQL语句如果要显示则需要设置
``` ```Go
engine.ShowSQL = true engine.ShowSQL = true
``` ```
2.所有的ORM操作都针对一个或多个结构体一个结构体对应一张表定义一个结构体如下 2.所有的ORM操作都针对一个或多个结构体一个结构体对应一张表定义一个结构体如下
``` ```Go
type User struct { type User struct {
Id int Id int
Name string Name string
@ -74,19 +75,19 @@ type User struct {
3.在程序初始化时,可能会需要创建表 3.在程序初始化时,可能会需要创建表
``` ```Go
err := engine.CreateTables(&User{}) err := engine.CreateTables(&User{})
``` ```
4.然后,可以将一个结构体作为一条记录插入到表中。 4.然后,可以将一个结构体作为一条记录插入到表中。
``` ```Go
id, err := engine.Insert(&User{Name:"lunny"}) id, err := engine.Insert(&User{Name:"lunny"})
``` ```
或者执行更新操作: 或者执行更新操作:
``` ```Go
user := User{Name:"xlw"} user := User{Name:"xlw"}
rows, err := engine.Update(&user, &User{Id:1}) rows, err := engine.Update(&user, &User{Id:1})
// rows, err := engine.Where("id = ?", 1).Update(&user) // rows, err := engine.Where("id = ?", 1).Update(&user)
@ -95,7 +96,7 @@ rows, err := engine.Update(&user, &User{Id:1})
5.获取单个对象可以用Get方法 5.获取单个对象可以用Get方法
``` ```Go
var user = User{Id:27} var user = User{Id:27}
err := engine.Get(&user) err := engine.Get(&user)
// or err := engine.Id(27).Get(&user) // or err := engine.Id(27).Get(&user)
@ -105,42 +106,42 @@ err := engine.Get(&user)
6.获取多个对象可以用Find方法 6.获取多个对象可以用Find方法
``` ```Go
var everyone []Userinfo var everyone []Userinfo
err := engine.Find(&everyone) err := engine.Find(&everyone)
``` ```
6.1 你也可以使用Where和Limit方法设定条件和查询数量 6.1 你也可以使用Where和Limit方法设定条件和查询数量
``` ```Go
var allusers []Userinfo var allusers []Userinfo
err := engine.Where("id > ?", "3").Limit(10,20).Find(&allusers) //Get id>3 limit 10 offset 20 err := engine.Where("id > ?", "3").Limit(10,20).Find(&allusers) //Get id>3 limit 10 offset 20
``` ```
6.2 用一个结构体作为查询条件也是允许的 6.2 用一个结构体作为查询条件也是允许的
``` ```Go
var tenusers []Userinfo var tenusers []Userinfo
err := engine.Limit(10).Find(&tenusers, &Userinfo{Name:"xlw"}) //Get All Name="xlw" limit 10 offset 0 err := engine.Limit(10).Find(&tenusers, &Userinfo{Name:"xlw"}) //Get All Name="xlw" limit 10 offset 0
``` ```
6.3 也可以调用In函数 6.3 也可以调用In函数
``` ```Go
var tenusers []Userinfo var tenusers []Userinfo
err := engine.In("id", 1, 3, 5).Find(&tenusers) //Get All id in (1, 3, 5) err := engine.In("id", 1, 3, 5).Find(&tenusers) //Get All id in (1, 3, 5)
``` ```
7.Delete方法 7.Delete方法
``` ```Go
err := engine.Delete(&User{Id:1}) err := engine.Delete(&User{Id:1})
// or err := engine.Id(1).Delete(&User{}) // or err := engine.Id(1).Delete(&User{})
``` ```
8.Count方法 8.Count方法
``` ```Go
total, err := engine.Count(&User{Name:"xlw"}) total, err := engine.Count(&User{Name:"xlw"})
``` ```
@ -149,14 +150,14 @@ total, err := engine.Count(&User{Name:"xlw"})
如果执行Select请用Query() 如果执行Select请用Query()
``` ```Go
sql := "select * from userinfo" sql := "select * from userinfo"
results, err := engine.Query(sql) results, err := engine.Query(sql)
``` ```
如果执行Insert Update Delete 等操作请用Exec() 如果执行Insert Update Delete 等操作请用Exec()
``` ```Go
sql = "update userinfo set username=? where id=?" sql = "update userinfo set username=? where id=?"
res, err := engine.Exec(sql, "xiaolun", 1) res, err := engine.Exec(sql, "xiaolun", 1)
``` ```
@ -165,7 +166,7 @@ res, err := engine.Exec(sql, "xiaolun", 1)
<a name="mapping" id="mapping"></a> <a name="mapping" id="mapping"></a>
更高级的用法我们必须要使用session对象session对象在创建时会立刻创建一个数据库连接。 更高级的用法我们必须要使用session对象session对象在创建时会立刻创建一个数据库连接。
``` ```Go
session, err := engine.MakeSession() session, err := engine.MakeSession()
defer session.Close() defer session.Close()
if err != nil { if err != nil {
@ -175,7 +176,7 @@ if err != nil {
1.session对象同样也可以查询 1.session对象同样也可以查询
``` ```Go
var user Userinfo var user Userinfo
session.Where("id=?", 27).Get(&user) session.Where("id=?", 27).Get(&user)
@ -188,7 +189,7 @@ session.Where("name = ? and age < ?", "john", 88).Get(&user4) // even more compl
2.获取多个对象 2.获取多个对象
``` ```Go
var allusers []Userinfo var allusers []Userinfo
err := session.Where("id > ?", "3").Limit(10,20).Find(&allusers) //Get id>3 limit 10 offset 20 err := session.Where("id > ?", "3").Limit(10,20).Find(&allusers) //Get id>3 limit 10 offset 20
@ -201,7 +202,7 @@ err := session.Find(&everyone)
3.事务处理 3.事务处理
``` ```Go
// add Begin() before any action // add Begin() before any action
session.Begin() session.Begin()
user1 := Userinfo{Username: "xiaoxiao", Departname: "dev", Alias: "lunny", Created: time.Now()} user1 := Userinfo{Username: "xiaoxiao", Departname: "dev", Alias: "lunny", Created: time.Now()}
@ -232,7 +233,7 @@ if err != nil {
4.混合型事务这个事务中既有直接的SQL语句又有ORM方法 4.混合型事务这个事务中既有直接的SQL语句又有ORM方法
``` ```Go
// add Begin() before any action // add Begin() before any action
session.Begin() session.Begin()
user1 := Userinfo{Username: "xiaoxiao", Departname: "dev", Alias: "lunny", Created: time.Now()} user1 := Userinfo{Username: "xiaoxiao", Departname: "dev", Alias: "lunny", Created: time.Now()}
@ -298,7 +299,7 @@ UserInfo中的成员UserName将会自动对应名为user_name的字段。
</table> </table>
例如: 例如:
``` ```Go
type Userinfo struct { type Userinfo struct {
Uid int `xorm:"id pk not null autoincr"` Uid int `xorm:"id pk not null autoincr"`
Username string Username string
@ -316,7 +317,7 @@ type Userinfo struct {
答案:使用空格分开 答案:使用空格分开
``` ```Go
type User struct { type User struct {
Name string `json:"name" xorm:"name"` Name string `json:"name" xorm:"name"`
} }

View File

@ -23,6 +23,7 @@ type Engine struct {
Tables map[reflect.Type]Table Tables map[reflect.Type]Table
AutoIncrement string AutoIncrement string
ShowSQL bool ShowSQL bool
InsertMany bool
QuoteIdentifier string QuoteIdentifier string
Statement Statement Statement Statement
} }

View File

@ -16,11 +16,13 @@ type Session struct {
Tx *sql.Tx Tx *sql.Tx
Statement Statement Statement Statement
IsAutoCommit bool IsAutoCommit bool
IsCommitedOrRollbacked bool
} }
func (session *Session) Init() { func (session *Session) Init() {
session.Statement = Statement{} session.Statement = Statement{}
session.IsAutoCommit = true session.IsAutoCommit = true
session.IsCommitedOrRollbacked = false
} }
func (session *Session) Close() { func (session *Session) Close() {
@ -69,27 +71,39 @@ func (session *Session) Having(conditions string) *Session {
} }
func (session *Session) Begin() error { func (session *Session) Begin() error {
if session.IsAutoCommit {
session.IsAutoCommit = false session.IsAutoCommit = false
session.IsCommitedOrRollbacked = false
tx, err := session.Db.Begin() tx, err := session.Db.Begin()
session.Tx = tx session.Tx = tx
if session.Engine.ShowSQL { if session.Engine.ShowSQL {
fmt.Println("BEGIN TRANSACTION") fmt.Println("BEGIN TRANSACTION")
} }
return err return err
}
return nil
} }
func (session *Session) Rollback() error { func (session *Session) Rollback() error {
if !session.IsAutoCommit && !session.IsCommitedOrRollbacked {
if session.Engine.ShowSQL { if session.Engine.ShowSQL {
fmt.Println("ROLL BACK") fmt.Println("ROLL BACK")
} }
session.IsCommitedOrRollbacked = true
return session.Tx.Rollback() return session.Tx.Rollback()
}
return nil
} }
func (session *Session) Commit() error { func (session *Session) Commit() error {
if !session.IsAutoCommit && !session.IsCommitedOrRollbacked {
if session.Engine.ShowSQL { if session.Engine.ShowSQL {
fmt.Println("COMMIT") fmt.Println("COMMIT")
} }
session.IsCommitedOrRollbacked = true
return session.Tx.Commit() return session.Tx.Commit()
}
return nil
} }
func (session *Session) scanMapIntoStruct(obj interface{}, objMap map[string][]byte) error { func (session *Session) scanMapIntoStruct(obj interface{}, objMap map[string][]byte) error {
@ -359,13 +373,108 @@ func (session *Session) Query(sql string, paramStr ...interface{}) (resultsSlice
func (session *Session) Insert(beans ...interface{}) (int64, error) { func (session *Session) Insert(beans ...interface{}) (int64, error) {
var lastId int64 = -1 var lastId int64 = -1
var err error = nil
isInTransaction := !session.IsAutoCommit
if !isInTransaction {
session.Begin()
}
for _, bean := range beans { for _, bean := range beans {
lastId, err := session.InsertOne(bean) sliceValue := reflect.Indirect(reflect.ValueOf(bean))
if sliceValue.Kind() == reflect.Slice {
if session.Engine.InsertMany {
lastId, err = session.InsertMulti(bean)
if err != nil { if err != nil {
if !isInTransaction {
session.Rollback()
}
return lastId, err
}
} else {
size := sliceValue.Len()
for i := 0; i < size; i++ {
lastId, err = session.InsertOne(sliceValue.Index(i).Interface())
if err != nil {
if !isInTransaction {
session.Rollback()
}
return lastId, err return lastId, err
} }
} }
return lastId, nil }
} else {
lastId, err = session.InsertOne(bean)
if err != nil {
if !isInTransaction {
session.Rollback()
}
return lastId, err
}
}
}
if !isInTransaction {
err = session.Commit()
}
return lastId, err
}
func (session *Session) InsertMulti(rowsSlicePtr interface{}) (int64, error) {
sliceValue := reflect.Indirect(reflect.ValueOf(rowsSlicePtr))
if sliceValue.Kind() != reflect.Slice {
return -1, errors.New("needs a pointer to a slice")
}
bean := sliceValue.Index(0).Interface()
sliceElementType := Type(bean)
table := session.Engine.Tables[sliceElementType]
session.Statement.Table = &table
size := sliceValue.Len()
colNames := make([]string, 0)
colMultiPlaces := make([]string, 0)
var args = make([]interface{}, 0)
for i := 0; i < size; i++ {
elemValue := sliceValue.Index(i).Interface()
colPlaces := make([]string, 0)
for _, col := range table.Columns {
fieldValue := reflect.Indirect(reflect.ValueOf(elemValue)).FieldByName(col.FieldName)
val := fieldValue.Interface()
if col.IsAutoIncrement && fieldValue.Int() == 0 {
continue
}
args = append(args, val)
if i == 0 {
colNames = append(colNames, col.Name)
}
colPlaces = append(colPlaces, "?")
}
colMultiPlaces = append(colMultiPlaces, strings.Join(colPlaces, ", "))
}
statement := fmt.Sprintf("INSERT INTO %v%v%v (%v) VALUES (%v)",
session.Engine.QuoteIdentifier,
table.Name,
session.Engine.QuoteIdentifier,
strings.Join(colNames, ", "),
strings.Join(colMultiPlaces, "),("))
res, err := session.Exec(statement, args...)
if err != nil {
return -1, err
}
id, err := res.LastInsertId()
if err != nil {
return -1, err
}
return id, nil
} }
func (session *Session) InsertOne(bean interface{}) (int64, error) { func (session *Session) InsertOne(bean interface{}) (int64, error) {

View File

@ -10,6 +10,7 @@ func Create(driverName string, dataSourceName string) Engine {
engine.Tables = make(map[reflect.Type]Table) engine.Tables = make(map[reflect.Type]Table)
engine.Statement.Engine = &engine engine.Statement.Engine = &engine
engine.InsertMany = true
if driverName == SQLITE { if driverName == SQLITE {
engine.AutoIncrement = "AUTOINCREMENT" engine.AutoIncrement = "AUTOINCREMENT"
} else { } else {

View File

@ -106,24 +106,33 @@ func insertAutoIncr(t *testing.T) {
} }
func insertMulti(t *testing.T) { func insertMulti(t *testing.T) {
user1 := Userinfo{Username: "xlw", Departname: "dev", Alias: "lunny2", Created: time.Now()} users := []*Userinfo{
user2 := Userinfo{Username: "xlw2", Departname: "dev", Alias: "lunny3", Created: time.Now()} {Username: "xlw", Departname: "dev", Alias: "lunny2", Created: time.Now()},
_, err := engine.Insert(&user1, &user2) {Username: "xlw2", Departname: "dev", Alias: "lunny3", Created: time.Now()},
}
_, err := engine.Insert(&users)
if err != nil { if err != nil {
t.Error(err) t.Error(err)
} }
engine.InsertMany = false
users = []*Userinfo{
{Username: "xlw9", Departname: "dev", Alias: "lunny9", Created: time.Now()},
{Username: "xlw10", Departname: "dev", Alias: "lunny10", Created: time.Now()},
}
_, err = engine.Insert(&users)
if err != nil {
t.Error(err)
}
engine.InsertMany = true
} }
func insertTwoTable(t *testing.T) { func insertTwoTable(t *testing.T) {
userinfo := Userinfo{Username: "xlw3", Departname: "dev", Alias: "lunny4", Created: time.Now()} userinfo := Userinfo{Username: "xlw3", Departname: "dev", Alias: "lunny4", Created: time.Now()}
uid, err := engine.Insert(&userinfo) userdetail := Userdetail{Uid: 1, Intro: "I'm a very beautiful women.", Profile: "sfsaf"}
if err != nil { _, err := engine.Insert(&userinfo, &userdetail)
t.Error(err)
return
}
userdetail := Userdetail{Uid: int(uid), Intro: "I'm a very beautiful women.", Profile: "sfsaf"}
_, err = engine.Insert(&userdetail)
if err != nil { if err != nil {
t.Error(err) t.Error(err)
} }
@ -199,7 +208,8 @@ func in(t *testing.T) {
} }
fmt.Println(users) fmt.Println(users)
err = engine.Where("id > ?", 2).In("id", 1, 2, 3).Find(&users) ids := []interface{}{1, 2, 3}
err = engine.Where("id > ?", 2).In("id", ids...).Find(&users)
if err != nil { if err != nil {
t.Error(err) t.Error(err)
return return
@ -352,6 +362,7 @@ func TestMysql(t *testing.T) {
exec(t) exec(t)
insertAutoIncr(t) insertAutoIncr(t)
insertMulti(t) insertMulti(t)
insertTwoTable(t)
update(t) update(t)
delete(t) delete(t)
get(t) get(t)
@ -378,6 +389,7 @@ func TestSqlite(t *testing.T) {
exec(t) exec(t)
insertAutoIncr(t) insertAutoIncr(t)
insertMulti(t) insertMulti(t)
insertTwoTable(t)
update(t) update(t)
delete(t) delete(t)
get(t) get(t)