Browse Source

fix migrate failed and org dashboard failed on MSSQL database (#1448)

tags/v1.2.0-rc1
Lunny Xiao 7 years ago
parent
commit
5acfc7c4bc
36 changed files with 1993 additions and 1628 deletions
  1. 21
    4
      models/org.go
  2. 22
    11
      vendor/github.com/go-xorm/xorm/README.md
  3. 21
    8
      vendor/github.com/go-xorm/xorm/README_CN.md
  4. 0
    1
      vendor/github.com/go-xorm/xorm/VERSION
  5. 37
    0
      vendor/github.com/go-xorm/xorm/convert.go
  6. 28
    3
      vendor/github.com/go-xorm/xorm/dialect_mssql.go
  7. 92
    0
      vendor/github.com/go-xorm/xorm/dialect_mysql.go
  8. 60
    0
      vendor/github.com/go-xorm/xorm/dialect_oracle.go
  9. 110
    1
      vendor/github.com/go-xorm/xorm/dialect_postgres.go
  10. 10
    0
      vendor/github.com/go-xorm/xorm/dialect_sqlite3.go
  11. 31
    12
      vendor/github.com/go-xorm/xorm/doc.go
  12. 128
    177
      vendor/github.com/go-xorm/xorm/engine.go
  13. 0
    42
      vendor/github.com/go-xorm/xorm/goracle_driver.go
  14. 14
    0
      vendor/github.com/go-xorm/xorm/helpers.go
  15. 0
    65
      vendor/github.com/go-xorm/xorm/mymysql_driver.go
  16. 0
    50
      vendor/github.com/go-xorm/xorm/mysql_driver.go
  17. 0
    37
      vendor/github.com/go-xorm/xorm/oci8_driver.go
  18. 0
    34
      vendor/github.com/go-xorm/xorm/odbc_driver.go
  19. 0
    119
      vendor/github.com/go-xorm/xorm/pq_driver.go
  20. 10
    9
      vendor/github.com/go-xorm/xorm/rows.go
  21. 68
    888
      vendor/github.com/go-xorm/xorm/session.go
  22. 84
    0
      vendor/github.com/go-xorm/xorm/session_cols.go
  23. 70
    0
      vendor/github.com/go-xorm/xorm/session_cond.go
  24. 673
    0
      vendor/github.com/go-xorm/xorm/session_convert.go
  25. 61
    41
      vendor/github.com/go-xorm/xorm/session_find.go
  26. 31
    21
      vendor/github.com/go-xorm/xorm/session_get.go
  27. 27
    11
      vendor/github.com/go-xorm/xorm/session_insert.go
  28. 10
    1
      vendor/github.com/go-xorm/xorm/session_raw.go
  29. 4
    1
      vendor/github.com/go-xorm/xorm/session_schema.go
  30. 1
    1
      vendor/github.com/go-xorm/xorm/session_sum.go
  31. 39
    28
      vendor/github.com/go-xorm/xorm/session_update.go
  32. 0
    20
      vendor/github.com/go-xorm/xorm/sqlite3_driver.go
  33. 55
    39
      vendor/github.com/go-xorm/xorm/statement.go
  34. 281
    0
      vendor/github.com/go-xorm/xorm/tag.go
  35. 2
    1
      vendor/github.com/go-xorm/xorm/xorm.go
  36. 3
    3
      vendor/vendor.json

+ 21
- 4
models/org.go View File

Find(&repos) Find(&repos)
} }


func (env *accessibleReposEnv) MirrorRepos() ([]*Repository, error) {
repos := make([]*Repository, 0, 10)
return repos, x.
Select("`repository`.*").
func (env *accessibleReposEnv) MirrorRepoIDs() ([]int64, error) {
repoIDs := make([]int64, 0, 10)
return repoIDs, x.
Table("repository").
Join("INNER", "team_repo", "`team_repo`.repo_id=`repository`.id AND `repository`.is_mirror=?", true). Join("INNER", "team_repo", "`team_repo`.repo_id=`repository`.id AND `repository`.is_mirror=?", true).
Where(env.cond()). Where(env.cond()).
GroupBy("`repository`.id"). GroupBy("`repository`.id").
OrderBy("updated_unix DESC"). OrderBy("updated_unix DESC").
Cols("`repository`.id").
Find(&repoIDs)
}

func (env *accessibleReposEnv) MirrorRepos() ([]*Repository, error) {
repoIDs, err := env.MirrorRepoIDs()
if err != nil {
return nil, fmt.Errorf("MirrorRepoIDs: %v", err)
}

repos := make([]*Repository, 0, len(repoIDs))
if len(repoIDs) <= 0 {
return repos, nil
}

return repos, x.
In("`repository`.id", repoIDs).
Find(&repos) Find(&repos)
} }

+ 22
- 11
vendor/github.com/go-xorm/xorm/README.md View File



