summaryrefslogtreecommitdiffstats
path: root/vendor/github.com/go-xorm/xorm
diff options
context:
space:
mode:
authorLunny Xiao <xiaolunwen@gmail.com>2018-01-27 09:20:59 -0600
committerLauris BH <lauris@nix.lv>2018-01-27 17:20:59 +0200
commit97fe773491ae69531141316a1178d22c8a5d1257 (patch)
tree7b000f9bfd595ef9ac063197ff8a9aa8a1fd22c7 /vendor/github.com/go-xorm/xorm
parenta0c397df08b3e2de0e438a2404dd6f8edf866acb (diff)
downloadgitea-97fe773491ae69531141316a1178d22c8a5d1257.tar.gz
gitea-97fe773491ae69531141316a1178d22c8a5d1257.zip
fix MSSQL bug on org (#3405)
Diffstat (limited to 'vendor/github.com/go-xorm/xorm')
-rw-r--r--vendor/github.com/go-xorm/xorm/CONTRIBUTING.md9
-rw-r--r--vendor/github.com/go-xorm/xorm/README.md155
-rw-r--r--vendor/github.com/go-xorm/xorm/README_CN.md136
-rw-r--r--vendor/github.com/go-xorm/xorm/context.go26
-rw-r--r--vendor/github.com/go-xorm/xorm/convert.go6
-rw-r--r--vendor/github.com/go-xorm/xorm/dialect_postgres.go77
-rw-r--r--vendor/github.com/go-xorm/xorm/engine.go94
-rw-r--r--vendor/github.com/go-xorm/xorm/engine_group.go194
-rw-r--r--vendor/github.com/go-xorm/xorm/engine_group_policy.go116
-rw-r--r--vendor/github.com/go-xorm/xorm/engine_maxlife.go8
-rw-r--r--vendor/github.com/go-xorm/xorm/error.go2
-rw-r--r--vendor/github.com/go-xorm/xorm/interface.go103
-rw-r--r--vendor/github.com/go-xorm/xorm/session.go9
-rw-r--r--vendor/github.com/go-xorm/xorm/session_convert.go14
-rw-r--r--vendor/github.com/go-xorm/xorm/session_exist.go13
-rw-r--r--vendor/github.com/go-xorm/xorm/session_get.go8
-rw-r--r--vendor/github.com/go-xorm/xorm/session_insert.go4
-rw-r--r--vendor/github.com/go-xorm/xorm/session_query.go91
-rw-r--r--vendor/github.com/go-xorm/xorm/session_raw.go13
-rw-r--r--vendor/github.com/go-xorm/xorm/session_update.go21
-rw-r--r--vendor/github.com/go-xorm/xorm/statement.go12
21 files changed, 974 insertions, 137 deletions
diff --git a/vendor/github.com/go-xorm/xorm/CONTRIBUTING.md b/vendor/github.com/go-xorm/xorm/CONTRIBUTING.md
index e0f6cfcdf2..37f4bc5fa8 100644
--- a/vendor/github.com/go-xorm/xorm/CONTRIBUTING.md
+++ b/vendor/github.com/go-xorm/xorm/CONTRIBUTING.md
@@ -32,13 +32,10 @@ proposed functionality.
We appreciate any bug reports, but especially ones with self-contained
(doesn't depend on code outside of xorm), minimal (can't be simplified
further) test cases. It's especially helpful if you can submit a pull
-request with just the failing test case (you'll probably want to
-pattern it after the tests in
-[base.go](https://github.com/go-xorm/tests/blob/master/base.go) AND
-[benchmark.go](https://github.com/go-xorm/tests/blob/master/benchmark.go).
+request with just the failing test case(you can find some example test file like [session_get_test.go](https://github.com/go-xorm/xorm/blob/master/session_get_test.go)).
-If you implements a new database interface, you maybe need to add a <databasename>_test.go file.
-For example, [mysql_test.go](https://github.com/go-xorm/tests/blob/master/mysql/mysql_test.go)
+If you implements a new database interface, you maybe need to add a test_<databasename>.sh file.
+For example, [mysql_test.go](https://github.com/go-xorm/xorm/blob/master/test_mysql.sh)
### New functionality
diff --git a/vendor/github.com/go-xorm/xorm/README.md b/vendor/github.com/go-xorm/xorm/README.md
index c8c43894c3..9f6c20cbda 100644
--- a/vendor/github.com/go-xorm/xorm/README.md
+++ b/vendor/github.com/go-xorm/xorm/README.md
@@ -28,6 +28,8 @@ Xorm is a simple and powerful ORM for Go.
* SQL Builder support via [github.com/go-xorm/builder](https://github.com/go-xorm/builder)
+* Automatical Read/Write seperatelly
+
# Drivers Support
Drivers for Go's sql package which currently support database/sql includes:
@@ -48,6 +50,13 @@ Drivers for Go's sql package which currently support database/sql includes:
# Changelog
+* **v0.6.4**
+ * Automatical Read/Write seperatelly
+ * Query/QueryString/QueryInterface and action with Where/And
+ * Get support non-struct variables
+ * BufferSize on Iterate
+ * fix some other bugs.
+
* **v0.6.3**
* merge tests to main project
* add `Exist` function
@@ -61,13 +70,6 @@ Drivers for Go's sql package which currently support database/sql includes:
* add Scan features to Get
* add QueryString method
-* **v0.6.0**
- * remove support for ql
- * add query condition builder support via [github.com/go-xorm/builder](https://github.com/go-xorm/builder), so `Where`, `And`, `Or`
-methods can use `builder.Cond` as parameter
- * add Sum, SumInt, SumInt64 and NotIn methods
- * some bugs fixed
-
[More changes ...](https://github.com/go-xorm/manual-en-US/tree/master/chapter-16)
# Installation
@@ -106,15 +108,36 @@ type User struct {
err := engine.Sync2(new(User))
```
-* `Query` runs a SQL string, the returned results is `[]map[string][]byte`, `QueryString` returns `[]map[string]string`.
+* Create Engine Group
+
+```Go
+dataSourceNameSlice := []string{masterDataSourceName, slave1DataSourceName, slave2DataSourceName}
+engineGroup, err := xorm.NewEngineGroup(driverName, dataSourceNameSlice)
+```
+
+```Go
+masterEngine, err := xorm.NewEngine(driverName, masterDataSourceName)
+slave1Engine, err := xorm.NewEngine(driverName, slave1DataSourceName)
+slave2Engine, err := xorm.NewEngine(driverName, slave2DataSourceName)
+engineGroup, err := xorm.NewEngineGroup(masterEngine, []*Engine{slave1Engine, slave2Engine})
+```
+
+Then all place where `engine` you can just use `engineGroup`.
+
+* `Query` runs a SQL string, the returned results is `[]map[string][]byte`, `QueryString` returns `[]map[string]string`, `QueryInterface` returns `[]map[string]interface{}`.
```Go
results, err := engine.Query("select * from user")
+results, err := engine.Where("a = 1").Query()
results, err := engine.QueryString("select * from user")
+results, err := engine.Where("a = 1").QueryString()
+
+results, err := engine.QueryInterface("select * from user")
+results, err := engine.Where("a = 1").QueryInterface()
```
-* `Execute` runs a SQL string, it returns `affected` and `error`
+* `Exec` runs a SQL string, it returns `affected` and `error`
```Go
affected, err := engine.Exec("update user set age = ? where name = ?", age, name)
@@ -125,62 +148,76 @@ affected, err := engine.Exec("update user set age = ? where name = ?", age, name
```Go
affected, err := engine.Insert(&user)
// INSERT INTO struct () values ()
+
affected, err := engine.Insert(&user1, &user2)
// INSERT INTO struct1 () values ()
// INSERT INTO struct2 () values ()
+
affected, err := engine.Insert(&users)
// INSERT INTO struct () values (),(),()
+
affected, err := engine.Insert(&user1, &users)
// INSERT INTO struct1 () values ()
// INSERT INTO struct2 () values (),(),()
```
-* Query one record from database
+* `Get` query one record from database
```Go
has, err := engine.Get(&user)
// SELECT * FROM user LIMIT 1
+
has, err := engine.Where("name = ?", name).Desc("id").Get(&user)
// SELECT * FROM user WHERE name = ? ORDER BY id DESC LIMIT 1
+
var name string
has, err := engine.Where("id = ?", id).Cols("name").Get(&name)
// SELECT name FROM user WHERE id = ?
+
var id int64
has, err := engine.Where("name = ?", name).Cols("id").Get(&id)
+has, err := engine.SQL("select id from user").Get(&id)
// SELECT id FROM user WHERE name = ?
+
var valuesMap = make(map[string]string)
has, err := engine.Where("id = ?", id).Get(&valuesMap)
// SELECT * FROM user WHERE id = ?
+
var valuesSlice = make([]interface{}, len(cols))
has, err := engine.Where("id = ?", id).Cols(cols...).Get(&valuesSlice)
// SELECT col1, col2, col3 FROM user WHERE id = ?
```
-* Check if one record exist on table
+* `Exist` check if one record exist on table
```Go
has, err := testEngine.Exist(new(RecordExist))
// SELECT * FROM record_exist LIMIT 1
+
has, err = testEngine.Exist(&RecordExist{
Name: "test1",
})
// SELECT * FROM record_exist WHERE name = ? LIMIT 1
+
has, err = testEngine.Where("name = ?", "test1").Exist(&RecordExist{})
// SELECT * FROM record_exist WHERE name = ? LIMIT 1
+
has, err = testEngine.SQL("select * from record_exist where name = ?", "test1").Exist()
// select * from record_exist where name = ?
+
has, err = testEngine.Table("record_exist").Exist()
// SELECT * FROM record_exist LIMIT 1
+
has, err = testEngine.Table("record_exist").Where("name = ?", "test1").Exist()
// SELECT * FROM record_exist WHERE name = ? LIMIT 1
```
-* Query multiple records from database, also you can use join and extends
+* `Find` query multiple records from database, also you can use join and extends
```Go
var users []User
err := engine.Where("name = ?", name).And("age > 10").Limit(10, 0).Find(&users)
-// SELECT * FROM user WHERE name = ? AND age > 10 limit 0 offset 10
+// SELECT * FROM user WHERE name = ? AND age > 10 limit 10 offset 0
type Detail struct {
Id int64
@@ -193,14 +230,14 @@ type UserDetail struct {
}
var users []UserDetail
-err := engine.Table("user").Select("user.*, detail.*")
+err := engine.Table("user").Select("user.*, detail.*").
Join("INNER", "detail", "detail.user_id = user.id").
Where("user.name = ?", name).Limit(10, 0).
Find(&users)
-// SELECT user.*, detail.* FROM user INNER JOIN detail WHERE user.name = ? limit 0 offset 10
+// SELECT user.*, detail.* FROM user INNER JOIN detail WHERE user.name = ? limit 10 offset 0
```
-* Query multiple records and record by record handle, there are two methods Iterate and Rows
+* `Iterate` and `Rows` query multiple records and record by record handle, there are two methods Iterate and Rows
```Go
err := engine.Iterate(&User{Name:name}, func(idx int, bean interface{}) error {
@@ -209,6 +246,13 @@ err := engine.Iterate(&User{Name:name}, func(idx int, bean interface{}) error {
})
// SELECT * FROM user
+err := engine.BufferSize(100).Iterate(&User{Name:name}, func(idx int, bean interface{}) error {
+ user := bean.(*User)
+ return nil
+})
+// SELECT * FROM user Limit 0, 100
+// SELECT * FROM user Limit 101, 100
+
rows, err := engine.Rows(&User{Name:name})
// SELECT * FROM user
defer rows.Close()
@@ -218,7 +262,7 @@ for rows.Next() {
}
```
-* Update one or more records, default will update non-empty and non-zero fields except when you use Cols, AllCols and so on.
+* `Update` update one or more records, default will update non-empty and non-zero fields except when you use Cols, AllCols and so on.
```Go
affected, err := engine.Id(1).Update(&user)
@@ -243,21 +287,39 @@ affected, err := engine.Id(1).AllCols().Update(&user)
// UPDATE user SET name=?,age=?,salt=?,passwd=?,updated=? Where id = ?
```
-* Delete one or more records, Delete MUST have condition
+* `Delete` delete one or more records, Delete MUST have condition
```Go
affected, err := engine.Where(...).Delete(&user)
// DELETE FROM user Where ...
-affected, err := engine.Id(2).Delete(&user)
+
+affected, err := engine.ID(2).Delete(&user)
+// DELETE FROM user Where id = ?
```
-* Count records
+* `Count` count records
```Go
counts, err := engine.Count(&user)
// SELECT count(*) AS total FROM user
```
+* `Sum` sum functions
+
+```Go
+agesFloat64, err := engine.Sum(&user, "age")
+// SELECT sum(age) AS total FROM user
+
+agesInt64, err := engine.SumInt(&user, "age")
+// SELECT sum(age) AS total FROM user
+
+sumFloat64Slice, err := engine.Sums(&user, "age", "score")
+// SELECT sum(age), sum(score) FROM user
+
+sumInt64Slice, err := engine.SumsInt(&user, "age", "score")
+// SELECT sum(age), sum(score) FROM user
+```
+
* Query conditions builder
```Go
@@ -265,6 +327,59 @@ err := engine.Where(builder.NotIn("a", 1, 2).And(builder.In("b", "c", "d", "e"))
// SELECT id, name ... FROM user WHERE a NOT IN (?, ?) AND b IN (?, ?, ?)
```
+* Multiple operations in one go routine, no transation here but resue session memory
+
+```Go
+session := engine.NewSession()
+defer session.Close()
+
+user1 := Userinfo{Username: "xiaoxiao", Departname: "dev", Alias: "lunny", Created: time.Now()}
+if _, err := session.Insert(&user1); err != nil {
+ return err
+}
+
+user2 := Userinfo{Username: "yyy"}
+if _, err := session.Where("id = ?", 2).Update(&user2); err != nil {
+ return err
+}
+
+if _, err := session.Exec("delete from userinfo where username = ?", user2.Username); err != nil {
+ return err
+}
+
+return nil
+```
+
+* Transation should on one go routine. There is transaction and resue session memory
+
+```Go
+session := engine.NewSession()
+defer session.Close()
+
+// add Begin() before any action
+if err := session.Begin(); err != nil {
+ // if returned then will rollback automatically
+ return err
+}
+
+user1 := Userinfo{Username: "xiaoxiao", Departname: "dev", Alias: "lunny", Created: time.Now()}
+if _, err := session.Insert(&user1); err != nil {
+ return err
+}
+
+user2 := Userinfo{Username: "yyy"}
+if _, err := session.Where("id = ?", 2).Update(&user2); err != nil {
+ return err
+}
+
+if _, err := session.Exec("delete from userinfo where username = ?", user2.Username); err != nil {
+ return err
+}
+
+// add Commit() after all actions
+return session.Commit()
+```
+
# Cases
* [studygolang](http://studygolang.com/) - [github.com/studygolang/studygolang](https://github.com/studygolang/studygolang)
diff --git a/vendor/github.com/go-xorm/xorm/README_CN.md b/vendor/github.com/go-xorm/xorm/README_CN.md
index cb2c1799ea..b4258d5405 100644
--- a/vendor/github.com/go-xorm/xorm/README_CN.md
+++ b/vendor/github.com/go-xorm/xorm/README_CN.md
@@ -115,12 +115,33 @@ type User struct {
err := engine.Sync2(new(User))
```
-* `Query` 最原始的也支持SQL语句查询,返回的结果类型为 []map[string][]byte。`QueryString` 返回 []map[string]string
+* 创建Engine组
+
+```Go
+dataSourceNameSlice := []string{masterDataSourceName, slave1DataSourceName, slave2DataSourceName}
+engineGroup, err := xorm.NewEngineGroup(driverName, dataSourceNameSlice)
+```
+
+```Go
+masterEngine, err := xorm.NewEngine(driverName, masterDataSourceName)
+slave1Engine, err := xorm.NewEngine(driverName, slave1DataSourceName)
+slave2Engine, err := xorm.NewEngine(driverName, slave2DataSourceName)
+engineGroup, err := xorm.NewEngineGroup(masterEngine, []*Engine{slave1Engine, slave2Engine})
+```
+
+所有使用 `engine` 都可以简单的用 `engineGroup` 来替换。
+
+* `Query` 最原始的也支持SQL语句查询,返回的结果类型为 []map[string][]byte。`QueryString` 返回 []map[string]string, `QueryInterface` 返回 `[]map[string]interface{}`.
```Go
results, err := engine.Query("select * from user")
+results, err := engine.Where("a = 1").Query()
results, err := engine.QueryString("select * from user")
+results, err := engine.Where("a = 1").QueryString()
+
+results, err := engine.QueryInterface("select * from user")
+results, err := engine.Where("a = 1").QueryInterface()
```
* `Exec` 执行一个SQL语句
@@ -129,67 +150,81 @@ results, err := engine.QueryString("select * from user")
affected, err := engine.Exec("update user set age = ? where name = ?", age, name)
```
-* 插入一条或者多条记录
+* `Insert` 插入一条或者多条记录
```Go
affected, err := engine.Insert(&user)
// INSERT INTO struct () values ()
+
affected, err := engine.Insert(&user1, &user2)
// INSERT INTO struct1 () values ()
// INSERT INTO struct2 () values ()
+
affected, err := engine.Insert(&users)
// INSERT INTO struct () values (),(),()
+
affected, err := engine.Insert(&user1, &users)
// INSERT INTO struct1 () values ()
// INSERT INTO struct2 () values (),(),()
```
-* 查询单条记录
+* `Get` 查询单条记录
```Go
has, err := engine.Get(&user)
// SELECT * FROM user LIMIT 1
+
has, err := engine.Where("name = ?", name).Desc("id").Get(&user)
// SELECT * FROM user WHERE name = ? ORDER BY id DESC LIMIT 1
+
var name string
has, err := engine.Where("id = ?", id).Cols("name").Get(&name)
// SELECT name FROM user WHERE id = ?
+
var id int64
has, err := engine.Where("name = ?", name).Cols("id").Get(&id)
+has, err := engine.SQL("select id from user").Get(&id)
// SELECT id FROM user WHERE name = ?
+
var valuesMap = make(map[string]string)
has, err := engine.Where("id = ?", id).Get(&valuesMap)
// SELECT * FROM user WHERE id = ?
+
var valuesSlice = make([]interface{}, len(cols))
has, err := engine.Where("id = ?", id).Cols(cols...).Get(&valuesSlice)
// SELECT col1, col2, col3 FROM user WHERE id = ?
```
-* 检测记录是否存在
+* `Exist` 检测记录是否存在
```Go
has, err := testEngine.Exist(new(RecordExist))
// SELECT * FROM record_exist LIMIT 1
+
has, err = testEngine.Exist(&RecordExist{
Name: "test1",
})
// SELECT * FROM record_exist WHERE name = ? LIMIT 1
+
has, err = testEngine.Where("name = ?", "test1").Exist(&RecordExist{})
// SELECT * FROM record_exist WHERE name = ? LIMIT 1
+
has, err = testEngine.SQL("select * from record_exist where name = ?", "test1").Exist()
// select * from record_exist where name = ?
+
has, err = testEngine.Table("record_exist").Exist()
// SELECT * FROM record_exist LIMIT 1
+
has, err = testEngine.Table("record_exist").Where("name = ?", "test1").Exist()
// SELECT * FROM record_exist WHERE name = ? LIMIT 1
```
-* 查询多条记录,当然可以使用Join和extends来组合使用
+* `Find` 查询多条记录,当然可以使用Join和extends来组合使用
```Go
var users []User
err := engine.Where("name = ?", name).And("age > 10").Limit(10, 0).Find(&users)
-// SELECT * FROM user WHERE name = ? AND age > 10 limit 0 offset 10
+// SELECT * FROM user WHERE name = ? AND age > 10 limit 10 offset 0
type Detail struct {
Id int64
@@ -206,10 +241,10 @@ err := engine.Table("user").Select("user.*, detail.*")
Join("INNER", "detail", "detail.user_id = user.id").
Where("user.name = ?", name).Limit(10, 0).
Find(&users)
-// SELECT user.*, detail.* FROM user INNER JOIN detail WHERE user.name = ? limit 0 offset 10
+// SELECT user.*, detail.* FROM user INNER JOIN detail WHERE user.name = ? limit 10 offset 0
```
-* 根据条件遍历数据库,可以有两种方式: Iterate and Rows
+* `Iterate` 和 `Rows` 根据条件遍历数据库,可以有两种方式: Iterate and Rows
```Go
err := engine.Iterate(&User{Name:name}, func(idx int, bean interface{}) error {
@@ -218,6 +253,13 @@ err := engine.Iterate(&User{Name:name}, func(idx int, bean interface{}) error {
})
// SELECT * FROM user
+err := engine.BufferSize(100).Iterate(&User{Name:name}, func(idx int, bean interface{}) error {
+ user := bean.(*User)
+ return nil
+})
+// SELECT * FROM user Limit 0, 100
+// SELECT * FROM user Limit 101, 100
+
rows, err := engine.Rows(&User{Name:name})
// SELECT * FROM user
defer rows.Close()
@@ -227,7 +269,7 @@ for rows.Next() {
}
```
-* 更新数据,除非使用Cols,AllCols函数指明,默认只更新非空和非0的字段
+* `Update` 更新数据,除非使用Cols,AllCols函数指明,默认只更新非空和非0的字段
```Go
affected, err := engine.Id(1).Update(&user)
@@ -252,20 +294,39 @@ affected, err := engine.Id(1).AllCols().Update(&user)
// UPDATE user SET name=?,age=?,salt=?,passwd=?,updated=? Where id = ?
```
-* 删除记录,需要注意,删除必须至少有一个条件,否则会报错。要清空数据库可以用EmptyTable
+* `Delete` 删除记录,需要注意,删除必须至少有一个条件,否则会报错。要清空数据库可以用EmptyTable
```Go
affected, err := engine.Where(...).Delete(&user)
// DELETE FROM user Where ...
+
+affected, err := engine.ID(2).Delete(&user)
+// DELETE FROM user Where id = ?
```
-* 获取记录条数
+* `Count` 获取记录条数
```Go
counts, err := engine.Count(&user)
// SELECT count(*) AS total FROM user
```
+* `Sum` 求和函数
+
+```Go
+agesFloat64, err := engine.Sum(&user, "age")
+// SELECT sum(age) AS total FROM user
+
+agesInt64, err := engine.SumInt(&user, "age")
+// SELECT sum(age) AS total FROM user
+
+sumFloat64Slice, err := engine.Sums(&user, "age", "score")
+// SELECT sum(age), sum(score) FROM user
+
+sumInt64Slice, err := engine.SumsInt(&user, "age", "score")
+// SELECT sum(age), sum(score) FROM user
+```
+
* 条件编辑器
```Go
@@ -273,6 +334,59 @@ err := engine.Where(builder.NotIn("a", 1, 2).And(builder.In("b", "c", "d", "e"))
// SELECT id, name ... FROM user WHERE a NOT IN (?, ?) AND b IN (?, ?, ?)
```
+* 在一个Go程中多次操作数据库,但没有事务
+
+```Go
+session := engine.NewSession()
+defer session.Close()
+
+user1 := Userinfo{Username: "xiaoxiao", Departname: "dev", Alias: "lunny", Created: time.Now()}
+if _, err := session.Insert(&user1); err != nil {
+ return err
+}
+
+user2 := Userinfo{Username: "yyy"}
+if _, err := session.Where("id = ?", 2).Update(&user2); err != nil {
+ return err
+}
+
+if _, err := session.Exec("delete from userinfo where username = ?", user2.Username); err != nil {
+ return err
+}
+
+return nil
+```
+
+* 在一个Go程中有事务
+
+```Go
+session := engine.NewSession()
+defer session.Close()
+
+// add Begin() before any action
+if err := session.Begin(); err != nil {
+ // if returned then will rollback automatically
+ return err
+}
+
+user1 := Userinfo{Username: "xiaoxiao", Departname: "dev", Alias: "lunny", Created: time.Now()}
+if _, err := session.Insert(&user1); err != nil {
+ return err
+}
+
+user2 := Userinfo{Username: "yyy"}
+if _, err := session.Where("id = ?", 2).Update(&user2); err != nil {
+ return err
+}
+
+if _, err := session.Exec("delete from userinfo where username = ?", user2.Username); err != nil {
+ return err
+}
+
+// add Commit() after all actions
+return session.Commit()
+```
+
# 案例
* [Go语言中文网](http://studygolang.com/) - [github.com/studygolang/studygolang](https://github.com/studygolang/studygolang)
diff --git a/vendor/github.com/go-xorm/xorm/context.go b/vendor/github.com/go-xorm/xorm/context.go
new file mode 100644
index 0000000000..074ba35a80
--- /dev/null
+++ b/vendor/github.com/go-xorm/xorm/context.go
@@ -0,0 +1,26 @@
+// 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.
+
+// +build go1.8
+
+package xorm
+
+import "context"
+
+// PingContext tests if database is alive
+func (engine *Engine) PingContext(ctx context.Context) error {
+ session := engine.NewSession()
+ defer session.Close()
+ return session.PingContext(ctx)
+}
+
+// PingContext test if database is ok
+func (session *Session) PingContext(ctx context.Context) error {
+ if session.isAutoClose {
+ defer session.Close()
+ }
+
+ session.engine.logger.Infof("PING DATABASE %v", session.engine.DriverName())
+ return session.DB().PingContext(ctx)
+}
diff --git a/vendor/github.com/go-xorm/xorm/convert.go b/vendor/github.com/go-xorm/xorm/convert.go
index 0504bef155..2316ca0b4d 100644
--- a/vendor/github.com/go-xorm/xorm/convert.go
+++ b/vendor/github.com/go-xorm/xorm/convert.go
@@ -209,10 +209,10 @@ func convertAssign(dest, src interface{}) error {
if src == nil {
dv.Set(reflect.Zero(dv.Type()))
return nil
- } else {
- dv.Set(reflect.New(dv.Type().Elem()))
- return convertAssign(dv.Interface(), src)
}
+
+ dv.Set(reflect.New(dv.Type().Elem()))
+ return convertAssign(dv.Interface(), src)
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
s := asString(src)
i64, err := strconv.ParseInt(s, 10, dv.Type().Bits())
diff --git a/vendor/github.com/go-xorm/xorm/dialect_postgres.go b/vendor/github.com/go-xorm/xorm/dialect_postgres.go
index 3f5c526f72..d6f71acc1d 100644
--- a/vendor/github.com/go-xorm/xorm/dialect_postgres.go
+++ b/vendor/github.com/go-xorm/xorm/dialect_postgres.go
@@ -8,7 +8,6 @@ import (
"errors"
"fmt"
"net/url"
- "sort"
"strconv"
"strings"
@@ -765,13 +764,18 @@ var (
"YES": true,
"ZONE": true,
}
+
+ // DefaultPostgresSchema default postgres schema
+ DefaultPostgresSchema = "public"
)
type postgres struct {
core.Base
+ schema string
}
func (db *postgres) Init(d *core.DB, uri *core.Uri, drivername, dataSourceName string) error {
+ db.schema = DefaultPostgresSchema
return db.Base.Init(d, db, uri, drivername, dataSourceName)
}
@@ -923,7 +927,7 @@ func (db *postgres) IsColumnExist(tableName, colName string) (bool, error) {
func (db *postgres) GetColumns(tableName string) ([]string, map[string]*core.Column, error) {
// FIXME: the schema should be replaced by user custom's
- args := []interface{}{tableName, "public"}
+ args := []interface{}{tableName, db.schema}
s := `SELECT column_name, column_default, is_nullable, data_type, character_maximum_length, numeric_precision, numeric_precision_radix ,
CASE WHEN p.contype = 'p' THEN true ELSE false END AS primarykey,
CASE WHEN p.contype = 'u' THEN true ELSE false END AS uniquekey
@@ -1024,8 +1028,7 @@ WHERE c.relkind = 'r'::char AND c.relname = $1 AND s.table_schema = $2 AND f.att
}
func (db *postgres) GetTables() ([]*core.Table, error) {
- // FIXME: replace public to user customrize schema
- args := []interface{}{"public"}
+ args := []interface{}{db.schema}
s := fmt.Sprintf("SELECT tablename FROM pg_tables WHERE schemaname = $1")
db.LogSQL(s, args)
@@ -1050,8 +1053,7 @@ func (db *postgres) GetTables() ([]*core.Table, error) {
}
func (db *postgres) GetIndexes(tableName string) (map[string]*core.Index, error) {
- // FIXME: replace the public schema to user specify schema
- args := []interface{}{"public", tableName}
+ args := []interface{}{db.schema, tableName}
s := fmt.Sprintf("SELECT indexname, indexdef FROM pg_indexes WHERE schemaname=$1 AND tablename=$2")
db.LogSQL(s, args)
@@ -1117,10 +1119,6 @@ func (vs values) Get(k string) (v string) {
return vs[k]
}
-func errorf(s string, args ...interface{}) {
- panic(fmt.Errorf("pq: %s", fmt.Sprintf(s, args...)))
-}
-
func parseURL(connstr string) (string, error) {
u, err := url.Parse(connstr)
if err != nil {
@@ -1131,46 +1129,18 @@ func parseURL(connstr string) (string, error) {
return "", fmt.Errorf("invalid connection protocol: %s", u.Scheme)
}
- var kvs []string
escaper := strings.NewReplacer(` `, `\ `, `'`, `\'`, `\`, `\\`)
- accrue := func(k, v string) {
- if v != "" {
- kvs = append(kvs, k+"="+escaper.Replace(v))
- }
- }
-
- if u.User != nil {
- v := u.User.Username()
- accrue("user", v)
-
- v, _ = u.User.Password()
- accrue("password", v)
- }
-
- i := strings.Index(u.Host, ":")
- if i < 0 {
- accrue("host", u.Host)
- } else {
- accrue("host", u.Host[:i])
- accrue("port", u.Host[i+1:])
- }
if u.Path != "" {
- accrue("dbname", u.Path[1:])
+ return escaper.Replace(u.Path[1:]), nil
}
- q := u.Query()
- for k := range q {
- accrue(k, q.Get(k))
- }
-
- sort.Strings(kvs) // Makes testing easier (not a performance concern)
- return strings.Join(kvs, " "), nil
+ return "", nil
}
-func parseOpts(name string, o values) {
+func parseOpts(name string, o values) error {
if len(name) == 0 {
- return
+ return fmt.Errorf("invalid options: %s", name)
}
name = strings.TrimSpace(name)
@@ -1179,31 +1149,36 @@ func parseOpts(name string, o values) {
for _, p := range ps {
kv := strings.Split(p, "=")
if len(kv) < 2 {
- errorf("invalid option: %q", p)
+ return fmt.Errorf("invalid option: %q", p)
}
o.Set(kv[0], kv[1])
}
+
+ return nil
}
func (p *pqDriver) Parse(driverName, dataSourceName string) (*core.Uri, error) {
db := &core.Uri{DbType: core.POSTGRES}
- o := make(values)
var err error
+
if strings.HasPrefix(dataSourceName, "postgresql://") || strings.HasPrefix(dataSourceName, "postgres://") {
- dataSourceName, err = parseURL(dataSourceName)
+ db.DbName, err = parseURL(dataSourceName)
+ if err != nil {
+ return nil, err
+ }
+ } else {
+ o := make(values)
+ err = parseOpts(dataSourceName, o)
if err != nil {
return nil, err
}
+
+ db.DbName = o.Get("dbname")
}
- parseOpts(dataSourceName, o)
- db.DbName = o.Get("dbname")
if db.DbName == "" {
return nil, errors.New("dbname is empty")
}
- /*db.Schema = o.Get("schema")
- if len(db.Schema) == 0 {
- db.Schema = "public"
- }*/
+
return db, nil
}
diff --git a/vendor/github.com/go-xorm/xorm/engine.go b/vendor/github.com/go-xorm/xorm/engine.go
index 15c619d33b..444611afb1 100644
--- a/vendor/github.com/go-xorm/xorm/engine.go
+++ b/vendor/github.com/go-xorm/xorm/engine.go
@@ -47,6 +47,23 @@ type Engine struct {
disableGlobalCache bool
tagHandlers map[string]tagHandler
+
+ engineGroup *EngineGroup
+}
+
+// BufferSize sets buffer size for iterate
+func (engine *Engine) BufferSize(size int) *Session {
+ session := engine.NewSession()
+ session.isAutoClose = true
+ return session.BufferSize(size)
+}
+
+// CondDeleted returns the conditions whether a record is soft deleted.
+func (engine *Engine) CondDeleted(colName string) builder.Cond {
+ if engine.dialect.DBType() == core.MSSQL {
+ return builder.IsNull{colName}
+ }
+ return builder.IsNull{colName}.Or(builder.Eq{colName: zeroTime1})
}
// ShowSQL show SQL statement or not on logger if log level is great than INFO
@@ -79,6 +96,11 @@ func (engine *Engine) SetLogger(logger core.ILogger) {
engine.dialect.SetLogger(logger)
}
+// SetLogLevel sets the logger level
+func (engine *Engine) SetLogLevel(level core.LogLevel) {
+ engine.logger.SetLevel(level)
+}
+
// SetDisableGlobalCache disable global cache or not
func (engine *Engine) SetDisableGlobalCache(disable bool) {
if engine.disableGlobalCache != disable {
@@ -201,6 +223,11 @@ func (engine *Engine) SetDefaultCacher(cacher core.Cacher) {
engine.Cacher = cacher
}
+// GetDefaultCacher returns the default cacher
+func (engine *Engine) GetDefaultCacher() core.Cacher {
+ return engine.Cacher
+}
+
// NoCache If you has set default cacher, and you want temporilly stop use cache,
// you can use NoCache()
func (engine *Engine) NoCache() *Session {
@@ -736,6 +763,13 @@ func (engine *Engine) OrderBy(order string) *Session {
return session.OrderBy(order)
}
+// Prepare enables prepare statement
+func (engine *Engine) Prepare() *Session {
+ session := engine.NewSession()
+ session.isAutoClose = true
+ return session.Prepare()
+}
+
// Join the join_operator should be one of INNER, LEFT OUTER, CROSS etc - this will be prepended to JOIN
func (engine *Engine) Join(joinOperator string, tablename interface{}, condition string, args ...interface{}) *Session {
session := engine.NewSession()
@@ -757,7 +791,8 @@ func (engine *Engine) Having(conditions string) *Session {
return session.Having(conditions)
}
-func (engine *Engine) unMapType(t reflect.Type) {
+// UnMapType removes the datbase mapper of a type
+func (engine *Engine) UnMapType(t reflect.Type) {
engine.mutex.Lock()
defer engine.mutex.Unlock()
delete(engine.Tables, t)
@@ -914,7 +949,7 @@ func (engine *Engine) mapType(v reflect.Value) (*core.Table, error) {
}
if pStart > -1 {
if !strings.HasSuffix(k, ")") {
- return nil, errors.New("cannot match ) charactor")
+ return nil, fmt.Errorf("field %s tag %s cannot match ) charactor", col.FieldName, key)
}
ctx.tagName = k[:pStart]
@@ -1341,24 +1376,24 @@ func (engine *Engine) Exec(sql string, args ...interface{}) (sql.Result, error)
}
// Query a raw sql and return records as []map[string][]byte
-func (engine *Engine) Query(sql string, paramStr ...interface{}) (resultsSlice []map[string][]byte, err error) {
+func (engine *Engine) Query(sqlorArgs ...interface{}) (resultsSlice []map[string][]byte, err error) {
session := engine.NewSession()
defer session.Close()
- return session.Query(sql, paramStr...)
+ return session.Query(sqlorArgs...)
}
// QueryString runs a raw sql and return records as []map[string]string
-func (engine *Engine) QueryString(sqlStr string, args ...interface{}) ([]map[string]string, error) {
+func (engine *Engine) QueryString(sqlorArgs ...interface{}) ([]map[string]string, error) {
session := engine.NewSession()
defer session.Close()
- return session.QueryString(sqlStr, args...)
+ return session.QueryString(sqlorArgs...)
}
// QueryInterface runs a raw sql and return records as []map[string]interface{}
-func (engine *Engine) QueryInterface(sqlStr string, args ...interface{}) ([]map[string]interface{}, error) {
+func (engine *Engine) QueryInterface(sqlorArgs ...interface{}) ([]map[string]interface{}, error) {
session := engine.NewSession()
defer session.Close()
- return session.QueryInterface(sqlStr, args...)
+ return session.QueryInterface(sqlorArgs...)
}
// Insert one or more records
@@ -1564,24 +1599,39 @@ func (engine *Engine) formatTime(sqlTypeName string, t time.Time) (v interface{}
return
}
-// Unscoped always disable struct tag "deleted"
-func (engine *Engine) Unscoped() *Session {
- session := engine.NewSession()
- session.isAutoClose = true
- return session.Unscoped()
+// GetColumnMapper returns the column name mapper
+func (engine *Engine) GetColumnMapper() core.IMapper {
+ return engine.ColumnMapper
}
-// CondDeleted returns the conditions whether a record is soft deleted.
-func (engine *Engine) CondDeleted(colName string) builder.Cond {
- if engine.dialect.DBType() == core.MSSQL {
- return builder.IsNull{colName}
- }
- return builder.IsNull{colName}.Or(builder.Eq{colName: zeroTime1})
+// GetTableMapper returns the table name mapper
+func (engine *Engine) GetTableMapper() core.IMapper {
+ return engine.TableMapper
}
-// BufferSize sets buffer size for iterate
-func (engine *Engine) BufferSize(size int) *Session {
+// GetTZLocation returns time zone of the application
+func (engine *Engine) GetTZLocation() *time.Location {
+ return engine.TZLocation
+}
+
+// SetTZLocation sets time zone of the application
+func (engine *Engine) SetTZLocation(tz *time.Location) {
+ engine.TZLocation = tz
+}
+
+// GetTZDatabase returns time zone of the database
+func (engine *Engine) GetTZDatabase() *time.Location {
+ return engine.DatabaseTZ
+}
+
+// SetTZDatabase sets time zone of the database
+func (engine *Engine) SetTZDatabase(tz *time.Location) {
+ engine.DatabaseTZ = tz
+}
+
+// Unscoped always disable struct tag "deleted"
+func (engine *Engine) Unscoped() *Session {
session := engine.NewSession()
session.isAutoClose = true
- return session.BufferSize(size)
+ return session.Unscoped()
}
diff --git a/vendor/github.com/go-xorm/xorm/engine_group.go b/vendor/github.com/go-xorm/xorm/engine_group.go
new file mode 100644
index 0000000000..1de425f372
--- /dev/null
+++ b/vendor/github.com/go-xorm/xorm/engine_group.go
@@ -0,0 +1,194 @@
+// 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 (
+ "github.com/go-xorm/core"
+)
+
+// EngineGroup defines an engine group
+type EngineGroup struct {
+ *Engine
+ slaves []*Engine
+ policy GroupPolicy
+}
+
+// NewEngineGroup creates a new engine group
+func NewEngineGroup(args1 interface{}, args2 interface{}, policies ...GroupPolicy) (*EngineGroup, error) {
+ var eg EngineGroup
+ if len(policies) > 0 {
+ eg.policy = policies[0]
+ } else {
+ eg.policy = RoundRobinPolicy()
+ }
+
+ driverName, ok1 := args1.(string)
+ conns, ok2 := args2.([]string)
+ if ok1 && ok2 {
+ engines := make([]*Engine, len(conns))
+ for i, conn := range conns {
+ engine, err := NewEngine(driverName, conn)
+ if err != nil {
+ return nil, err
+ }
+ engine.engineGroup = &eg
+ engines[i] = engine
+ }
+
+ eg.Engine = engines[0]
+ eg.slaves = engines[1:]
+ return &eg, nil
+ }
+
+ master, ok3 := args1.(*Engine)
+ slaves, ok4 := args2.([]*Engine)
+ if ok3 && ok4 {
+ master.engineGroup = &eg
+ for i := 0; i < len(slaves); i++ {
+ slaves[i].engineGroup = &eg
+ }
+ eg.Engine = master
+ eg.slaves = slaves
+ return &eg, nil
+ }
+ return nil, ErrParamsType
+}
+
+// Close the engine
+func (eg *EngineGroup) Close() error {
+ err := eg.Engine.Close()
+ if err != nil {
+ return err
+ }
+
+ for i := 0; i < len(eg.slaves); i++ {
+ err := eg.slaves[i].Close()
+ if err != nil {
+ return err
+ }
+ }
+ return nil
+}
+
+// Master returns the master engine
+func (eg *EngineGroup) Master() *Engine {
+ return eg.Engine
+}
+
+// Ping tests if database is alive
+func (eg *EngineGroup) Ping() error {
+ if err := eg.Engine.Ping(); err != nil {
+ return err
+ }
+
+ for _, slave := range eg.slaves {
+ if err := slave.Ping(); err != nil {
+ return err
+ }
+ }
+ return nil
+}
+
+// SetColumnMapper set the column name mapping rule
+func (eg *EngineGroup) SetColumnMapper(mapper core.IMapper) {
+ eg.Engine.ColumnMapper = mapper
+ for i := 0; i < len(eg.slaves); i++ {
+ eg.slaves[i].ColumnMapper = mapper
+ }
+}
+
+// SetDefaultCacher set the default cacher
+func (eg *EngineGroup) SetDefaultCacher(cacher core.Cacher) {
+ eg.Engine.SetDefaultCacher(cacher)
+ for i := 0; i < len(eg.slaves); i++ {
+ eg.slaves[i].SetDefaultCacher(cacher)
+ }
+}
+
+// SetLogger set the new logger
+func (eg *EngineGroup) SetLogger(logger core.ILogger) {
+ eg.Engine.SetLogger(logger)
+ for i := 0; i < len(eg.slaves); i++ {
+ eg.slaves[i].SetLogger(logger)
+ }
+}
+
+// SetLogLevel sets the logger level
+func (eg *EngineGroup) SetLogLevel(level core.LogLevel) {
+ eg.Engine.SetLogLevel(level)
+ for i := 0; i < len(eg.slaves); i++ {
+ eg.slaves[i].SetLogLevel(level)
+ }
+}
+
+// SetMapper set the name mapping rules
+func (eg *EngineGroup) SetMapper(mapper core.IMapper) {
+ eg.Engine.SetMapper(mapper)
+ for i := 0; i < len(eg.slaves); i++ {
+ eg.slaves[i].SetMapper(mapper)
+ }
+}
+
+// SetMaxIdleConns set the max idle connections on pool, default is 2
+func (eg *EngineGroup) SetMaxIdleConns(conns int) {
+ eg.Engine.db.SetMaxIdleConns(conns)
+ for i := 0; i < len(eg.slaves); i++ {
+ eg.slaves[i].db.SetMaxIdleConns(conns)
+ }
+}
+
+// SetMaxOpenConns is only available for go 1.2+
+func (eg *EngineGroup) SetMaxOpenConns(conns int) {
+ eg.Engine.db.SetMaxOpenConns(conns)
+ for i := 0; i < len(eg.slaves); i++ {
+ eg.slaves[i].db.SetMaxOpenConns(conns)
+ }
+}
+
+// SetPolicy set the group policy
+func (eg *EngineGroup) SetPolicy(policy GroupPolicy) *EngineGroup {
+ eg.policy = policy
+ return eg
+}
+
+// SetTableMapper set the table name mapping rule
+func (eg *EngineGroup) SetTableMapper(mapper core.IMapper) {
+ eg.Engine.TableMapper = mapper
+ for i := 0; i < len(eg.slaves); i++ {
+ eg.slaves[i].TableMapper = mapper
+ }
+}
+
+// ShowExecTime show SQL statement and execute time or not on logger if log level is great than INFO
+func (eg *EngineGroup) ShowExecTime(show ...bool) {
+ eg.Engine.ShowExecTime(show...)
+ for i := 0; i < len(eg.slaves); i++ {
+ eg.slaves[i].ShowExecTime(show...)
+ }
+}
+
+// ShowSQL show SQL statement or not on logger if log level is great than INFO
+func (eg *EngineGroup) ShowSQL(show ...bool) {
+ eg.Engine.ShowSQL(show...)
+ for i := 0; i < len(eg.slaves); i++ {
+ eg.slaves[i].ShowSQL(show...)
+ }
+}
+
+// Slave returns one of the physical databases which is a slave according the policy
+func (eg *EngineGroup) Slave() *Engine {
+ switch len(eg.slaves) {
+ case 0:
+ return eg.Engine
+ case 1:
+ return eg.slaves[0]
+ }
+ return eg.policy.Slave(eg)
+}
+
+// Slaves returns all the slaves
+func (eg *EngineGroup) Slaves() []*Engine {
+ return eg.slaves
+}
diff --git a/vendor/github.com/go-xorm/xorm/engine_group_policy.go b/vendor/github.com/go-xorm/xorm/engine_group_policy.go
new file mode 100644
index 0000000000..5b56e8995f
--- /dev/null
+++ b/vendor/github.com/go-xorm/xorm/engine_group_policy.go
@@ -0,0 +1,116 @@
+// 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 (
+ "math/rand"
+ "sync"
+ "time"
+)
+
+// GroupPolicy is be used by chosing the current slave from slaves
+type GroupPolicy interface {
+ Slave(*EngineGroup) *Engine
+}
+
+// GroupPolicyHandler should be used when a function is a GroupPolicy
+type GroupPolicyHandler func(*EngineGroup) *Engine
+
+// Slave implements the chosen of slaves
+func (h GroupPolicyHandler) Slave(eg *EngineGroup) *Engine {
+ return h(eg)
+}
+
+// RandomPolicy implmentes randomly chose the slave of slaves
+func RandomPolicy() GroupPolicyHandler {
+ var r = rand.New(rand.NewSource(time.Now().UnixNano()))
+ return func(g *EngineGroup) *Engine {
+ return g.Slaves()[r.Intn(len(g.Slaves()))]
+ }
+}
+
+// WeightRandomPolicy implmentes randomly chose the slave of slaves
+func WeightRandomPolicy(weights []int) GroupPolicyHandler {
+ var rands = make([]int, 0, len(weights))
+ for i := 0; i < len(weights); i++ {
+ for n := 0; n < weights[i]; n++ {
+ rands = append(rands, i)
+ }
+ }
+ var r = rand.New(rand.NewSource(time.Now().UnixNano()))
+
+ return func(g *EngineGroup) *Engine {
+ var slaves = g.Slaves()
+ idx := rands[r.Intn(len(rands))]
+ if idx >= len(slaves) {
+ idx = len(slaves) - 1
+ }
+ return slaves[idx]
+ }
+}
+
+func RoundRobinPolicy() GroupPolicyHandler {
+ var pos = -1
+ var lock sync.Mutex
+ return func(g *EngineGroup) *Engine {
+ var slaves = g.Slaves()
+
+ lock.Lock()
+ defer lock.Unlock()
+ pos++
+ if pos >= len(slaves) {
+ pos = 0
+ }
+
+ return slaves[pos]
+ }
+}
+
+func WeightRoundRobinPolicy(weights []int) GroupPolicyHandler {
+ var rands = make([]int, 0, len(weights))
+ for i := 0; i < len(weights); i++ {
+ for n := 0; n < weights[i]; n++ {
+ rands = append(rands, i)
+ }
+ }
+ var pos = -1
+ var lock sync.Mutex
+
+ return func(g *EngineGroup) *Engine {
+ var slaves = g.Slaves()
+ lock.Lock()
+ defer lock.Unlock()
+ pos++
+ if pos >= len(rands) {
+ pos = 0
+ }
+
+ idx := rands[pos]
+ if idx >= len(slaves) {
+ idx = len(slaves) - 1
+ }
+ return slaves[idx]
+ }
+}
+
+// LeastConnPolicy implements GroupPolicy, every time will get the least connections slave
+func LeastConnPolicy() GroupPolicyHandler {
+ return func(g *EngineGroup) *Engine {
+ var slaves = g.Slaves()
+ connections := 0
+ idx := 0
+ for i := 0; i < len(slaves); i++ {
+ openConnections := slaves[i].DB().Stats().OpenConnections
+ if i == 0 {
+ connections = openConnections
+ idx = i
+ } else if openConnections <= connections {
+ connections = openConnections
+ idx = i
+ }
+ }
+ return slaves[idx]
+ }
+}
diff --git a/vendor/github.com/go-xorm/xorm/engine_maxlife.go b/vendor/github.com/go-xorm/xorm/engine_maxlife.go
index 21daeaa1b8..22666c5f44 100644
--- a/vendor/github.com/go-xorm/xorm/engine_maxlife.go
+++ b/vendor/github.com/go-xorm/xorm/engine_maxlife.go
@@ -12,3 +12,11 @@ import "time"
func (engine *Engine) SetConnMaxLifetime(d time.Duration) {
engine.db.SetConnMaxLifetime(d)
}
+
+// SetConnMaxLifetime sets the maximum amount of time a connection may be reused.
+func (eg *EngineGroup) SetConnMaxLifetime(d time.Duration) {
+ eg.Engine.SetConnMaxLifetime(d)
+ for i := 0; i < len(eg.slaves); i++ {
+ eg.slaves[i].SetConnMaxLifetime(d)
+ }
+}
diff --git a/vendor/github.com/go-xorm/xorm/error.go b/vendor/github.com/go-xorm/xorm/error.go
index 2a334f47c2..cfeefc31e8 100644
--- a/vendor/github.com/go-xorm/xorm/error.go
+++ b/vendor/github.com/go-xorm/xorm/error.go
@@ -23,4 +23,6 @@ var (
ErrNeedDeletedCond = errors.New("Delete need at least one condition")
// ErrNotImplemented not implemented
ErrNotImplemented = errors.New("Not implemented")
+ // ErrConditionType condition type unsupported
+ ErrConditionType = errors.New("Unsupported conditon type")
)
diff --git a/vendor/github.com/go-xorm/xorm/interface.go b/vendor/github.com/go-xorm/xorm/interface.go
new file mode 100644
index 0000000000..9a3b6da0b2
--- /dev/null
+++ b/vendor/github.com/go-xorm/xorm/interface.go
@@ -0,0 +1,103 @@
+// 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 (
+ "database/sql"
+ "reflect"
+ "time"
+
+ "github.com/go-xorm/core"
+)
+
+// Interface defines the interface which Engine, EngineGroup and Session will implementate.
+type Interface interface {
+ AllCols() *Session
+ Alias(alias string) *Session
+ Asc(colNames ...string) *Session
+ BufferSize(size int) *Session
+ Cols(columns ...string) *Session
+ Count(...interface{}) (int64, error)
+ CreateIndexes(bean interface{}) error
+ CreateUniques(bean interface{}) error
+ Decr(column string, arg ...interface{}) *Session
+ Desc(...string) *Session
+ Delete(interface{}) (int64, error)
+ Distinct(columns ...string) *Session
+ DropIndexes(bean interface{}) error
+ Exec(string, ...interface{}) (sql.Result, error)
+ Exist(bean ...interface{}) (bool, error)
+ Find(interface{}, ...interface{}) error
+ Get(interface{}) (bool, error)
+ GroupBy(keys string) *Session
+ ID(interface{}) *Session
+ In(string, ...interface{}) *Session
+ Incr(column string, arg ...interface{}) *Session
+ Insert(...interface{}) (int64, error)
+ InsertOne(interface{}) (int64, error)
+ IsTableEmpty(bean interface{}) (bool, error)
+ IsTableExist(beanOrTableName interface{}) (bool, error)
+ Iterate(interface{}, IterFunc) error
+ Limit(int, ...int) *Session
+ NoAutoCondition(...bool) *Session
+ NotIn(string, ...interface{}) *Session
+ Join(joinOperator string, tablename interface{}, condition string, args ...interface{}) *Session
+ Omit(columns ...string) *Session
+ OrderBy(order string) *Session
+ Ping() error
+ Query(sqlOrAgrs ...interface{}) (resultsSlice []map[string][]byte, err error)
+ QueryInterface(sqlorArgs ...interface{}) ([]map[string]interface{}, error)
+ QueryString(sqlorArgs ...interface{}) ([]map[string]string, error)
+ Rows(bean interface{}) (*Rows, error)
+ SetExpr(string, string) *Session
+ SQL(interface{}, ...interface{}) *Session
+ Sum(bean interface{}, colName string) (float64, error)
+ SumInt(bean interface{}, colName string) (int64, error)
+ Sums(bean interface{}, colNames ...string) ([]float64, error)
+ SumsInt(bean interface{}, colNames ...string) ([]int64, error)
+ Table(tableNameOrBean interface{}) *Session
+ Unscoped() *Session
+ Update(bean interface{}, condiBeans ...interface{}) (int64, error)
+ UseBool(...string) *Session
+ Where(interface{}, ...interface{}) *Session
+}
+
+// EngineInterface defines the interface which Engine, EngineGroup will implementate.
+type EngineInterface interface {
+ Interface
+
+ Before(func(interface{})) *Session
+ Charset(charset string) *Session
+ CreateTables(...interface{}) error
+ DBMetas() ([]*core.Table, error)
+ Dialect() core.Dialect
+ DropTables(...interface{}) error
+ DumpAllToFile(fp string, tp ...core.DbType) error
+ GetColumnMapper() core.IMapper
+ GetDefaultCacher() core.Cacher
+ GetTableMapper() core.IMapper
+ GetTZDatabase() *time.Location
+ GetTZLocation() *time.Location
+ NewSession() *Session
+ NoAutoTime() *Session
+ Quote(string) string
+ SetDefaultCacher(core.Cacher)
+ SetLogLevel(core.LogLevel)
+ SetMapper(core.IMapper)
+ SetTZDatabase(tz *time.Location)
+ SetTZLocation(tz *time.Location)
+ ShowSQL(show ...bool)
+ Sync(...interface{}) error
+ Sync2(...interface{}) error
+ StoreEngine(storeEngine string) *Session
+ TableInfo(bean interface{}) *Table
+ UnMapType(reflect.Type)
+}
+
+var (
+ _ Interface = &Session{}
+ _ EngineInterface = &Engine{}
+ _ EngineInterface = &EngineGroup{}
+)
diff --git a/vendor/github.com/go-xorm/xorm/session.go b/vendor/github.com/go-xorm/xorm/session.go
index ed25205880..5c6cb5f9de 100644
--- a/vendor/github.com/go-xorm/xorm/session.go
+++ b/vendor/github.com/go-xorm/xorm/session.go
@@ -76,6 +76,7 @@ func (session *Session) Init() {
session.afterDeleteBeans = make(map[interface{}]*[]func(interface{}), 0)
session.beforeClosures = make([]func(interface{}), 0)
session.afterClosures = make([]func(interface{}), 0)
+ session.stmtCache = make(map[uint32]*core.Stmt)
session.afterProcessors = make([]executedProcessor, 0)
@@ -262,13 +263,13 @@ func (session *Session) canCache() bool {
return true
}
-func (session *Session) doPrepare(sqlStr string) (stmt *core.Stmt, err error) {
+func (session *Session) doPrepare(db *core.DB, sqlStr string) (stmt *core.Stmt, err error) {
crc := crc32.ChecksumIEEE([]byte(sqlStr))
// TODO try hash(sqlStr+len(sqlStr))
var has bool
stmt, has = session.stmtCache[crc]
if !has {
- stmt, err = session.DB().Prepare(sqlStr)
+ stmt, err = db.Prepare(sqlStr)
if err != nil {
return nil, err
}
@@ -461,6 +462,10 @@ func (session *Session) slice2Bean(scanResults []interface{}, fields []string, b
hasAssigned = true
if len(bs) > 0 {
+ if fieldType.Kind() == reflect.String {
+ fieldValue.SetString(string(bs))
+ continue
+ }
if fieldValue.CanAddr() {
err := json.Unmarshal(bs, fieldValue.Addr().Interface())
if err != nil {
diff --git a/vendor/github.com/go-xorm/xorm/session_convert.go b/vendor/github.com/go-xorm/xorm/session_convert.go
index f2c949bac8..1f9d8aa1bd 100644
--- a/vendor/github.com/go-xorm/xorm/session_convert.go
+++ b/vendor/github.com/go-xorm/xorm/session_convert.go
@@ -34,27 +34,27 @@ func (session *Session) str2Time(col *core.Column, data string) (outTime time.Ti
sd, err := strconv.ParseInt(sdata, 10, 64)
if err == nil {
x = time.Unix(sd, 0)
- session.engine.logger.Debugf("time(0) key[%v]: %+v | sdata: [%v]\n", col.FieldName, x, sdata)
+ //session.engine.logger.Debugf("time(0) key[%v]: %+v | sdata: [%v]\n", col.FieldName, x, sdata)
} else {
- session.engine.logger.Debugf("time(0) err key[%v]: %+v | sdata: [%v]\n", col.FieldName, x, sdata)
+ //session.engine.logger.Debugf("time(0) err key[%v]: %+v | sdata: [%v]\n", col.FieldName, x, sdata)
}
} else if len(sdata) > 19 && strings.Contains(sdata, "-") {
x, err = time.ParseInLocation(time.RFC3339Nano, sdata, parseLoc)
session.engine.logger.Debugf("time(1) key[%v]: %+v | sdata: [%v]\n", col.FieldName, x, sdata)
if err != nil {
x, err = time.ParseInLocation("2006-01-02 15:04:05.999999999", sdata, parseLoc)
- session.engine.logger.Debugf("time(2) key[%v]: %+v | sdata: [%v]\n", col.FieldName, x, sdata)
+ //session.engine.logger.Debugf("time(2) key[%v]: %+v | sdata: [%v]\n", col.FieldName, x, sdata)
}
if err != nil {
x, err = time.ParseInLocation("2006-01-02 15:04:05.9999999 Z07:00", sdata, parseLoc)
- session.engine.logger.Debugf("time(3) key[%v]: %+v | sdata: [%v]\n", col.FieldName, x, sdata)
+ //session.engine.logger.Debugf("time(3) key[%v]: %+v | sdata: [%v]\n", col.FieldName, x, sdata)
}
} else if len(sdata) == 19 && strings.Contains(sdata, "-") {
x, err = time.ParseInLocation("2006-01-02 15:04:05", sdata, parseLoc)
- session.engine.logger.Debugf("time(4) key[%v]: %+v | sdata: [%v]\n", col.FieldName, x, sdata)
+ //session.engine.logger.Debugf("time(4) key[%v]: %+v | sdata: [%v]\n", col.FieldName, x, sdata)
} else if len(sdata) == 10 && sdata[4] == '-' && sdata[7] == '-' {
x, err = time.ParseInLocation("2006-01-02", sdata, parseLoc)
- session.engine.logger.Debugf("time(5) key[%v]: %+v | sdata: [%v]\n", col.FieldName, x, sdata)
+ //session.engine.logger.Debugf("time(5) key[%v]: %+v | sdata: [%v]\n", col.FieldName, x, sdata)
} else if col.SQLType.Name == core.Time {
if strings.Contains(sdata, " ") {
ssd := strings.Split(sdata, " ")
@@ -68,7 +68,7 @@ func (session *Session) str2Time(col *core.Column, data string) (outTime time.Ti
st := fmt.Sprintf("2006-01-02 %v", sdata)
x, err = time.ParseInLocation("2006-01-02 15:04:05", st, parseLoc)
- session.engine.logger.Debugf("time(6) key[%v]: %+v | sdata: [%v]\n", col.FieldName, x, sdata)
+ //session.engine.logger.Debugf("time(6) key[%v]: %+v | sdata: [%v]\n", col.FieldName, x, sdata)
} else {
outErr = fmt.Errorf("unsupported time format %v", sdata)
return
diff --git a/vendor/github.com/go-xorm/xorm/session_exist.go b/vendor/github.com/go-xorm/xorm/session_exist.go
index 049c1ddff1..378a648376 100644
--- a/vendor/github.com/go-xorm/xorm/session_exist.go
+++ b/vendor/github.com/go-xorm/xorm/session_exist.go
@@ -10,6 +10,7 @@ import (
"reflect"
"github.com/go-xorm/builder"
+ "github.com/go-xorm/core"
)
// Exist returns true if the record exist otherwise return false
@@ -35,10 +36,18 @@ func (session *Session) Exist(bean ...interface{}) (bool, error) {
return false, err
}
- sqlStr = fmt.Sprintf("SELECT * FROM %s WHERE %s LIMIT 1", tableName, condSQL)
+ if session.engine.dialect.DBType() == core.MSSQL {
+ sqlStr = fmt.Sprintf("SELECT top 1 * FROM %s WHERE %s", tableName, condSQL)
+ } else {
+ sqlStr = fmt.Sprintf("SELECT * FROM %s WHERE %s LIMIT 1", tableName, condSQL)
+ }
args = condArgs
} else {
- sqlStr = fmt.Sprintf("SELECT * FROM %s LIMIT 1", tableName)
+ if session.engine.dialect.DBType() == core.MSSQL {
+ sqlStr = fmt.Sprintf("SELECT top 1 * FROM %s", tableName)
+ } else {
+ sqlStr = fmt.Sprintf("SELECT * FROM %s LIMIT 1", tableName)
+ }
args = []interface{}{}
}
} else {
diff --git a/vendor/github.com/go-xorm/xorm/session_get.go b/vendor/github.com/go-xorm/xorm/session_get.go
index 8faf53c02c..68b37af7f1 100644
--- a/vendor/github.com/go-xorm/xorm/session_get.go
+++ b/vendor/github.com/go-xorm/xorm/session_get.go
@@ -5,6 +5,7 @@
package xorm
import (
+ "database/sql"
"errors"
"reflect"
"strconv"
@@ -79,6 +80,13 @@ func (session *Session) nocacheGet(beanKind reflect.Kind, table *core.Table, bea
return false, nil
}
+ switch bean.(type) {
+ case sql.NullInt64, sql.NullBool, sql.NullFloat64, sql.NullString:
+ return true, rows.Scan(&bean)
+ case *sql.NullInt64, *sql.NullBool, *sql.NullFloat64, *sql.NullString:
+ return true, rows.Scan(bean)
+ }
+
switch beanKind {
case reflect.Struct:
fields, err := rows.Columns()
diff --git a/vendor/github.com/go-xorm/xorm/session_insert.go b/vendor/github.com/go-xorm/xorm/session_insert.go
index 478501f0b2..129ee23098 100644
--- a/vendor/github.com/go-xorm/xorm/session_insert.go
+++ b/vendor/github.com/go-xorm/xorm/session_insert.go
@@ -400,7 +400,7 @@ func (session *Session) innerInsert(bean interface{}) (int64, error) {
return 0, err
}
- handleAfterInsertProcessorFunc(bean)
+ defer handleAfterInsertProcessorFunc(bean)
if cacher := session.engine.getCacher2(table); cacher != nil && session.statement.UseCache {
session.cacheInsert(table, tableName)
@@ -445,7 +445,7 @@ func (session *Session) innerInsert(bean interface{}) (int64, error) {
if err != nil {
return 0, err
}
- handleAfterInsertProcessorFunc(bean)
+ defer handleAfterInsertProcessorFunc(bean)
if cacher := session.engine.getCacher2(table); cacher != nil && session.statement.UseCache {
session.cacheInsert(table, tableName)
diff --git a/vendor/github.com/go-xorm/xorm/session_query.go b/vendor/github.com/go-xorm/xorm/session_query.go
index a693bace3f..f8098f849c 100644
--- a/vendor/github.com/go-xorm/xorm/session_query.go
+++ b/vendor/github.com/go-xorm/xorm/session_query.go
@@ -8,17 +8,92 @@ import (
"fmt"
"reflect"
"strconv"
+ "strings"
"time"
+ "github.com/go-xorm/builder"
"github.com/go-xorm/core"
)
+func (session *Session) genQuerySQL(sqlorArgs ...interface{}) (string, []interface{}, error) {
+ if len(sqlorArgs) > 0 {
+ switch sqlorArgs[0].(type) {
+ case string:
+ return sqlorArgs[0].(string), sqlorArgs[1:], nil
+ case *builder.Builder:
+ return sqlorArgs[0].(*builder.Builder).ToSQL()
+ case builder.Builder:
+ bd := sqlorArgs[0].(builder.Builder)
+ return bd.ToSQL()
+ default:
+ return "", nil, ErrUnSupportedType
+ }
+ }
+
+ if session.statement.RawSQL != "" {
+ return session.statement.RawSQL, session.statement.RawParams, nil
+ }
+
+ if len(session.statement.TableName()) <= 0 {
+ return "", nil, ErrTableNotFound
+ }
+
+ var columnStr = session.statement.ColumnStr
+ if len(session.statement.selectStr) > 0 {
+ columnStr = session.statement.selectStr
+ } else {
+ if session.statement.JoinStr == "" {
+ if columnStr == "" {
+ if session.statement.GroupByStr != "" {
+ columnStr = session.statement.Engine.Quote(strings.Replace(session.statement.GroupByStr, ",", session.engine.Quote(","), -1))
+ } else {
+ columnStr = session.statement.genColumnStr()
+ }
+ }
+ } else {
+ if columnStr == "" {
+ if session.statement.GroupByStr != "" {
+ columnStr = session.statement.Engine.Quote(strings.Replace(session.statement.GroupByStr, ",", session.engine.Quote(","), -1))
+ } else {
+ columnStr = "*"
+ }
+ }
+ }
+ if columnStr == "" {
+ columnStr = "*"
+ }
+ }
+
+ condSQL, condArgs, err := builder.ToSQL(session.statement.cond)
+ if err != nil {
+ return "", nil, err
+ }
+
+ args := append(session.statement.joinArgs, condArgs...)
+ sqlStr, err := session.statement.genSelectSQL(columnStr, condSQL)
+ if err != nil {
+ return "", nil, err
+ }
+ // for mssql and use limit
+ qs := strings.Count(sqlStr, "?")
+ if len(args)*2 == qs {
+ args = append(args, args...)
+ }
+
+ return sqlStr, args, nil
+}
+
// Query runs a raw sql and return records as []map[string][]byte
-func (session *Session) Query(sqlStr string, args ...interface{}) ([]map[string][]byte, error) {
+func (session *Session) Query(sqlorArgs ...interface{}) ([]map[string][]byte, error) {
if session.isAutoClose {
defer session.Close()
}
+ sqlStr, args, err := session.genQuerySQL(sqlorArgs...)
+ if err != nil {
+ return nil, err
+ }
+
return session.queryBytes(sqlStr, args...)
}
@@ -114,11 +189,16 @@ func rows2Strings(rows *core.Rows) (resultsSlice []map[string]string, err error)
}
// QueryString runs a raw sql and return records as []map[string]string
-func (session *Session) QueryString(sqlStr string, args ...interface{}) ([]map[string]string, error) {
+func (session *Session) QueryString(sqlorArgs ...interface{}) ([]map[string]string, error) {
if session.isAutoClose {
defer session.Close()
}
+ sqlStr, args, err := session.genQuerySQL(sqlorArgs...)
+ if err != nil {
+ return nil, err
+ }
+
rows, err := session.queryRows(sqlStr, args...)
if err != nil {
return nil, err
@@ -162,11 +242,16 @@ func rows2Interfaces(rows *core.Rows) (resultsSlice []map[string]interface{}, er
}
// QueryInterface runs a raw sql and return records as []map[string]interface{}
-func (session *Session) QueryInterface(sqlStr string, args ...interface{}) ([]map[string]interface{}, error) {
+func (session *Session) QueryInterface(sqlorArgs ...interface{}) ([]map[string]interface{}, error) {
if session.isAutoClose {
defer session.Close()
}
+ sqlStr, args, err := session.genQuerySQL(sqlorArgs...)
+ if err != nil {
+ return nil, err
+ }
+
rows, err := session.queryRows(sqlStr, args...)
if err != nil {
return nil, err
diff --git a/vendor/github.com/go-xorm/xorm/session_raw.go b/vendor/github.com/go-xorm/xorm/session_raw.go
index c225598e60..69bf9b3c6b 100644
--- a/vendor/github.com/go-xorm/xorm/session_raw.go
+++ b/vendor/github.com/go-xorm/xorm/session_raw.go
@@ -47,9 +47,16 @@ func (session *Session) queryRows(sqlStr string, args ...interface{}) (*core.Row
}
if session.isAutoCommit {
+ var db *core.DB
+ if session.engine.engineGroup != nil {
+ db = session.engine.engineGroup.Slave().DB()
+ } else {
+ db = session.DB()
+ }
+
if session.prepareStmt {
// don't clear stmt since session will cache them
- stmt, err := session.doPrepare(sqlStr)
+ stmt, err := session.doPrepare(db, sqlStr)
if err != nil {
return nil, err
}
@@ -61,7 +68,7 @@ func (session *Session) queryRows(sqlStr string, args ...interface{}) (*core.Row
return rows, nil
}
- rows, err := session.DB().Query(sqlStr, args...)
+ rows, err := db.Query(sqlStr, args...)
if err != nil {
return nil, err
}
@@ -171,7 +178,7 @@ func (session *Session) exec(sqlStr string, args ...interface{}) (sql.Result, er
}
if session.prepareStmt {
- stmt, err := session.doPrepare(sqlStr)
+ stmt, err := session.doPrepare(session.DB(), sqlStr)
if err != nil {
return nil, err
}
diff --git a/vendor/github.com/go-xorm/xorm/session_update.go b/vendor/github.com/go-xorm/xorm/session_update.go
index ca06298122..f558745667 100644
--- a/vendor/github.com/go-xorm/xorm/session_update.go
+++ b/vendor/github.com/go-xorm/xorm/session_update.go
@@ -242,10 +242,23 @@ func (session *Session) Update(bean interface{}, condiBean ...interface{}) (int6
var autoCond builder.Cond
if !session.statement.noAutoCondition && len(condiBean) > 0 {
- var err error
- autoCond, err = session.statement.buildConds(session.statement.RefTable, condiBean[0], true, true, false, true, false)
- if err != nil {
- return 0, err
+ if c, ok := condiBean[0].(map[string]interface{}); ok {
+ autoCond = builder.Eq(c)
+ } else {
+ ct := reflect.TypeOf(condiBean[0])
+ k := ct.Kind()
+ if k == reflect.Ptr {
+ k = ct.Elem().Kind()
+ }
+ if k == reflect.Struct {
+ var err error
+ autoCond, err = session.statement.buildConds(session.statement.RefTable, condiBean[0], true, true, false, true, false)
+ if err != nil {
+ return 0, err
+ }
+ } else {
+ return 0, ErrConditionType
+ }
}
}
diff --git a/vendor/github.com/go-xorm/xorm/statement.go b/vendor/github.com/go-xorm/xorm/statement.go
index 23346c7103..6400425b20 100644
--- a/vendor/github.com/go-xorm/xorm/statement.go
+++ b/vendor/github.com/go-xorm/xorm/statement.go
@@ -160,6 +160,9 @@ func (statement *Statement) And(query interface{}, args ...interface{}) *Stateme
case string:
cond := builder.Expr(query.(string), args...)
statement.cond = statement.cond.And(cond)
+ case map[string]interface{}:
+ cond := builder.Eq(query.(map[string]interface{}))
+ statement.cond = statement.cond.And(cond)
case builder.Cond:
cond := query.(builder.Cond)
statement.cond = statement.cond.And(cond)
@@ -181,6 +184,9 @@ func (statement *Statement) Or(query interface{}, args ...interface{}) *Statemen
case string:
cond := builder.Expr(query.(string), args...)
statement.cond = statement.cond.Or(cond)
+ case map[string]interface{}:
+ cond := builder.Eq(query.(map[string]interface{}))
+ statement.cond = statement.cond.Or(cond)
case builder.Cond:
cond := query.(builder.Cond)
statement.cond = statement.cond.Or(cond)
@@ -901,8 +907,12 @@ func (statement *Statement) genDelIndexSQL() []string {
func (statement *Statement) genAddColumnStr(col *core.Column) (string, []interface{}) {
quote := statement.Engine.Quote
- sql := fmt.Sprintf("ALTER TABLE %v ADD %v;", quote(statement.TableName()),
+ sql := fmt.Sprintf("ALTER TABLE %v ADD %v", quote(statement.TableName()),
col.String(statement.Engine.dialect))
+ if statement.Engine.dialect.DBType() == core.MYSQL && len(col.Comment) > 0 {
+ sql += " COMMENT '" + col.Comment + "'"
+ }
+ sql += ";"
return sql, []interface{}{}
}