aboutsummaryrefslogtreecommitdiffstats
path: root/vendor
diff options
context:
space:
mode:
authorLunny Xiao <xiaolunwen@gmail.com>2017-04-06 18:47:25 -0700
committerGitHub <noreply@github.com>2017-04-06 18:47:25 -0700
commit5acfc7c4bc93e547fcb31263da746263d64df7e9 (patch)
tree5750a669a0e46761df5d234361a17a71b2358317 /vendor
parentcf6699fb4f845f8f234baa82b556323f022d6788 (diff)
downloadgitea-5acfc7c4bc93e547fcb31263da746263d64df7e9.tar.gz
gitea-5acfc7c4bc93e547fcb31263da746263d64df7e9.zip
fix migrate failed and org dashboard failed on MSSQL database (#1448)
Diffstat (limited to 'vendor')
-rw-r--r--vendor/github.com/go-xorm/xorm/README.md33
-rw-r--r--vendor/github.com/go-xorm/xorm/README_CN.md29
-rw-r--r--vendor/github.com/go-xorm/xorm/VERSION1
-rw-r--r--vendor/github.com/go-xorm/xorm/convert.go37
-rw-r--r--vendor/github.com/go-xorm/xorm/dialect_mssql.go (renamed from vendor/github.com/go-xorm/xorm/mssql_dialect.go)31
-rw-r--r--vendor/github.com/go-xorm/xorm/dialect_mysql.go (renamed from vendor/github.com/go-xorm/xorm/mysql_dialect.go)92
-rw-r--r--vendor/github.com/go-xorm/xorm/dialect_oracle.go (renamed from vendor/github.com/go-xorm/xorm/oracle_dialect.go)60
-rw-r--r--vendor/github.com/go-xorm/xorm/dialect_postgres.go (renamed from vendor/github.com/go-xorm/xorm/postgres_dialect.go)111
-rw-r--r--vendor/github.com/go-xorm/xorm/dialect_sqlite3.go (renamed from vendor/github.com/go-xorm/xorm/sqlite3_dialect.go)10
-rw-r--r--vendor/github.com/go-xorm/xorm/doc.go43
-rw-r--r--vendor/github.com/go-xorm/xorm/engine.go305
-rw-r--r--vendor/github.com/go-xorm/xorm/goracle_driver.go42
-rw-r--r--vendor/github.com/go-xorm/xorm/helpers.go14
-rw-r--r--vendor/github.com/go-xorm/xorm/mymysql_driver.go65
-rw-r--r--vendor/github.com/go-xorm/xorm/mysql_driver.go50
-rw-r--r--vendor/github.com/go-xorm/xorm/oci8_driver.go37
-rw-r--r--vendor/github.com/go-xorm/xorm/odbc_driver.go34
-rw-r--r--vendor/github.com/go-xorm/xorm/pq_driver.go119
-rw-r--r--vendor/github.com/go-xorm/xorm/rows.go19
-rw-r--r--vendor/github.com/go-xorm/xorm/session.go956
-rw-r--r--vendor/github.com/go-xorm/xorm/session_cols.go84
-rw-r--r--vendor/github.com/go-xorm/xorm/session_cond.go70
-rw-r--r--vendor/github.com/go-xorm/xorm/session_convert.go673
-rw-r--r--vendor/github.com/go-xorm/xorm/session_find.go102
-rw-r--r--vendor/github.com/go-xorm/xorm/session_get.go52
-rw-r--r--vendor/github.com/go-xorm/xorm/session_insert.go38
-rw-r--r--vendor/github.com/go-xorm/xorm/session_raw.go11
-rw-r--r--vendor/github.com/go-xorm/xorm/session_schema.go5
-rw-r--r--vendor/github.com/go-xorm/xorm/session_sum.go2
-rw-r--r--vendor/github.com/go-xorm/xorm/session_update.go67
-rw-r--r--vendor/github.com/go-xorm/xorm/sqlite3_driver.go20
-rw-r--r--vendor/github.com/go-xorm/xorm/statement.go94
-rw-r--r--vendor/github.com/go-xorm/xorm/tag.go281
-rw-r--r--vendor/github.com/go-xorm/xorm/xorm.go3
-rw-r--r--vendor/vendor.json6
35 files changed, 1972 insertions, 1624 deletions
diff --git a/vendor/github.com/go-xorm/xorm/README.md b/vendor/github.com/go-xorm/xorm/README.md
index 12f6ca90b9..da55878ea0 100644
--- a/vendor/github.com/go-xorm/xorm/README.md
+++ b/vendor/github.com/go-xorm/xorm/README.md
@@ -46,12 +46,15 @@ Drivers for Go's sql package which currently support database/sql includes:
* MsSql: [github.com/denisenkom/go-mssqldb](https://github.com/denisenkom/go-mssqldb)
-* MsSql: [github.com/lunny/godbc](https://github.com/lunny/godbc)
-
* Oracle: [github.com/mattn/go-oci8](https://github.com/mattn/go-oci8) (experiment)
# Changelog
+* **v0.6.2**
+ * refactor tag parse methods
+ * 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`
@@ -79,12 +82,6 @@ methods can use `builder.Cond` as parameter
# Installation
-If you have [gopm](https://github.com/gpmgo/gopm) installed,
-
- gopm get github.com/go-xorm/xorm
-
-Or
-
go get github.com/go-xorm/xorm
# Documents
@@ -119,19 +116,21 @@ type User struct {
err := engine.Sync2(new(User))
```
-* Query a SQL string, the returned results is []map[string][]byte
+* `Query` runs a SQL string, the returned results is `[]map[string][]byte`, `QueryString` returns `[]map[string]string`.
```Go
results, err := engine.Query("select * from user")
+
+results, err := engine.QueryString("select * from user")
```
-* Execute a SQL string, the returned results
+* `Execute` runs a SQL string, it returns `affetcted` and `error`
```Go
affected, err := engine.Exec("update user set age = ? where name = ?", age, name)
```
-* Insert one or multiple records to database
+* `Insert` one or multiple records to database
```Go
affected, err := engine.Insert(&user)
@@ -153,6 +152,18 @@ 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)
+// 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 = ?
```
* Query multiple records from database, also you can use join and extends
diff --git a/vendor/github.com/go-xorm/xorm/README_CN.md b/vendor/github.com/go-xorm/xorm/README_CN.md
index 3919b3ed8a..40f5f6009a 100644
--- a/vendor/github.com/go-xorm/xorm/README_CN.md
+++ b/vendor/github.com/go-xorm/xorm/README_CN.md
@@ -54,6 +54,11 @@ xorm是一个简单而强大的Go语言ORM库. 通过它可以使数据库操作
## 更新日志
+* **v0.6.2**
+ * 重构Tag解析方式
+ * Get方法新增类似Sacn的特性
+ * 新增 QueryString 方法
+
* **v0.6.0**
* 去除对 ql 的支持
* 新增条件查询分析器 [github.com/go-xorm/builder](https://github.com/go-xorm/builder), 从因此 `Where, And, Or` 函数
@@ -81,12 +86,6 @@ xorm是一个简单而强大的Go语言ORM库. 通过它可以使数据库操作
## 安装
-推荐使用 [gopm](https://github.com/gpmgo/gopm) 进行安装:
-
- gopm get github.com/go-xorm/xorm
-
-或者您也可以使用go工具进行安装:
-
go get github.com/go-xorm/xorm
## 文档
@@ -121,13 +120,15 @@ type User struct {
err := engine.Sync2(new(User))
```
-* 最原始的也支持SQL语句查询,返回的结果类型为 []map[string][]byte
+* `Query` 最原始的也支持SQL语句查询,返回的结果类型为 []map[string][]byte。`QueryString` 返回 []map[string]string
```Go
results, err := engine.Query("select * from user")
+
+results, err := engine.QueryString("select * from user")
```
-* 执行一个SQL语句
+* `Exec` 执行一个SQL语句
```Go
affected, err := engine.Exec("update user set age = ? where name = ?", age, name)
@@ -155,6 +156,18 @@ 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)
+// 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 = ?
```
* 查询多条记录,当然可以使用Join和extends来组合使用
diff --git a/vendor/github.com/go-xorm/xorm/VERSION b/vendor/github.com/go-xorm/xorm/VERSION
deleted file mode 100644
index 22c1aa4d02..0000000000
--- a/vendor/github.com/go-xorm/xorm/VERSION
+++ /dev/null
@@ -1 +0,0 @@
-xorm v0.6.0.1022 \ No newline at end of file
diff --git a/vendor/github.com/go-xorm/xorm/convert.go b/vendor/github.com/go-xorm/xorm/convert.go
index 87f0d3f1ec..5748e3798c 100644
--- a/vendor/github.com/go-xorm/xorm/convert.go
+++ b/vendor/github.com/go-xorm/xorm/convert.go
@@ -247,3 +247,40 @@ func convertAssign(dest, src interface{}) error {
return fmt.Errorf("unsupported Scan, storing driver.Value type %T into type %T", src, dest)
}
+
+func asKind(vv reflect.Value, tp reflect.Type) (interface{}, error) {
+ switch tp.Kind() {
+ case reflect.Int64:
+ return vv.Int(), nil
+ case reflect.Int:
+ return int(vv.Int()), nil
+ case reflect.Int32:
+ return int32(vv.Int()), nil
+ case reflect.Int16:
+ return int16(vv.Int()), nil
+ case reflect.Int8:
+ return int8(vv.Int()), nil
+ case reflect.Uint64:
+ return vv.Uint(), nil
+ case reflect.Uint:
+ return uint(vv.Uint()), nil
+ case reflect.Uint32:
+ return uint32(vv.Uint()), nil
+ case reflect.Uint16:
+ return uint16(vv.Uint()), nil
+ case reflect.Uint8:
+ return uint8(vv.Uint()), nil
+ case reflect.String:
+ return vv.String(), nil
+ case reflect.Slice:
+ if tp.Elem().Kind() == reflect.Uint8 {
+ v, err := strconv.ParseInt(string(vv.Interface().([]byte)), 10, 64)
+ if err != nil {
+ return nil, err
+ }
+ return v, nil
+ }
+
+ }
+ return nil, fmt.Errorf("unsupported primary key type: %v, %v", tp, vv)
+}
diff --git a/vendor/github.com/go-xorm/xorm/mssql_dialect.go b/vendor/github.com/go-xorm/xorm/dialect_mssql.go
index e9bda1fd5b..f83cfc1733 100644
--- a/vendor/github.com/go-xorm/xorm/mssql_dialect.go
+++ b/vendor/github.com/go-xorm/xorm/dialect_mssql.go
@@ -5,6 +5,7 @@
package xorm
import (
+ "errors"
"fmt"
"strconv"
"strings"
@@ -215,9 +216,9 @@ func (db *mssql) SqlType(c *core.Column) string {
switch t := c.SQLType.Name; t {
case core.Bool:
res = core.TinyInt
- if c.Default == "true" {
+ if strings.EqualFold(c.Default, "true") {
c.Default = "1"
- } else if c.Default == "false" {
+ } else {
c.Default = "0"
}
case core.Serial:
@@ -467,9 +468,10 @@ WHERE IXS.TYPE_DESC='NONCLUSTERED' and OBJECT_NAME(IXS.OBJECT_ID) =?
}
colName = strings.Trim(colName, "` ")
-
+ var isRegular bool
if strings.HasPrefix(indexName, "IDX_"+tableName) || strings.HasPrefix(indexName, "UQE_"+tableName) {
indexName = indexName[5+len(tableName):]
+ isRegular = true
}
var index *core.Index
@@ -478,6 +480,7 @@ WHERE IXS.TYPE_DESC='NONCLUSTERED' and OBJECT_NAME(IXS.OBJECT_ID) =?
index = new(core.Index)
index.Type = indexType
index.Name = indexName
+ index.IsRegular = isRegular
indexes[indexName] = index
}
index.AddColumn(colName)
@@ -526,3 +529,25 @@ func (db *mssql) ForUpdateSql(query string) string {
func (db *mssql) Filters() []core.Filter {
return []core.Filter{&core.IdFilter{}, &core.QuoteFilter{}}
}
+
+type odbcDriver struct {
+}
+
+func (p *odbcDriver) Parse(driverName, dataSourceName string) (*core.Uri, error) {
+ kv := strings.Split(dataSourceName, ";")
+ var dbName string
+
+ for _, c := range kv {
+ vv := strings.Split(strings.TrimSpace(c), "=")
+ if len(vv) == 2 {
+ switch strings.ToLower(vv[0]) {
+ case "database":
+ dbName = vv[1]
+ }
+ }
+ }
+ if dbName == "" {
+ return nil, errors.New("no db name provided")
+ }
+ return &core.Uri{DbName: dbName, DbType: core.MSSQL}, nil
+}
diff --git a/vendor/github.com/go-xorm/xorm/mysql_dialect.go b/vendor/github.com/go-xorm/xorm/dialect_mysql.go
index ab756f3595..55cfdd7640 100644
--- a/vendor/github.com/go-xorm/xorm/mysql_dialect.go
+++ b/vendor/github.com/go-xorm/xorm/dialect_mysql.go
@@ -6,7 +6,9 @@ package xorm
import (
"crypto/tls"
+ "errors"
"fmt"
+ "regexp"
"strconv"
"strings"
"time"
@@ -486,3 +488,93 @@ func (db *mysql) GetIndexes(tableName string) (map[string]*core.Index, error) {
func (db *mysql) Filters() []core.Filter {
return []core.Filter{&core.IdFilter{}}
}
+
+type mymysqlDriver struct {
+}
+
+func (p *mymysqlDriver) Parse(driverName, dataSourceName string) (*core.Uri, error) {
+ db := &core.Uri{DbType: core.MYSQL}
+
+ pd := strings.SplitN(dataSourceName, "*", 2)
+ if len(pd) == 2 {
+ // Parse protocol part of URI
+ p := strings.SplitN(pd[0], ":", 2)
+ if len(p) != 2 {
+ return nil, errors.New("Wrong protocol part of URI")
+ }
+ db.Proto = p[0]
+ options := strings.Split(p[1], ",")
+ db.Raddr = options[0]
+ for _, o := range options[1:] {
+ kv := strings.SplitN(o, "=", 2)
+ var k, v string
+ if len(kv) == 2 {
+ k, v = kv[0], kv[1]
+ } else {
+ k, v = o, "true"
+ }
+ switch k {
+ case "laddr":
+ db.Laddr = v
+ case "timeout":
+ to, err := time.ParseDuration(v)
+ if err != nil {
+ return nil, err
+ }
+ db.Timeout = to
+ default:
+ return nil, errors.New("Unknown option: " + k)
+ }
+ }
+ // Remove protocol part
+ pd = pd[1:]
+ }
+ // Parse database part of URI
+ dup := strings.SplitN(pd[0], "/", 3)
+ if len(dup) != 3 {
+ return nil, errors.New("Wrong database part of URI")
+ }
+ db.DbName = dup[0]
+ db.User = dup[1]
+ db.Passwd = dup[2]
+
+ return db, nil
+}
+
+type mysqlDriver struct {
+}
+
+func (p *mysqlDriver) Parse(driverName, dataSourceName string) (*core.Uri, error) {
+ dsnPattern := regexp.MustCompile(
+ `^(?:(?P<user>.*?)(?::(?P<passwd>.*))?@)?` + // [user[:password]@]
+ `(?:(?P<net>[^\(]*)(?:\((?P<addr>[^\)]*)\))?)?` + // [net[(addr)]]
+ `\/(?P<dbname>.*?)` + // /dbname
+ `(?:\?(?P<params>[^\?]*))?$`) // [?param1=value1&paramN=valueN]
+ matches := dsnPattern.FindStringSubmatch(dataSourceName)
+ //tlsConfigRegister := make(map[string]*tls.Config)
+ names := dsnPattern.SubexpNames()
+
+ uri := &core.Uri{DbType: core.MYSQL}
+
+ for i, match := range matches {
+ switch names[i] {
+ case "dbname":
+ uri.DbName = match
+ case "params":
+ if len(match) > 0 {
+ kvs := strings.Split(match, "&")
+ for _, kv := range kvs {
+ splits := strings.Split(kv, "=")
+ if len(splits) == 2 {
+ switch splits[0] {
+ case "charset":
+ uri.Charset = splits[1]
+ }
+ }
+ }
+ }
+
+ }
+ }
+ return uri, nil
+}
diff --git a/vendor/github.com/go-xorm/xorm/oracle_dialect.go b/vendor/github.com/go-xorm/xorm/dialect_oracle.go
index b19ea38bbf..ac0081b38f 100644
--- a/vendor/github.com/go-xorm/xorm/oracle_dialect.go
+++ b/vendor/github.com/go-xorm/xorm/dialect_oracle.go
@@ -5,7 +5,9 @@
package xorm
import (
+ "errors"
"fmt"
+ "regexp"
"strconv"
"strings"
@@ -822,6 +824,12 @@ func (db *oracle) GetIndexes(tableName string) (map[string]*core.Index, error) {
indexName = strings.Trim(indexName, `" `)
+ var isRegular bool
+ if strings.HasPrefix(indexName, "IDX_"+tableName) || strings.HasPrefix(indexName, "UQE_"+tableName) {
+ indexName = indexName[5+len(tableName):]
+ isRegular = true
+ }
+
if uniqueness == "UNIQUE" {
indexType = core.UniqueType
} else {
@@ -834,6 +842,7 @@ func (db *oracle) GetIndexes(tableName string) (map[string]*core.Index, error) {
index = new(core.Index)
index.Type = indexType
index.Name = indexName
+ index.IsRegular = isRegular
indexes[indexName] = index
}
index.AddColumn(colName)
@@ -844,3 +853,54 @@ func (db *oracle) GetIndexes(tableName string) (map[string]*core.Index, error) {
func (db *oracle) Filters() []core.Filter {
return []core.Filter{&core.QuoteFilter{}, &core.SeqFilter{Prefix: ":", Start: 1}, &core.IdFilter{}}
}
+
+type goracleDriver struct {
+}
+
+func (cfg *goracleDriver) Parse(driverName, dataSourceName string) (*core.Uri, error) {
+ db := &core.Uri{DbType: core.ORACLE}
+ dsnPattern := regexp.MustCompile(
+ `^(?:(?P<user>.*?)(?::(?P<passwd>.*))?@)?` + // [user[:password]@]
+ `(?:(?P<net>[^\(]*)(?:\((?P<addr>[^\)]*)\))?)?` + // [net[(addr)]]
+ `\/(?P<dbname>.*?)` + // /dbname
+ `(?:\?(?P<params>[^\?]*))?$`) // [?param1=value1&paramN=valueN]
+ matches := dsnPattern.FindStringSubmatch(dataSourceName)
+ //tlsConfigRegister := make(map[string]*tls.Config)
+ names := dsnPattern.SubexpNames()
+
+ for i, match := range matches {
+ switch names[i] {
+ case "dbname":
+ db.DbName = match
+ }
+ }
+ if db.DbName == "" {
+ return nil, errors.New("dbname is empty")
+ }
+ return db, nil
+}
+
+type oci8Driver struct {
+}
+
+//dataSourceName=user/password@ipv4:port/dbname
+//dataSourceName=user/password@[ipv6]:port/dbname
+func (p *oci8Driver) Parse(driverName, dataSourceName string) (*core.Uri, error) {
+ db := &core.Uri{DbType: core.ORACLE}
+ dsnPattern := regexp.MustCompile(
+ `^(?P<user>.*)\/(?P<password>.*)@` + // user:password@
+ `(?P<net>.*)` + // ip:port
+ `\/(?P<dbname>.*)`) // dbname
+ matches := dsnPattern.FindStringSubmatch(dataSourceName)
+ names := dsnPattern.SubexpNames()
+ for i, match := range matches {
+ switch names[i] {
+ case "dbname":
+ db.DbName = match
+ }
+ }
+ if db.DbName == "" {
+ return nil, errors.New("dbname is empty")
+ }
+ return db, nil
+}
diff --git a/vendor/github.com/go-xorm/xorm/postgres_dialect.go b/vendor/github.com/go-xorm/xorm/dialect_postgres.go
index c23ab6f31d..1d4daa2798 100644
--- a/vendor/github.com/go-xorm/xorm/postgres_dialect.go
+++ b/vendor/github.com/go-xorm/xorm/dialect_postgres.go
@@ -5,7 +5,10 @@
package xorm
import (
+ "errors"
"fmt"
+ "net/url"
+ "sort"
"strconv"
"strings"
@@ -1075,9 +1078,10 @@ func (db *postgres) GetIndexes(tableName string) (map[string]*core.Index, error)
}
cs := strings.Split(indexdef, "(")
colNames = strings.Split(cs[1][0:len(cs[1])-1], ",")
-
+ var isRegular bool
if strings.HasPrefix(indexName, "IDX_"+tableName) || strings.HasPrefix(indexName, "UQE_"+tableName) {
newIdxName := indexName[5+len(tableName):]
+ isRegular = true
if newIdxName != "" {
indexName = newIdxName
}
@@ -1087,6 +1091,7 @@ func (db *postgres) GetIndexes(tableName string) (map[string]*core.Index, error)
for _, colName := range colNames {
index.Cols = append(index.Cols, strings.Trim(colName, `" `))
}
+ index.IsRegular = isRegular
indexes[index.Name] = index
}
return indexes, nil
@@ -1095,3 +1100,107 @@ func (db *postgres) GetIndexes(tableName string) (map[string]*core.Index, error)
func (db *postgres) Filters() []core.Filter {
return []core.Filter{&core.IdFilter{}, &core.QuoteFilter{}, &core.SeqFilter{Prefix: "$", Start: 1}}
}
+
+type pqDriver struct {
+}
+
+type values map[string]string
+
+func (vs values) Set(k, v string) {
+ vs[k] = v
+}
+
+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 {
+ return "", err
+ }
+
+ if u.Scheme != "postgresql" && u.Scheme != "postgres" {
+ 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:])
+ }
+
+ 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
+}
+
+func parseOpts(name string, o values) {
+ if len(name) == 0 {
+ return
+ }
+
+ name = strings.TrimSpace(name)
+
+ ps := strings.Split(name, " ")
+ for _, p := range ps {
+ kv := strings.Split(p, "=")
+ if len(kv) < 2 {
+ errorf("invalid option: %q", p)
+ }
+ o.Set(kv[0], kv[1])
+ }
+}
+
+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)
+ if err != nil {
+ return nil, err
+ }
+ }
+ 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/sqlite3_dialect.go b/vendor/github.com/go-xorm/xorm/dialect_sqlite3.go
index b72459aeb9..c13fd02bed 100644
--- a/vendor/github.com/go-xorm/xorm/sqlite3_dialect.go
+++ b/vendor/github.com/go-xorm/xorm/dialect_sqlite3.go
@@ -405,8 +405,10 @@ func (db *sqlite3) GetIndexes(tableName string) (map[string]*core.Index, error)
}
indexName := strings.Trim(sql[nNStart+6:nNEnd], "` []")
+ var isRegular bool
if strings.HasPrefix(indexName, "IDX_"+tableName) || strings.HasPrefix(indexName, "UQE_"+tableName) {
index.Name = indexName[5+len(tableName):]
+ isRegular = true
} else {
index.Name = indexName
}
@@ -425,6 +427,7 @@ func (db *sqlite3) GetIndexes(tableName string) (map[string]*core.Index, error)
for _, col := range colIndexes {
index.Cols = append(index.Cols, strings.Trim(col, "` []"))
}
+ index.IsRegular = isRegular
indexes[index.Name] = index
}
@@ -434,3 +437,10 @@ func (db *sqlite3) GetIndexes(tableName string) (map[string]*core.Index, error)
func (db *sqlite3) Filters() []core.Filter {
return []core.Filter{&core.IdFilter{}}
}
+
+type sqlite3Driver struct {
+}
+
+func (p *sqlite3Driver) Parse(driverName, dataSourceName string) (*core.Uri, error) {
+ return &core.Uri{DbType: core.SQLITE, DbName: dataSourceName}, nil
+}
diff --git a/vendor/github.com/go-xorm/xorm/doc.go b/vendor/github.com/go-xorm/xorm/doc.go
index cc71930dd0..5b36fcd80b 100644
--- a/vendor/github.com/go-xorm/xorm/doc.go
+++ b/vendor/github.com/go-xorm/xorm/doc.go
@@ -24,7 +24,7 @@ Generally, one engine for an application is enough. You can set it as package va
Raw Methods
-Xorm also support raw sql execution:
+XORM also support raw SQL execution:
1. query a SQL string, the returned results is []map[string][]byte
@@ -36,7 +36,7 @@ Xorm also support raw sql execution:
ORM Methods
-There are 7 major ORM methods and many helpful methods to use to operate database.
+There are 8 major ORM methods and many helpful methods to use to operate database.
1. Insert one or multiple records to database
@@ -58,10 +58,18 @@ There are 7 major ORM methods and many helpful methods to use to operate databas
3. Query multiple records from database
- sliceOfStructs := new(Struct)
- err := engine.Find(sliceOfStructs)
+ var sliceOfStructs []Struct
+ err := engine.Find(&sliceOfStructs)
// SELECT * FROM user
+ var mapOfStructs = make(map[int64]Struct)
+ err := engine.Find(&mapOfStructs)
+ // SELECT * FROM user
+
+ var int64s []int64
+ err := engine.Table("user").Cols("id").Find(&int64s)
+ // SELECT id FROM user
+
4. Query multiple records and record by record handle, there two methods, one is Iterate,
another is Rows
@@ -91,20 +99,31 @@ another is Rows
counts, err := engine.Count(&user)
// SELECT count(*) AS total FROM user
+8. Sum records
+
+ sumFloat64, err := engine.Sum(&user, "id")
+ // SELECT sum(id) from user
+
+ sumFloat64s, err := engine.Sums(&user, "id1", "id2")
+ // SELECT sum(id1), sum(id2) from user
+
+ sumInt64s, err := engine.SumsInt(&user, "id1", "id2")
+ // SELECT sum(id1), sum(id2) from user
+
Conditions
-The above 7 methods could use with condition methods chainable.
-Attention: the above 7 methods should be the last chainable method.
+The above 8 methods could use with condition methods chainable.
+Attention: the above 8 methods should be the last chainable method.
-1. Id, In
+1. ID, In
- engine.Id(1).Get(&user) // for single primary key
+ engine.ID(1).Get(&user) // for single primary key
// SELECT * FROM user WHERE id = 1
- engine.Id(core.PK{1, 2}).Get(&user) // for composite primary keys
+ engine.ID(core.PK{1, 2}).Get(&user) // for composite primary keys
// SELECT * FROM user WHERE id1 = 1 AND id2 = 2
engine.In("id", 1, 2, 3).Find(&users)
// SELECT * FROM user WHERE id IN (1, 2, 3)
- engine.In("id", []int{1, 2, 3})
+ engine.In("id", []int{1, 2, 3}).Find(&users)
// SELECT * FROM user WHERE id IN (1, 2, 3)
2. Where, And, Or
@@ -127,10 +146,10 @@ Attention: the above 7 methods should be the last chainable method.
// SELECT TOP 5 * FROM user // for mssql
// SELECT * FROM user LIMIT .. OFFSET 0 //for other databases
-5. Sql, let you custom SQL
+5. SQL, let you custom SQL
var users []User
- engine.Sql("select * from user").Find(&users)
+ engine.SQL("select * from user").Find(&users)
6. Cols, Omit, Distinct
diff --git a/vendor/github.com/go-xorm/xorm/engine.go b/vendor/github.com/go-xorm/xorm/engine.go
index be90ddbe4e..a27b6bdf2f 100644
--- a/vendor/github.com/go-xorm/xorm/engine.go
+++ b/vendor/github.com/go-xorm/xorm/engine.go
@@ -44,6 +44,8 @@ type Engine struct {
DatabaseTZ *time.Location // The timezone of the database
disableGlobalCache bool
+
+ tagHandlers map[string]tagHandler
}
// ShowSQL show SQL statement or not on logger if log level is great than INFO
@@ -215,10 +217,15 @@ func (engine *Engine) NoCascade() *Session {
}
// MapCacher Set a table use a special cacher
-func (engine *Engine) MapCacher(bean interface{}, cacher core.Cacher) {
+func (engine *Engine) MapCacher(bean interface{}, cacher core.Cacher) error {
v := rValue(bean)
- tb := engine.autoMapType(v)
+ tb, err := engine.autoMapType(v)
+ if err != nil {
+ return err
+ }
+
tb.Cacher = cacher
+ return nil
}
// NewDB provides an interface to operate database directly
@@ -260,9 +267,9 @@ func (engine *Engine) Ping() error {
func (engine *Engine) logSQL(sqlStr string, sqlArgs ...interface{}) {
if engine.showSQL && !engine.showExecTime {
if len(sqlArgs) > 0 {
- engine.logger.Infof("[sql] %v [args] %v", sqlStr, sqlArgs)
+ engine.logger.Infof("[SQL] %v %v", sqlStr, sqlArgs)
} else {
- engine.logger.Infof("[sql] %v", sqlStr)
+ engine.logger.Infof("[SQL] %v", sqlStr)
}
}
}
@@ -273,9 +280,9 @@ func (engine *Engine) logSQLQueryTime(sqlStr string, args []interface{}, executi
stmt, res, err := executionBlock()
execDuration := time.Since(b4ExecTime)
if len(args) > 0 {
- engine.logger.Infof("[sql] %s [args] %v - took: %v", sqlStr, args, execDuration)
+ engine.logger.Infof("[SQL] %s %v - took: %v", sqlStr, args, execDuration)
} else {
- engine.logger.Infof("[sql] %s - took: %v", sqlStr, execDuration)
+ engine.logger.Infof("[SQL] %s - took: %v", sqlStr, execDuration)
}
return stmt, res, err
}
@@ -774,13 +781,18 @@ func (engine *Engine) Having(conditions string) *Session {
return session.Having(conditions)
}
-func (engine *Engine) autoMapType(v reflect.Value) *core.Table {
+func (engine *Engine) autoMapType(v reflect.Value) (*core.Table, error) {
t := v.Type()
engine.mutex.Lock()
defer engine.mutex.Unlock()
table, ok := engine.Tables[t]
if !ok {
- table = engine.mapType(v)
+ var err error
+ table, err = engine.mapType(v)
+ if err != nil {
+ return nil, err
+ }
+
engine.Tables[t] = table
if engine.Cacher != nil {
if v.CanAddr() {
@@ -790,12 +802,11 @@ func (engine *Engine) autoMapType(v reflect.Value) *core.Table {
}
}
}
- return table
+ return table, nil
}
// GobRegister register one struct to gob for cache use
func (engine *Engine) GobRegister(v interface{}) *Engine {
- //fmt.Printf("Type: %[1]T => Data: %[1]#v\n", v)
gob.Register(v)
return engine
}
@@ -806,10 +817,19 @@ type Table struct {
Name string
}
+// IsValid if table is valid
+func (t *Table) IsValid() bool {
+ return t.Table != nil && len(t.Name) > 0
+}
+
// TableInfo get table info according to bean's content
func (engine *Engine) TableInfo(bean interface{}) *Table {
v := rValue(bean)
- return &Table{engine.autoMapType(v), engine.tbName(v)}
+ tb, err := engine.autoMapType(v)
+ if err != nil {
+ engine.logger.Error(err)
+ }
+ return &Table{tb, engine.tbName(v)}
}
func addIndex(indexName string, table *core.Table, col *core.Column, indexType int) {
@@ -842,7 +862,7 @@ var (
tpTableName = reflect.TypeOf((*TableName)(nil)).Elem()
)
-func (engine *Engine) mapType(v reflect.Value) *core.Table {
+func (engine *Engine) mapType(v reflect.Value) (*core.Table, error) {
t := v.Type()
table := engine.newTable()
if tb, ok := v.Interface().(TableName); ok {
@@ -861,7 +881,6 @@ func (engine *Engine) mapType(v reflect.Value) *core.Table {
table.Type = t
var idFieldColName string
- var err error
var hasCacheTag, hasNoCacheTag bool
for i := 0; i < t.NumField(); i++ {
@@ -881,186 +900,94 @@ func (engine *Engine) mapType(v reflect.Value) *core.Table {
if tags[0] == "-" {
continue
}
+
+ var ctx = tagContext{
+ table: table,
+ col: col,
+ fieldValue: fieldValue,
+ indexNames: make(map[string]int),
+ engine: engine,
+ }
+
if strings.ToUpper(tags[0]) == "EXTENDS" {
- switch fieldValue.Kind() {
- case reflect.Ptr:
- f := fieldValue.Type().Elem()
- if f.Kind() == reflect.Struct {
- fieldPtr := fieldValue
- fieldValue = fieldValue.Elem()
- if !fieldValue.IsValid() || fieldPtr.IsNil() {
- fieldValue = reflect.New(f).Elem()
- }
- }
- fallthrough
- case reflect.Struct:
- parentTable := engine.mapType(fieldValue)
- for _, col := range parentTable.Columns() {
- col.FieldName = fmt.Sprintf("%v.%v", t.Field(i).Name, col.FieldName)
- table.AddColumn(col)
- for indexName, indexType := range col.Indexes {
- addIndex(indexName, table, col, indexType)
- }
- }
- continue
- default:
- //TODO: warning
+ if err := ExtendsTagHandler(&ctx); err != nil {
+ return nil, err
}
+ continue
}
- indexNames := make(map[string]int)
- var isIndex, isUnique bool
- var preKey string
for j, key := range tags {
+ if ctx.ignoreNext {
+ ctx.ignoreNext = false
+ continue
+ }
+
k := strings.ToUpper(key)
- switch {
- case k == "<-":
- col.MapType = core.ONLYFROMDB
- case k == "->":
- col.MapType = core.ONLYTODB
- case k == "PK":
- col.IsPrimaryKey = true
- col.Nullable = false
- case k == "NULL":
- if j == 0 {
- col.Nullable = true
- } else {
- col.Nullable = (strings.ToUpper(tags[j-1]) != "NOT")
- }
- // TODO: for postgres how add autoincr?
- /*case strings.HasPrefix(k, "AUTOINCR(") && strings.HasSuffix(k, ")"):
- col.IsAutoIncrement = true
+ ctx.tagName = k
- autoStart := k[len("AUTOINCR")+1 : len(k)-1]
- autoStartInt, err := strconv.Atoi(autoStart)
- if err != nil {
- engine.LogError(err)
+ pStart := strings.Index(k, "(")
+ if pStart == 0 {
+ return nil, errors.New("( could not be the first charactor")
}
- col.AutoIncrStart = autoStartInt*/
- case k == "AUTOINCR":
- col.IsAutoIncrement = true
- //col.AutoIncrStart = 1
- case k == "DEFAULT":
- col.Default = tags[j+1]
- case k == "CREATED":
- col.IsCreated = true
- case k == "VERSION":
- col.IsVersion = true
- col.Default = "1"
- case k == "UTC":
- col.TimeZone = time.UTC
- case k == "LOCAL":
- col.TimeZone = time.Local
- case strings.HasPrefix(k, "LOCALE(") && strings.HasSuffix(k, ")"):
- location := k[len("LOCALE")+1 : len(k)-1]
- col.TimeZone, err = time.LoadLocation(location)
- if err != nil {
- engine.logger.Error(err)
- }
- case k == "UPDATED":
- col.IsUpdated = true
- case k == "DELETED":
- col.IsDeleted = true
- case strings.HasPrefix(k, "INDEX(") && strings.HasSuffix(k, ")"):
- indexName := k[len("INDEX")+1 : len(k)-1]
- indexNames[indexName] = core.IndexType
- case k == "INDEX":
- isIndex = true
- case strings.HasPrefix(k, "UNIQUE(") && strings.HasSuffix(k, ")"):
- indexName := k[len("UNIQUE")+1 : len(k)-1]
- indexNames[indexName] = core.UniqueType
- case k == "UNIQUE":
- isUnique = true
- case k == "NOTNULL":
- col.Nullable = false
- case k == "CACHE":
- if !hasCacheTag {
- hasCacheTag = true
+ if pStart > -1 {
+ if !strings.HasSuffix(k, ")") {
+ return nil, errors.New("cannot match ) charactor")
}
- case k == "NOCACHE":
- if !hasNoCacheTag {
- hasNoCacheTag = true
+
+ ctx.tagName = k[:pStart]
+ ctx.params = strings.Split(k[pStart+1:len(k)-1], ",")
+ }
+
+ if j > 0 {
+ ctx.preTag = strings.ToUpper(tags[j-1])
+ }
+ if j < len(tags)-1 {
+ ctx.nextTag = strings.ToUpper(tags[j+1])
+ } else {
+ ctx.nextTag = ""
+ }
+
+ if h, ok := engine.tagHandlers[ctx.tagName]; ok {
+ if err := h(&ctx); err != nil {
+ return nil, err
}
- case k == "NOT":
- default:
- if strings.HasPrefix(k, "'") && strings.HasSuffix(k, "'") {
- if preKey != "DEFAULT" {
- col.Name = key[1 : len(key)-1]
- }
- } else if strings.Contains(k, "(") && strings.HasSuffix(k, ")") {
- fs := strings.Split(k, "(")
-
- if _, ok := core.SqlTypes[fs[0]]; !ok {
- preKey = k
- continue
- }
- col.SQLType = core.SQLType{Name: fs[0]}
- if fs[0] == core.Enum && fs[1][0] == '\'' { //enum
- options := strings.Split(fs[1][0:len(fs[1])-1], ",")
- col.EnumOptions = make(map[string]int)
- for k, v := range options {
- v = strings.TrimSpace(v)
- v = strings.Trim(v, "'")
- col.EnumOptions[v] = k
- }
- } else if fs[0] == core.Set && fs[1][0] == '\'' { //set
- options := strings.Split(fs[1][0:len(fs[1])-1], ",")
- col.SetOptions = make(map[string]int)
- for k, v := range options {
- v = strings.TrimSpace(v)
- v = strings.Trim(v, "'")
- col.SetOptions[v] = k
- }
- } else {
- fs2 := strings.Split(fs[1][0:len(fs[1])-1], ",")
- if len(fs2) == 2 {
- col.Length, err = strconv.Atoi(fs2[0])
- if err != nil {
- engine.logger.Error(err)
- }
- col.Length2, err = strconv.Atoi(fs2[1])
- if err != nil {
- engine.logger.Error(err)
- }
- } else if len(fs2) == 1 {
- col.Length, err = strconv.Atoi(fs2[0])
- if err != nil {
- engine.logger.Error(err)
- }
- }
- }
+ } else {
+ if strings.HasPrefix(key, "'") && strings.HasSuffix(key, "'") {
+ col.Name = key[1 : len(key)-1]
} else {
- if _, ok := core.SqlTypes[k]; ok {
- col.SQLType = core.SQLType{Name: k}
- } else if key != col.Default {
- col.Name = key
- }
+ col.Name = key
}
- engine.dialect.SqlType(col)
}
- preKey = k
+
+ if ctx.hasCacheTag {
+ hasCacheTag = true
+ }
+ if ctx.hasNoCacheTag {
+ hasNoCacheTag = true
+ }
}
+
if col.SQLType.Name == "" {
col.SQLType = core.Type2SQLType(fieldType)
}
+ engine.dialect.SqlType(col)
if col.Length == 0 {
col.Length = col.SQLType.DefaultLength
}
if col.Length2 == 0 {
col.Length2 = col.SQLType.DefaultLength2
}
-
if col.Name == "" {
col.Name = engine.ColumnMapper.Obj2Table(t.Field(i).Name)
}
- if isUnique {
- indexNames[col.Name] = core.UniqueType
- } else if isIndex {
- indexNames[col.Name] = core.IndexType
+ if ctx.isUnique {
+ ctx.indexNames[col.Name] = core.UniqueType
+ } else if ctx.isIndex {
+ ctx.indexNames[col.Name] = core.IndexType
}
- for indexName, indexType := range indexNames {
+ for indexName, indexType := range ctx.indexNames {
addIndex(indexName, table, col, indexType)
}
}
@@ -1114,7 +1041,7 @@ func (engine *Engine) mapType(v reflect.Value) *core.Table {
table.Cacher = nil
}
- return table
+ return table, nil
}
// IsTableEmpty if a table has any reocrd
@@ -1152,8 +1079,21 @@ func (engine *Engine) IdOfV(rv reflect.Value) core.PK {
// IDOfV get id from one value of struct
func (engine *Engine) IDOfV(rv reflect.Value) core.PK {
+ pk, err := engine.idOfV(rv)
+ if err != nil {
+ engine.logger.Error(err)
+ return nil
+ }
+ return pk
+}
+
+func (engine *Engine) idOfV(rv reflect.Value) (core.PK, error) {
v := reflect.Indirect(rv)
- table := engine.autoMapType(v)
+ table, err := engine.autoMapType(v)
+ if err != nil {
+ return nil, err
+ }
+
pk := make([]interface{}, len(table.PrimaryKeys))
for i, col := range table.PKColumns() {
pkField := v.FieldByName(col.FieldName)
@@ -1166,7 +1106,7 @@ func (engine *Engine) IDOfV(rv reflect.Value) core.PK {
pk[i] = pkField.Uint()
}
}
- return core.PK(pk)
+ return core.PK(pk), nil
}
// CreateIndexes create indexes
@@ -1187,13 +1127,6 @@ func (engine *Engine) getCacher2(table *core.Table) core.Cacher {
return table.Cacher
}
-func (engine *Engine) getCacher(v reflect.Value) core.Cacher {
- if table := engine.autoMapType(v); table != nil {
- return table.Cacher
- }
- return engine.Cacher
-}
-
// ClearCacheBean if enabled cache, clear the cache bean
func (engine *Engine) ClearCacheBean(bean interface{}, id string) error {
v := rValue(bean)
@@ -1202,7 +1135,10 @@ func (engine *Engine) ClearCacheBean(bean interface{}, id string) error {
return errors.New("error params")
}
tableName := engine.tbName(v)
- table := engine.autoMapType(v)
+ table, err := engine.autoMapType(v)
+ if err != nil {
+ return err
+ }
cacher := table.Cacher
if cacher == nil {
cacher = engine.Cacher
@@ -1223,7 +1159,11 @@ func (engine *Engine) ClearCache(beans ...interface{}) error {
return errors.New("error params")
}
tableName := engine.tbName(v)
- table := engine.autoMapType(v)
+ table, err := engine.autoMapType(v)
+ if err != nil {
+ return err
+ }
+
cacher := table.Cacher
if cacher == nil {
cacher = engine.Cacher
@@ -1243,7 +1183,11 @@ func (engine *Engine) Sync(beans ...interface{}) error {
for _, bean := range beans {
v := rValue(bean)
tableName := engine.tbName(v)
- table := engine.autoMapType(v)
+ table, err := engine.autoMapType(v)
+ fmt.Println(v, table, err)
+ if err != nil {
+ return err
+ }
s := engine.NewSession()
defer s.Close()
@@ -1426,6 +1370,13 @@ func (engine *Engine) Query(sql string, paramStr ...interface{}) (resultsSlice [
return session.Query(sql, paramStr...)
}
+// QueryString runs a raw sql and return records as []map[string]string
+func (engine *Engine) QueryString(sqlStr string, args ...interface{}) ([]map[string]string, error) {
+ session := engine.NewSession()
+ defer session.Close()
+ return session.QueryString(sqlStr, args...)
+}
+
// Insert one or more records
func (engine *Engine) Insert(beans ...interface{}) (int64, error) {
session := engine.NewSession()
diff --git a/vendor/github.com/go-xorm/xorm/goracle_driver.go b/vendor/github.com/go-xorm/xorm/goracle_driver.go
deleted file mode 100644
index 9fcde48f05..0000000000
--- a/vendor/github.com/go-xorm/xorm/goracle_driver.go
+++ /dev/null
@@ -1,42 +0,0 @@
-// Copyright 2015 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"
- "regexp"
-
- "github.com/go-xorm/core"
-)
-
-// func init() {
-// core.RegisterDriver("goracle", &goracleDriver{})
-// }
-
-type goracleDriver struct {
-}
-
-func (cfg *goracleDriver) Parse(driverName, dataSourceName string) (*core.Uri, error) {
- db := &core.Uri{DbType: core.ORACLE}
- dsnPattern := regexp.MustCompile(
- `^(?:(?P<user>.*?)(?::(?P<passwd>.*))?@)?` + // [user[:password]@]
- `(?:(?P<net>[^\(]*)(?:\((?P<addr>[^\)]*)\))?)?` + // [net[(addr)]]
- `\/(?P<dbname>.*?)` + // /dbname
- `(?:\?(?P<params>[^\?]*))?$`) // [?param1=value1&paramN=valueN]
- matches := dsnPattern.FindStringSubmatch(dataSourceName)
- //tlsConfigRegister := make(map[string]*tls.Config)
- names := dsnPattern.SubexpNames()
-
- for i, match := range matches {
- switch names[i] {
- case "dbname":
- db.DbName = match
- }
- }
- if db.DbName == "" {
- return nil, errors.New("dbname is empty")
- }
- return db, nil
-}
diff --git a/vendor/github.com/go-xorm/xorm/helpers.go b/vendor/github.com/go-xorm/xorm/helpers.go
index 4e26e84143..398ec679fe 100644
--- a/vendor/github.com/go-xorm/xorm/helpers.go
+++ b/vendor/github.com/go-xorm/xorm/helpers.go
@@ -180,6 +180,20 @@ func isStructZero(v reflect.Value) bool {
return true
}
+func isArrayValueZero(v reflect.Value) bool {
+ if !v.IsValid() || v.Len() == 0 {
+ return true
+ }
+
+ for i := 0; i < v.Len(); i++ {
+ if !isZero(v.Index(i).Interface()) {
+ return false
+ }
+ }
+
+ return true
+}
+
func int64ToIntValue(id int64, tp reflect.Type) reflect.Value {
var v interface{}
switch tp.Kind() {
diff --git a/vendor/github.com/go-xorm/xorm/mymysql_driver.go b/vendor/github.com/go-xorm/xorm/mymysql_driver.go
deleted file mode 100644
index ef3086a422..0000000000
--- a/vendor/github.com/go-xorm/xorm/mymysql_driver.go
+++ /dev/null
@@ -1,65 +0,0 @@
-// Copyright 2015 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"
- "strings"
- "time"
-
- "github.com/go-xorm/core"
-)
-
-type mymysqlDriver struct {
-}
-
-func (p *mymysqlDriver) Parse(driverName, dataSourceName string) (*core.Uri, error) {
- db := &core.Uri{DbType: core.MYSQL}
-
- pd := strings.SplitN(dataSourceName, "*", 2)
- if len(pd) == 2 {
- // Parse protocol part of URI
- p := strings.SplitN(pd[0], ":", 2)
- if len(p) != 2 {
- return nil, errors.New("Wrong protocol part of URI")
- }
- db.Proto = p[0]
- options := strings.Split(p[1], ",")
- db.Raddr = options[0]
- for _, o := range options[1:] {
- kv := strings.SplitN(o, "=", 2)
- var k, v string
- if len(kv) == 2 {
- k, v = kv[0], kv[1]
- } else {
- k, v = o, "true"
- }
- switch k {
- case "laddr":
- db.Laddr = v
- case "timeout":
- to, err := time.ParseDuration(v)
- if err != nil {
- return nil, err
- }
- db.Timeout = to
- default:
- return nil, errors.New("Unknown option: " + k)
- }
- }
- // Remove protocol part
- pd = pd[1:]
- }
- // Parse database part of URI
- dup := strings.SplitN(pd[0], "/", 3)
- if len(dup) != 3 {
- return nil, errors.New("Wrong database part of URI")
- }
- db.DbName = dup[0]
- db.User = dup[1]
- db.Passwd = dup[2]
-
- return db, nil
-}
diff --git a/vendor/github.com/go-xorm/xorm/mysql_driver.go b/vendor/github.com/go-xorm/xorm/mysql_driver.go
deleted file mode 100644
index 6ceeed58f0..0000000000
--- a/vendor/github.com/go-xorm/xorm/mysql_driver.go
+++ /dev/null
@@ -1,50 +0,0 @@
-// Copyright 2015 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 (
- "regexp"
- "strings"
-
- "github.com/go-xorm/core"
-)
-
-type mysqlDriver struct {
-}
-
-func (p *mysqlDriver) Parse(driverName, dataSourceName string) (*core.Uri, error) {
- dsnPattern := regexp.MustCompile(
- `^(?:(?P<user>.*?)(?::(?P<passwd>.*))?@)?` + // [user[:password]@]
- `(?:(?P<net>[^\(]*)(?:\((?P<addr>[^\)]*)\))?)?` + // [net[(addr)]]
- `\/(?P<dbname>.*?)` + // /dbname
- `(?:\?(?P<params>[^\?]*))?$`) // [?param1=value1&paramN=valueN]
- matches := dsnPattern.FindStringSubmatch(dataSourceName)
- //tlsConfigRegister := make(map[string]*tls.Config)
- names := dsnPattern.SubexpNames()
-
- uri := &core.Uri{DbType: core.MYSQL}
-
- for i, match := range matches {
- switch names[i] {
- case "dbname":
- uri.DbName = match
- case "params":
- if len(match) > 0 {
- kvs := strings.Split(match, "&")
- for _, kv := range kvs {
- splits := strings.Split(kv, "=")
- if len(splits) == 2 {
- switch splits[0] {
- case "charset":
- uri.Charset = splits[1]
- }
- }
- }
- }
-
- }
- }
- return uri, nil
-}
diff --git a/vendor/github.com/go-xorm/xorm/oci8_driver.go b/vendor/github.com/go-xorm/xorm/oci8_driver.go
deleted file mode 100644
index ec5f20228d..0000000000
--- a/vendor/github.com/go-xorm/xorm/oci8_driver.go
+++ /dev/null
@@ -1,37 +0,0 @@
-// Copyright 2015 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"
- "regexp"
-
- "github.com/go-xorm/core"
-)
-
-type oci8Driver struct {
-}
-
-//dataSourceName=user/password@ipv4:port/dbname
-//dataSourceName=user/password@[ipv6]:port/dbname
-func (p *oci8Driver) Parse(driverName, dataSourceName string) (*core.Uri, error) {
- db := &core.Uri{DbType: core.ORACLE}
- dsnPattern := regexp.MustCompile(
- `^(?P<user>.*)\/(?P<password>.*)@` + // user:password@
- `(?P<net>.*)` + // ip:port
- `\/(?P<dbname>.*)`) // dbname
- matches := dsnPattern.FindStringSubmatch(dataSourceName)
- names := dsnPattern.SubexpNames()
- for i, match := range matches {
- switch names[i] {
- case "dbname":
- db.DbName = match
- }
- }
- if db.DbName == "" {
- return nil, errors.New("dbname is empty")
- }
- return db, nil
-}
diff --git a/vendor/github.com/go-xorm/xorm/odbc_driver.go b/vendor/github.com/go-xorm/xorm/odbc_driver.go
deleted file mode 100644
index 6770de6076..0000000000
--- a/vendor/github.com/go-xorm/xorm/odbc_driver.go
+++ /dev/null
@@ -1,34 +0,0 @@
-// Copyright 2015 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"
- "strings"
-
- "github.com/go-xorm/core"
-)
-
-type odbcDriver struct {
-}
-
-func (p *odbcDriver) Parse(driverName, dataSourceName string) (*core.Uri, error) {
- kv := strings.Split(dataSourceName, ";")
- var dbName string
-
- for _, c := range kv {
- vv := strings.Split(strings.TrimSpace(c), "=")
- if len(vv) == 2 {
- switch strings.ToLower(vv[0]) {
- case "database":
- dbName = vv[1]
- }
- }
- }
- if dbName == "" {
- return nil, errors.New("no db name provided")
- }
- return &core.Uri{DbName: dbName, DbType: core.MSSQL}, nil
-}
diff --git a/vendor/github.com/go-xorm/xorm/pq_driver.go b/vendor/github.com/go-xorm/xorm/pq_driver.go
deleted file mode 100644
index 5d608f250a..0000000000
--- a/vendor/github.com/go-xorm/xorm/pq_driver.go
+++ /dev/null
@@ -1,119 +0,0 @@
-// Copyright 2015 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"
- "net/url"
- "sort"
- "strings"
-
- "github.com/go-xorm/core"
-)
-
-type pqDriver struct {
-}
-
-type values map[string]string
-
-func (vs values) Set(k, v string) {
- vs[k] = v
-}
-
-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 {
- return "", err
- }
-
- if u.Scheme != "postgresql" && u.Scheme != "postgres" {
- 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:])
- }
-
- 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
-}
-
-func parseOpts(name string, o values) {
- if len(name) == 0 {
- return
- }
-
- name = strings.TrimSpace(name)
-
- ps := strings.Split(name, " ")
- for _, p := range ps {
- kv := strings.Split(p, "=")
- if len(kv) < 2 {
- errorf("invalid option: %q", p)
- }
- o.Set(kv[0], kv[1])
- }
-}
-
-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)
- if err != nil {
- return nil, err
- }
- }
- 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/rows.go b/vendor/github.com/go-xorm/xorm/rows.go
index e9cf8597cc..a91d08b779 100644
--- a/vendor/github.com/go-xorm/xorm/rows.go
+++ b/vendor/github.com/go-xorm/xorm/rows.go
@@ -16,13 +16,12 @@ import (
type Rows struct {
NoTypeCheck bool
- session *Session
- stmt *core.Stmt
- rows *core.Rows
- fields []string
- fieldsCount int
- beanType reflect.Type
- lastError error
+ session *Session
+ stmt *core.Stmt
+ rows *core.Rows
+ fields []string
+ beanType reflect.Type
+ lastError error
}
func newRows(session *Session, bean interface{}) (*Rows, error) {
@@ -82,7 +81,6 @@ func newRows(session *Session, bean interface{}) (*Rows, error) {
rows.Close()
return nil, err
}
- rows.fieldsCount = len(rows.fields)
return rows, nil
}
@@ -114,7 +112,10 @@ func (rows *Rows) Scan(bean interface{}) error {
return fmt.Errorf("scan arg is incompatible type to [%v]", rows.beanType)
}
- _, err := rows.session.row2Bean(rows.rows, rows.fields, rows.fieldsCount, bean)
+ dataStruct := rValue(bean)
+ rows.session.Statement.setRefValue(dataStruct)
+ _, err := rows.session.row2Bean(rows.rows, rows.fields, len(rows.fields), bean, &dataStruct, rows.session.Statement.RefTable)
+
return err
}
diff --git a/vendor/github.com/go-xorm/xorm/session.go b/vendor/github.com/go-xorm/xorm/session.go
index 2efc74b285..2e9eb9d877 100644
--- a/vendor/github.com/go-xorm/xorm/session.go
+++ b/vendor/github.com/go-xorm/xorm/session.go
@@ -6,17 +6,14 @@ package xorm
import (
"database/sql"
- "database/sql/driver"
"encoding/json"
"errors"
"fmt"
"hash/crc32"
"reflect"
- "strconv"
"strings"
"time"
- "github.com/go-xorm/builder"
"github.com/go-xorm/core"
)
@@ -113,52 +110,6 @@ func (session *Session) Prepare() *Session {
return session
}
-// Sql provides raw sql input parameter. When you have a complex SQL statement
-// and cannot use Where, Id, In and etc. Methods to describe, you can use SQL.
-//
-// Deprecated: use SQL instead.
-func (session *Session) Sql(query string, args ...interface{}) *Session {
- return session.SQL(query, args...)
-}
-
-// SQL provides raw sql input parameter. When you have a complex SQL statement
-// and cannot use Where, Id, In and etc. Methods to describe, you can use SQL.
-func (session *Session) SQL(query interface{}, args ...interface{}) *Session {
- session.Statement.SQL(query, args...)
- return session
-}
-
-// Where provides custom query condition.
-func (session *Session) Where(query interface{}, args ...interface{}) *Session {
- session.Statement.Where(query, args...)
- return session
-}
-
-// And provides custom query condition.
-func (session *Session) And(query interface{}, args ...interface{}) *Session {
- session.Statement.And(query, args...)
- return session
-}
-
-// Or provides custom query condition.
-func (session *Session) Or(query interface{}, args ...interface{}) *Session {
- session.Statement.Or(query, args...)
- return session
-}
-
-// Id provides converting id as a query condition
-//
-// Deprecated: use ID instead
-func (session *Session) Id(id interface{}) *Session {
- return session.ID(id)
-}
-
-// ID provides converting id as a query condition
-func (session *Session) ID(id interface{}) *Session {
- session.Statement.ID(id)
- return session
-}
-
// Before Apply before Processor, affected bean is passed to closure arg
func (session *Session) Before(closures func(interface{})) *Session {
if closures != nil {
@@ -187,109 +138,18 @@ func (session *Session) Alias(alias string) *Session {
return session
}
-// In provides a query string like "id in (1, 2, 3)"
-func (session *Session) In(column string, args ...interface{}) *Session {
- session.Statement.In(column, args...)
- return session
-}
-
-// NotIn provides a query string like "id in (1, 2, 3)"
-func (session *Session) NotIn(column string, args ...interface{}) *Session {
- session.Statement.NotIn(column, args...)
- return session
-}
-
-// Incr provides a query string like "count = count + 1"
-func (session *Session) Incr(column string, arg ...interface{}) *Session {
- session.Statement.Incr(column, arg...)
- return session
-}
-
-// Decr provides a query string like "count = count - 1"
-func (session *Session) Decr(column string, arg ...interface{}) *Session {
- session.Statement.Decr(column, arg...)
- return session
-}
-
-// SetExpr provides a query string like "column = {expression}"
-func (session *Session) SetExpr(column string, expression string) *Session {
- session.Statement.SetExpr(column, expression)
- return session
-}
-
-// Select provides some columns to special
-func (session *Session) Select(str string) *Session {
- session.Statement.Select(str)
- return session
-}
-
-// Cols provides some columns to special
-func (session *Session) Cols(columns ...string) *Session {
- session.Statement.Cols(columns...)
- return session
-}
-
-// AllCols ask all columns
-func (session *Session) AllCols() *Session {
- session.Statement.AllCols()
- return session
-}
-
-// MustCols specify some columns must use even if they are empty
-func (session *Session) MustCols(columns ...string) *Session {
- session.Statement.MustCols(columns...)
- return session
-}
-
// NoCascade indicate that no cascade load child object
func (session *Session) NoCascade() *Session {
session.Statement.UseCascade = false
return session
}
-// UseBool automatically retrieve condition according struct, but
-// if struct has bool field, it will ignore them. So use UseBool
-// to tell system to do not ignore them.
-// If no parameters, it will use all the bool field of struct, or
-// it will use parameters's columns
-func (session *Session) UseBool(columns ...string) *Session {
- session.Statement.UseBool(columns...)
- return session
-}
-
-// Distinct use for distinct columns. Caution: when you are using cache,
-// distinct will not be cached because cache system need id,
-// but distinct will not provide id
-func (session *Session) Distinct(columns ...string) *Session {
- session.Statement.Distinct(columns...)
- return session
-}
-
// ForUpdate Set Read/Write locking for UPDATE
func (session *Session) ForUpdate() *Session {
session.Statement.IsForUpdate = true
return session
}
-// Omit Only not use the parameters as select or update columns
-func (session *Session) Omit(columns ...string) *Session {
- session.Statement.Omit(columns...)
- return session
-}
-
-// Nullable Set null when column is zero-value and nullable for update
-func (session *Session) Nullable(columns ...string) *Session {
- session.Statement.Nullable(columns...)
- return session
-}
-
-// NoAutoTime means do not automatically give created field and updated field
-// the current time on the current session temporarily
-func (session *Session) NoAutoTime() *Session {
- session.Statement.UseAutoTime = false
- return session
-}
-
// NoAutoCondition disable generate SQL condition from beans
func (session *Session) NoAutoCondition(no ...bool) *Session {
session.Statement.NoAutoCondition(no...)
@@ -375,11 +235,6 @@ func (session *Session) DB() *core.DB {
return session.db
}
-// Conds returns session query conditions
-func (session *Session) Conds() builder.Cond {
- return session.Statement.cond
-}
-
func cleanupProcessorsClosures(slices *[]func(interface{})) {
if len(*slices) > 0 {
*slices = make([]func(interface{}), 0)
@@ -438,13 +293,13 @@ func (session *Session) getField(dataStruct *reflect.Value, key string, table *c
type Cell *interface{}
func (session *Session) rows2Beans(rows *core.Rows, fields []string, fieldsCount int,
- table *core.Table, newElemFunc func() reflect.Value,
+ table *core.Table, newElemFunc func([]string) reflect.Value,
sliceValueSetFunc func(*reflect.Value, core.PK) error) error {
for rows.Next() {
- var newValue = newElemFunc()
+ var newValue = newElemFunc(fields)
bean := newValue.Interface()
dataStruct := rValue(bean)
- pk, err := session._row2Bean(rows, fields, fieldsCount, bean, &dataStruct, table)
+ pk, err := session.row2Bean(rows, fields, fieldsCount, bean, &dataStruct, table)
if err != nil {
return err
}
@@ -457,18 +312,7 @@ func (session *Session) rows2Beans(rows *core.Rows, fields []string, fieldsCount
return nil
}
-func (session *Session) row2Bean(rows *core.Rows, fields []string, fieldsCount int, bean interface{}) (core.PK, error) {
- dataStruct := rValue(bean)
- if dataStruct.Kind() != reflect.Struct {
- return nil, errors.New("Expected a pointer to a struct")
- }
-
- session.Statement.setRefValue(dataStruct)
-
- return session._row2Bean(rows, fields, fieldsCount, bean, &dataStruct, session.Statement.RefTable)
-}
-
-func (session *Session) _row2Bean(rows *core.Rows, fields []string, fieldsCount int, bean interface{}, dataStruct *reflect.Value, table *core.Table) (core.PK, error) {
+func (session *Session) row2Bean(rows *core.Rows, fields []string, fieldsCount int, bean interface{}, dataStruct *reflect.Value, table *core.Table) (core.PK, error) {
scanResults := make([]interface{}, fieldsCount)
for i := 0; i < len(fields); i++ {
var cell interface{}
@@ -492,6 +336,15 @@ func (session *Session) _row2Bean(rows *core.Rows, fields []string, fieldsCount
}
}()
+ dbTZ := session.Engine.DatabaseTZ
+ if dbTZ == nil {
+ if session.Engine.dialect.DBType() == core.SQLITE {
+ dbTZ = time.UTC
+ } else {
+ dbTZ = time.Local
+ }
+ }
+
var tempMap = make(map[string]int)
var pk core.PK
for ii, key := range fields {
@@ -613,7 +466,21 @@ func (session *Session) _row2Bean(rows *core.Rows, fields []string, fieldsCount
case reflect.Uint8:
if fieldType.Elem().Kind() == reflect.Uint8 {
hasAssigned = true
- fieldValue.Set(vv)
+ if col.SQLType.IsText() {
+ x := reflect.New(fieldType)
+ err := json.Unmarshal(vv.Bytes(), x.Interface())
+ if err != nil {
+ session.Engine.logger.Error(err)
+ return nil, err
+ }
+ fieldValue.Set(x.Elem())
+ } else {
+ for i := 0; i < fieldValue.Len(); i++ {
+ if i < vv.Len() {
+ fieldValue.Index(i).Set(vv.Index(i))
+ }
+ }
+ }
}
}
}
@@ -650,21 +517,19 @@ func (session *Session) _row2Bean(rows *core.Rows, fields []string, fieldsCount
}
case reflect.Struct:
if fieldType.ConvertibleTo(core.TimeType) {
+ var tz *time.Location
+ if col.TimeZone == nil {
+ tz = session.Engine.TZLocation
+ } else {
+ tz = col.TimeZone
+ }
+
if rawValueType == core.TimeType {
hasAssigned = true
t := vv.Convert(core.TimeType).Interface().(time.Time)
z, _ := t.Zone()
- dbTZ := session.Engine.DatabaseTZ
- if dbTZ == nil {
- if session.Engine.dialect.DBType() == core.SQLITE {
- dbTZ = time.UTC
- } else {
- dbTZ = time.Local
- }
- }
-
// set new location if database don't save timezone or give an incorrect timezone
if len(z) == 0 || t.Year() == 0 || t.Location().String() != dbTZ.String() { // !nashtsai! HACK tmp work around for lib/pq doesn't properly time with location
session.Engine.logger.Debugf("empty zone key[%v] : %v | zone: %v | location: %+v\n", key, t, z, *t.Location())
@@ -673,11 +538,7 @@ func (session *Session) _row2Bean(rows *core.Rows, fields []string, fieldsCount
}
// !nashtsai! convert to engine location
- if col.TimeZone == nil {
- t = t.In(session.Engine.TZLocation)
- } else {
- t = t.In(col.TimeZone)
- }
+ t = t.In(tz)
fieldValue.Set(reflect.ValueOf(t).Convert(fieldType))
// t = fieldValue.Interface().(time.Time)
@@ -686,12 +547,7 @@ func (session *Session) _row2Bean(rows *core.Rows, fields []string, fieldsCount
} else if rawValueType == core.IntType || rawValueType == core.Int64Type ||
rawValueType == core.Int32Type {
hasAssigned = true
- var tz *time.Location
- if col.TimeZone == nil {
- tz = session.Engine.TZLocation
- } else {
- tz = col.TimeZone
- }
+
t := time.Unix(vv.Int(), 0).In(tz)
//vv = reflect.ValueOf(t)
fieldValue.Set(reflect.ValueOf(t).Convert(fieldType))
@@ -750,64 +606,39 @@ func (session *Session) _row2Bean(rows *core.Rows, fields []string, fieldsCount
}
}
} else if session.Statement.UseCascade {
- table := session.Engine.autoMapType(*fieldValue)
- if table != nil {
- hasAssigned = true
- if len(table.PrimaryKeys) != 1 {
- panic("unsupported non or composited primary key cascade")
- }
- var pk = make(core.PK, len(table.PrimaryKeys))
-
- switch rawValueType.Kind() {
- case reflect.Int64:
- pk[0] = vv.Int()
- case reflect.Int:
- pk[0] = int(vv.Int())
- case reflect.Int32:
- pk[0] = int32(vv.Int())
- case reflect.Int16:
- pk[0] = int16(vv.Int())
- case reflect.Int8:
- pk[0] = int8(vv.Int())
- case reflect.Uint64:
- pk[0] = vv.Uint()
- case reflect.Uint:
- pk[0] = uint(vv.Uint())
- case reflect.Uint32:
- pk[0] = uint32(vv.Uint())
- case reflect.Uint16:
- pk[0] = uint16(vv.Uint())
- case reflect.Uint8:
- pk[0] = uint8(vv.Uint())
- case reflect.String:
- pk[0] = vv.String()
- case reflect.Slice:
- pk[0], _ = strconv.ParseInt(string(rawValue.Interface().([]byte)), 10, 64)
- default:
- panic(fmt.Sprintf("unsupported primary key type: %v, %v", rawValueType, fieldValue))
- }
+ table, err := session.Engine.autoMapType(*fieldValue)
+ if err != nil {
+ return nil, err
+ }
- if !isPKZero(pk) {
- // !nashtsai! TODO for hasOne relationship, it's preferred to use join query for eager fetch
- // however, also need to consider adding a 'lazy' attribute to xorm tag which allow hasOne
- // property to be fetched lazily
- structInter := reflect.New(fieldValue.Type())
- newsession := session.Engine.NewSession()
- defer newsession.Close()
- has, err := newsession.Id(pk).NoCascade().Get(structInter.Interface())
- if err != nil {
- return nil, err
- }
- if has {
- //v := structInter.Elem().Interface()
- //fieldValue.Set(reflect.ValueOf(v))
- fieldValue.Set(structInter.Elem())
- } else {
- return nil, errors.New("cascade obj is not exist")
- }
+ hasAssigned = true
+ if len(table.PrimaryKeys) != 1 {
+ panic("unsupported non or composited primary key cascade")
+ }
+ var pk = make(core.PK, len(table.PrimaryKeys))
+ pk[0], err = asKind(vv, rawValueType)
+ if err != nil {
+ return nil, err
+ }
+
+ if !isPKZero(pk) {
+ // !nashtsai! TODO for hasOne relationship, it's preferred to use join query for eager fetch
+ // however, also need to consider adding a 'lazy' attribute to xorm tag which allow hasOne
+ // property to be fetched lazily
+ structInter := reflect.New(fieldValue.Type())
+ newsession := session.Engine.NewSession()
+ defer newsession.Close()
+ has, err := newsession.Id(pk).NoCascade().Get(structInter.Interface())
+ if err != nil {
+ return nil, err
+ }
+ if has {
+ //v := structInter.Elem().Interface()
+ //fieldValue.Set(reflect.ValueOf(v))
+ fieldValue.Set(structInter.Elem())
+ } else {
+ return nil, errors.New("cascade obj is not exist")
}
- } else {
- session.Engine.logger.Error("unsupported struct type in Scan: ", fieldValue.Type().String())
}
}
case reflect.Ptr:
@@ -954,657 +785,6 @@ func (session *Session) queryPreprocess(sqlStr *string, paramStr ...interface{})
session.saveLastSQL(*sqlStr, paramStr...)
}
-func (session *Session) str2Time(col *core.Column, data string) (outTime time.Time, outErr error) {
- sdata := strings.TrimSpace(data)
- var x time.Time
- var err error
-
- if sdata == "0000-00-00 00:00:00" ||
- sdata == "0001-01-01 00:00:00" {
- } else if !strings.ContainsAny(sdata, "- :") { // !nashtsai! has only found that mymysql driver is using this for time type column
- // time stamp
- sd, err := strconv.ParseInt(sdata, 10, 64)
- if err == nil {
- x = time.Unix(sd, 0)
- // !nashtsai! HACK mymysql driver is causing Local location being change to CHAT and cause wrong time conversion
- if col.TimeZone == nil {
- x = x.In(session.Engine.TZLocation)
- } else {
- x = x.In(col.TimeZone)
- }
- 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)
- }
- } else if len(sdata) > 19 && strings.Contains(sdata, "-") {
- x, err = time.ParseInLocation(time.RFC3339Nano, sdata, session.Engine.TZLocation)
- 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, session.Engine.TZLocation)
- 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, session.Engine.TZLocation)
- 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, session.Engine.TZLocation)
- 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, session.Engine.TZLocation)
- 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, " ")
- sdata = ssd[1]
- }
-
- sdata = strings.TrimSpace(sdata)
- if session.Engine.dialect.DBType() == core.MYSQL && len(sdata) > 8 {
- sdata = sdata[len(sdata)-8:]
- }
-
- st := fmt.Sprintf("2006-01-02 %v", sdata)
- x, err = time.ParseInLocation("2006-01-02 15:04:05", st, session.Engine.TZLocation)
- 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
- }
- if err != nil {
- outErr = fmt.Errorf("unsupported time format %v: %v", sdata, err)
- return
- }
- outTime = x
- return
-}
-
-func (session *Session) byte2Time(col *core.Column, data []byte) (outTime time.Time, outErr error) {
- return session.str2Time(col, string(data))
-}
-
-// convert a db data([]byte) to a field value
-func (session *Session) bytes2Value(col *core.Column, fieldValue *reflect.Value, data []byte) error {
- if structConvert, ok := fieldValue.Addr().Interface().(core.Conversion); ok {
- return structConvert.FromDB(data)
- }
-
- if structConvert, ok := fieldValue.Interface().(core.Conversion); ok {
- return structConvert.FromDB(data)
- }
-
- var v interface{}
- key := col.Name
- fieldType := fieldValue.Type()
-
- switch fieldType.Kind() {
- case reflect.Complex64, reflect.Complex128:
- x := reflect.New(fieldType)
- if len(data) > 0 {
- err := json.Unmarshal(data, x.Interface())
- if err != nil {
- session.Engine.logger.Error(err)
- return err
- }
- fieldValue.Set(x.Elem())
- }
- case reflect.Slice, reflect.Array, reflect.Map:
- v = data
- t := fieldType.Elem()
- k := t.Kind()
- if col.SQLType.IsText() {
- x := reflect.New(fieldType)
- if len(data) > 0 {
- err := json.Unmarshal(data, x.Interface())
- if err != nil {
- session.Engine.logger.Error(err)
- return err
- }
- fieldValue.Set(x.Elem())
- }
- } else if col.SQLType.IsBlob() {
- if k == reflect.Uint8 {
- fieldValue.Set(reflect.ValueOf(v))
- } else {
- x := reflect.New(fieldType)
- if len(data) > 0 {
- err := json.Unmarshal(data, x.Interface())
- if err != nil {
- session.Engine.logger.Error(err)
- return err
- }
- fieldValue.Set(x.Elem())
- }
- }
- } else {
- return ErrUnSupportedType
- }
- case reflect.String:
- fieldValue.SetString(string(data))
- case reflect.Bool:
- d := string(data)
- v, err := strconv.ParseBool(d)
- if err != nil {
- return fmt.Errorf("arg %v as bool: %s", key, err.Error())
- }
- fieldValue.Set(reflect.ValueOf(v))
- case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
- sdata := string(data)
- var x int64
- var err error
- // for mysql, when use bit, it returned \x01
- if col.SQLType.Name == core.Bit &&
- session.Engine.dialect.DBType() == core.MYSQL { // !nashtsai! TODO dialect needs to provide conversion interface API
- if len(data) == 1 {
- x = int64(data[0])
- } else {
- x = 0
- }
- } else if strings.HasPrefix(sdata, "0x") {
- x, err = strconv.ParseInt(sdata, 16, 64)
- } else if strings.HasPrefix(sdata, "0") {
- x, err = strconv.ParseInt(sdata, 8, 64)
- } else if strings.EqualFold(sdata, "true") {
- x = 1
- } else if strings.EqualFold(sdata, "false") {
- x = 0
- } else {
- x, err = strconv.ParseInt(sdata, 10, 64)
- }
- if err != nil {
- return fmt.Errorf("arg %v as int: %s", key, err.Error())
- }
- fieldValue.SetInt(x)
- case reflect.Float32, reflect.Float64:
- x, err := strconv.ParseFloat(string(data), 64)
- if err != nil {
- return fmt.Errorf("arg %v as float64: %s", key, err.Error())
- }
- fieldValue.SetFloat(x)
- case reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uint:
- x, err := strconv.ParseUint(string(data), 10, 64)
- if err != nil {
- return fmt.Errorf("arg %v as int: %s", key, err.Error())
- }
- fieldValue.SetUint(x)
- //Currently only support Time type
- case reflect.Struct:
- // !<winxxp>! 增加支持sql.Scanner接口的结构,如sql.NullString
- if nulVal, ok := fieldValue.Addr().Interface().(sql.Scanner); ok {
- if err := nulVal.Scan(data); err != nil {
- return fmt.Errorf("sql.Scan(%v) failed: %s ", data, err.Error())
- }
- } else {
- if fieldType.ConvertibleTo(core.TimeType) {
- x, err := session.byte2Time(col, data)
- if err != nil {
- return err
- }
- v = x
- fieldValue.Set(reflect.ValueOf(v).Convert(fieldType))
- } else if session.Statement.UseCascade {
- table := session.Engine.autoMapType(*fieldValue)
- if table != nil {
- // TODO: current only support 1 primary key
- if len(table.PrimaryKeys) > 1 {
- panic("unsupported composited primary key cascade")
- }
- var pk = make(core.PK, len(table.PrimaryKeys))
- rawValueType := table.ColumnType(table.PKColumns()[0].FieldName)
- var err error
- pk[0], err = str2PK(string(data), rawValueType)
- if err != nil {
- return err
- }
-
- if !isPKZero(pk) {
- // !nashtsai! TODO for hasOne relationship, it's preferred to use join query for eager fetch
- // however, also need to consider adding a 'lazy' attribute to xorm tag which allow hasOne
- // property to be fetched lazily
- structInter := reflect.New(fieldValue.Type())
- newsession := session.Engine.NewSession()
- defer newsession.Close()
- has, err := newsession.Id(pk).NoCascade().Get(structInter.Interface())
- if err != nil {
- return err
- }
- if has {
- v = structInter.Elem().Interface()
- fieldValue.Set(reflect.ValueOf(v))
- } else {
- return errors.New("cascade obj is not exist")
- }
- }
- } else {
- return fmt.Errorf("unsupported struct type in Scan: %s", fieldValue.Type().String())
- }
- }
- }
- case reflect.Ptr:
- // !nashtsai! TODO merge duplicated codes above
- //typeStr := fieldType.String()
- switch fieldType.Elem().Kind() {
- // case "*string":
- case core.StringType.Kind():
- x := string(data)
- fieldValue.Set(reflect.ValueOf(&x).Convert(fieldType))
- // case "*bool":
- case core.BoolType.Kind():
- d := string(data)
- v, err := strconv.ParseBool(d)
- if err != nil {
- return fmt.Errorf("arg %v as bool: %s", key, err.Error())
- }
- fieldValue.Set(reflect.ValueOf(&v).Convert(fieldType))
- // case "*complex64":
- case core.Complex64Type.Kind():
- var x complex64
- if len(data) > 0 {
- err := json.Unmarshal(data, &x)
- if err != nil {
- session.Engine.logger.Error(err)
- return err
- }
- fieldValue.Set(reflect.ValueOf(&x).Convert(fieldType))
- }
- // case "*complex128":
- case core.Complex128Type.Kind():
- var x complex128
- if len(data) > 0 {
- err := json.Unmarshal(data, &x)
- if err != nil {
- session.Engine.logger.Error(err)
- return err
- }
- fieldValue.Set(reflect.ValueOf(&x).Convert(fieldType))
- }
- // case "*float64":
- case core.Float64Type.Kind():
- x, err := strconv.ParseFloat(string(data), 64)
- if err != nil {
- return fmt.Errorf("arg %v as float64: %s", key, err.Error())
- }
- fieldValue.Set(reflect.ValueOf(&x).Convert(fieldType))
- // case "*float32":
- case core.Float32Type.Kind():
- var x float32
- x1, err := strconv.ParseFloat(string(data), 32)
- if err != nil {
- return fmt.Errorf("arg %v as float32: %s", key, err.Error())
- }
- x = float32(x1)
- fieldValue.Set(reflect.ValueOf(&x).Convert(fieldType))
- // case "*uint64":
- case core.Uint64Type.Kind():
- var x uint64
- x, err := strconv.ParseUint(string(data), 10, 64)
- if err != nil {
- return fmt.Errorf("arg %v as int: %s", key, err.Error())
- }
- fieldValue.Set(reflect.ValueOf(&x).Convert(fieldType))
- // case "*uint":
- case core.UintType.Kind():
- var x uint
- x1, err := strconv.ParseUint(string(data), 10, 64)
- if err != nil {
- return fmt.Errorf("arg %v as int: %s", key, err.Error())
- }
- x = uint(x1)
- fieldValue.Set(reflect.ValueOf(&x).Convert(fieldType))
- // case "*uint32":
- case core.Uint32Type.Kind():
- var x uint32
- x1, err := strconv.ParseUint(string(data), 10, 64)
- if err != nil {
- return fmt.Errorf("arg %v as int: %s", key, err.Error())
- }
- x = uint32(x1)
- fieldValue.Set(reflect.ValueOf(&x).Convert(fieldType))
- // case "*uint8":
- case core.Uint8Type.Kind():
- var x uint8
- x1, err := strconv.ParseUint(string(data), 10, 64)
- if err != nil {
- return fmt.Errorf("arg %v as int: %s", key, err.Error())
- }
- x = uint8(x1)
- fieldValue.Set(reflect.ValueOf(&x).Convert(fieldType))
- // case "*uint16":
- case core.Uint16Type.Kind():
- var x uint16
- x1, err := strconv.ParseUint(string(data), 10, 64)
- if err != nil {
- return fmt.Errorf("arg %v as int: %s", key, err.Error())
- }
- x = uint16(x1)
- fieldValue.Set(reflect.ValueOf(&x).Convert(fieldType))
- // case "*int64":
- case core.Int64Type.Kind():
- sdata := string(data)
- var x int64
- var err error
- // for mysql, when use bit, it returned \x01
- if col.SQLType.Name == core.Bit &&
- strings.Contains(session.Engine.DriverName(), "mysql") {
- if len(data) == 1 {
- x = int64(data[0])
- } else {
- x = 0
- }
- } else if strings.HasPrefix(sdata, "0x") {
- x, err = strconv.ParseInt(sdata, 16, 64)
- } else if strings.HasPrefix(sdata, "0") {
- x, err = strconv.ParseInt(sdata, 8, 64)
- } else {
- x, err = strconv.ParseInt(sdata, 10, 64)
- }
- if err != nil {
- return fmt.Errorf("arg %v as int: %s", key, err.Error())
- }
- fieldValue.Set(reflect.ValueOf(&x).Convert(fieldType))
- // case "*int":
- case core.IntType.Kind():
- sdata := string(data)
- var x int
- var x1 int64
- var err error
- // for mysql, when use bit, it returned \x01
- if col.SQLType.Name == core.Bit &&
- strings.Contains(session.Engine.DriverName(), "mysql") {
- if len(data) == 1 {
- x = int(data[0])
- } else {
- x = 0
- }
- } else if strings.HasPrefix(sdata, "0x") {
- x1, err = strconv.ParseInt(sdata, 16, 64)
- x = int(x1)
- } else if strings.HasPrefix(sdata, "0") {
- x1, err = strconv.ParseInt(sdata, 8, 64)
- x = int(x1)
- } else {
- x1, err = strconv.ParseInt(sdata, 10, 64)
- x = int(x1)
- }
- if err != nil {
- return fmt.Errorf("arg %v as int: %s", key, err.Error())
- }
- fieldValue.Set(reflect.ValueOf(&x).Convert(fieldType))
- // case "*int32":
- case core.Int32Type.Kind():
- sdata := string(data)
- var x int32
- var x1 int64
- var err error
- // for mysql, when use bit, it returned \x01
- if col.SQLType.Name == core.Bit &&
- session.Engine.dialect.DBType() == core.MYSQL {
- if len(data) == 1 {
- x = int32(data[0])
- } else {
- x = 0
- }
- } else if strings.HasPrefix(sdata, "0x") {
- x1, err = strconv.ParseInt(sdata, 16, 64)
- x = int32(x1)
- } else if strings.HasPrefix(sdata, "0") {
- x1, err = strconv.ParseInt(sdata, 8, 64)
- x = int32(x1)
- } else {
- x1, err = strconv.ParseInt(sdata, 10, 64)
- x = int32(x1)
- }
- if err != nil {
- return fmt.Errorf("arg %v as int: %s", key, err.Error())
- }
- fieldValue.Set(reflect.ValueOf(&x).Convert(fieldType))
- // case "*int8":
- case core.Int8Type.Kind():
- sdata := string(data)
- var x int8
- var x1 int64
- var err error
- // for mysql, when use bit, it returned \x01
- if col.SQLType.Name == core.Bit &&
- strings.Contains(session.Engine.DriverName(), "mysql") {
- if len(data) == 1 {
- x = int8(data[0])
- } else {
- x = 0
- }
- } else if strings.HasPrefix(sdata, "0x") {
- x1, err = strconv.ParseInt(sdata, 16, 64)
- x = int8(x1)
- } else if strings.HasPrefix(sdata, "0") {
- x1, err = strconv.ParseInt(sdata, 8, 64)
- x = int8(x1)
- } else {
- x1, err = strconv.ParseInt(sdata, 10, 64)
- x = int8(x1)
- }
- if err != nil {
- return fmt.Errorf("arg %v as int: %s", key, err.Error())
- }
- fieldValue.Set(reflect.ValueOf(&x).Convert(fieldType))
- // case "*int16":
- case core.Int16Type.Kind():
- sdata := string(data)
- var x int16
- var x1 int64
- var err error
- // for mysql, when use bit, it returned \x01
- if col.SQLType.Name == core.Bit &&
- strings.Contains(session.Engine.DriverName(), "mysql") {
- if len(data) == 1 {
- x = int16(data[0])
- } else {
- x = 0
- }
- } else if strings.HasPrefix(sdata, "0x") {
- x1, err = strconv.ParseInt(sdata, 16, 64)
- x = int16(x1)
- } else if strings.HasPrefix(sdata, "0") {
- x1, err = strconv.ParseInt(sdata, 8, 64)
- x = int16(x1)
- } else {
- x1, err = strconv.ParseInt(sdata, 10, 64)
- x = int16(x1)
- }
- if err != nil {
- return fmt.Errorf("arg %v as int: %s", key, err.Error())
- }
- fieldValue.Set(reflect.ValueOf(&x).Convert(fieldType))
- // case "*SomeStruct":
- case reflect.Struct:
- switch fieldType {
- // case "*.time.Time":
- case core.PtrTimeType:
- x, err := session.byte2Time(col, data)
- if err != nil {
- return err
- }
- v = x
- fieldValue.Set(reflect.ValueOf(&x))
- default:
- if session.Statement.UseCascade {
- structInter := reflect.New(fieldType.Elem())
- table := session.Engine.autoMapType(structInter.Elem())
- if table != nil {
- if len(table.PrimaryKeys) > 1 {
- panic("unsupported composited primary key cascade")
- }
- var pk = make(core.PK, len(table.PrimaryKeys))
- var err error
- rawValueType := table.ColumnType(table.PKColumns()[0].FieldName)
- pk[0], err = str2PK(string(data), rawValueType)
- if err != nil {
- return err
- }
-
- if !isPKZero(pk) {
- // !nashtsai! TODO for hasOne relationship, it's preferred to use join query for eager fetch
- // however, also need to consider adding a 'lazy' attribute to xorm tag which allow hasOne
- // property to be fetched lazily
- newsession := session.Engine.NewSession()
- defer newsession.Close()
- has, err := newsession.Id(pk).NoCascade().Get(structInter.Interface())
- if err != nil {
- return err
- }
- if has {
- v = structInter.Interface()
- fieldValue.Set(reflect.ValueOf(v))
- } else {
- return errors.New("cascade obj is not exist")
- }
- }
- }
- } else {
- return fmt.Errorf("unsupported struct type in Scan: %s", fieldValue.Type().String())
- }
- }
- default:
- return fmt.Errorf("unsupported type in Scan: %s", fieldValue.Type().String())
- }
- default:
- return fmt.Errorf("unsupported type in Scan: %s", fieldValue.Type().String())
- }
-
- return nil
-}
-
-// convert a field value of a struct to interface for put into db
-func (session *Session) value2Interface(col *core.Column, fieldValue reflect.Value) (interface{}, error) {
- if fieldValue.CanAddr() {
- if fieldConvert, ok := fieldValue.Addr().Interface().(core.Conversion); ok {
- data, err := fieldConvert.ToDB()
- if err != nil {
- return 0, err
- }
- if col.SQLType.IsBlob() {
- return data, nil
- }
- return string(data), nil
- }
- }
-
- if fieldConvert, ok := fieldValue.Interface().(core.Conversion); ok {
- data, err := fieldConvert.ToDB()
- if err != nil {
- return 0, err
- }
- if col.SQLType.IsBlob() {
- return data, nil
- }
- return string(data), nil
- }
-
- fieldType := fieldValue.Type()
- k := fieldType.Kind()
- if k == reflect.Ptr {
- if fieldValue.IsNil() {
- return nil, nil
- } else if !fieldValue.IsValid() {
- session.Engine.logger.Warn("the field[", col.FieldName, "] is invalid")
- return nil, nil
- } else {
- // !nashtsai! deference pointer type to instance type
- fieldValue = fieldValue.Elem()
- fieldType = fieldValue.Type()
- k = fieldType.Kind()
- }
- }
-
- switch k {
- case reflect.Bool:
- return fieldValue.Bool(), nil
- case reflect.String:
- return fieldValue.String(), nil
- case reflect.Struct:
- if fieldType.ConvertibleTo(core.TimeType) {
- t := fieldValue.Convert(core.TimeType).Interface().(time.Time)
- if session.Engine.dialect.DBType() == core.MSSQL {
- if t.IsZero() {
- return nil, nil
- }
- }
- tf := session.Engine.FormatTime(col.SQLType.Name, t)
- return tf, nil
- }
-
- if !col.SQLType.IsJson() {
- // !<winxxp>! 增加支持driver.Valuer接口的结构,如sql.NullString
- if v, ok := fieldValue.Interface().(driver.Valuer); ok {
- return v.Value()
- }
-
- fieldTable := session.Engine.autoMapType(fieldValue)
- if len(fieldTable.PrimaryKeys) == 1 {
- pkField := reflect.Indirect(fieldValue).FieldByName(fieldTable.PKColumns()[0].FieldName)
- return pkField.Interface(), nil
- }
- return 0, fmt.Errorf("no primary key for col %v", col.Name)
- }
-
- if col.SQLType.IsText() {
- bytes, err := json.Marshal(fieldValue.Interface())
- if err != nil {
- session.Engine.logger.Error(err)
- return 0, err
- }
- return string(bytes), nil
- } else if col.SQLType.IsBlob() {
- bytes, err := json.Marshal(fieldValue.Interface())
- if err != nil {
- session.Engine.logger.Error(err)
- return 0, err
- }
- return bytes, nil
- }
- return nil, fmt.Errorf("Unsupported type %v", fieldValue.Type())
- case reflect.Complex64, reflect.Complex128:
- bytes, err := json.Marshal(fieldValue.Interface())
- if err != nil {
- session.Engine.logger.Error(err)
- return 0, err
- }
- return string(bytes), nil
- case reflect.Array, reflect.Slice, reflect.Map:
- if !fieldValue.IsValid() {
- return fieldValue.Interface(), nil
- }
-
- if col.SQLType.IsText() {
- bytes, err := json.Marshal(fieldValue.Interface())
- if err != nil {
- session.Engine.logger.Error(err)
- return 0, err
- }
- return string(bytes), nil
- } else if col.SQLType.IsBlob() {
- var bytes []byte
- var err error
- if (k == reflect.Array || k == reflect.Slice) &&
- (fieldValue.Type().Elem().Kind() == reflect.Uint8) {
- bytes = fieldValue.Bytes()
- } else {
- bytes, err = json.Marshal(fieldValue.Interface())
- if err != nil {
- session.Engine.logger.Error(err)
- return 0, err
- }
- }
- return bytes, nil
- }
- return nil, ErrUnSupportedType
- case reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uint:
- return int64(fieldValue.Uint()), nil
- default:
- return fieldValue.Interface(), nil
- }
-}
-
// saveLastSQL stores executed query information
func (session *Session) saveLastSQL(sql string, args ...interface{}) {
session.lastSQL = sql
diff --git a/vendor/github.com/go-xorm/xorm/session_cols.go b/vendor/github.com/go-xorm/xorm/session_cols.go
new file mode 100644
index 0000000000..91185defc8
--- /dev/null
+++ b/vendor/github.com/go-xorm/xorm/session_cols.go
@@ -0,0 +1,84 @@
+// 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
+
+// Incr provides a query string like "count = count + 1"
+func (session *Session) Incr(column string, arg ...interface{}) *Session {
+ session.Statement.Incr(column, arg...)
+ return session
+}
+
+// Decr provides a query string like "count = count - 1"
+func (session *Session) Decr(column string, arg ...interface{}) *Session {
+ session.Statement.Decr(column, arg...)
+ return session
+}
+
+// SetExpr provides a query string like "column = {expression}"
+func (session *Session) SetExpr(column string, expression string) *Session {
+ session.Statement.SetExpr(column, expression)
+ return session
+}
+
+// Select provides some columns to special
+func (session *Session) Select(str string) *Session {
+ session.Statement.Select(str)
+ return session
+}
+
+// Cols provides some columns to special
+func (session *Session) Cols(columns ...string) *Session {
+ session.Statement.Cols(columns...)
+ return session
+}
+
+// AllCols ask all columns
+func (session *Session) AllCols() *Session {
+ session.Statement.AllCols()
+ return session
+}
+
+// MustCols specify some columns must use even if they are empty
+func (session *Session) MustCols(columns ...string) *Session {
+ session.Statement.MustCols(columns...)
+ return session
+}
+
+// UseBool automatically retrieve condition according struct, but
+// if struct has bool field, it will ignore them. So use UseBool
+// to tell system to do not ignore them.
+// If no parameters, it will use all the bool field of struct, or
+// it will use parameters's columns
+func (session *Session) UseBool(columns ...string) *Session {
+ session.Statement.UseBool(columns...)
+ return session
+}
+
+// Distinct use for distinct columns. Caution: when you are using cache,
+// distinct will not be cached because cache system need id,
+// but distinct will not provide id
+func (session *Session) Distinct(columns ...string) *Session {
+ session.Statement.Distinct(columns...)
+ return session
+}
+
+// Omit Only not use the parameters as select or update columns
+func (session *Session) Omit(columns ...string) *Session {
+ session.Statement.Omit(columns...)
+ return session
+}
+
+// Nullable Set null when column is zero-value and nullable for update
+func (session *Session) Nullable(columns ...string) *Session {
+ session.Statement.Nullable(columns...)
+ return session
+}
+
+// NoAutoTime means do not automatically give created field and updated field
+// the current time on the current session temporarily
+func (session *Session) NoAutoTime() *Session {
+ session.Statement.UseAutoTime = false
+ return session
+}
diff --git a/vendor/github.com/go-xorm/xorm/session_cond.go b/vendor/github.com/go-xorm/xorm/session_cond.go
new file mode 100644
index 0000000000..948a90bc1f
--- /dev/null
+++ b/vendor/github.com/go-xorm/xorm/session_cond.go
@@ -0,0 +1,70 @@
+// 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/builder"
+
+// Sql provides raw sql input parameter. When you have a complex SQL statement
+// and cannot use Where, Id, In and etc. Methods to describe, you can use SQL.
+//
+// Deprecated: use SQL instead.
+func (session *Session) Sql(query string, args ...interface{}) *Session {
+ return session.SQL(query, args...)
+}
+
+// SQL provides raw sql input parameter. When you have a complex SQL statement
+// and cannot use Where, Id, In and etc. Methods to describe, you can use SQL.
+func (session *Session) SQL(query interface{}, args ...interface{}) *Session {
+ session.Statement.SQL(query, args...)
+ return session
+}
+
+// Where provides custom query condition.
+func (session *Session) Where(query interface{}, args ...interface{}) *Session {
+ session.Statement.Where(query, args...)
+ return session
+}
+
+// And provides custom query condition.
+func (session *Session) And(query interface{}, args ...interface{}) *Session {
+ session.Statement.And(query, args...)
+ return session
+}
+
+// Or provides custom query condition.
+func (session *Session) Or(query interface{}, args ...interface{}) *Session {
+ session.Statement.Or(query, args...)
+ return session
+}
+
+// Id provides converting id as a query condition
+//
+// Deprecated: use ID instead
+func (session *Session) Id(id interface{}) *Session {
+ return session.ID(id)
+}
+
+// ID provides converting id as a query condition
+func (session *Session) ID(id interface{}) *Session {
+ session.Statement.ID(id)
+ return session
+}
+
+// In provides a query string like "id in (1, 2, 3)"
+func (session *Session) In(column string, args ...interface{}) *Session {
+ session.Statement.In(column, args...)
+ return session
+}
+
+// NotIn provides a query string like "id in (1, 2, 3)"
+func (session *Session) NotIn(column string, args ...interface{}) *Session {
+ session.Statement.NotIn(column, args...)
+ return session
+}
+
+// Conds returns session query conditions
+func (session *Session) Conds() builder.Cond {
+ return session.Statement.cond
+}
diff --git a/vendor/github.com/go-xorm/xorm/session_convert.go b/vendor/github.com/go-xorm/xorm/session_convert.go
new file mode 100644
index 0000000000..7ef57b5f38
--- /dev/null
+++ b/vendor/github.com/go-xorm/xorm/session_convert.go
@@ -0,0 +1,673 @@
+// 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"
+ "database/sql/driver"
+ "encoding/json"
+ "errors"
+ "fmt"
+ "reflect"
+ "strconv"
+ "strings"
+ "time"
+
+ "github.com/go-xorm/core"
+)
+
+func (session *Session) str2Time(col *core.Column, data string) (outTime time.Time, outErr error) {
+ sdata := strings.TrimSpace(data)
+ var x time.Time
+ var err error
+
+ if sdata == "0000-00-00 00:00:00" ||
+ sdata == "0001-01-01 00:00:00" {
+ } else if !strings.ContainsAny(sdata, "- :") { // !nashtsai! has only found that mymysql driver is using this for time type column
+ // time stamp
+ sd, err := strconv.ParseInt(sdata, 10, 64)
+ if err == nil {
+ x = time.Unix(sd, 0)
+ // !nashtsai! HACK mymysql driver is causing Local location being change to CHAT and cause wrong time conversion
+ if col.TimeZone == nil {
+ x = x.In(session.Engine.TZLocation)
+ } else {
+ x = x.In(col.TimeZone)
+ }
+ 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)
+ }
+ } else if len(sdata) > 19 && strings.Contains(sdata, "-") {
+ x, err = time.ParseInLocation(time.RFC3339Nano, sdata, session.Engine.TZLocation)
+ 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, session.Engine.TZLocation)
+ 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, session.Engine.TZLocation)
+ 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, session.Engine.TZLocation)
+ 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, session.Engine.TZLocation)
+ 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, " ")
+ sdata = ssd[1]
+ }
+
+ sdata = strings.TrimSpace(sdata)
+ if session.Engine.dialect.DBType() == core.MYSQL && len(sdata) > 8 {
+ sdata = sdata[len(sdata)-8:]
+ }
+
+ st := fmt.Sprintf("2006-01-02 %v", sdata)
+ x, err = time.ParseInLocation("2006-01-02 15:04:05", st, session.Engine.TZLocation)
+ 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
+ }
+ if err != nil {
+ outErr = fmt.Errorf("unsupported time format %v: %v", sdata, err)
+ return
+ }
+ outTime = x
+ return
+}
+
+func (session *Session) byte2Time(col *core.Column, data []byte) (outTime time.Time, outErr error) {
+ return session.str2Time(col, string(data))
+}
+
+// convert a db data([]byte) to a field value
+func (session *Session) bytes2Value(col *core.Column, fieldValue *reflect.Value, data []byte) error {
+ if structConvert, ok := fieldValue.Addr().Interface().(core.Conversion); ok {
+ return structConvert.FromDB(data)
+ }
+
+ if structConvert, ok := fieldValue.Interface().(core.Conversion); ok {
+ return structConvert.FromDB(data)
+ }
+
+ var v interface{}
+ key := col.Name
+ fieldType := fieldValue.Type()
+
+ switch fieldType.Kind() {
+ case reflect.Complex64, reflect.Complex128:
+ x := reflect.New(fieldType)
+ if len(data) > 0 {
+ err := json.Unmarshal(data, x.Interface())
+ if err != nil {
+ session.Engine.logger.Error(err)
+ return err
+ }
+ fieldValue.Set(x.Elem())
+ }
+ case reflect.Slice, reflect.Array, reflect.Map:
+ v = data
+ t := fieldType.Elem()
+ k := t.Kind()
+ if col.SQLType.IsText() {
+ x := reflect.New(fieldType)
+ if len(data) > 0 {
+ err := json.Unmarshal(data, x.Interface())
+ if err != nil {
+ session.Engine.logger.Error(err)
+ return err
+ }
+ fieldValue.Set(x.Elem())
+ }
+ } else if col.SQLType.IsBlob() {
+ if k == reflect.Uint8 {
+ fieldValue.Set(reflect.ValueOf(v))
+ } else {
+ x := reflect.New(fieldType)
+ if len(data) > 0 {
+ err := json.Unmarshal(data, x.Interface())
+ if err != nil {
+ session.Engine.logger.Error(err)
+ return err
+ }
+ fieldValue.Set(x.Elem())
+ }
+ }
+ } else {
+ return ErrUnSupportedType
+ }
+ case reflect.String:
+ fieldValue.SetString(string(data))
+ case reflect.Bool:
+ d := string(data)
+ v, err := strconv.ParseBool(d)
+ if err != nil {
+ return fmt.Errorf("arg %v as bool: %s", key, err.Error())
+ }
+ fieldValue.Set(reflect.ValueOf(v))
+ case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
+ sdata := string(data)
+ var x int64
+ var err error
+ // for mysql, when use bit, it returned \x01
+ if col.SQLType.Name == core.Bit &&
+ session.Engine.dialect.DBType() == core.MYSQL { // !nashtsai! TODO dialect needs to provide conversion interface API
+ if len(data) == 1 {
+ x = int64(data[0])
+ } else {
+ x = 0
+ }
+ } else if strings.HasPrefix(sdata, "0x") {
+ x, err = strconv.ParseInt(sdata, 16, 64)
+ } else if strings.HasPrefix(sdata, "0") {
+ x, err = strconv.ParseInt(sdata, 8, 64)
+ } else if strings.EqualFold(sdata, "true") {
+ x = 1
+ } else if strings.EqualFold(sdata, "false") {
+ x = 0
+ } else {
+ x, err = strconv.ParseInt(sdata, 10, 64)
+ }
+ if err != nil {
+ return fmt.Errorf("arg %v as int: %s", key, err.Error())
+ }
+ fieldValue.SetInt(x)
+ case reflect.Float32, reflect.Float64:
+ x, err := strconv.ParseFloat(string(data), 64)
+ if err != nil {
+ return fmt.Errorf("arg %v as float64: %s", key, err.Error())
+ }
+ fieldValue.SetFloat(x)
+ case reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uint:
+ x, err := strconv.ParseUint(string(data), 10, 64)
+ if err != nil {
+ return fmt.Errorf("arg %v as int: %s", key, err.Error())
+ }
+ fieldValue.SetUint(x)
+ //Currently only support Time type
+ case reflect.Struct:
+ // !<winxxp>! 增加支持sql.Scanner接口的结构,如sql.NullString
+ if nulVal, ok := fieldValue.Addr().Interface().(sql.Scanner); ok {
+ if err := nulVal.Scan(data); err != nil {
+ return fmt.Errorf("sql.Scan(%v) failed: %s ", data, err.Error())
+ }
+ } else {
+ if fieldType.ConvertibleTo(core.TimeType) {
+ x, err := session.byte2Time(col, data)
+ if err != nil {
+ return err
+ }
+ v = x
+ fieldValue.Set(reflect.ValueOf(v).Convert(fieldType))
+ } else if session.Statement.UseCascade {
+ table, err := session.Engine.autoMapType(*fieldValue)
+ if err != nil {
+ return err
+ }
+
+ // TODO: current only support 1 primary key
+ if len(table.PrimaryKeys) > 1 {
+ panic("unsupported composited primary key cascade")
+ }
+ var pk = make(core.PK, len(table.PrimaryKeys))
+ rawValueType := table.ColumnType(table.PKColumns()[0].FieldName)
+ pk[0], err = str2PK(string(data), rawValueType)
+ if err != nil {
+ return err
+ }
+
+ if !isPKZero(pk) {
+ // !nashtsai! TODO for hasOne relationship, it's preferred to use join query for eager fetch
+ // however, also need to consider adding a 'lazy' attribute to xorm tag which allow hasOne
+ // property to be fetched lazily
+ structInter := reflect.New(fieldValue.Type())
+ newsession := session.Engine.NewSession()
+ defer newsession.Close()
+ has, err := newsession.Id(pk).NoCascade().Get(structInter.Interface())
+ if err != nil {
+ return err
+ }
+ if has {
+ v = structInter.Elem().Interface()
+ fieldValue.Set(reflect.ValueOf(v))
+ } else {
+ return errors.New("cascade obj is not exist")
+ }
+ }
+ }
+ }
+ case reflect.Ptr:
+ // !nashtsai! TODO merge duplicated codes above
+ //typeStr := fieldType.String()
+ switch fieldType.Elem().Kind() {
+ // case "*string":
+ case core.StringType.Kind():
+ x := string(data)
+ fieldValue.Set(reflect.ValueOf(&x).Convert(fieldType))
+ // case "*bool":
+ case core.BoolType.Kind():
+ d := string(data)
+ v, err := strconv.ParseBool(d)
+ if err != nil {
+ return fmt.Errorf("arg %v as bool: %s", key, err.Error())
+ }
+ fieldValue.Set(reflect.ValueOf(&v).Convert(fieldType))
+ // case "*complex64":
+ case core.Complex64Type.Kind():
+ var x complex64
+ if len(data) > 0 {
+ err := json.Unmarshal(data, &x)
+ if err != nil {
+ session.Engine.logger.Error(err)
+ return err
+ }
+ fieldValue.Set(reflect.ValueOf(&x).Convert(fieldType))
+ }
+ // case "*complex128":
+ case core.Complex128Type.Kind():
+ var x complex128
+ if len(data) > 0 {
+ err := json.Unmarshal(data, &x)
+ if err != nil {
+ session.Engine.logger.Error(err)
+ return err
+ }
+ fieldValue.Set(reflect.ValueOf(&x).Convert(fieldType))
+ }
+ // case "*float64":
+ case core.Float64Type.Kind():
+ x, err := strconv.ParseFloat(string(data), 64)
+ if err != nil {
+ return fmt.Errorf("arg %v as float64: %s", key, err.Error())
+ }
+ fieldValue.Set(reflect.ValueOf(&x).Convert(fieldType))
+ // case "*float32":
+ case core.Float32Type.Kind():
+ var x float32
+ x1, err := strconv.ParseFloat(string(data), 32)
+ if err != nil {
+ return fmt.Errorf("arg %v as float32: %s", key, err.Error())
+ }
+ x = float32(x1)
+ fieldValue.Set(reflect.ValueOf(&x).Convert(fieldType))
+ // case "*uint64":
+ case core.Uint64Type.Kind():
+ var x uint64
+ x, err := strconv.ParseUint(string(data), 10, 64)
+ if err != nil {
+ return fmt.Errorf("arg %v as int: %s", key, err.Error())
+ }
+ fieldValue.Set(reflect.ValueOf(&x).Convert(fieldType))
+ // case "*uint":
+ case core.UintType.Kind():
+ var x uint
+ x1, err := strconv.ParseUint(string(data), 10, 64)
+ if err != nil {
+ return fmt.Errorf("arg %v as int: %s", key, err.Error())
+ }
+ x = uint(x1)
+ fieldValue.Set(reflect.ValueOf(&x).Convert(fieldType))
+ // case "*uint32":
+ case core.Uint32Type.Kind():
+ var x uint32
+ x1, err := strconv.ParseUint(string(data), 10, 64)
+ if err != nil {
+ return fmt.Errorf("arg %v as int: %s", key, err.Error())
+ }
+ x = uint32(x1)
+ fieldValue.Set(reflect.ValueOf(&x).Convert(fieldType))
+ // case "*uint8":
+ case core.Uint8Type.Kind():
+ var x uint8
+ x1, err := strconv.ParseUint(string(data), 10, 64)
+ if err != nil {
+ return fmt.Errorf("arg %v as int: %s", key, err.Error())
+ }
+ x = uint8(x1)
+ fieldValue.Set(reflect.ValueOf(&x).Convert(fieldType))
+ // case "*uint16":
+ case core.Uint16Type.Kind():
+ var x uint16
+ x1, err := strconv.ParseUint(string(data), 10, 64)
+ if err != nil {
+ return fmt.Errorf("arg %v as int: %s", key, err.Error())
+ }
+ x = uint16(x1)
+ fieldValue.Set(reflect.ValueOf(&x).Convert(fieldType))
+ // case "*int64":
+ case core.Int64Type.Kind():
+ sdata := string(data)
+ var x int64
+ var err error
+ // for mysql, when use bit, it returned \x01
+ if col.SQLType.Name == core.Bit &&
+ strings.Contains(session.Engine.DriverName(), "mysql") {
+ if len(data) == 1 {
+ x = int64(data[0])
+ } else {
+ x = 0
+ }
+ } else if strings.HasPrefix(sdata, "0x") {
+ x, err = strconv.ParseInt(sdata, 16, 64)
+ } else if strings.HasPrefix(sdata, "0") {
+ x, err = strconv.ParseInt(sdata, 8, 64)
+ } else {
+ x, err = strconv.ParseInt(sdata, 10, 64)
+ }
+ if err != nil {
+ return fmt.Errorf("arg %v as int: %s", key, err.Error())
+ }
+ fieldValue.Set(reflect.ValueOf(&x).Convert(fieldType))
+ // case "*int":
+ case core.IntType.Kind():
+ sdata := string(data)
+ var x int
+ var x1 int64
+ var err error
+ // for mysql, when use bit, it returned \x01
+ if col.SQLType.Name == core.Bit &&
+ strings.Contains(session.Engine.DriverName(), "mysql") {
+ if len(data) == 1 {
+ x = int(data[0])
+ } else {
+ x = 0
+ }
+ } else if strings.HasPrefix(sdata, "0x") {
+ x1, err = strconv.ParseInt(sdata, 16, 64)
+ x = int(x1)
+ } else if strings.HasPrefix(sdata, "0") {
+ x1, err = strconv.ParseInt(sdata, 8, 64)
+ x = int(x1)
+ } else {
+ x1, err = strconv.ParseInt(sdata, 10, 64)
+ x = int(x1)
+ }
+ if err != nil {
+ return fmt.Errorf("arg %v as int: %s", key, err.Error())
+ }
+ fieldValue.Set(reflect.ValueOf(&x).Convert(fieldType))
+ // case "*int32":
+ case core.Int32Type.Kind():
+ sdata := string(data)
+ var x int32
+ var x1 int64
+ var err error
+ // for mysql, when use bit, it returned \x01
+ if col.SQLType.Name == core.Bit &&
+ session.Engine.dialect.DBType() == core.MYSQL {
+ if len(data) == 1 {
+ x = int32(data[0])
+ } else {
+ x = 0
+ }
+ } else if strings.HasPrefix(sdata, "0x") {
+ x1, err = strconv.ParseInt(sdata, 16, 64)
+ x = int32(x1)
+ } else if strings.HasPrefix(sdata, "0") {
+ x1, err = strconv.ParseInt(sdata, 8, 64)
+ x = int32(x1)
+ } else {
+ x1, err = strconv.ParseInt(sdata, 10, 64)
+ x = int32(x1)
+ }
+ if err != nil {
+ return fmt.Errorf("arg %v as int: %s", key, err.Error())
+ }
+ fieldValue.Set(reflect.ValueOf(&x).Convert(fieldType))
+ // case "*int8":
+ case core.Int8Type.Kind():
+ sdata := string(data)
+ var x int8
+ var x1 int64
+ var err error
+ // for mysql, when use bit, it returned \x01
+ if col.SQLType.Name == core.Bit &&
+ strings.Contains(session.Engine.DriverName(), "mysql") {
+ if len(data) == 1 {
+ x = int8(data[0])
+ } else {
+ x = 0
+ }
+ } else if strings.HasPrefix(sdata, "0x") {
+ x1, err = strconv.ParseInt(sdata, 16, 64)
+ x = int8(x1)
+ } else if strings.HasPrefix(sdata, "0") {
+ x1, err = strconv.ParseInt(sdata, 8, 64)
+ x = int8(x1)
+ } else {
+ x1, err = strconv.ParseInt(sdata, 10, 64)
+ x = int8(x1)
+ }
+ if err != nil {
+ return fmt.Errorf("arg %v as int: %s", key, err.Error())
+ }
+ fieldValue.Set(reflect.ValueOf(&x).Convert(fieldType))
+ // case "*int16":
+ case core.Int16Type.Kind():
+ sdata := string(data)
+ var x int16
+ var x1 int64
+ var err error
+ // for mysql, when use bit, it returned \x01
+ if col.SQLType.Name == core.Bit &&
+ strings.Contains(session.Engine.DriverName(), "mysql") {
+ if len(data) == 1 {
+ x = int16(data[0])
+ } else {
+ x = 0
+ }
+ } else if strings.HasPrefix(sdata, "0x") {
+ x1, err = strconv.ParseInt(sdata, 16, 64)
+ x = int16(x1)
+ } else if strings.HasPrefix(sdata, "0") {
+ x1, err = strconv.ParseInt(sdata, 8, 64)
+ x = int16(x1)
+ } else {
+ x1, err = strconv.ParseInt(sdata, 10, 64)
+ x = int16(x1)
+ }
+ if err != nil {
+ return fmt.Errorf("arg %v as int: %s", key, err.Error())
+ }
+ fieldValue.Set(reflect.ValueOf(&x).Convert(fieldType))
+ // case "*SomeStruct":
+ case reflect.Struct:
+ switch fieldType {
+ // case "*.time.Time":
+ case core.PtrTimeType:
+ x, err := session.byte2Time(col, data)
+ if err != nil {
+ return err
+ }
+ v = x
+ fieldValue.Set(reflect.ValueOf(&x))
+ default:
+ if session.Statement.UseCascade {
+ structInter := reflect.New(fieldType.Elem())
+ table, err := session.Engine.autoMapType(structInter.Elem())
+ if err != nil {
+ return err
+ }
+
+ if len(table.PrimaryKeys) > 1 {
+ panic("unsupported composited primary key cascade")
+ }
+ var pk = make(core.PK, len(table.PrimaryKeys))
+ rawValueType := table.ColumnType(table.PKColumns()[0].FieldName)
+ pk[0], err = str2PK(string(data), rawValueType)
+ if err != nil {
+ return err
+ }
+
+ if !isPKZero(pk) {
+ // !nashtsai! TODO for hasOne relationship, it's preferred to use join query for eager fetch
+ // however, also need to consider adding a 'lazy' attribute to xorm tag which allow hasOne
+ // property to be fetched lazily
+ newsession := session.Engine.NewSession()
+ defer newsession.Close()
+ has, err := newsession.Id(pk).NoCascade().Get(structInter.Interface())
+ if err != nil {
+ return err
+ }
+ if has {
+ v = structInter.Interface()
+ fieldValue.Set(reflect.ValueOf(v))
+ } else {
+ return errors.New("cascade obj is not exist")
+ }
+ }
+ } else {
+ return fmt.Errorf("unsupported struct type in Scan: %s", fieldValue.Type().String())
+ }
+ }
+ default:
+ return fmt.Errorf("unsupported type in Scan: %s", fieldValue.Type().String())
+ }
+ default:
+ return fmt.Errorf("unsupported type in Scan: %s", fieldValue.Type().String())
+ }
+
+ return nil
+}
+
+// convert a field value of a struct to interface for put into db
+func (session *Session) value2Interface(col *core.Column, fieldValue reflect.Value) (interface{}, error) {
+ if fieldValue.CanAddr() {
+ if fieldConvert, ok := fieldValue.Addr().Interface().(core.Conversion); ok {
+ data, err := fieldConvert.ToDB()
+ if err != nil {
+ return 0, err
+ }
+ if col.SQLType.IsBlob() {
+ return data, nil
+ }
+ return string(data), nil
+ }
+ }
+
+ if fieldConvert, ok := fieldValue.Interface().(core.Conversion); ok {
+ data, err := fieldConvert.ToDB()
+ if err != nil {
+ return 0, err
+ }
+ if col.SQLType.IsBlob() {
+ return data, nil
+ }
+ return string(data), nil
+ }
+
+ fieldType := fieldValue.Type()
+ k := fieldType.Kind()
+ if k == reflect.Ptr {
+ if fieldValue.IsNil() {
+ return nil, nil
+ } else if !fieldValue.IsValid() {
+ session.Engine.logger.Warn("the field[", col.FieldName, "] is invalid")
+ return nil, nil
+ } else {
+ // !nashtsai! deference pointer type to instance type
+ fieldValue = fieldValue.Elem()
+ fieldType = fieldValue.Type()
+ k = fieldType.Kind()
+ }
+ }
+
+ switch k {
+ case reflect.Bool:
+ return fieldValue.Bool(), nil
+ case reflect.String:
+ return fieldValue.String(), nil
+ case reflect.Struct:
+ if fieldType.ConvertibleTo(core.TimeType) {
+ t := fieldValue.Convert(core.TimeType).Interface().(time.Time)
+ if session.Engine.dialect.DBType() == core.MSSQL {
+ if t.IsZero() {
+ return nil, nil
+ }
+ }
+ tf := session.Engine.FormatTime(col.SQLType.Name, t)
+ return tf, nil
+ }
+
+ if !col.SQLType.IsJson() {
+ // !<winxxp>! 增加支持driver.Valuer接口的结构,如sql.NullString
+ if v, ok := fieldValue.Interface().(driver.Valuer); ok {
+ return v.Value()
+ }
+
+ fieldTable, err := session.Engine.autoMapType(fieldValue)
+ if err != nil {
+ return nil, err
+ }
+ if len(fieldTable.PrimaryKeys) == 1 {
+ pkField := reflect.Indirect(fieldValue).FieldByName(fieldTable.PKColumns()[0].FieldName)
+ return pkField.Interface(), nil
+ }
+ return 0, fmt.Errorf("no primary key for col %v", col.Name)
+ }
+
+ if col.SQLType.IsText() {
+ bytes, err := json.Marshal(fieldValue.Interface())
+ if err != nil {
+ session.Engine.logger.Error(err)
+ return 0, err
+ }
+ return string(bytes), nil
+ } else if col.SQLType.IsBlob() {
+ bytes, err := json.Marshal(fieldValue.Interface())
+ if err != nil {
+ session.Engine.logger.Error(err)
+ return 0, err
+ }
+ return bytes, nil
+ }
+ return nil, fmt.Errorf("Unsupported type %v", fieldValue.Type())
+ case reflect.Complex64, reflect.Complex128:
+ bytes, err := json.Marshal(fieldValue.Interface())
+ if err != nil {
+ session.Engine.logger.Error(err)
+ return 0, err
+ }
+ return string(bytes), nil
+ case reflect.Array, reflect.Slice, reflect.Map:
+ if !fieldValue.IsValid() {
+ return fieldValue.Interface(), nil
+ }
+
+ if col.SQLType.IsText() {
+ bytes, err := json.Marshal(fieldValue.Interface())
+ if err != nil {
+ session.Engine.logger.Error(err)
+ return 0, err
+ }
+ return string(bytes), nil
+ } else if col.SQLType.IsBlob() {
+ var bytes []byte
+ var err error
+ if (k == reflect.Array || k == reflect.Slice) &&
+ (fieldValue.Type().Elem().Kind() == reflect.Uint8) {
+ bytes = fieldValue.Bytes()
+ } else {
+ bytes, err = json.Marshal(fieldValue.Interface())
+ if err != nil {
+ session.Engine.logger.Error(err)
+ return 0, err
+ }
+ }
+ return bytes, nil
+ }
+ return nil, ErrUnSupportedType
+ case reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uint:
+ return int64(fieldValue.Uint()), nil
+ default:
+ return fieldValue.Interface(), nil
+ }
+}
diff --git a/vendor/github.com/go-xorm/xorm/session_find.go b/vendor/github.com/go-xorm/xorm/session_find.go
index ff79033b91..61862edd71 100644
--- a/vendor/github.com/go-xorm/xorm/session_find.go
+++ b/vendor/github.com/go-xorm/xorm/session_find.go
@@ -169,31 +169,43 @@ func (session *Session) noCacheFind(table *core.Table, containerValue reflect.Va
return err
}
- var newElemFunc func() reflect.Value
+ var newElemFunc func(fields []string) reflect.Value
elemType := containerValue.Type().Elem()
+ var isPointer bool
if elemType.Kind() == reflect.Ptr {
- newElemFunc = func() reflect.Value {
- return reflect.New(elemType.Elem())
- }
- } else {
- newElemFunc = func() reflect.Value {
- return reflect.New(elemType)
+ isPointer = true
+ elemType = elemType.Elem()
+ }
+ if elemType.Kind() == reflect.Ptr {
+ return errors.New("pointer to pointer is not supported")
+ }
+
+ newElemFunc = func(fields []string) reflect.Value {
+ switch elemType.Kind() {
+ case reflect.Slice:
+ slice := reflect.MakeSlice(elemType, len(fields), len(fields))
+ x := reflect.New(slice.Type())
+ x.Elem().Set(slice)
+ return x
+ case reflect.Map:
+ mp := reflect.MakeMap(elemType)
+ x := reflect.New(mp.Type())
+ x.Elem().Set(mp)
+ return x
}
+ return reflect.New(elemType)
}
var containerValueSetFunc func(*reflect.Value, core.PK) error
if containerValue.Kind() == reflect.Slice {
- if elemType.Kind() == reflect.Ptr {
- containerValueSetFunc = func(newValue *reflect.Value, pk core.PK) error {
- containerValue.Set(reflect.Append(containerValue, reflect.ValueOf(newValue.Interface())))
- return nil
- }
- } else {
- containerValueSetFunc = func(newValue *reflect.Value, pk core.PK) error {
- containerValue.Set(reflect.Append(containerValue, reflect.Indirect(reflect.ValueOf(newValue.Interface()))))
- return nil
+ containerValueSetFunc = func(newValue *reflect.Value, pk core.PK) error {
+ if isPointer {
+ containerValue.Set(reflect.Append(containerValue, newValue.Elem().Addr()))
+ } else {
+ containerValue.Set(reflect.Append(containerValue, newValue.Elem()))
}
+ return nil
}
} else {
keyType := containerValue.Type().Key()
@@ -204,40 +216,45 @@ func (session *Session) noCacheFind(table *core.Table, containerValue reflect.Va
return errors.New("don't support multiple primary key's map has non-slice key type")
}
- if elemType.Kind() == reflect.Ptr {
- containerValueSetFunc = func(newValue *reflect.Value, pk core.PK) error {
- keyValue := reflect.New(keyType)
- err := convertPKToValue(table, keyValue.Interface(), pk)
- if err != nil {
- return err
- }
- containerValue.SetMapIndex(keyValue.Elem(), reflect.ValueOf(newValue.Interface()))
- return nil
+ containerValueSetFunc = func(newValue *reflect.Value, pk core.PK) error {
+ keyValue := reflect.New(keyType)
+ err := convertPKToValue(table, keyValue.Interface(), pk)
+ if err != nil {
+ return err
}
- } else {
- containerValueSetFunc = func(newValue *reflect.Value, pk core.PK) error {
- keyValue := reflect.New(keyType)
- err := convertPKToValue(table, keyValue.Interface(), pk)
- if err != nil {
- return err
- }
- containerValue.SetMapIndex(keyValue.Elem(), reflect.Indirect(reflect.ValueOf(newValue.Interface())))
- return nil
+ if isPointer {
+ containerValue.SetMapIndex(keyValue.Elem(), newValue.Elem().Addr())
+ } else {
+ containerValue.SetMapIndex(keyValue.Elem(), newValue.Elem())
}
+ return nil
}
}
- var newValue = newElemFunc()
- dataStruct := rValue(newValue.Interface())
- if dataStruct.Kind() == reflect.Struct {
- return session.rows2Beans(rawRows, fields, len(fields), session.Engine.autoMapType(dataStruct), newElemFunc, containerValueSetFunc)
+ if elemType.Kind() == reflect.Struct {
+ var newValue = newElemFunc(fields)
+ dataStruct := rValue(newValue.Interface())
+ tb, err := session.Engine.autoMapType(dataStruct)
+ if err != nil {
+ return err
+ }
+ return session.rows2Beans(rawRows, fields, len(fields), tb, newElemFunc, containerValueSetFunc)
}
for rawRows.Next() {
- var newValue = newElemFunc()
+ var newValue = newElemFunc(fields)
bean := newValue.Interface()
- if err := rawRows.Scan(bean); err != nil {
+ switch elemType.Kind() {
+ case reflect.Slice:
+ err = rawRows.ScanSlice(bean)
+ case reflect.Map:
+ err = rawRows.ScanMap(bean)
+ default:
+ err = rawRows.Scan(bean)
+ }
+
+ if err != nil {
return err
}
@@ -394,7 +411,10 @@ func (session *Session) cacheFind(t reflect.Type, sqlStr string, rowsSlicePtr in
if rv.Kind() != reflect.Ptr {
rv = rv.Addr()
}
- id := session.Engine.IdOfV(rv)
+ id, err := session.Engine.idOfV(rv)
+ if err != nil {
+ return err
+ }
sid, err := id.ToString()
if err != nil {
return err
diff --git a/vendor/github.com/go-xorm/xorm/session_get.go b/vendor/github.com/go-xorm/xorm/session_get.go
index ac0c5ebbf7..bf61963cfc 100644
--- a/vendor/github.com/go-xorm/xorm/session_get.go
+++ b/vendor/github.com/go-xorm/xorm/session_get.go
@@ -20,7 +20,14 @@ func (session *Session) Get(bean interface{}) (bool, error) {
defer session.Close()
}
- session.Statement.setRefValue(rValue(bean))
+ beanValue := reflect.ValueOf(bean)
+ if beanValue.Kind() != reflect.Ptr {
+ return false, errors.New("needs a pointer")
+ }
+
+ if beanValue.Elem().Kind() == reflect.Struct {
+ session.Statement.setRefValue(beanValue.Elem())
+ }
var sqlStr string
var args []interface{}
@@ -36,7 +43,7 @@ func (session *Session) Get(bean interface{}) (bool, error) {
args = session.Statement.RawParams
}
- if session.canCache() {
+ if session.canCache() && beanValue.Elem().Kind() == reflect.Struct {
if cacher := session.Engine.getCacher2(session.Statement.RefTable); cacher != nil &&
!session.Statement.unscoped {
has, err := session.cacheGet(bean, sqlStr, args...)
@@ -46,13 +53,14 @@ func (session *Session) Get(bean interface{}) (bool, error) {
}
}
- return session.nocacheGet(bean, sqlStr, args...)
+ return session.nocacheGet(beanValue.Elem().Kind(), bean, sqlStr, args...)
}
-func (session *Session) nocacheGet(bean interface{}, sqlStr string, args ...interface{}) (bool, error) {
+func (session *Session) nocacheGet(beanKind reflect.Kind, bean interface{}, sqlStr string, args ...interface{}) (bool, error) {
+ session.queryPreprocess(&sqlStr, args...)
+
var rawRows *core.Rows
var err error
- session.queryPreprocess(&sqlStr, args...)
if session.IsAutoCommit {
_, rawRows, err = session.innerQuery(sqlStr, args...)
} else {
@@ -65,10 +73,24 @@ func (session *Session) nocacheGet(bean interface{}, sqlStr string, args ...inte
defer rawRows.Close()
if rawRows.Next() {
- fields, err := rawRows.Columns()
- if err == nil {
- _, err = session.row2Bean(rawRows, fields, len(fields), bean)
+ switch beanKind {
+ case reflect.Struct:
+ fields, err := rawRows.Columns()
+ if err != nil {
+ // WARN: Alougth rawRows return true, but get fields failed
+ return true, err
+ }
+ dataStruct := rValue(bean)
+ session.Statement.setRefValue(dataStruct)
+ _, err = session.row2Bean(rawRows, fields, len(fields), bean, &dataStruct, session.Statement.RefTable)
+ case reflect.Slice:
+ err = rawRows.ScanSlice(bean)
+ case reflect.Map:
+ err = rawRows.ScanMap(bean)
+ default:
+ err = rawRows.Scan(bean)
}
+
return true, err
}
return false, nil
@@ -145,20 +167,8 @@ func (session *Session) cacheGet(bean interface{}, sqlStr string, args ...interf
}
cacheBean := cacher.GetBean(tableName, sid)
if cacheBean == nil {
- /*newSession := session.Engine.NewSession()
- defer newSession.Close()
- cacheBean = reflect.New(structValue.Type()).Interface()
- newSession.Id(id).NoCache()
- if session.Statement.AltTableName != "" {
- newSession.Table(session.Statement.AltTableName)
- }
- if !session.Statement.UseCascade {
- newSession.NoCascade()
- }
- has, err = newSession.Get(cacheBean)
- */
cacheBean = bean
- has, err = session.nocacheGet(cacheBean, sqlStr, args...)
+ has, err = session.nocacheGet(reflect.Struct, cacheBean, sqlStr, args...)
if err != nil || !has {
return has, err
}
diff --git a/vendor/github.com/go-xorm/xorm/session_insert.go b/vendor/github.com/go-xorm/xorm/session_insert.go
index 96e969c2a3..5b607b1fec 100644
--- a/vendor/github.com/go-xorm/xorm/session_insert.go
+++ b/vendor/github.com/go-xorm/xorm/session_insert.go
@@ -210,13 +210,29 @@ func (session *Session) innerInsertMulti(rowsSlicePtr interface{}) (int64, error
}
cleanupProcessorsClosures(&session.beforeClosures)
- statement := fmt.Sprintf("INSERT INTO %s (%v%v%v) VALUES (%v)",
- session.Engine.Quote(session.Statement.TableName()),
- session.Engine.QuoteStr(),
- strings.Join(colNames, session.Engine.QuoteStr()+", "+session.Engine.QuoteStr()),
- session.Engine.QuoteStr(),
- strings.Join(colMultiPlaces, "),("))
-
+ var sql = "INSERT INTO %s (%v%v%v) VALUES (%v)"
+ var statement string
+ if session.Engine.dialect.DBType() == core.ORACLE {
+ sql = "INSERT ALL INTO %s (%v%v%v) VALUES (%v) SELECT 1 FROM DUAL"
+ temp := fmt.Sprintf(") INTO %s (%v%v%v) VALUES (",
+ session.Engine.Quote(session.Statement.TableName()),
+ session.Engine.QuoteStr(),
+ strings.Join(colNames, session.Engine.QuoteStr() + ", " + session.Engine.QuoteStr()),
+ session.Engine.QuoteStr())
+ statement = fmt.Sprintf(sql,
+ session.Engine.Quote(session.Statement.TableName()),
+ session.Engine.QuoteStr(),
+ strings.Join(colNames, session.Engine.QuoteStr() + ", " + session.Engine.QuoteStr()),
+ session.Engine.QuoteStr(),
+ strings.Join(colMultiPlaces, temp))
+ } else {
+ statement = fmt.Sprintf(sql,
+ session.Engine.Quote(session.Statement.TableName()),
+ session.Engine.QuoteStr(),
+ strings.Join(colNames, session.Engine.QuoteStr() + ", " + session.Engine.QuoteStr()),
+ session.Engine.QuoteStr(),
+ strings.Join(colMultiPlaces, "),("))
+ }
res, err := session.exec(statement, args...)
if err != nil {
return 0, err
@@ -309,8 +325,8 @@ func (session *Session) innerInsert(bean interface{}) (int64, error) {
// remove the expr columns
for i, colName := range colNames {
if colName == v.colName {
- colNames = append(colNames[:i], colNames[i+1:]...)
- args = append(args[:i], args[i+1:]...)
+ colNames = append(colNames[:i], colNames[i + 1:]...)
+ args = append(args[:i], args[i + 1:]...)
}
}
@@ -319,11 +335,11 @@ func (session *Session) innerInsert(bean interface{}) (int64, error) {
exprColVals = append(exprColVals, v.expr)
}
- colPlaces := strings.Repeat("?, ", len(colNames)-len(exprColumns))
+ colPlaces := strings.Repeat("?, ", len(colNames) - len(exprColumns))
if len(exprColVals) > 0 {
colPlaces = colPlaces + strings.Join(exprColVals, ", ")
} else {
- colPlaces = colPlaces[0 : len(colPlaces)-2]
+ colPlaces = colPlaces[0 : len(colPlaces) - 2]
}
sqlStr := fmt.Sprintf("INSERT INTO %s (%v%v%v) VALUES (%v)",
diff --git a/vendor/github.com/go-xorm/xorm/session_raw.go b/vendor/github.com/go-xorm/xorm/session_raw.go
index 9351d5cf94..587addef60 100644
--- a/vendor/github.com/go-xorm/xorm/session_raw.go
+++ b/vendor/github.com/go-xorm/xorm/session_raw.go
@@ -70,7 +70,7 @@ func (session *Session) innerQuery2(sqlStr string, params ...interface{}) ([]map
return rows2maps(rows)
}
-// Query a raw sql and return records as []map[string][]byte
+// Query runs a raw sql and return records as []map[string][]byte
func (session *Session) Query(sqlStr string, paramStr ...interface{}) (resultsSlice []map[string][]byte, err error) {
defer session.resetStatement()
if session.IsAutoClose {
@@ -80,6 +80,15 @@ func (session *Session) Query(sqlStr string, paramStr ...interface{}) (resultsSl
return session.query(sqlStr, paramStr...)
}
+// QueryString runs a raw sql and return records as []map[string]string
+func (session *Session) QueryString(sqlStr string, args ...interface{}) ([]map[string]string, error) {
+ defer session.resetStatement()
+ if session.IsAutoClose {
+ defer session.Close()
+ }
+ return session.query2(sqlStr, args...)
+}
+
// =============================
// for string
// =============================
diff --git a/vendor/github.com/go-xorm/xorm/session_schema.go b/vendor/github.com/go-xorm/xorm/session_schema.go
index 9011adadfe..21fa299614 100644
--- a/vendor/github.com/go-xorm/xorm/session_schema.go
+++ b/vendor/github.com/go-xorm/xorm/session_schema.go
@@ -306,7 +306,10 @@ func (session *Session) Sync2(beans ...interface{}) error {
for _, bean := range beans {
v := rValue(bean)
- table := engine.mapType(v)
+ table, err := engine.mapType(v)
+ if err != nil {
+ return err
+ }
structTables = append(structTables, table)
var tbName = session.tbNameNoSchema(table)
diff --git a/vendor/github.com/go-xorm/xorm/session_sum.go b/vendor/github.com/go-xorm/xorm/session_sum.go
index 127f83f281..e1409c7ff4 100644
--- a/vendor/github.com/go-xorm/xorm/session_sum.go
+++ b/vendor/github.com/go-xorm/xorm/session_sum.go
@@ -123,7 +123,7 @@ func (session *Session) SumsInt(bean interface{}, columnNames ...string) ([]int6
session.queryPreprocess(&sqlStr, args...)
var err error
- var res = make([]int64, 0, len(columnNames))
+ var res = make([]int64, len(columnNames), len(columnNames))
if session.IsAutoCommit {
err = session.DB().QueryRow(sqlStr, args...).ScanSlice(&res)
} else {
diff --git a/vendor/github.com/go-xorm/xorm/session_update.go b/vendor/github.com/go-xorm/xorm/session_update.go
index 27e2deb0fe..0f2d1b5cef 100644
--- a/vendor/github.com/go-xorm/xorm/session_update.go
+++ b/vendor/github.com/go-xorm/xorm/session_update.go
@@ -253,48 +253,59 @@ func (session *Session) Update(bean interface{}, condiBean ...interface{}) (int6
var condSQL string
cond := session.Statement.cond.And(autoCond)
- doIncVer := false
+ var doIncVer = (table != nil && table.Version != "" && session.Statement.checkVersion)
var verValue *reflect.Value
- if table != nil && table.Version != "" && session.Statement.checkVersion {
+ if doIncVer {
verValue, err = table.VersionColumn().ValueOf(bean)
if err != nil {
return 0, err
}
cond = cond.And(builder.Eq{session.Engine.Quote(table.Version): verValue.Interface()})
- condSQL, condArgs, _ = builder.ToSQL(cond)
-
- if len(condSQL) > 0 {
- condSQL = "WHERE " + condSQL
- }
-
- if st.LimitN > 0 {
- condSQL = condSQL + fmt.Sprintf(" LIMIT %d", st.LimitN)
- }
+ colNames = append(colNames, session.Engine.Quote(table.Version)+" = "+session.Engine.Quote(table.Version)+" + 1")
+ }
- sqlStr = fmt.Sprintf("UPDATE %v SET %v, %v %v",
- session.Engine.Quote(session.Statement.TableName()),
- strings.Join(colNames, ", "),
- session.Engine.Quote(table.Version)+" = "+session.Engine.Quote(table.Version)+" + 1",
- condSQL)
+ condSQL, condArgs, _ = builder.ToSQL(cond)
+ if len(condSQL) > 0 {
+ condSQL = "WHERE " + condSQL
+ }
- doIncVer = true
- } else {
- condSQL, condArgs, _ = builder.ToSQL(cond)
- if len(condSQL) > 0 {
- condSQL = "WHERE " + condSQL
- }
+ if st.OrderStr != "" {
+ condSQL = condSQL + fmt.Sprintf(" ORDER BY %v", st.OrderStr)
+ }
- if st.LimitN > 0 {
+ // TODO: Oracle support needed
+ var top string
+ if st.LimitN > 0 {
+ if st.Engine.dialect.DBType() == core.MYSQL {
condSQL = condSQL + fmt.Sprintf(" LIMIT %d", st.LimitN)
+ } else if st.Engine.dialect.DBType() == core.SQLITE {
+ tempCondSQL := condSQL + fmt.Sprintf(" LIMIT %d", st.LimitN)
+ cond = cond.And(builder.Expr(fmt.Sprintf("rowid IN (SELECT rowid FROM %v %v)",
+ session.Engine.Quote(session.Statement.TableName()), tempCondSQL), condArgs...))
+ condSQL, condArgs, _ = builder.ToSQL(cond)
+ if len(condSQL) > 0 {
+ condSQL = "WHERE " + condSQL
+ }
+ } else if st.Engine.dialect.DBType() == core.POSTGRES {
+ tempCondSQL := condSQL + fmt.Sprintf(" LIMIT %d", st.LimitN)
+ cond = cond.And(builder.Expr(fmt.Sprintf("CTID IN (SELECT CTID FROM %v %v)",
+ session.Engine.Quote(session.Statement.TableName()), tempCondSQL), condArgs...))
+ condSQL, condArgs, _ = builder.ToSQL(cond)
+ if len(condSQL) > 0 {
+ condSQL = "WHERE " + condSQL
+ }
+ } else if st.Engine.dialect.DBType() == core.MSSQL {
+ top = fmt.Sprintf("top (%d) ", st.LimitN)
}
-
- sqlStr = fmt.Sprintf("UPDATE %v SET %v %v",
- session.Engine.Quote(session.Statement.TableName()),
- strings.Join(colNames, ", "),
- condSQL)
}
+ sqlStr = fmt.Sprintf("UPDATE %v%v SET %v %v",
+ top,
+ session.Engine.Quote(session.Statement.TableName()),
+ strings.Join(colNames, ", "),
+ condSQL)
+
res, err := session.exec(sqlStr, append(args, condArgs...)...)
if err != nil {
return 0, err
diff --git a/vendor/github.com/go-xorm/xorm/sqlite3_driver.go b/vendor/github.com/go-xorm/xorm/sqlite3_driver.go
deleted file mode 100644
index 6ae19569ef..0000000000
--- a/vendor/github.com/go-xorm/xorm/sqlite3_driver.go
+++ /dev/null
@@ -1,20 +0,0 @@
-// Copyright 2015 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"
-)
-
-// func init() {
-// core.RegisterDriver("sqlite3", &sqlite3Driver{})
-// }
-
-type sqlite3Driver struct {
-}
-
-func (p *sqlite3Driver) Parse(driverName, dataSourceName string) (*core.Uri, error) {
- return &core.Uri{DbType: core.SQLITE, DbName: dataSourceName}, nil
-}
diff --git a/vendor/github.com/go-xorm/xorm/statement.go b/vendor/github.com/go-xorm/xorm/statement.go
index fb116b9493..d411f739b8 100644
--- a/vendor/github.com/go-xorm/xorm/statement.go
+++ b/vendor/github.com/go-xorm/xorm/statement.go
@@ -39,7 +39,7 @@ type Statement struct {
Engine *Engine
Start int
LimitN int
- IdParam *core.PK
+ idParam *core.PK
OrderStr string
JoinStr string
joinArgs []interface{}
@@ -91,7 +91,7 @@ func (statement *Statement) Init() {
statement.columnMap = make(map[string]bool)
statement.AltTableName = ""
statement.tableName = ""
- statement.IdParam = nil
+ statement.idParam = nil
statement.RawSQL = ""
statement.RawParams = make([]interface{}, 0)
statement.UseCache = true
@@ -195,29 +195,26 @@ func (statement *Statement) Or(query interface{}, args ...interface{}) *Statemen
// In generate "Where column IN (?) " statement
func (statement *Statement) In(column string, args ...interface{}) *Statement {
- if len(args) == 0 {
- return statement
- }
-
- in := builder.In(column, args...)
+ in := builder.In(statement.Engine.Quote(column), args...)
statement.cond = statement.cond.And(in)
return statement
}
// NotIn generate "Where column NOT IN (?) " statement
func (statement *Statement) NotIn(column string, args ...interface{}) *Statement {
- if len(args) == 0 {
- return statement
- }
-
- in := builder.NotIn(column, args...)
- statement.cond = statement.cond.And(in)
+ notIn := builder.NotIn(statement.Engine.Quote(column), args...)
+ statement.cond = statement.cond.And(notIn)
return statement
}
-func (statement *Statement) setRefValue(v reflect.Value) {
- statement.RefTable = statement.Engine.autoMapType(reflect.Indirect(v))
+func (statement *Statement) setRefValue(v reflect.Value) error {
+ var err error
+ statement.RefTable, err = statement.Engine.autoMapType(reflect.Indirect(v))
+ if err != nil {
+ return err
+ }
statement.tableName = statement.Engine.tbName(v)
+ return nil
}
// Table tempororily set table name, the parameter could be a string or a pointer of struct
@@ -227,7 +224,12 @@ func (statement *Statement) Table(tableNameOrBean interface{}) *Statement {
if t.Kind() == reflect.String {
statement.AltTableName = tableNameOrBean.(string)
} else if t.Kind() == reflect.Struct {
- statement.RefTable = statement.Engine.autoMapType(v)
+ var err error
+ statement.RefTable, err = statement.Engine.autoMapType(v)
+ if err != nil {
+ statement.Engine.logger.Error(err)
+ return statement
+ }
statement.AltTableName = statement.Engine.tbName(v)
}
return statement
@@ -418,7 +420,11 @@ func buildUpdates(engine *Engine, table *core.Table, bean interface{},
if fieldValue == reflect.Zero(fieldType) {
continue
}
- if fieldValue.IsNil() || !fieldValue.IsValid() || fieldValue.Len() == 0 {
+ if fieldType.Kind() == reflect.Array {
+ if isArrayValueZero(fieldValue) {
+ continue
+ }
+ } else if fieldValue.IsNil() || !fieldValue.IsValid() || fieldValue.Len() == 0 {
continue
}
}
@@ -433,13 +439,16 @@ func buildUpdates(engine *Engine, table *core.Table, bean interface{},
} else if col.SQLType.IsBlob() {
var bytes []byte
var err error
- if (fieldType.Kind() == reflect.Array || fieldType.Kind() == reflect.Slice) &&
+ if fieldType.Kind() == reflect.Slice &&
fieldType.Elem().Kind() == reflect.Uint8 {
if fieldValue.Len() > 0 {
val = fieldValue.Bytes()
} else {
continue
}
+ } else if fieldType.Kind() == reflect.Array &&
+ fieldType.Elem().Kind() == reflect.Uint8 {
+ val = fieldValue.Slice(0, 0).Interface()
} else {
bytes, err = json.Marshal(fieldValue.Interface())
if err != nil {
@@ -651,7 +660,9 @@ func buildConds(engine *Engine, table *core.Table, bean interface{},
}
}
}
- case reflect.Array, reflect.Slice, reflect.Map:
+ case reflect.Array:
+ continue
+ case reflect.Slice, reflect.Map:
if fieldValue == reflect.Zero(fieldType) {
continue
}
@@ -706,13 +717,6 @@ func (statement *Statement) TableName() string {
return statement.tableName
}
-// Id generate "where id = ? " statement or for composite key "where key1 = ? and key2 = ?"
-//
-// Deprecated: use ID instead
-func (statement *Statement) Id(id interface{}) *Statement {
- return statement.ID(id)
-}
-
// ID generate "where id = ? " statement or for composite key "where key1 = ? and key2 = ?"
func (statement *Statement) ID(id interface{}) *Statement {
idValue := reflect.ValueOf(id)
@@ -721,23 +725,23 @@ func (statement *Statement) ID(id interface{}) *Statement {
switch idType {
case ptrPkType:
if pkPtr, ok := (id).(*core.PK); ok {
- statement.IdParam = pkPtr
+ statement.idParam = pkPtr
return statement
}
case pkType:
if pk, ok := (id).(core.PK); ok {
- statement.IdParam = &pk
+ statement.idParam = &pk
return statement
}
}
switch idType.Kind() {
case reflect.String:
- statement.IdParam = &core.PK{idValue.Convert(reflect.TypeOf("")).Interface()}
+ statement.idParam = &core.PK{idValue.Convert(reflect.TypeOf("")).Interface()}
return statement
}
- statement.IdParam = &core.PK{id}
+ statement.idParam = &core.PK{id}
return statement
}
@@ -1120,7 +1124,11 @@ func (statement *Statement) genConds(bean interface{}) (string, []interface{}, e
}
func (statement *Statement) genGetSQL(bean interface{}) (string, []interface{}) {
- statement.setRefValue(rValue(bean))
+ v := rValue(bean)
+ isStruct := v.Kind() == reflect.Struct
+ if isStruct {
+ statement.setRefValue(v)
+ }
var columnStr = statement.ColumnStr
if len(statement.selectStr) > 0 {
@@ -1139,14 +1147,22 @@ func (statement *Statement) genGetSQL(bean interface{}) (string, []interface{})
if len(columnStr) == 0 {
if len(statement.GroupByStr) > 0 {
columnStr = statement.Engine.Quote(strings.Replace(statement.GroupByStr, ",", statement.Engine.Quote(","), -1))
- } else {
- columnStr = "*"
}
}
}
}
- condSQL, condArgs, _ := statement.genConds(bean)
+ if len(columnStr) == 0 {
+ columnStr = "*"
+ }
+
+ var condSQL string
+ var condArgs []interface{}
+ if isStruct {
+ condSQL, condArgs, _ = statement.genConds(bean)
+ } else {
+ condSQL, condArgs, _ = builder.ToSQL(statement.cond)
+ }
return statement.genSelectSQL(columnStr, condSQL), append(statement.joinArgs, condArgs...)
}
@@ -1172,7 +1188,7 @@ func (statement *Statement) genSumSQL(bean interface{}, columns ...string) (stri
var sumStrs = make([]string, 0, len(columns))
for _, colName := range columns {
- sumStrs = append(sumStrs, fmt.Sprintf("COALESCE(sum(%s),0)", colName))
+ sumStrs = append(sumStrs, fmt.Sprintf("COALESCE(sum(%s),0)", statement.Engine.Quote(colName)))
}
condSQL, condArgs, _ := statement.genConds(bean)
@@ -1182,7 +1198,7 @@ func (statement *Statement) genSumSQL(bean interface{}, columns ...string) (stri
func (statement *Statement) genSelectSQL(columnStr, condSQL string) (a string) {
var distinct string
- if statement.IsDistinct {
+ if statement.IsDistinct && !strings.HasPrefix(columnStr, "count") {
distinct = "DISTINCT "
}
@@ -1289,14 +1305,14 @@ func (statement *Statement) genSelectSQL(columnStr, condSQL string) (a string) {
}
func (statement *Statement) processIDParam() {
- if statement.IdParam == nil {
+ if statement.idParam == nil {
return
}
for i, col := range statement.RefTable.PKColumns() {
var colName = statement.colName(col, statement.TableName())
- if i < len(*(statement.IdParam)) {
- statement.cond = statement.cond.And(builder.Eq{colName: (*(statement.IdParam))[i]})
+ if i < len(*(statement.idParam)) {
+ statement.cond = statement.cond.And(builder.Eq{colName: (*(statement.idParam))[i]})
} else {
statement.cond = statement.cond.And(builder.Eq{colName: ""})
}
diff --git a/vendor/github.com/go-xorm/xorm/tag.go b/vendor/github.com/go-xorm/xorm/tag.go
new file mode 100644
index 0000000000..4b0e3f54a5
--- /dev/null
+++ b/vendor/github.com/go-xorm/xorm/tag.go
@@ -0,0 +1,281 @@
+// 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 (
+ "fmt"
+ "reflect"
+ "strconv"
+ "strings"
+ "time"
+
+ "github.com/go-xorm/core"
+)
+
+type tagContext struct {
+ tagName string
+ params []string
+ preTag, nextTag string
+ table *core.Table
+ col *core.Column
+ fieldValue reflect.Value
+ isIndex bool
+ isUnique bool
+ indexNames map[string]int
+ engine *Engine
+ hasCacheTag bool
+ hasNoCacheTag bool
+ ignoreNext bool
+}
+
+// tagHandler describes tag handler for XORM
+type tagHandler func(ctx *tagContext) error
+
+var (
+ // defaultTagHandlers enumerates all the default tag handler
+ defaultTagHandlers = map[string]tagHandler{
+ "<-": OnlyFromDBTagHandler,
+ "->": OnlyToDBTagHandler,
+ "PK": PKTagHandler,
+ "NULL": NULLTagHandler,
+ "NOT": IgnoreTagHandler,
+ "AUTOINCR": AutoIncrTagHandler,
+ "DEFAULT": DefaultTagHandler,
+ "CREATED": CreatedTagHandler,
+ "UPDATED": UpdatedTagHandler,
+ "DELETED": DeletedTagHandler,
+ "VERSION": VersionTagHandler,
+ "UTC": UTCTagHandler,
+ "LOCAL": LocalTagHandler,
+ "NOTNULL": NotNullTagHandler,
+ "INDEX": IndexTagHandler,
+ "UNIQUE": UniqueTagHandler,
+ "CACHE": CacheTagHandler,
+ "NOCACHE": NoCacheTagHandler,
+ }
+)
+
+func init() {
+ for k := range core.SqlTypes {
+ defaultTagHandlers[k] = SQLTypeTagHandler
+ }
+}
+
+// IgnoreTagHandler describes ignored tag handler
+func IgnoreTagHandler(ctx *tagContext) error {
+ return nil
+}
+
+// OnlyFromDBTagHandler describes mapping direction tag handler
+func OnlyFromDBTagHandler(ctx *tagContext) error {
+ ctx.col.MapType = core.ONLYFROMDB
+ return nil
+}
+
+// OnlyToDBTagHandler describes mapping direction tag handler
+func OnlyToDBTagHandler(ctx *tagContext) error {
+ ctx.col.MapType = core.ONLYTODB
+ return nil
+}
+
+// PKTagHandler decribes primary key tag handler
+func PKTagHandler(ctx *tagContext) error {
+ ctx.col.IsPrimaryKey = true
+ ctx.col.Nullable = false
+ return nil
+}
+
+// NULLTagHandler describes null tag handler
+func NULLTagHandler(ctx *tagContext) error {
+ ctx.col.Nullable = (strings.ToUpper(ctx.preTag) != "NOT")
+ return nil
+}
+
+// NotNullTagHandler describes notnull tag handler
+func NotNullTagHandler(ctx *tagContext) error {
+ ctx.col.Nullable = false
+ return nil
+}
+
+// AutoIncrTagHandler describes autoincr tag handler
+func AutoIncrTagHandler(ctx *tagContext) error {
+ ctx.col.IsAutoIncrement = true
+ /*
+ if len(ctx.params) > 0 {
+ autoStartInt, err := strconv.Atoi(ctx.params[0])
+ if err != nil {
+ return err
+ }
+ ctx.col.AutoIncrStart = autoStartInt
+ } else {
+ ctx.col.AutoIncrStart = 1
+ }
+ */
+ return nil
+}
+
+// DefaultTagHandler describes default tag handler
+func DefaultTagHandler(ctx *tagContext) error {
+ if len(ctx.params) > 0 {
+ ctx.col.Default = ctx.params[0]
+ } else {
+ ctx.col.Default = ctx.nextTag
+ ctx.ignoreNext = true
+ }
+ return nil
+}
+
+// CreatedTagHandler describes created tag handler
+func CreatedTagHandler(ctx *tagContext) error {
+ ctx.col.IsCreated = true
+ return nil
+}
+
+// VersionTagHandler describes version tag handler
+func VersionTagHandler(ctx *tagContext) error {
+ ctx.col.IsVersion = true
+ ctx.col.Default = "1"
+ return nil
+}
+
+// UTCTagHandler describes utc tag handler
+func UTCTagHandler(ctx *tagContext) error {
+ ctx.col.TimeZone = time.UTC
+ return nil
+}
+
+// LocalTagHandler describes local tag handler
+func LocalTagHandler(ctx *tagContext) error {
+ if len(ctx.params) == 0 {
+ ctx.col.TimeZone = time.Local
+ } else {
+ var err error
+ ctx.col.TimeZone, err = time.LoadLocation(ctx.params[0])
+ if err != nil {
+ return err
+ }
+ }
+ return nil
+}
+
+// UpdatedTagHandler describes updated tag handler
+func UpdatedTagHandler(ctx *tagContext) error {
+ ctx.col.IsUpdated = true
+ return nil
+}
+
+// DeletedTagHandler describes deleted tag handler
+func DeletedTagHandler(ctx *tagContext) error {
+ ctx.col.IsDeleted = true
+ return nil
+}
+
+// IndexTagHandler describes index tag handler
+func IndexTagHandler(ctx *tagContext) error {
+ if len(ctx.params) > 0 {
+ ctx.indexNames[ctx.params[0]] = core.IndexType
+ } else {
+ ctx.isIndex = true
+ }
+ return nil
+}
+
+// UniqueTagHandler describes unique tag handler
+func UniqueTagHandler(ctx *tagContext) error {
+ if len(ctx.params) > 0 {
+ ctx.indexNames[ctx.params[0]] = core.UniqueType
+ } else {
+ ctx.isUnique = true
+ }
+ return nil
+}
+
+// SQLTypeTagHandler describes SQL Type tag handler
+func SQLTypeTagHandler(ctx *tagContext) error {
+ ctx.col.SQLType = core.SQLType{Name: ctx.tagName}
+ if len(ctx.params) > 0 {
+ if ctx.tagName == core.Enum {
+ ctx.col.EnumOptions = make(map[string]int)
+ for k, v := range ctx.params {
+ v = strings.TrimSpace(v)
+ v = strings.Trim(v, "'")
+ ctx.col.EnumOptions[v] = k
+ }
+ } else if ctx.tagName == core.Set {
+ ctx.col.SetOptions = make(map[string]int)
+ for k, v := range ctx.params {
+ v = strings.TrimSpace(v)
+ v = strings.Trim(v, "'")
+ ctx.col.SetOptions[v] = k
+ }
+ } else {
+ var err error
+ if len(ctx.params) == 2 {
+ ctx.col.Length, err = strconv.Atoi(ctx.params[0])
+ if err != nil {
+ return err
+ }
+ ctx.col.Length2, err = strconv.Atoi(ctx.params[1])
+ if err != nil {
+ return err
+ }
+ } else if len(ctx.params) == 1 {
+ ctx.col.Length, err = strconv.Atoi(ctx.params[0])
+ if err != nil {
+ return err
+ }
+ }
+ }
+ }
+ return nil
+}
+
+// ExtendsTagHandler describes extends tag handler
+func ExtendsTagHandler(ctx *tagContext) error {
+ var fieldValue = ctx.fieldValue
+ switch fieldValue.Kind() {
+ case reflect.Ptr:
+ f := fieldValue.Type().Elem()
+ if f.Kind() == reflect.Struct {
+ fieldPtr := fieldValue
+ fieldValue = fieldValue.Elem()
+ if !fieldValue.IsValid() || fieldPtr.IsNil() {
+ fieldValue = reflect.New(f).Elem()
+ }
+ }
+ fallthrough
+ case reflect.Struct:
+ parentTable, err := ctx.engine.mapType(fieldValue)
+ if err != nil {
+ return err
+ }
+ for _, col := range parentTable.Columns() {
+ col.FieldName = fmt.Sprintf("%v.%v", ctx.col.FieldName, col.FieldName)
+ ctx.table.AddColumn(col)
+ for indexName, indexType := range col.Indexes {
+ addIndex(indexName, ctx.table, col, indexType)
+ }
+ }
+ default:
+ //TODO: warning
+ }
+ return nil
+}
+
+// CacheTagHandler describes cache tag handler
+func CacheTagHandler(ctx *tagContext) error {
+ if !ctx.hasCacheTag {
+ ctx.hasCacheTag = true
+ }
+ return nil
+}
+
+// NoCacheTagHandler describes nocache tag handler
+func NoCacheTagHandler(ctx *tagContext) error {
+ if !ctx.hasNoCacheTag {
+ ctx.hasNoCacheTag = true
+ }
+ return nil
+}
diff --git a/vendor/github.com/go-xorm/xorm/xorm.go b/vendor/github.com/go-xorm/xorm/xorm.go
index 6414d8a26b..0d9debdf6e 100644
--- a/vendor/github.com/go-xorm/xorm/xorm.go
+++ b/vendor/github.com/go-xorm/xorm/xorm.go
@@ -17,7 +17,7 @@ import (
const (
// Version show the xorm's version
- Version string = "0.6.0.1022"
+ Version string = "0.6.2.0401"
)
func regDrvsNDialects() bool {
@@ -86,6 +86,7 @@ func NewEngine(driverName string, dataSourceName string) (*Engine, error) {
mutex: &sync.RWMutex{},
TagIdentifier: "xorm",
TZLocation: time.Local,
+ tagHandlers: defaultTagHandlers,
}
logger := NewSimpleLogger(os.Stdout)
diff --git a/vendor/vendor.json b/vendor/vendor.json
index 00c20c63c9..fa7520a913 100644
--- a/vendor/vendor.json
+++ b/vendor/vendor.json
@@ -455,10 +455,10 @@
"revisionTime": "2016-08-11T02:11:45Z"
},
{
- "checksumSHA1": "COlm4o3G1rUSqr33iumtjY1qKD8=",
+ "checksumSHA1": "3FEBM0FYERf8jpaResApwcQpr40=",
"path": "github.com/go-xorm/xorm",
- "revision": "1bc93ba022236fcc94092fa40105b96e1d1d2346",
- "revisionTime": "2017-02-20T09:51:59Z"
+ "revision": "7e70eb82224bc950d4fb936036e925a51947c245",
+ "revisionTime": "2017-04-02T10:02:47Z"
},
{
"checksumSHA1": "1ft/4j5MFa7C9dPI9whL03HSUzk=",