* MsSql: [github.com/denisenkom/go-mssqldb](https://github.com/denisenkom/go-mssqldb) * 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) * Oracle: [github.com/mattn/go-oci8](https://github.com/mattn/go-oci8) (experiment)


# Changelog # Changelog


* **v0.6.2**
* refactor tag parse methods
* add Scan features to Get
* add QueryString method

* **v0.6.0** * **v0.6.0**
* remove support for ql * 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` * add query condition builder support via [github.com/go-xorm/builder](https://github.com/go-xorm/builder), so `Where`, `And`, `Or`


# Installation # 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 go get github.com/go-xorm/xorm


# Documents # Documents
err := engine.Sync2(new(User)) 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 ```Go
results, err := engine.Query("select * from user") 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 ```Go
affected, err := engine.Exec("update user set age = ? where name = ?", age, name) 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 ```Go
affected, err := engine.Insert(&user) affected, err := engine.Insert(&user)
// SELECT * FROM user LIMIT 1 // SELECT * FROM user LIMIT 1
has, err := engine.Where("name = ?", name).Desc("id").Get(&user) has, err := engine.Where("name = ?", name).Desc("id").Get(&user)
// SELECT * FROM user WHERE name = ? ORDER BY id DESC LIMIT 1 // 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 * Query multiple records from database, also you can use join and extends

+ 21
- 8
vendor/github.com/go-xorm/xorm/README_CN.md View File



## 更新日志 ## 更新日志


* **v0.6.2**
* 重构Tag解析方式
* Get方法新增类似Sacn的特性
* 新增 QueryString 方法

* **v0.6.0** * **v0.6.0**
* 去除对 ql 的支持 * 去除对 ql 的支持
* 新增条件查询分析器 [github.com/go-xorm/builder](https://github.com/go-xorm/builder), 从因此 `Where, And, Or` 函数 * 新增条件查询分析器 [github.com/go-xorm/builder](https://github.com/go-xorm/builder), 从因此 `Where, And, Or` 函数


## 安装 ## 安装


推荐使用 [gopm](https://github.com/gpmgo/gopm) 进行安装:

gopm get github.com/go-xorm/xorm

或者您也可以使用go工具进行安装:

go get github.com/go-xorm/xorm go get github.com/go-xorm/xorm


## 文档 ## 文档
err := engine.Sync2(new(User)) err := engine.Sync2(new(User))
``` ```


* 最原始的也支持SQL语句查询,返回的结果类型为 []map[string][]byte
* `Query` 最原始的也支持SQL语句查询,返回的结果类型为 []map[string][]byte。`QueryString` 返回 []map[string]string


```Go ```Go
results, err := engine.Query("select * from user") results, err := engine.Query("select * from user")

results, err := engine.QueryString("select * from user")
``` ```


* 执行一个SQL语句
* `Exec` 执行一个SQL语句


```Go ```Go
affected, err := engine.Exec("update user set age = ? where name = ?", age, name) affected, err := engine.Exec("update user set age = ? where name = ?", age, name)
// SELECT * FROM user LIMIT 1 // SELECT * FROM user LIMIT 1
has, err := engine.Where("name = ?", name).Desc("id").Get(&user) has, err := engine.Where("name = ?", name).Desc("id").Get(&user)
// SELECT * FROM user WHERE name = ? ORDER BY id DESC LIMIT 1 // 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来组合使用 * 查询多条记录,当然可以使用Join和extends来组合使用

+ 0
- 1
vendor/github.com/go-xorm/xorm/VERSION View File

xorm v0.6.0.1022

+ 37
- 0
vendor/github.com/go-xorm/xorm/convert.go View File



return fmt.Errorf("unsupported Scan, storing driver.Value type %T into type %T", src, dest) 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)
}

vendor/github.com/go-xorm/xorm/mssql_dialect.go → vendor/github.com/go-xorm/xorm/dialect_mssql.go View File

package xorm package xorm


import ( import (
"errors"
"fmt" "fmt"
"strconv" "strconv"
"strings" "strings"
switch t := c.SQLType.Name; t { switch t := c.SQLType.Name; t {
case core.Bool: case core.Bool:
res = core.TinyInt res = core.TinyInt
if c.Default == "true" {
if strings.EqualFold(c.Default, "true") {
c.Default = "1" c.Default = "1"
} else if c.Default == "false" {
} else {
c.Default = "0" c.Default = "0"
} }
case core.Serial: case core.Serial:
} }


colName = strings.Trim(colName, "` ") colName = strings.Trim(colName, "` ")
var isRegular bool
if strings.HasPrefix(indexName, "IDX_"+tableName) || strings.HasPrefix(indexName, "UQE_"+tableName) { if strings.HasPrefix(indexName, "IDX_"+tableName) || strings.HasPrefix(indexName, "UQE_"+tableName) {
indexName = indexName[5+len(tableName):] indexName = indexName[5+len(tableName):]
isRegular = true
} }


var index *core.Index var index *core.Index
index = new(core.Index) index = new(core.Index)
index.Type = indexType index.Type = indexType
index.Name = indexName index.Name = indexName
index.IsRegular = isRegular
indexes[indexName] = index indexes[indexName] = index
} }
index.AddColumn(colName) index.AddColumn(colName)
func (db *mssql) Filters() []core.Filter { func (db *mssql) Filters() []core.Filter {
return []core.Filter{&core.IdFilter{}, &core.QuoteFilter{}} 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
}

vendor/github.com/go-xorm/xorm/mysql_dialect.go → vendor/github.com/go-xorm/xorm/dialect_mysql.go View File



import ( import (
"crypto/tls" "crypto/tls"
"errors"
"fmt" "fmt"
"regexp"
"strconv" "strconv"
"strings" "strings"
"time" "time"
func (db *mysql) Filters() []core.Filter { func (db *mysql) Filters() []core.Filter {
return []core.Filter{&core.IdFilter{}} 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
}

vendor/github.com/go-xorm/xorm/oracle_dialect.go → vendor/github.com/go-xorm/xorm/dialect_oracle.go View File

package xorm package xorm


import ( import (
"errors"
"fmt" "fmt"
"regexp"
"strconv" "strconv"
"strings" "strings"




indexName = strings.Trim(indexName, `" `) 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" { if uniqueness == "UNIQUE" {
indexType = core.UniqueType indexType = core.UniqueType
} else { } else {
index = new(core.Index) index = new(core.Index)
index.Type = indexType index.Type = indexType
index.Name = indexName index.Name = indexName
index.IsRegular = isRegular
indexes[indexName] = index indexes[indexName] = index
} }
index.AddColumn(colName) index.AddColumn(colName)
func (db *oracle) Filters() []core.Filter { func (db *oracle) Filters() []core.Filter {
return []core.Filter{&core.QuoteFilter{}, &core.SeqFilter{Prefix: ":", Start: 1}, &core.IdFilter{}} 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
}

vendor/github.com/go-xorm/xorm/postgres_dialect.go → vendor/github.com/go-xorm/xorm/dialect_postgres.go View File

package xorm package xorm


import ( import (
"errors"
"fmt" "fmt"
"net/url"
"sort"
"strconv" "strconv"
"strings" "strings"


} }
cs := strings.Split(indexdef, "(") cs := strings.Split(indexdef, "(")
colNames = strings.Split(cs[1][0:len(cs[1])-1], ",") colNames = strings.Split(cs[1][0:len(cs[1])-1], ",")
var isRegular bool
if strings.HasPrefix(indexName, "IDX_"+tableName) || strings.HasPrefix(indexName, "UQE_"+tableName) { if strings.HasPrefix(indexName, "IDX_"+tableName) || strings.HasPrefix(indexName, "UQE_"+tableName) {
newIdxName := indexName[5+len(tableName):] newIdxName := indexName[5+len(tableName):]
isRegular = true
if newIdxName != "" { if newIdxName != "" {
indexName = newIdxName indexName = newIdxName
} }
for _, colName := range colNames { for _, colName := range colNames {
index.Cols = append(index.Cols, strings.Trim(colName, `" `)) index.Cols = append(index.Cols, strings.Trim(colName, `" `))
} }
index.IsRegular = isRegular
indexes[index.Name] = index indexes[index.Name] = index
} }
return indexes, nil return indexes, nil
func (db *postgres) Filters() []core.Filter { func (db *postgres) Filters() []core.Filter {
return []core.Filter{&core.IdFilter{}, &core.QuoteFilter{}, &core.SeqFilter{Prefix: "$", Start: 1}} 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
}

vendor/github.com/go-xorm/xorm/sqlite3_dialect.go → vendor/github.com/go-xorm/xorm/dialect_sqlite3.go View File

} }


indexName := strings.Trim(sql[nNStart+6:nNEnd], "` []") indexName := strings.Trim(sql[nNStart+6:nNEnd], "` []")
var isRegular bool
if strings.HasPrefix(indexName, "IDX_"+tableName) || strings.HasPrefix(indexName, "UQE_"+tableName) { if strings.HasPrefix(indexName, "IDX_"+tableName) || strings.HasPrefix(indexName, "UQE_"+tableName) {
index.Name = indexName[5+len(tableName):] index.Name = indexName[5+len(tableName):]
isRegular = true
} else { } else {
index.Name = indexName index.Name = indexName
} }
for _, col := range colIndexes { for _, col := range colIndexes {
index.Cols = append(index.Cols, strings.Trim(col, "` []")) index.Cols = append(index.Cols, strings.Trim(col, "` []"))
} }
index.IsRegular = isRegular
indexes[index.Name] = index indexes[index.Name] = index
} }


func (db *sqlite3) Filters() []core.Filter { func (db *sqlite3) Filters() []core.Filter {
return []core.Filter{&core.IdFilter{}} 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
}

+ 31
- 12
vendor/github.com/go-xorm/xorm/doc.go View File



Raw Methods 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 1. query a SQL string, the returned results is []map[string][]byte




ORM Methods 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 1. Insert one or multiple records to database




3. Query multiple records from database 3. Query multiple records from database


sliceOfStructs := new(Struct)
err := engine.Find(sliceOfStructs)
var sliceOfStructs []Struct
err := engine.Find(&sliceOfStructs)
// SELECT * FROM user // 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, 4. Query multiple records and record by record handle, there two methods, one is Iterate,
another is Rows another is Rows


counts, err := engine.Count(&user) counts, err := engine.Count(&user)
// SELECT count(*) AS total FROM 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 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 // 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 // SELECT * FROM user WHERE id1 = 1 AND id2 = 2
engine.In("id", 1, 2, 3).Find(&users) engine.In("id", 1, 2, 3).Find(&users)
// SELECT * FROM user WHERE id IN (1, 2, 3) // 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) // SELECT * FROM user WHERE id IN (1, 2, 3)


2. Where, And, Or 2. Where, And, Or
// SELECT TOP 5 * FROM user // for mssql // SELECT TOP 5 * FROM user // for mssql
// SELECT * FROM user LIMIT .. OFFSET 0 //for other databases // SELECT * FROM user LIMIT .. OFFSET 0 //for other databases


5. Sql, let you custom SQL
5. SQL, let you custom SQL


var users []User var users []User
engine.Sql("select * from user").Find(&users)
engine.SQL("select * from user").Find(&users)


6. Cols, Omit, Distinct 6. Cols, Omit, Distinct



+ 128
- 177
vendor/github.com/go-xorm/xorm/engine.go View File

DatabaseTZ *time.Location // The timezone of the database DatabaseTZ *time.Location // The timezone of the database


disableGlobalCache bool disableGlobalCache bool

tagHandlers map[string]tagHandler
} }


// ShowSQL show SQL statement or not on logger if log level is great than INFO // ShowSQL show SQL statement or not on logger if log level is great than INFO
} }


// MapCacher Set a table use a special cacher // 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) v := rValue(bean)
tb := engine.autoMapType(v)
tb, err := engine.autoMapType(v)
if err != nil {
return err
}

tb.Cacher = cacher tb.Cacher = cacher
return nil
} }


// NewDB provides an interface to operate database directly // NewDB provides an interface to operate database directly
func (engine *Engine) logSQL(sqlStr string, sqlArgs ...interface{}) { func (engine *Engine) logSQL(sqlStr string, sqlArgs ...interface{}) {
if engine.showSQL && !engine.showExecTime { if engine.showSQL && !engine.showExecTime {
if len(sqlArgs) > 0 { if len(sqlArgs) > 0 {
engine.logger.Infof("[sql] %v [args] %v", sqlStr, sqlArgs)
engine.logger.Infof("[SQL] %v %v", sqlStr, sqlArgs)
} else { } else {
engine.logger.Infof("[sql] %v", sqlStr)
engine.logger.Infof("[SQL] %v", sqlStr)
} }
} }
} }
stmt, res, err := executionBlock() stmt, res, err := executionBlock()
execDuration := time.Since(b4ExecTime) execDuration := time.Since(b4ExecTime)
if len(args) > 0 { 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 { } else {
engine.logger.Infof("[sql] %s - took: %v", sqlStr, execDuration)
engine.logger.Infof("[SQL] %s - took: %v", sqlStr, execDuration)
} }
return stmt, res, err return stmt, res, err
} }
return session.Having(conditions) 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() t := v.Type()
engine.mutex.Lock() engine.mutex.Lock()
defer engine.mutex.Unlock() defer engine.mutex.Unlock()
table, ok := engine.Tables[t] table, ok := engine.Tables[t]
if !ok { if !ok {
table = engine.mapType(v)
var err error
table, err = engine.mapType(v)
if err != nil {
return nil, err
}

engine.Tables[t] = table engine.Tables[t] = table
if engine.Cacher != nil { if engine.Cacher != nil {
if v.CanAddr() { if v.CanAddr() {
} }
} }
} }
return table
return table, nil
} }


// GobRegister register one struct to gob for cache use // GobRegister register one struct to gob for cache use
func (engine *Engine) GobRegister(v interface{}) *Engine { func (engine *Engine) GobRegister(v interface{}) *Engine {
//fmt.Printf("Type: %[1]T => Data: %[1]#v\n", v)
gob.Register(v) gob.Register(v)
return engine return engine
} }
Name string 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 // TableInfo get table info according to bean's content
func (engine *Engine) TableInfo(bean interface{}) *Table { func (engine *Engine) TableInfo(bean interface{}) *Table {
v := rValue(bean) 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) { func addIndex(indexName string, table *core.Table, col *core.Column, indexType int) {
tpTableName = reflect.TypeOf((*TableName)(nil)).Elem() 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() t := v.Type()
table := engine.newTable() table := engine.newTable()
if tb, ok := v.Interface().(TableName); ok { if tb, ok := v.Interface().(TableName); ok {
table.Type = t table.Type = t


var idFieldColName string var idFieldColName string
var err error
var hasCacheTag, hasNoCacheTag bool var hasCacheTag, hasNoCacheTag bool


for i := 0; i < t.NumField(); i++ { for i := 0; i < t.NumField(); i++ {
if tags[0] == "-" { if tags[0] == "-" {
continue continue
} }

var ctx = tagContext{
table: table,
col: col,
fieldValue: fieldValue,
indexNames: make(map[string]int),
engine: engine,
}

if strings.ToUpper(tags[0]) == "EXTENDS" { 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 { for j, key := range tags {
if ctx.ignoreNext {
ctx.ignoreNext = false
continue
}

k := strings.ToUpper(key) 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 { } 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 == "" { if col.SQLType.Name == "" {
col.SQLType = core.Type2SQLType(fieldType) col.SQLType = core.Type2SQLType(fieldType)
} }
engine.dialect.SqlType(col)
if col.Length == 0 { if col.Length == 0 {
col.Length = col.SQLType.DefaultLength col.Length = col.SQLType.DefaultLength
} }
if col.Length2 == 0 { if col.Length2 == 0 {
col.Length2 = col.SQLType.DefaultLength2 col.Length2 = col.SQLType.DefaultLength2
} }

if col.Name == "" { if col.Name == "" {
col.Name = engine.ColumnMapper.Obj2Table(t.Field(i).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) addIndex(indexName, table, col, indexType)
} }
} }
table.Cacher = nil table.Cacher = nil
} }


return table
return table, nil
} }


// IsTableEmpty if a table has any reocrd // IsTableEmpty if a table has any reocrd


// IDOfV get id from one value of struct // IDOfV get id from one value of struct
func (engine *Engine) IDOfV(rv reflect.Value) core.PK { 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) 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)) pk := make([]interface{}, len(table.PrimaryKeys))
for i, col := range table.PKColumns() { for i, col := range table.PKColumns() {
pkField := v.FieldByName(col.FieldName) pkField := v.FieldByName(col.FieldName)
pk[i] = pkField.Uint() pk[i] = pkField.Uint()
} }
} }
return core.PK(pk)
return core.PK(pk), nil
} }


// CreateIndexes create indexes // CreateIndexes create indexes
return table.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 // ClearCacheBean if enabled cache, clear the cache bean
func (engine *Engine) ClearCacheBean(bean interface{}, id string) error { func (engine *Engine) ClearCacheBean(bean interface{}, id string) error {
v := rValue(bean) v := rValue(bean)
return errors.New("error params") return errors.New("error params")
} }
tableName := engine.tbName(v) tableName := engine.tbName(v)
table := engine.autoMapType(v)
table, err := engine.autoMapType(v)
if err != nil {
return err
}
cacher := table.Cacher cacher := table.Cacher
if cacher == nil { if cacher == nil {
cacher = engine.Cacher cacher = engine.Cacher
return errors.New("error params") return errors.New("error params")
} }
tableName := engine.tbName(v) tableName := engine.tbName(v)
table := engine.autoMapType(v)
table, err := engine.autoMapType(v)
if err != nil {
return err
}

cacher := table.Cacher cacher := table.Cacher
if cacher == nil { if cacher == nil {
cacher = engine.Cacher cacher = engine.Cacher
for _, bean := range beans { for _, bean := range beans {
v := rValue(bean) v := rValue(bean)
tableName := engine.tbName(v) 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() s := engine.NewSession()
defer s.Close() defer s.Close()
return session.Query(sql, paramStr...) 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 // Insert one or more records
func (engine *Engine) Insert(beans ...interface{}) (int64, error) { func (engine *Engine) Insert(beans ...interface{}) (int64, error) {
session := engine.NewSession() session := engine.NewSession()

+ 0
- 42
vendor/github.com/go-xorm/xorm/goracle_driver.go View File

// 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
}

+ 14
- 0
vendor/github.com/go-xorm/xorm/helpers.go View File

return true 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 { func int64ToIntValue(id int64, tp reflect.Type) reflect.Value {
var v interface{} var v interface{}
switch tp.Kind() { switch tp.Kind() {

+ 0
- 65
vendor/github.com/go-xorm/xorm/mymysql_driver.go View File

// 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
}

+ 0
- 50
vendor/github.com/go-xorm/xorm/mysql_driver.go View File

// 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
}

+ 0
- 37
vendor/github.com/go-xorm/xorm/oci8_driver.go View File

// 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
}

+ 0
- 34
vendor/github.com/go-xorm/xorm/odbc_driver.go View File

// 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
}

+ 0
- 119
vendor/github.com/go-xorm/xorm/pq_driver.go View File

// 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
}

+ 10
- 9
vendor/github.com/go-xorm/xorm/rows.go View File

type Rows struct { type Rows struct {
NoTypeCheck bool 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) { func newRows(session *Session, bean interface{}) (*Rows, error) {
rows.Close() rows.Close()
return nil, err return nil, err
} }
rows.fieldsCount = len(rows.fields)


return rows, nil return rows, nil
} }
return fmt.Errorf("scan arg is incompatible type to [%v]", rows.beanType) 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 return err
} }



+ 68
- 888
vendor/github.com/go-xorm/xorm/session.go
File diff suppressed because it is too large
View File


+ 84
- 0
vendor/github.com/go-xorm/xorm/session_cols.go View File

// 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
}

+ 70
- 0
vendor/github.com/go-xorm/xorm/session_cond.go View File

// 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
}

+ 673
- 0
vendor/github.com/go-xorm/xorm/session_convert.go View File

// 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
}
}

+ 61
- 41
vendor/github.com/go-xorm/xorm/session_find.go View File

return err return err
} }


var newElemFunc func() reflect.Value
var newElemFunc func(fields []string) reflect.Value
elemType := containerValue.Type().Elem() elemType := containerValue.Type().Elem()
var isPointer bool
if elemType.Kind() == reflect.Ptr { 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 var containerValueSetFunc func(*reflect.Value, core.PK) error


if containerValue.Kind() == reflect.Slice { 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 { } else {
keyType := containerValue.Type().Key() keyType := containerValue.Type().Key()
return errors.New("don't support multiple primary key's map has non-slice key type") 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() { for rawRows.Next() {
var newValue = newElemFunc()
var newValue = newElemFunc(fields)
bean := newValue.Interface() 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 return err
} }


if rv.Kind() != reflect.Ptr { if rv.Kind() != reflect.Ptr {
rv = rv.Addr() rv = rv.Addr()
} }
id := session.Engine.IdOfV(rv)
id, err := session.Engine.idOfV(rv)
if err != nil {
return err
}
sid, err := id.ToString() sid, err := id.ToString()
if err != nil { if err != nil {
return err return err

+ 31
- 21
vendor/github.com/go-xorm/xorm/session_get.go View File

defer session.Close() 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 sqlStr string
var args []interface{} var args []interface{}
args = session.Statement.RawParams 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 && if cacher := session.Engine.getCacher2(session.Statement.RefTable); cacher != nil &&
!session.Statement.unscoped { !session.Statement.unscoped {
has, err := session.cacheGet(bean, sqlStr, args...) has, err := session.cacheGet(bean, sqlStr, args...)
} }
} }


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 rawRows *core.Rows
var err error var err error
session.queryPreprocess(&sqlStr, args...)
if session.IsAutoCommit { if session.IsAutoCommit {
_, rawRows, err = session.innerQuery(sqlStr, args...) _, rawRows, err = session.innerQuery(sqlStr, args...)
} else { } else {
defer rawRows.Close() defer rawRows.Close()


if rawRows.Next() { 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 true, err
} }
return false, nil return false, nil
} }
cacheBean := cacher.GetBean(tableName, sid) cacheBean := cacher.GetBean(tableName, sid)
if cacheBean == nil { 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 cacheBean = bean
has, err = session.nocacheGet(cacheBean, sqlStr, args...)
has, err = session.nocacheGet(reflect.Struct, cacheBean, sqlStr, args...)
if err != nil || !has { if err != nil || !has {
return has, err return has, err
} }

+ 27
- 11
vendor/github.com/go-xorm/xorm/session_insert.go View File

} }
cleanupProcessorsClosures(&session.beforeClosures) 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...) res, err := session.exec(statement, args...)
if err != nil { if err != nil {
return 0, err return 0, err
// remove the expr columns // remove the expr columns
for i, colName := range colNames { for i, colName := range colNames {
if colName == v.colName { 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:]...)
} }
} }


exprColVals = append(exprColVals, v.expr) exprColVals = append(exprColVals, v.expr)
} }


colPlaces := strings.Repeat("?, ", len(colNames)-len(exprColumns))
colPlaces := strings.Repeat("?, ", len(colNames) - len(exprColumns))
if len(exprColVals) > 0 { if len(exprColVals) > 0 {
colPlaces = colPlaces + strings.Join(exprColVals, ", ") colPlaces = colPlaces + strings.Join(exprColVals, ", ")
} else { } else {
colPlaces = colPlaces[0 : len(colPlaces)-2]
colPlaces = colPlaces[0 : len(colPlaces) - 2]
} }


sqlStr := fmt.Sprintf("INSERT INTO %s (%v%v%v) VALUES (%v)", sqlStr := fmt.Sprintf("INSERT INTO %s (%v%v%v) VALUES (%v)",

+ 10
- 1
vendor/github.com/go-xorm/xorm/session_raw.go View File

return rows2maps(rows) 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) { func (session *Session) Query(sqlStr string, paramStr ...interface{}) (resultsSlice []map[string][]byte, err error) {
defer session.resetStatement() defer session.resetStatement()
if session.IsAutoClose { if session.IsAutoClose {
return session.query(sqlStr, paramStr...) 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 // for string
// ============================= // =============================

+ 4
- 1
vendor/github.com/go-xorm/xorm/session_schema.go View File



for _, bean := range beans { for _, bean := range beans {
v := rValue(bean) v := rValue(bean)
table := engine.mapType(v)
table, err := engine.mapType(v)
if err != nil {
return err
}
structTables = append(structTables, table) structTables = append(structTables, table)
var tbName = session.tbNameNoSchema(table) var tbName = session.tbNameNoSchema(table)



+ 1
- 1
vendor/github.com/go-xorm/xorm/session_sum.go View File

session.queryPreprocess(&sqlStr, args...) session.queryPreprocess(&sqlStr, args...)


var err error var err error
var res = make([]int64, 0, len(columnNames))
var res = make([]int64, len(columnNames), len(columnNames))
if session.IsAutoCommit { if session.IsAutoCommit {
err = session.DB().QueryRow(sqlStr, args...).ScanSlice(&res) err = session.DB().QueryRow(sqlStr, args...).ScanSlice(&res)
} else { } else {

+ 39
- 28
vendor/github.com/go-xorm/xorm/session_update.go View File

var condSQL string var condSQL string
cond := session.Statement.cond.And(autoCond) cond := session.Statement.cond.And(autoCond)


doIncVer := false
var doIncVer = (table != nil && table.Version != "" && session.Statement.checkVersion)
var verValue *reflect.Value var verValue *reflect.Value
if table != nil && table.Version != "" && session.Statement.checkVersion {
if doIncVer {
verValue, err = table.VersionColumn().ValueOf(bean) verValue, err = table.VersionColumn().ValueOf(bean)
if err != nil { if err != nil {
return 0, err return 0, err
} }


cond = cond.And(builder.Eq{session.Engine.Quote(table.Version): verValue.Interface()}) 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) 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...)...) res, err := session.exec(sqlStr, append(args, condArgs...)...)
if err != nil { if err != nil {
return 0, err return 0, err

+ 0
- 20
vendor/github.com/go-xorm/xorm/sqlite3_driver.go View File

// 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
}

+ 55
- 39
vendor/github.com/go-xorm/xorm/statement.go View File

Engine *Engine Engine *Engine
Start int Start int
LimitN int LimitN int
IdParam *core.PK
idParam *core.PK
OrderStr string OrderStr string
JoinStr string JoinStr string
joinArgs []interface{} joinArgs []interface{}
statement.columnMap = make(map[string]bool) statement.columnMap = make(map[string]bool)
statement.AltTableName = "" statement.AltTableName = ""
statement.tableName = "" statement.tableName = ""
statement.IdParam = nil
statement.idParam = nil
statement.RawSQL = "" statement.RawSQL = ""
statement.RawParams = make([]interface{}, 0) statement.RawParams = make([]interface{}, 0)
statement.UseCache = true statement.UseCache = true


// In generate "Where column IN (?) " statement // In generate "Where column IN (?) " statement
func (statement *Statement) In(column string, args ...interface{}) *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) statement.cond = statement.cond.And(in)
return statement return statement
} }


// NotIn generate "Where column NOT IN (?) " statement // NotIn generate "Where column NOT IN (?) " statement
func (statement *Statement) NotIn(column string, args ...interface{}) *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 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) statement.tableName = statement.Engine.tbName(v)
return nil
} }


// Table tempororily set table name, the parameter could be a string or a pointer of struct // Table tempororily set table name, the parameter could be a string or a pointer of struct
if t.Kind() == reflect.String { if t.Kind() == reflect.String {
statement.AltTableName = tableNameOrBean.(string) statement.AltTableName = tableNameOrBean.(string)
} else if t.Kind() == reflect.Struct { } 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) statement.AltTableName = statement.Engine.tbName(v)
} }
return statement return statement
if fieldValue == reflect.Zero(fieldType) { if fieldValue == reflect.Zero(fieldType) {
continue 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 continue
} }
} }
} else if col.SQLType.IsBlob() { } else if col.SQLType.IsBlob() {
var bytes []byte var bytes []byte
var err error var err error
if (fieldType.Kind() == reflect.Array || fieldType.Kind() == reflect.Slice) &&
if fieldType.Kind() == reflect.Slice &&
fieldType.Elem().Kind() == reflect.Uint8 { fieldType.Elem().Kind() == reflect.Uint8 {
if fieldValue.Len() > 0 { if fieldValue.Len() > 0 {
val = fieldValue.Bytes() val = fieldValue.Bytes()
} else { } else {
continue continue
} }
} else if fieldType.Kind() == reflect.Array &&
fieldType.Elem().Kind() == reflect.Uint8 {
val = fieldValue.Slice(0, 0).Interface()
} else { } else {
bytes, err = json.Marshal(fieldValue.Interface()) bytes, err = json.Marshal(fieldValue.Interface())
if err != nil { if err != nil {
} }
} }
} }
case reflect.Array, reflect.Slice, reflect.Map:
case reflect.Array:
continue
case reflect.Slice, reflect.Map:
if fieldValue == reflect.Zero(fieldType) { if fieldValue == reflect.Zero(fieldType) {
continue continue
} }
return statement.tableName 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 = ?" // ID generate "where id = ? " statement or for composite key "where key1 = ? and key2 = ?"
func (statement *Statement) ID(id interface{}) *Statement { func (statement *Statement) ID(id interface{}) *Statement {
idValue := reflect.ValueOf(id) idValue := reflect.ValueOf(id)
switch idType { switch idType {
case ptrPkType: case ptrPkType:
if pkPtr, ok := (id).(*core.PK); ok { if pkPtr, ok := (id).(*core.PK); ok {
statement.IdParam = pkPtr
statement.idParam = pkPtr
return statement return statement
} }
case pkType: case pkType:
if pk, ok := (id).(core.PK); ok { if pk, ok := (id).(core.PK); ok {
statement.IdParam = &pk
statement.idParam = &pk
return statement return statement
} }
} }


switch idType.Kind() { switch idType.Kind() {
case reflect.String: case reflect.String:
statement.IdParam = &core.PK{idValue.Convert(reflect.TypeOf("")).Interface()}
statement.idParam = &core.PK{idValue.Convert(reflect.TypeOf("")).Interface()}
return statement return statement
} }


statement.IdParam = &core.PK{id}
statement.idParam = &core.PK{id}
return statement return statement
} }


} }


func (statement *Statement) genGetSQL(bean interface{}) (string, []interface{}) { 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 var columnStr = statement.ColumnStr
if len(statement.selectStr) > 0 { if len(statement.selectStr) > 0 {
if len(columnStr) == 0 { if len(columnStr) == 0 {
if len(statement.GroupByStr) > 0 { if len(statement.GroupByStr) > 0 {
columnStr = statement.Engine.Quote(strings.Replace(statement.GroupByStr, ",", statement.Engine.Quote(","), -1)) 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...) return statement.genSelectSQL(columnStr, condSQL), append(statement.joinArgs, condArgs...)
} }


var sumStrs = make([]string, 0, len(columns)) var sumStrs = make([]string, 0, len(columns))
for _, colName := range 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) condSQL, condArgs, _ := statement.genConds(bean)


func (statement *Statement) genSelectSQL(columnStr, condSQL string) (a string) { func (statement *Statement) genSelectSQL(columnStr, condSQL string) (a string) {
var distinct string var distinct string
if statement.IsDistinct {
if statement.IsDistinct && !strings.HasPrefix(columnStr, "count") {
distinct = "DISTINCT " distinct = "DISTINCT "
} }


} }


func (statement *Statement) processIDParam() { func (statement *Statement) processIDParam() {
if statement.IdParam == nil {
if statement.idParam == nil {
return return
} }


for i, col := range statement.RefTable.PKColumns() { for i, col := range statement.RefTable.PKColumns() {
var colName = statement.colName(col, statement.TableName()) 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 { } else {
statement.cond = statement.cond.And(builder.Eq{colName: ""}) statement.cond = statement.cond.And(builder.Eq{colName: ""})
} }

+ 281
- 0
vendor/github.com/go-xorm/xorm/tag.go View File

// 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
}

+ 2
- 1
vendor/github.com/go-xorm/xorm/xorm.go View File



const ( const (
// Version show the xorm's version // Version show the xorm's version
Version string = "0.6.0.1022"
Version string = "0.6.2.0401"
) )


func regDrvsNDialects() bool { func regDrvsNDialects() bool {
mutex: &sync.RWMutex{}, mutex: &sync.RWMutex{},
TagIdentifier: "xorm", TagIdentifier: "xorm",
TZLocation: time.Local, TZLocation: time.Local,
tagHandlers: defaultTagHandlers,
} }


logger := NewSimpleLogger(os.Stdout) logger := NewSimpleLogger(os.Stdout)

+ 3
- 3
vendor/vendor.json View File

"revisionTime": "2016-08-11T02:11:45Z" "revisionTime": "2016-08-11T02:11:45Z"
}, },
{ {
"checksumSHA1": "COlm4o3G1rUSqr33iumtjY1qKD8=",
"checksumSHA1": "3FEBM0FYERf8jpaResApwcQpr40=",
"path": "github.com/go-xorm/xorm", "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=", "checksumSHA1": "1ft/4j5MFa7C9dPI9whL03HSUzk=",

Loading…
Cancel
Save