mirror of
				https://github.com/go-gitea/gitea.git
				synced 2025-10-26 12:27:06 +00:00 
			
		
		
		
	fix migrate failed and org dashboard failed on MSSQL database (#1448)
This commit is contained in:
		| @@ -670,13 +670,30 @@ func (env *accessibleReposEnv) Repos(page, pageSize int) ([]*Repository, error) | |||||||
| 		Find(&repos) | 		Find(&repos) | ||||||
| } | } | ||||||
|  |  | ||||||
| func (env *accessibleReposEnv) MirrorRepos() ([]*Repository, error) { | func (env *accessibleReposEnv) MirrorRepoIDs() ([]int64, error) { | ||||||
| 	repos := make([]*Repository, 0, 10) | 	repoIDs := make([]int64, 0, 10) | ||||||
| 	return repos, x. | 	return repoIDs, x. | ||||||
| 		Select("`repository`.*"). | 		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) | ||||||
| } | } | ||||||
|   | |||||||
							
								
								
									
										33
									
								
								vendor/github.com/go-xorm/xorm/README.md
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										33
									
								
								vendor/github.com/go-xorm/xorm/README.md
									
									
									
										generated
									
									
										vendored
									
									
								
							| @@ -46,12 +46,15 @@ Drivers for Go's sql package which currently support database/sql includes: | |||||||
|  |  | ||||||
| * MsSql: [github.com/denisenkom/go-mssqldb](https://github.com/denisenkom/go-mssqldb) | * MsSql: [github.com/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`  | ||||||
| @@ -79,12 +82,6 @@ methods can use `builder.Cond` as parameter | |||||||
|  |  | ||||||
| # 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 | ||||||
| @@ -119,19 +116,21 @@ type User struct { | |||||||
| 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) | ||||||
| @@ -153,6 +152,18 @@ has, err := engine.Get(&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 | ||||||
|   | |||||||
							
								
								
									
										29
									
								
								vendor/github.com/go-xorm/xorm/README_CN.md
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										29
									
								
								vendor/github.com/go-xorm/xorm/README_CN.md
									
									
									
										generated
									
									
										vendored
									
									
								
							| @@ -54,6 +54,11 @@ xorm是一个简单而强大的Go语言ORM库. 通过它可以使数据库操作 | |||||||
|  |  | ||||||
| ## 更新日志 | ## 更新日志 | ||||||
|  |  | ||||||
|  | * **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` 函数 | ||||||
| @@ -81,12 +86,6 @@ xorm是一个简单而强大的Go语言ORM库. 通过它可以使数据库操作 | |||||||
|  |  | ||||||
| ## 安装 | ## 安装 | ||||||
|  |  | ||||||
| 推荐使用 [gopm](https://github.com/gpmgo/gopm) 进行安装: |  | ||||||
|  |  | ||||||
| 	gopm get github.com/go-xorm/xorm |  | ||||||
|  |  | ||||||
| 或者您也可以使用go工具进行安装: |  | ||||||
|  |  | ||||||
| 	go get github.com/go-xorm/xorm | 	go get github.com/go-xorm/xorm | ||||||
|  |  | ||||||
| ## 文档 | ## 文档 | ||||||
| @@ -121,13 +120,15 @@ type User struct { | |||||||
| 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) | ||||||
| @@ -155,6 +156,18 @@ has, err := engine.Get(&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 = ? | ||||||
| ``` | ``` | ||||||
|  |  | ||||||
| * 查询多条记录,当然可以使用Join和extends来组合使用 | * 查询多条记录,当然可以使用Join和extends来组合使用 | ||||||
|   | |||||||
							
								
								
									
										1
									
								
								vendor/github.com/go-xorm/xorm/VERSION
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										1
									
								
								vendor/github.com/go-xorm/xorm/VERSION
									
									
									
										generated
									
									
										vendored
									
									
								
							| @@ -1 +0,0 @@ | |||||||
| xorm v0.6.0.1022 |  | ||||||
							
								
								
									
										37
									
								
								vendor/github.com/go-xorm/xorm/convert.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										37
									
								
								vendor/github.com/go-xorm/xorm/convert.go
									
									
									
										generated
									
									
										vendored
									
									
								
							| @@ -247,3 +247,40 @@ func convertAssign(dest, src interface{}) error { | |||||||
|  |  | ||||||
| 	return fmt.Errorf("unsupported Scan, storing driver.Value type %T into type %T", src, dest) | 	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) | ||||||
|  | } | ||||||
|   | |||||||
| @@ -5,6 +5,7 @@ | |||||||
| package xorm | package xorm | ||||||
| 
 | 
 | ||||||
| import ( | import ( | ||||||
|  | 	"errors" | ||||||
| 	"fmt" | 	"fmt" | ||||||
| 	"strconv" | 	"strconv" | ||||||
| 	"strings" | 	"strings" | ||||||
| @@ -215,9 +216,9 @@ func (db *mssql) SqlType(c *core.Column) string { | |||||||
| 	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: | ||||||
| @@ -467,9 +468,10 @@ WHERE IXS.TYPE_DESC='NONCLUSTERED' and OBJECT_NAME(IXS.OBJECT_ID) =? | |||||||
| 		} | 		} | ||||||
| 
 | 
 | ||||||
| 		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 | ||||||
| @@ -478,6 +480,7 @@ WHERE IXS.TYPE_DESC='NONCLUSTERED' and OBJECT_NAME(IXS.OBJECT_ID) =? | |||||||
| 			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) | ||||||
| @@ -526,3 +529,25 @@ func (db *mssql) ForUpdateSql(query string) string { | |||||||
| 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 | ||||||
|  | } | ||||||
| @@ -6,7 +6,9 @@ package xorm | |||||||
| 
 | 
 | ||||||
| import ( | import ( | ||||||
| 	"crypto/tls" | 	"crypto/tls" | ||||||
|  | 	"errors" | ||||||
| 	"fmt" | 	"fmt" | ||||||
|  | 	"regexp" | ||||||
| 	"strconv" | 	"strconv" | ||||||
| 	"strings" | 	"strings" | ||||||
| 	"time" | 	"time" | ||||||
| @@ -486,3 +488,93 @@ func (db *mysql) GetIndexes(tableName string) (map[string]*core.Index, error) { | |||||||
| 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¶mN=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 | ||||||
|  | } | ||||||
| @@ -5,7 +5,9 @@ | |||||||
| package xorm | package xorm | ||||||
| 
 | 
 | ||||||
| import ( | import ( | ||||||
|  | 	"errors" | ||||||
| 	"fmt" | 	"fmt" | ||||||
|  | 	"regexp" | ||||||
| 	"strconv" | 	"strconv" | ||||||
| 	"strings" | 	"strings" | ||||||
| 
 | 
 | ||||||
| @@ -822,6 +824,12 @@ func (db *oracle) GetIndexes(tableName string) (map[string]*core.Index, error) { | |||||||
| 
 | 
 | ||||||
| 		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 { | ||||||
| @@ -834,6 +842,7 @@ func (db *oracle) GetIndexes(tableName string) (map[string]*core.Index, error) { | |||||||
| 			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) | ||||||
| @@ -844,3 +853,54 @@ func (db *oracle) GetIndexes(tableName string) (map[string]*core.Index, error) { | |||||||
| 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¶mN=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 | ||||||
|  | } | ||||||
| @@ -5,7 +5,10 @@ | |||||||
| package xorm | package xorm | ||||||
| 
 | 
 | ||||||
| import ( | import ( | ||||||
|  | 	"errors" | ||||||
| 	"fmt" | 	"fmt" | ||||||
|  | 	"net/url" | ||||||
|  | 	"sort" | ||||||
| 	"strconv" | 	"strconv" | ||||||
| 	"strings" | 	"strings" | ||||||
| 
 | 
 | ||||||
| @@ -1075,9 +1078,10 @@ func (db *postgres) GetIndexes(tableName string) (map[string]*core.Index, error) | |||||||
| 		} | 		} | ||||||
| 		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 | ||||||
| 			} | 			} | ||||||
| @@ -1087,6 +1091,7 @@ func (db *postgres) GetIndexes(tableName string) (map[string]*core.Index, error) | |||||||
| 		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 | ||||||
| @@ -1095,3 +1100,107 @@ func (db *postgres) GetIndexes(tableName string) (map[string]*core.Index, error) | |||||||
| 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 | ||||||
|  | } | ||||||
| @@ -405,8 +405,10 @@ func (db *sqlite3) GetIndexes(tableName string) (map[string]*core.Index, error) | |||||||
| 		} | 		} | ||||||
| 
 | 
 | ||||||
| 		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 | ||||||
| 		} | 		} | ||||||
| @@ -425,6 +427,7 @@ func (db *sqlite3) GetIndexes(tableName string) (map[string]*core.Index, error) | |||||||
| 		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 | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| @@ -434,3 +437,10 @@ func (db *sqlite3) GetIndexes(tableName string) (map[string]*core.Index, error) | |||||||
| 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 | ||||||
|  | } | ||||||
							
								
								
									
										43
									
								
								vendor/github.com/go-xorm/xorm/doc.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										43
									
								
								vendor/github.com/go-xorm/xorm/doc.go
									
									
									
										generated
									
									
										vendored
									
									
								
							| @@ -24,7 +24,7 @@ Generally, one engine for an application is enough. You can set it as package va | |||||||
|  |  | ||||||
| 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 | ||||||
|  |  | ||||||
| @@ -36,7 +36,7 @@ Xorm also support raw sql execution: | |||||||
|  |  | ||||||
| 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 | ||||||
|  |  | ||||||
| @@ -58,10 +58,18 @@ There are 7 major ORM methods and many helpful methods to use to operate databas | |||||||
|  |  | ||||||
| 3. Query multiple records from database | 3. Query multiple records from database | ||||||
|  |  | ||||||
|     sliceOfStructs := new(Struct) |     var sliceOfStructs []Struct | ||||||
|     err := engine.Find(sliceOfStructs) |     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 | ||||||
|  |  | ||||||
| @@ -91,20 +99,31 @@ 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. | The above 8 methods could use with condition methods chainable. | ||||||
| Attention: the above 7 methods should be the last chainable method. | 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 | ||||||
| @@ -127,10 +146,10 @@ Attention: the above 7 methods should be the last chainable method. | |||||||
|     // 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 | ||||||
|  |  | ||||||
|   | |||||||
							
								
								
									
										309
									
								
								vendor/github.com/go-xorm/xorm/engine.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										309
									
								
								vendor/github.com/go-xorm/xorm/engine.go
									
									
									
										generated
									
									
										vendored
									
									
								
							| @@ -44,6 +44,8 @@ type Engine struct { | |||||||
| 	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 | ||||||
| @@ -215,10 +217,15 @@ func (engine *Engine) NoCascade() *Session { | |||||||
| } | } | ||||||
|  |  | ||||||
| // 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 | ||||||
| @@ -260,9 +267,9 @@ func (engine *Engine) Ping() error { | |||||||
| 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) | ||||||
| 		} | 		} | ||||||
| 	} | 	} | ||||||
| } | } | ||||||
| @@ -273,9 +280,9 @@ func (engine *Engine) logSQLQueryTime(sqlStr string, args []interface{}, executi | |||||||
| 		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 | ||||||
| 	} | 	} | ||||||
| @@ -774,13 +781,18 @@ func (engine *Engine) Having(conditions string) *Session { | |||||||
| 	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() { | ||||||
| @@ -790,12 +802,11 @@ func (engine *Engine) autoMapType(v reflect.Value) *core.Table { | |||||||
| 			} | 			} | ||||||
| 		} | 		} | ||||||
| 	} | 	} | ||||||
| 	return table | 	return table, nil | ||||||
| } | } | ||||||
|  |  | ||||||
| // GobRegister register one struct to gob for cache use | // 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 | ||||||
| } | } | ||||||
| @@ -806,10 +817,19 @@ type Table struct { | |||||||
| 	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) { | ||||||
| @@ -842,7 +862,7 @@ var ( | |||||||
| 	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 { | ||||||
| @@ -861,7 +881,6 @@ func (engine *Engine) mapType(v reflect.Value) *core.Table { | |||||||
| 	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++ { | ||||||
| @@ -881,186 +900,94 @@ func (engine *Engine) mapType(v reflect.Value) *core.Table { | |||||||
| 				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() { | 					if err := ExtendsTagHandler(&ctx); err != nil { | ||||||
| 					case reflect.Ptr: | 						return nil, err | ||||||
| 						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 |  | ||||||
| 					} | 					} | ||||||
|  | 					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 { | 					ctx.tagName = k | ||||||
| 					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 |  | ||||||
|  |  | ||||||
| 					autoStart := k[len("AUTOINCR")+1 : len(k)-1] | 					pStart := strings.Index(k, "(") | ||||||
| 					autoStartInt, err := strconv.Atoi(autoStart) | 					if pStart == 0 { | ||||||
| 					if err != nil { | 						return nil, errors.New("( could not be the first charactor") | ||||||
| 						engine.LogError(err) |  | ||||||
| 					} | 					} | ||||||
| 					col.AutoIncrStart = autoStartInt*/ | 					if pStart > -1 { | ||||||
| 					case k == "AUTOINCR": | 						if !strings.HasSuffix(k, ")") { | ||||||
| 						col.IsAutoIncrement = true | 							return nil, errors.New("cannot match ) charactor") | ||||||
| 						//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 |  | ||||||
| 						} |  | ||||||
| 					case k == "NOCACHE": |  | ||||||
| 						if !hasNoCacheTag { |  | ||||||
| 							hasNoCacheTag = true |  | ||||||
| 						} |  | ||||||
| 					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 { | 						ctx.tagName = k[:pStart] | ||||||
| 								preKey = k | 						ctx.params = strings.Split(k[pStart+1:len(k)-1], ",") | ||||||
| 								continue | 					} | ||||||
| 							} |  | ||||||
| 							col.SQLType = core.SQLType{Name: fs[0]} | 					if j > 0 { | ||||||
| 							if fs[0] == core.Enum && fs[1][0] == '\'' { //enum | 						ctx.preTag = strings.ToUpper(tags[j-1]) | ||||||
| 								options := strings.Split(fs[1][0:len(fs[1])-1], ",") | 					} | ||||||
| 								col.EnumOptions = make(map[string]int) | 					if j < len(tags)-1 { | ||||||
| 								for k, v := range options { | 						ctx.nextTag = strings.ToUpper(tags[j+1]) | ||||||
| 									v = strings.TrimSpace(v) | 					} else { | ||||||
| 									v = strings.Trim(v, "'") | 						ctx.nextTag = "" | ||||||
| 									col.EnumOptions[v] = k | 					} | ||||||
| 								} |  | ||||||
| 							} else if fs[0] == core.Set && fs[1][0] == '\'' { //set | 					if h, ok := engine.tagHandlers[ctx.tagName]; ok { | ||||||
| 								options := strings.Split(fs[1][0:len(fs[1])-1], ",") | 						if err := h(&ctx); err != nil { | ||||||
| 								col.SetOptions = make(map[string]int) | 							return nil, err | ||||||
| 								for k, v := range options { | 						} | ||||||
| 									v = strings.TrimSpace(v) | 					} else { | ||||||
| 									v = strings.Trim(v, "'") | 						if strings.HasPrefix(key, "'") && strings.HasSuffix(key, "'") { | ||||||
| 									col.SetOptions[v] = k | 							col.Name = key[1 : len(key)-1] | ||||||
| 								} | 						} else { | ||||||
| 							} else { | 							col.Name = key | ||||||
| 								fs2 := strings.Split(fs[1][0:len(fs[1])-1], ",") | 						} | ||||||
| 								if len(fs2) == 2 { | 					} | ||||||
| 									col.Length, err = strconv.Atoi(fs2[0]) |  | ||||||
| 									if err != nil { | 					if ctx.hasCacheTag { | ||||||
| 										engine.logger.Error(err) | 						hasCacheTag = true | ||||||
| 									} | 					} | ||||||
| 									col.Length2, err = strconv.Atoi(fs2[1]) | 					if ctx.hasNoCacheTag { | ||||||
| 									if err != nil { | 						hasNoCacheTag = true | ||||||
| 										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 _, ok := core.SqlTypes[k]; ok { |  | ||||||
| 								col.SQLType = core.SQLType{Name: k} |  | ||||||
| 							} else if key != col.Default { |  | ||||||
| 								col.Name = key |  | ||||||
| 							} |  | ||||||
| 						} |  | ||||||
| 						engine.dialect.SqlType(col) |  | ||||||
| 					} | 					} | ||||||
| 					preKey = k |  | ||||||
| 				} | 				} | ||||||
|  |  | ||||||
| 				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 { | 				if ctx.isUnique { | ||||||
| 					indexNames[col.Name] = core.UniqueType | 					ctx.indexNames[col.Name] = core.UniqueType | ||||||
| 				} else if isIndex { | 				} else if ctx.isIndex { | ||||||
| 					indexNames[col.Name] = core.IndexType | 					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) | ||||||
| 				} | 				} | ||||||
| 			} | 			} | ||||||
| @@ -1114,7 +1041,7 @@ func (engine *Engine) mapType(v reflect.Value) *core.Table { | |||||||
| 		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 | ||||||
| @@ -1152,8 +1079,21 @@ func (engine *Engine) IdOfV(rv reflect.Value) core.PK { | |||||||
|  |  | ||||||
| // 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) | ||||||
| @@ -1166,7 +1106,7 @@ func (engine *Engine) IDOfV(rv reflect.Value) core.PK { | |||||||
| 			pk[i] = pkField.Uint() | 			pk[i] = pkField.Uint() | ||||||
| 		} | 		} | ||||||
| 	} | 	} | ||||||
| 	return core.PK(pk) | 	return core.PK(pk), nil | ||||||
| } | } | ||||||
|  |  | ||||||
| // CreateIndexes create indexes | // CreateIndexes create indexes | ||||||
| @@ -1187,13 +1127,6 @@ func (engine *Engine) getCacher2(table *core.Table) core.Cacher { | |||||||
| 	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) | ||||||
| @@ -1202,7 +1135,10 @@ func (engine *Engine) ClearCacheBean(bean interface{}, id string) error { | |||||||
| 		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 | ||||||
| @@ -1223,7 +1159,11 @@ func (engine *Engine) ClearCache(beans ...interface{}) error { | |||||||
| 			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 | ||||||
| @@ -1243,7 +1183,11 @@ func (engine *Engine) Sync(beans ...interface{}) error { | |||||||
| 	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() | ||||||
| @@ -1426,6 +1370,13 @@ func (engine *Engine) Query(sql string, paramStr ...interface{}) (resultsSlice [ | |||||||
| 	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() | ||||||
|   | |||||||
							
								
								
									
										42
									
								
								vendor/github.com/go-xorm/xorm/goracle_driver.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										42
									
								
								vendor/github.com/go-xorm/xorm/goracle_driver.go
									
									
									
										generated
									
									
										vendored
									
									
								
							| @@ -1,42 +0,0 @@ | |||||||
| // Copyright 2015 The Xorm Authors. All rights reserved. |  | ||||||
| // Use of this source code is governed by a BSD-style |  | ||||||
| // license that can be found in the LICENSE file. |  | ||||||
|  |  | ||||||
| package xorm |  | ||||||
|  |  | ||||||
| import ( |  | ||||||
| 	"errors" |  | ||||||
| 	"regexp" |  | ||||||
|  |  | ||||||
| 	"github.com/go-xorm/core" |  | ||||||
| ) |  | ||||||
|  |  | ||||||
| // func init() { |  | ||||||
| // 	core.RegisterDriver("goracle", &goracleDriver{}) |  | ||||||
| // } |  | ||||||
|  |  | ||||||
| type goracleDriver struct { |  | ||||||
| } |  | ||||||
|  |  | ||||||
| func (cfg *goracleDriver) Parse(driverName, dataSourceName string) (*core.Uri, error) { |  | ||||||
| 	db := &core.Uri{DbType: core.ORACLE} |  | ||||||
| 	dsnPattern := regexp.MustCompile( |  | ||||||
| 		`^(?:(?P<user>.*?)(?::(?P<passwd>.*))?@)?` + // [user[:password]@] |  | ||||||
| 			`(?:(?P<net>[^\(]*)(?:\((?P<addr>[^\)]*)\))?)?` + // [net[(addr)]] |  | ||||||
| 			`\/(?P<dbname>.*?)` + // /dbname |  | ||||||
| 			`(?:\?(?P<params>[^\?]*))?$`) // [?param1=value1¶mN=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
									
								
								vendor/github.com/go-xorm/xorm/helpers.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										14
									
								
								vendor/github.com/go-xorm/xorm/helpers.go
									
									
									
										generated
									
									
										vendored
									
									
								
							| @@ -180,6 +180,20 @@ func isStructZero(v reflect.Value) bool { | |||||||
| 	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() { | ||||||
|   | |||||||
							
								
								
									
										65
									
								
								vendor/github.com/go-xorm/xorm/mymysql_driver.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										65
									
								
								vendor/github.com/go-xorm/xorm/mymysql_driver.go
									
									
									
										generated
									
									
										vendored
									
									
								
							| @@ -1,65 +0,0 @@ | |||||||
| // Copyright 2015 The Xorm Authors. All rights reserved. |  | ||||||
| // Use of this source code is governed by a BSD-style |  | ||||||
| // license that can be found in the LICENSE file. |  | ||||||
|  |  | ||||||
| package xorm |  | ||||||
|  |  | ||||||
| import ( |  | ||||||
| 	"errors" |  | ||||||
| 	"strings" |  | ||||||
| 	"time" |  | ||||||
|  |  | ||||||
| 	"github.com/go-xorm/core" |  | ||||||
| ) |  | ||||||
|  |  | ||||||
| type mymysqlDriver struct { |  | ||||||
| } |  | ||||||
|  |  | ||||||
| func (p *mymysqlDriver) Parse(driverName, dataSourceName string) (*core.Uri, error) { |  | ||||||
| 	db := &core.Uri{DbType: core.MYSQL} |  | ||||||
|  |  | ||||||
| 	pd := strings.SplitN(dataSourceName, "*", 2) |  | ||||||
| 	if len(pd) == 2 { |  | ||||||
| 		// Parse protocol part of URI |  | ||||||
| 		p := strings.SplitN(pd[0], ":", 2) |  | ||||||
| 		if len(p) != 2 { |  | ||||||
| 			return nil, errors.New("Wrong protocol part of URI") |  | ||||||
| 		} |  | ||||||
| 		db.Proto = p[0] |  | ||||||
| 		options := strings.Split(p[1], ",") |  | ||||||
| 		db.Raddr = options[0] |  | ||||||
| 		for _, o := range options[1:] { |  | ||||||
| 			kv := strings.SplitN(o, "=", 2) |  | ||||||
| 			var k, v string |  | ||||||
| 			if len(kv) == 2 { |  | ||||||
| 				k, v = kv[0], kv[1] |  | ||||||
| 			} else { |  | ||||||
| 				k, v = o, "true" |  | ||||||
| 			} |  | ||||||
| 			switch k { |  | ||||||
| 			case "laddr": |  | ||||||
| 				db.Laddr = v |  | ||||||
| 			case "timeout": |  | ||||||
| 				to, err := time.ParseDuration(v) |  | ||||||
| 				if err != nil { |  | ||||||
| 					return nil, err |  | ||||||
| 				} |  | ||||||
| 				db.Timeout = to |  | ||||||
| 			default: |  | ||||||
| 				return nil, errors.New("Unknown option: " + k) |  | ||||||
| 			} |  | ||||||
| 		} |  | ||||||
| 		// Remove protocol part |  | ||||||
| 		pd = pd[1:] |  | ||||||
| 	} |  | ||||||
| 	// Parse database part of URI |  | ||||||
| 	dup := strings.SplitN(pd[0], "/", 3) |  | ||||||
| 	if len(dup) != 3 { |  | ||||||
| 		return nil, errors.New("Wrong database part of URI") |  | ||||||
| 	} |  | ||||||
| 	db.DbName = dup[0] |  | ||||||
| 	db.User = dup[1] |  | ||||||
| 	db.Passwd = dup[2] |  | ||||||
|  |  | ||||||
| 	return db, nil |  | ||||||
| } |  | ||||||
							
								
								
									
										50
									
								
								vendor/github.com/go-xorm/xorm/mysql_driver.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										50
									
								
								vendor/github.com/go-xorm/xorm/mysql_driver.go
									
									
									
										generated
									
									
										vendored
									
									
								
							| @@ -1,50 +0,0 @@ | |||||||
| // Copyright 2015 The Xorm Authors. All rights reserved. |  | ||||||
| // Use of this source code is governed by a BSD-style |  | ||||||
| // license that can be found in the LICENSE file. |  | ||||||
|  |  | ||||||
| package xorm |  | ||||||
|  |  | ||||||
| import ( |  | ||||||
| 	"regexp" |  | ||||||
| 	"strings" |  | ||||||
|  |  | ||||||
| 	"github.com/go-xorm/core" |  | ||||||
| ) |  | ||||||
|  |  | ||||||
| type mysqlDriver struct { |  | ||||||
| } |  | ||||||
|  |  | ||||||
| func (p *mysqlDriver) Parse(driverName, dataSourceName string) (*core.Uri, error) { |  | ||||||
| 	dsnPattern := regexp.MustCompile( |  | ||||||
| 		`^(?:(?P<user>.*?)(?::(?P<passwd>.*))?@)?` + // [user[:password]@] |  | ||||||
| 			`(?:(?P<net>[^\(]*)(?:\((?P<addr>[^\)]*)\))?)?` + // [net[(addr)]] |  | ||||||
| 			`\/(?P<dbname>.*?)` + // /dbname |  | ||||||
| 			`(?:\?(?P<params>[^\?]*))?$`) // [?param1=value1¶mN=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 |  | ||||||
| } |  | ||||||
							
								
								
									
										37
									
								
								vendor/github.com/go-xorm/xorm/oci8_driver.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										37
									
								
								vendor/github.com/go-xorm/xorm/oci8_driver.go
									
									
									
										generated
									
									
										vendored
									
									
								
							| @@ -1,37 +0,0 @@ | |||||||
| // Copyright 2015 The Xorm Authors. All rights reserved. |  | ||||||
| // Use of this source code is governed by a BSD-style |  | ||||||
| // license that can be found in the LICENSE file. |  | ||||||
|  |  | ||||||
| package xorm |  | ||||||
|  |  | ||||||
| import ( |  | ||||||
| 	"errors" |  | ||||||
| 	"regexp" |  | ||||||
|  |  | ||||||
| 	"github.com/go-xorm/core" |  | ||||||
| ) |  | ||||||
|  |  | ||||||
| type oci8Driver struct { |  | ||||||
| } |  | ||||||
|  |  | ||||||
| //dataSourceName=user/password@ipv4:port/dbname |  | ||||||
| //dataSourceName=user/password@[ipv6]:port/dbname |  | ||||||
| func (p *oci8Driver) Parse(driverName, dataSourceName string) (*core.Uri, error) { |  | ||||||
| 	db := &core.Uri{DbType: core.ORACLE} |  | ||||||
| 	dsnPattern := regexp.MustCompile( |  | ||||||
| 		`^(?P<user>.*)\/(?P<password>.*)@` + // user:password@ |  | ||||||
| 			`(?P<net>.*)` + // ip:port |  | ||||||
| 			`\/(?P<dbname>.*)`) // dbname |  | ||||||
| 	matches := dsnPattern.FindStringSubmatch(dataSourceName) |  | ||||||
| 	names := dsnPattern.SubexpNames() |  | ||||||
| 	for i, match := range matches { |  | ||||||
| 		switch names[i] { |  | ||||||
| 		case "dbname": |  | ||||||
| 			db.DbName = match |  | ||||||
| 		} |  | ||||||
| 	} |  | ||||||
| 	if db.DbName == "" { |  | ||||||
| 		return nil, errors.New("dbname is empty") |  | ||||||
| 	} |  | ||||||
| 	return db, nil |  | ||||||
| } |  | ||||||
							
								
								
									
										34
									
								
								vendor/github.com/go-xorm/xorm/odbc_driver.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										34
									
								
								vendor/github.com/go-xorm/xorm/odbc_driver.go
									
									
									
										generated
									
									
										vendored
									
									
								
							| @@ -1,34 +0,0 @@ | |||||||
| // Copyright 2015 The Xorm Authors. All rights reserved. |  | ||||||
| // Use of this source code is governed by a BSD-style |  | ||||||
| // license that can be found in the LICENSE file. |  | ||||||
|  |  | ||||||
| package xorm |  | ||||||
|  |  | ||||||
| import ( |  | ||||||
| 	"errors" |  | ||||||
| 	"strings" |  | ||||||
|  |  | ||||||
| 	"github.com/go-xorm/core" |  | ||||||
| ) |  | ||||||
|  |  | ||||||
| type odbcDriver struct { |  | ||||||
| } |  | ||||||
|  |  | ||||||
| func (p *odbcDriver) Parse(driverName, dataSourceName string) (*core.Uri, error) { |  | ||||||
| 	kv := strings.Split(dataSourceName, ";") |  | ||||||
| 	var dbName string |  | ||||||
|  |  | ||||||
| 	for _, c := range kv { |  | ||||||
| 		vv := strings.Split(strings.TrimSpace(c), "=") |  | ||||||
| 		if len(vv) == 2 { |  | ||||||
| 			switch strings.ToLower(vv[0]) { |  | ||||||
| 			case "database": |  | ||||||
| 				dbName = vv[1] |  | ||||||
| 			} |  | ||||||
| 		} |  | ||||||
| 	} |  | ||||||
| 	if dbName == "" { |  | ||||||
| 		return nil, errors.New("no db name provided") |  | ||||||
| 	} |  | ||||||
| 	return &core.Uri{DbName: dbName, DbType: core.MSSQL}, nil |  | ||||||
| } |  | ||||||
							
								
								
									
										119
									
								
								vendor/github.com/go-xorm/xorm/pq_driver.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										119
									
								
								vendor/github.com/go-xorm/xorm/pq_driver.go
									
									
									
										generated
									
									
										vendored
									
									
								
							| @@ -1,119 +0,0 @@ | |||||||
| // Copyright 2015 The Xorm Authors. All rights reserved. |  | ||||||
| // Use of this source code is governed by a BSD-style |  | ||||||
| // license that can be found in the LICENSE file. |  | ||||||
|  |  | ||||||
| package xorm |  | ||||||
|  |  | ||||||
| import ( |  | ||||||
| 	"errors" |  | ||||||
| 	"fmt" |  | ||||||
| 	"net/url" |  | ||||||
| 	"sort" |  | ||||||
| 	"strings" |  | ||||||
|  |  | ||||||
| 	"github.com/go-xorm/core" |  | ||||||
| ) |  | ||||||
|  |  | ||||||
| type pqDriver struct { |  | ||||||
| } |  | ||||||
|  |  | ||||||
| type values map[string]string |  | ||||||
|  |  | ||||||
| func (vs values) Set(k, v string) { |  | ||||||
| 	vs[k] = v |  | ||||||
| } |  | ||||||
|  |  | ||||||
| func (vs values) Get(k string) (v string) { |  | ||||||
| 	return vs[k] |  | ||||||
| } |  | ||||||
|  |  | ||||||
| func errorf(s string, args ...interface{}) { |  | ||||||
| 	panic(fmt.Errorf("pq: %s", fmt.Sprintf(s, args...))) |  | ||||||
| } |  | ||||||
|  |  | ||||||
| func parseURL(connstr string) (string, error) { |  | ||||||
| 	u, err := url.Parse(connstr) |  | ||||||
| 	if err != nil { |  | ||||||
| 		return "", err |  | ||||||
| 	} |  | ||||||
|  |  | ||||||
| 	if u.Scheme != "postgresql" && u.Scheme != "postgres" { |  | ||||||
| 		return "", fmt.Errorf("invalid connection protocol: %s", u.Scheme) |  | ||||||
| 	} |  | ||||||
|  |  | ||||||
| 	var kvs []string |  | ||||||
| 	escaper := strings.NewReplacer(` `, `\ `, `'`, `\'`, `\`, `\\`) |  | ||||||
| 	accrue := func(k, v string) { |  | ||||||
| 		if v != "" { |  | ||||||
| 			kvs = append(kvs, k+"="+escaper.Replace(v)) |  | ||||||
| 		} |  | ||||||
| 	} |  | ||||||
|  |  | ||||||
| 	if u.User != nil { |  | ||||||
| 		v := u.User.Username() |  | ||||||
| 		accrue("user", v) |  | ||||||
|  |  | ||||||
| 		v, _ = u.User.Password() |  | ||||||
| 		accrue("password", v) |  | ||||||
| 	} |  | ||||||
|  |  | ||||||
| 	i := strings.Index(u.Host, ":") |  | ||||||
| 	if i < 0 { |  | ||||||
| 		accrue("host", u.Host) |  | ||||||
| 	} else { |  | ||||||
| 		accrue("host", u.Host[:i]) |  | ||||||
| 		accrue("port", u.Host[i+1:]) |  | ||||||
| 	} |  | ||||||
|  |  | ||||||
| 	if u.Path != "" { |  | ||||||
| 		accrue("dbname", u.Path[1:]) |  | ||||||
| 	} |  | ||||||
|  |  | ||||||
| 	q := u.Query() |  | ||||||
| 	for k := range q { |  | ||||||
| 		accrue(k, q.Get(k)) |  | ||||||
| 	} |  | ||||||
|  |  | ||||||
| 	sort.Strings(kvs) // Makes testing easier (not a performance concern) |  | ||||||
| 	return strings.Join(kvs, " "), nil |  | ||||||
| } |  | ||||||
|  |  | ||||||
| func parseOpts(name string, o values) { |  | ||||||
| 	if len(name) == 0 { |  | ||||||
| 		return |  | ||||||
| 	} |  | ||||||
|  |  | ||||||
| 	name = strings.TrimSpace(name) |  | ||||||
|  |  | ||||||
| 	ps := strings.Split(name, " ") |  | ||||||
| 	for _, p := range ps { |  | ||||||
| 		kv := strings.Split(p, "=") |  | ||||||
| 		if len(kv) < 2 { |  | ||||||
| 			errorf("invalid option: %q", p) |  | ||||||
| 		} |  | ||||||
| 		o.Set(kv[0], kv[1]) |  | ||||||
| 	} |  | ||||||
| } |  | ||||||
|  |  | ||||||
| func (p *pqDriver) Parse(driverName, dataSourceName string) (*core.Uri, error) { |  | ||||||
| 	db := &core.Uri{DbType: core.POSTGRES} |  | ||||||
| 	o := make(values) |  | ||||||
| 	var err error |  | ||||||
| 	if strings.HasPrefix(dataSourceName, "postgresql://") || strings.HasPrefix(dataSourceName, "postgres://") { |  | ||||||
| 		dataSourceName, err = parseURL(dataSourceName) |  | ||||||
| 		if err != nil { |  | ||||||
| 			return nil, err |  | ||||||
| 		} |  | ||||||
| 	} |  | ||||||
| 	parseOpts(dataSourceName, o) |  | ||||||
|  |  | ||||||
| 	db.DbName = o.Get("dbname") |  | ||||||
| 	if db.DbName == "" { |  | ||||||
| 		return nil, errors.New("dbname is empty") |  | ||||||
| 	} |  | ||||||
| 	/*db.Schema = o.Get("schema") |  | ||||||
| 	if len(db.Schema) == 0 { |  | ||||||
| 		db.Schema = "public" |  | ||||||
| 	}*/ |  | ||||||
| 	return db, nil |  | ||||||
| } |  | ||||||
							
								
								
									
										19
									
								
								vendor/github.com/go-xorm/xorm/rows.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										19
									
								
								vendor/github.com/go-xorm/xorm/rows.go
									
									
									
										generated
									
									
										vendored
									
									
								
							| @@ -16,13 +16,12 @@ import ( | |||||||
| type Rows struct { | type Rows struct { | ||||||
| 	NoTypeCheck bool | 	NoTypeCheck bool | ||||||
|  |  | ||||||
| 	session     *Session | 	session   *Session | ||||||
| 	stmt        *core.Stmt | 	stmt      *core.Stmt | ||||||
| 	rows        *core.Rows | 	rows      *core.Rows | ||||||
| 	fields      []string | 	fields    []string | ||||||
| 	fieldsCount int | 	beanType  reflect.Type | ||||||
| 	beanType    reflect.Type | 	lastError error | ||||||
| 	lastError   error |  | ||||||
| } | } | ||||||
|  |  | ||||||
| func newRows(session *Session, bean interface{}) (*Rows, error) { | func newRows(session *Session, bean interface{}) (*Rows, error) { | ||||||
| @@ -82,7 +81,6 @@ 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 | ||||||
| } | } | ||||||
| @@ -114,7 +112,10 @@ func (rows *Rows) Scan(bean interface{}) error { | |||||||
| 		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 | ||||||
| } | } | ||||||
|  |  | ||||||
|   | |||||||
							
								
								
									
										954
									
								
								vendor/github.com/go-xorm/xorm/session.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										954
									
								
								vendor/github.com/go-xorm/xorm/session.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							
							
								
								
									
										84
									
								
								vendor/github.com/go-xorm/xorm/session_cols.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										84
									
								
								vendor/github.com/go-xorm/xorm/session_cols.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,84 @@ | |||||||
|  | // Copyright 2017 The Xorm Authors. All rights reserved. | ||||||
|  | // Use of this source code is governed by a BSD-style | ||||||
|  | // license that can be found in the LICENSE file. | ||||||
|  |  | ||||||
|  | package xorm | ||||||
|  |  | ||||||
|  | // Incr provides a query string like "count = count + 1" | ||||||
|  | func (session *Session) Incr(column string, arg ...interface{}) *Session { | ||||||
|  | 	session.Statement.Incr(column, arg...) | ||||||
|  | 	return session | ||||||
|  | } | ||||||
|  |  | ||||||
|  | // Decr provides a query string like "count = count - 1" | ||||||
|  | func (session *Session) Decr(column string, arg ...interface{}) *Session { | ||||||
|  | 	session.Statement.Decr(column, arg...) | ||||||
|  | 	return session | ||||||
|  | } | ||||||
|  |  | ||||||
|  | // SetExpr provides a query string like "column = {expression}" | ||||||
|  | func (session *Session) SetExpr(column string, expression string) *Session { | ||||||
|  | 	session.Statement.SetExpr(column, expression) | ||||||
|  | 	return session | ||||||
|  | } | ||||||
|  |  | ||||||
|  | // Select provides some columns to special | ||||||
|  | func (session *Session) Select(str string) *Session { | ||||||
|  | 	session.Statement.Select(str) | ||||||
|  | 	return session | ||||||
|  | } | ||||||
|  |  | ||||||
|  | // Cols provides some columns to special | ||||||
|  | func (session *Session) Cols(columns ...string) *Session { | ||||||
|  | 	session.Statement.Cols(columns...) | ||||||
|  | 	return session | ||||||
|  | } | ||||||
|  |  | ||||||
|  | // AllCols ask all columns | ||||||
|  | func (session *Session) AllCols() *Session { | ||||||
|  | 	session.Statement.AllCols() | ||||||
|  | 	return session | ||||||
|  | } | ||||||
|  |  | ||||||
|  | // MustCols specify some columns must use even if they are empty | ||||||
|  | func (session *Session) MustCols(columns ...string) *Session { | ||||||
|  | 	session.Statement.MustCols(columns...) | ||||||
|  | 	return session | ||||||
|  | } | ||||||
|  |  | ||||||
|  | // UseBool automatically retrieve condition according struct, but | ||||||
|  | // if struct has bool field, it will ignore them. So use UseBool | ||||||
|  | // to tell system to do not ignore them. | ||||||
|  | // If no parameters, it will use all the bool field of struct, or | ||||||
|  | // it will use parameters's columns | ||||||
|  | func (session *Session) UseBool(columns ...string) *Session { | ||||||
|  | 	session.Statement.UseBool(columns...) | ||||||
|  | 	return session | ||||||
|  | } | ||||||
|  |  | ||||||
|  | // Distinct use for distinct columns. Caution: when you are using cache, | ||||||
|  | // distinct will not be cached because cache system need id, | ||||||
|  | // but distinct will not provide id | ||||||
|  | func (session *Session) Distinct(columns ...string) *Session { | ||||||
|  | 	session.Statement.Distinct(columns...) | ||||||
|  | 	return session | ||||||
|  | } | ||||||
|  |  | ||||||
|  | // Omit Only not use the parameters as select or update columns | ||||||
|  | func (session *Session) Omit(columns ...string) *Session { | ||||||
|  | 	session.Statement.Omit(columns...) | ||||||
|  | 	return session | ||||||
|  | } | ||||||
|  |  | ||||||
|  | // Nullable Set null when column is zero-value and nullable for update | ||||||
|  | func (session *Session) Nullable(columns ...string) *Session { | ||||||
|  | 	session.Statement.Nullable(columns...) | ||||||
|  | 	return session | ||||||
|  | } | ||||||
|  |  | ||||||
|  | // NoAutoTime means do not automatically give created field and updated field | ||||||
|  | // the current time on the current session temporarily | ||||||
|  | func (session *Session) NoAutoTime() *Session { | ||||||
|  | 	session.Statement.UseAutoTime = false | ||||||
|  | 	return session | ||||||
|  | } | ||||||
							
								
								
									
										70
									
								
								vendor/github.com/go-xorm/xorm/session_cond.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										70
									
								
								vendor/github.com/go-xorm/xorm/session_cond.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,70 @@ | |||||||
|  | // Copyright 2017 The Xorm Authors. All rights reserved. | ||||||
|  | // Use of this source code is governed by a BSD-style | ||||||
|  | // license that can be found in the LICENSE file. | ||||||
|  |  | ||||||
|  | package xorm | ||||||
|  |  | ||||||
|  | import "github.com/go-xorm/builder" | ||||||
|  |  | ||||||
|  | // Sql provides raw sql input parameter. When you have a complex SQL statement | ||||||
|  | // and cannot use Where, Id, In and etc. Methods to describe, you can use SQL. | ||||||
|  | // | ||||||
|  | // Deprecated: use SQL instead. | ||||||
|  | func (session *Session) Sql(query string, args ...interface{}) *Session { | ||||||
|  | 	return session.SQL(query, args...) | ||||||
|  | } | ||||||
|  |  | ||||||
|  | // SQL provides raw sql input parameter. When you have a complex SQL statement | ||||||
|  | // and cannot use Where, Id, In and etc. Methods to describe, you can use SQL. | ||||||
|  | func (session *Session) SQL(query interface{}, args ...interface{}) *Session { | ||||||
|  | 	session.Statement.SQL(query, args...) | ||||||
|  | 	return session | ||||||
|  | } | ||||||
|  |  | ||||||
|  | // Where provides custom query condition. | ||||||
|  | func (session *Session) Where(query interface{}, args ...interface{}) *Session { | ||||||
|  | 	session.Statement.Where(query, args...) | ||||||
|  | 	return session | ||||||
|  | } | ||||||
|  |  | ||||||
|  | // And provides custom query condition. | ||||||
|  | func (session *Session) And(query interface{}, args ...interface{}) *Session { | ||||||
|  | 	session.Statement.And(query, args...) | ||||||
|  | 	return session | ||||||
|  | } | ||||||
|  |  | ||||||
|  | // Or provides custom query condition. | ||||||
|  | func (session *Session) Or(query interface{}, args ...interface{}) *Session { | ||||||
|  | 	session.Statement.Or(query, args...) | ||||||
|  | 	return session | ||||||
|  | } | ||||||
|  |  | ||||||
|  | // Id provides converting id as a query condition | ||||||
|  | // | ||||||
|  | // Deprecated: use ID instead | ||||||
|  | func (session *Session) Id(id interface{}) *Session { | ||||||
|  | 	return session.ID(id) | ||||||
|  | } | ||||||
|  |  | ||||||
|  | // ID provides converting id as a query condition | ||||||
|  | func (session *Session) ID(id interface{}) *Session { | ||||||
|  | 	session.Statement.ID(id) | ||||||
|  | 	return session | ||||||
|  | } | ||||||
|  |  | ||||||
|  | // In provides a query string like "id in (1, 2, 3)" | ||||||
|  | func (session *Session) In(column string, args ...interface{}) *Session { | ||||||
|  | 	session.Statement.In(column, args...) | ||||||
|  | 	return session | ||||||
|  | } | ||||||
|  |  | ||||||
|  | // NotIn provides a query string like "id in (1, 2, 3)" | ||||||
|  | func (session *Session) NotIn(column string, args ...interface{}) *Session { | ||||||
|  | 	session.Statement.NotIn(column, args...) | ||||||
|  | 	return session | ||||||
|  | } | ||||||
|  |  | ||||||
|  | // Conds returns session query conditions | ||||||
|  | func (session *Session) Conds() builder.Cond { | ||||||
|  | 	return session.Statement.cond | ||||||
|  | } | ||||||
							
								
								
									
										673
									
								
								vendor/github.com/go-xorm/xorm/session_convert.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										673
									
								
								vendor/github.com/go-xorm/xorm/session_convert.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,673 @@ | |||||||
|  | // Copyright 2017 The Xorm Authors. All rights reserved. | ||||||
|  | // Use of this source code is governed by a BSD-style | ||||||
|  | // license that can be found in the LICENSE file. | ||||||
|  |  | ||||||
|  | package xorm | ||||||
|  |  | ||||||
|  | import ( | ||||||
|  | 	"database/sql" | ||||||
|  | 	"database/sql/driver" | ||||||
|  | 	"encoding/json" | ||||||
|  | 	"errors" | ||||||
|  | 	"fmt" | ||||||
|  | 	"reflect" | ||||||
|  | 	"strconv" | ||||||
|  | 	"strings" | ||||||
|  | 	"time" | ||||||
|  |  | ||||||
|  | 	"github.com/go-xorm/core" | ||||||
|  | ) | ||||||
|  |  | ||||||
|  | func (session *Session) str2Time(col *core.Column, data string) (outTime time.Time, outErr error) { | ||||||
|  | 	sdata := strings.TrimSpace(data) | ||||||
|  | 	var x time.Time | ||||||
|  | 	var err error | ||||||
|  |  | ||||||
|  | 	if sdata == "0000-00-00 00:00:00" || | ||||||
|  | 		sdata == "0001-01-01 00:00:00" { | ||||||
|  | 	} else if !strings.ContainsAny(sdata, "- :") { // !nashtsai! has only found that mymysql driver is using this for time type column | ||||||
|  | 		// time stamp | ||||||
|  | 		sd, err := strconv.ParseInt(sdata, 10, 64) | ||||||
|  | 		if err == nil { | ||||||
|  | 			x = time.Unix(sd, 0) | ||||||
|  | 			// !nashtsai! HACK mymysql driver is causing Local location being change to CHAT and cause wrong time conversion | ||||||
|  | 			if col.TimeZone == nil { | ||||||
|  | 				x = x.In(session.Engine.TZLocation) | ||||||
|  | 			} else { | ||||||
|  | 				x = x.In(col.TimeZone) | ||||||
|  | 			} | ||||||
|  | 			session.Engine.logger.Debugf("time(0) key[%v]: %+v | sdata: [%v]\n", col.FieldName, x, sdata) | ||||||
|  | 		} else { | ||||||
|  | 			session.Engine.logger.Debugf("time(0) err key[%v]: %+v | sdata: [%v]\n", col.FieldName, x, sdata) | ||||||
|  | 		} | ||||||
|  | 	} else if len(sdata) > 19 && strings.Contains(sdata, "-") { | ||||||
|  | 		x, err = time.ParseInLocation(time.RFC3339Nano, sdata, session.Engine.TZLocation) | ||||||
|  | 		session.Engine.logger.Debugf("time(1) key[%v]: %+v | sdata: [%v]\n", col.FieldName, x, sdata) | ||||||
|  | 		if err != nil { | ||||||
|  | 			x, err = time.ParseInLocation("2006-01-02 15:04:05.999999999", sdata, session.Engine.TZLocation) | ||||||
|  | 			session.Engine.logger.Debugf("time(2) key[%v]: %+v | sdata: [%v]\n", col.FieldName, x, sdata) | ||||||
|  | 		} | ||||||
|  | 		if err != nil { | ||||||
|  | 			x, err = time.ParseInLocation("2006-01-02 15:04:05.9999999 Z07:00", sdata, session.Engine.TZLocation) | ||||||
|  | 			session.Engine.logger.Debugf("time(3) key[%v]: %+v | sdata: [%v]\n", col.FieldName, x, sdata) | ||||||
|  | 		} | ||||||
|  |  | ||||||
|  | 	} else if len(sdata) == 19 && strings.Contains(sdata, "-") { | ||||||
|  | 		x, err = time.ParseInLocation("2006-01-02 15:04:05", sdata, session.Engine.TZLocation) | ||||||
|  | 		session.Engine.logger.Debugf("time(4) key[%v]: %+v | sdata: [%v]\n", col.FieldName, x, sdata) | ||||||
|  | 	} else if len(sdata) == 10 && sdata[4] == '-' && sdata[7] == '-' { | ||||||
|  | 		x, err = time.ParseInLocation("2006-01-02", sdata, session.Engine.TZLocation) | ||||||
|  | 		session.Engine.logger.Debugf("time(5) key[%v]: %+v | sdata: [%v]\n", col.FieldName, x, sdata) | ||||||
|  | 	} else if col.SQLType.Name == core.Time { | ||||||
|  | 		if strings.Contains(sdata, " ") { | ||||||
|  | 			ssd := strings.Split(sdata, " ") | ||||||
|  | 			sdata = ssd[1] | ||||||
|  | 		} | ||||||
|  |  | ||||||
|  | 		sdata = strings.TrimSpace(sdata) | ||||||
|  | 		if session.Engine.dialect.DBType() == core.MYSQL && len(sdata) > 8 { | ||||||
|  | 			sdata = sdata[len(sdata)-8:] | ||||||
|  | 		} | ||||||
|  |  | ||||||
|  | 		st := fmt.Sprintf("2006-01-02 %v", sdata) | ||||||
|  | 		x, err = time.ParseInLocation("2006-01-02 15:04:05", st, session.Engine.TZLocation) | ||||||
|  | 		session.Engine.logger.Debugf("time(6) key[%v]: %+v | sdata: [%v]\n", col.FieldName, x, sdata) | ||||||
|  | 	} else { | ||||||
|  | 		outErr = fmt.Errorf("unsupported time format %v", sdata) | ||||||
|  | 		return | ||||||
|  | 	} | ||||||
|  | 	if err != nil { | ||||||
|  | 		outErr = fmt.Errorf("unsupported time format %v: %v", sdata, err) | ||||||
|  | 		return | ||||||
|  | 	} | ||||||
|  | 	outTime = x | ||||||
|  | 	return | ||||||
|  | } | ||||||
|  |  | ||||||
|  | func (session *Session) byte2Time(col *core.Column, data []byte) (outTime time.Time, outErr error) { | ||||||
|  | 	return session.str2Time(col, string(data)) | ||||||
|  | } | ||||||
|  |  | ||||||
|  | // convert a db data([]byte) to a field value | ||||||
|  | func (session *Session) bytes2Value(col *core.Column, fieldValue *reflect.Value, data []byte) error { | ||||||
|  | 	if structConvert, ok := fieldValue.Addr().Interface().(core.Conversion); ok { | ||||||
|  | 		return structConvert.FromDB(data) | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	if structConvert, ok := fieldValue.Interface().(core.Conversion); ok { | ||||||
|  | 		return structConvert.FromDB(data) | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	var v interface{} | ||||||
|  | 	key := col.Name | ||||||
|  | 	fieldType := fieldValue.Type() | ||||||
|  |  | ||||||
|  | 	switch fieldType.Kind() { | ||||||
|  | 	case reflect.Complex64, reflect.Complex128: | ||||||
|  | 		x := reflect.New(fieldType) | ||||||
|  | 		if len(data) > 0 { | ||||||
|  | 			err := json.Unmarshal(data, x.Interface()) | ||||||
|  | 			if err != nil { | ||||||
|  | 				session.Engine.logger.Error(err) | ||||||
|  | 				return err | ||||||
|  | 			} | ||||||
|  | 			fieldValue.Set(x.Elem()) | ||||||
|  | 		} | ||||||
|  | 	case reflect.Slice, reflect.Array, reflect.Map: | ||||||
|  | 		v = data | ||||||
|  | 		t := fieldType.Elem() | ||||||
|  | 		k := t.Kind() | ||||||
|  | 		if col.SQLType.IsText() { | ||||||
|  | 			x := reflect.New(fieldType) | ||||||
|  | 			if len(data) > 0 { | ||||||
|  | 				err := json.Unmarshal(data, x.Interface()) | ||||||
|  | 				if err != nil { | ||||||
|  | 					session.Engine.logger.Error(err) | ||||||
|  | 					return err | ||||||
|  | 				} | ||||||
|  | 				fieldValue.Set(x.Elem()) | ||||||
|  | 			} | ||||||
|  | 		} else if col.SQLType.IsBlob() { | ||||||
|  | 			if k == reflect.Uint8 { | ||||||
|  | 				fieldValue.Set(reflect.ValueOf(v)) | ||||||
|  | 			} else { | ||||||
|  | 				x := reflect.New(fieldType) | ||||||
|  | 				if len(data) > 0 { | ||||||
|  | 					err := json.Unmarshal(data, x.Interface()) | ||||||
|  | 					if err != nil { | ||||||
|  | 						session.Engine.logger.Error(err) | ||||||
|  | 						return err | ||||||
|  | 					} | ||||||
|  | 					fieldValue.Set(x.Elem()) | ||||||
|  | 				} | ||||||
|  | 			} | ||||||
|  | 		} else { | ||||||
|  | 			return ErrUnSupportedType | ||||||
|  | 		} | ||||||
|  | 	case reflect.String: | ||||||
|  | 		fieldValue.SetString(string(data)) | ||||||
|  | 	case reflect.Bool: | ||||||
|  | 		d := string(data) | ||||||
|  | 		v, err := strconv.ParseBool(d) | ||||||
|  | 		if err != nil { | ||||||
|  | 			return fmt.Errorf("arg %v as bool: %s", key, err.Error()) | ||||||
|  | 		} | ||||||
|  | 		fieldValue.Set(reflect.ValueOf(v)) | ||||||
|  | 	case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: | ||||||
|  | 		sdata := string(data) | ||||||
|  | 		var x int64 | ||||||
|  | 		var err error | ||||||
|  | 		// for mysql, when use bit, it returned \x01 | ||||||
|  | 		if col.SQLType.Name == core.Bit && | ||||||
|  | 			session.Engine.dialect.DBType() == core.MYSQL { // !nashtsai! TODO dialect needs to provide conversion interface API | ||||||
|  | 			if len(data) == 1 { | ||||||
|  | 				x = int64(data[0]) | ||||||
|  | 			} else { | ||||||
|  | 				x = 0 | ||||||
|  | 			} | ||||||
|  | 		} else if strings.HasPrefix(sdata, "0x") { | ||||||
|  | 			x, err = strconv.ParseInt(sdata, 16, 64) | ||||||
|  | 		} else if strings.HasPrefix(sdata, "0") { | ||||||
|  | 			x, err = strconv.ParseInt(sdata, 8, 64) | ||||||
|  | 		} else if strings.EqualFold(sdata, "true") { | ||||||
|  | 			x = 1 | ||||||
|  | 		} else if strings.EqualFold(sdata, "false") { | ||||||
|  | 			x = 0 | ||||||
|  | 		} else { | ||||||
|  | 			x, err = strconv.ParseInt(sdata, 10, 64) | ||||||
|  | 		} | ||||||
|  | 		if err != nil { | ||||||
|  | 			return fmt.Errorf("arg %v as int: %s", key, err.Error()) | ||||||
|  | 		} | ||||||
|  | 		fieldValue.SetInt(x) | ||||||
|  | 	case reflect.Float32, reflect.Float64: | ||||||
|  | 		x, err := strconv.ParseFloat(string(data), 64) | ||||||
|  | 		if err != nil { | ||||||
|  | 			return fmt.Errorf("arg %v as float64: %s", key, err.Error()) | ||||||
|  | 		} | ||||||
|  | 		fieldValue.SetFloat(x) | ||||||
|  | 	case reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uint: | ||||||
|  | 		x, err := strconv.ParseUint(string(data), 10, 64) | ||||||
|  | 		if err != nil { | ||||||
|  | 			return fmt.Errorf("arg %v as int: %s", key, err.Error()) | ||||||
|  | 		} | ||||||
|  | 		fieldValue.SetUint(x) | ||||||
|  | 	//Currently only support Time type | ||||||
|  | 	case reflect.Struct: | ||||||
|  | 		// !<winxxp>! 增加支持sql.Scanner接口的结构,如sql.NullString | ||||||
|  | 		if nulVal, ok := fieldValue.Addr().Interface().(sql.Scanner); ok { | ||||||
|  | 			if err := nulVal.Scan(data); err != nil { | ||||||
|  | 				return fmt.Errorf("sql.Scan(%v) failed: %s ", data, err.Error()) | ||||||
|  | 			} | ||||||
|  | 		} else { | ||||||
|  | 			if fieldType.ConvertibleTo(core.TimeType) { | ||||||
|  | 				x, err := session.byte2Time(col, data) | ||||||
|  | 				if err != nil { | ||||||
|  | 					return err | ||||||
|  | 				} | ||||||
|  | 				v = x | ||||||
|  | 				fieldValue.Set(reflect.ValueOf(v).Convert(fieldType)) | ||||||
|  | 			} else if session.Statement.UseCascade { | ||||||
|  | 				table, err := session.Engine.autoMapType(*fieldValue) | ||||||
|  | 				if err != nil { | ||||||
|  | 					return err | ||||||
|  | 				} | ||||||
|  |  | ||||||
|  | 				// TODO: current only support 1 primary key | ||||||
|  | 				if len(table.PrimaryKeys) > 1 { | ||||||
|  | 					panic("unsupported composited primary key cascade") | ||||||
|  | 				} | ||||||
|  | 				var pk = make(core.PK, len(table.PrimaryKeys)) | ||||||
|  | 				rawValueType := table.ColumnType(table.PKColumns()[0].FieldName) | ||||||
|  | 				pk[0], err = str2PK(string(data), rawValueType) | ||||||
|  | 				if err != nil { | ||||||
|  | 					return err | ||||||
|  | 				} | ||||||
|  |  | ||||||
|  | 				if !isPKZero(pk) { | ||||||
|  | 					// !nashtsai! TODO for hasOne relationship, it's preferred to use join query for eager fetch | ||||||
|  | 					// however, also need to consider adding a 'lazy' attribute to xorm tag which allow hasOne | ||||||
|  | 					// property to be fetched lazily | ||||||
|  | 					structInter := reflect.New(fieldValue.Type()) | ||||||
|  | 					newsession := session.Engine.NewSession() | ||||||
|  | 					defer newsession.Close() | ||||||
|  | 					has, err := newsession.Id(pk).NoCascade().Get(structInter.Interface()) | ||||||
|  | 					if err != nil { | ||||||
|  | 						return err | ||||||
|  | 					} | ||||||
|  | 					if has { | ||||||
|  | 						v = structInter.Elem().Interface() | ||||||
|  | 						fieldValue.Set(reflect.ValueOf(v)) | ||||||
|  | 					} else { | ||||||
|  | 						return errors.New("cascade obj is not exist") | ||||||
|  | 					} | ||||||
|  | 				} | ||||||
|  | 			} | ||||||
|  | 		} | ||||||
|  | 	case reflect.Ptr: | ||||||
|  | 		// !nashtsai! TODO merge duplicated codes above | ||||||
|  | 		//typeStr := fieldType.String() | ||||||
|  | 		switch fieldType.Elem().Kind() { | ||||||
|  | 		// case "*string": | ||||||
|  | 		case core.StringType.Kind(): | ||||||
|  | 			x := string(data) | ||||||
|  | 			fieldValue.Set(reflect.ValueOf(&x).Convert(fieldType)) | ||||||
|  | 		// case "*bool": | ||||||
|  | 		case core.BoolType.Kind(): | ||||||
|  | 			d := string(data) | ||||||
|  | 			v, err := strconv.ParseBool(d) | ||||||
|  | 			if err != nil { | ||||||
|  | 				return fmt.Errorf("arg %v as bool: %s", key, err.Error()) | ||||||
|  | 			} | ||||||
|  | 			fieldValue.Set(reflect.ValueOf(&v).Convert(fieldType)) | ||||||
|  | 		// case "*complex64": | ||||||
|  | 		case core.Complex64Type.Kind(): | ||||||
|  | 			var x complex64 | ||||||
|  | 			if len(data) > 0 { | ||||||
|  | 				err := json.Unmarshal(data, &x) | ||||||
|  | 				if err != nil { | ||||||
|  | 					session.Engine.logger.Error(err) | ||||||
|  | 					return err | ||||||
|  | 				} | ||||||
|  | 				fieldValue.Set(reflect.ValueOf(&x).Convert(fieldType)) | ||||||
|  | 			} | ||||||
|  | 		// case "*complex128": | ||||||
|  | 		case core.Complex128Type.Kind(): | ||||||
|  | 			var x complex128 | ||||||
|  | 			if len(data) > 0 { | ||||||
|  | 				err := json.Unmarshal(data, &x) | ||||||
|  | 				if err != nil { | ||||||
|  | 					session.Engine.logger.Error(err) | ||||||
|  | 					return err | ||||||
|  | 				} | ||||||
|  | 				fieldValue.Set(reflect.ValueOf(&x).Convert(fieldType)) | ||||||
|  | 			} | ||||||
|  | 		// case "*float64": | ||||||
|  | 		case core.Float64Type.Kind(): | ||||||
|  | 			x, err := strconv.ParseFloat(string(data), 64) | ||||||
|  | 			if err != nil { | ||||||
|  | 				return fmt.Errorf("arg %v as float64: %s", key, err.Error()) | ||||||
|  | 			} | ||||||
|  | 			fieldValue.Set(reflect.ValueOf(&x).Convert(fieldType)) | ||||||
|  | 		// case "*float32": | ||||||
|  | 		case core.Float32Type.Kind(): | ||||||
|  | 			var x float32 | ||||||
|  | 			x1, err := strconv.ParseFloat(string(data), 32) | ||||||
|  | 			if err != nil { | ||||||
|  | 				return fmt.Errorf("arg %v as float32: %s", key, err.Error()) | ||||||
|  | 			} | ||||||
|  | 			x = float32(x1) | ||||||
|  | 			fieldValue.Set(reflect.ValueOf(&x).Convert(fieldType)) | ||||||
|  | 		// case "*uint64": | ||||||
|  | 		case core.Uint64Type.Kind(): | ||||||
|  | 			var x uint64 | ||||||
|  | 			x, err := strconv.ParseUint(string(data), 10, 64) | ||||||
|  | 			if err != nil { | ||||||
|  | 				return fmt.Errorf("arg %v as int: %s", key, err.Error()) | ||||||
|  | 			} | ||||||
|  | 			fieldValue.Set(reflect.ValueOf(&x).Convert(fieldType)) | ||||||
|  | 		// case "*uint": | ||||||
|  | 		case core.UintType.Kind(): | ||||||
|  | 			var x uint | ||||||
|  | 			x1, err := strconv.ParseUint(string(data), 10, 64) | ||||||
|  | 			if err != nil { | ||||||
|  | 				return fmt.Errorf("arg %v as int: %s", key, err.Error()) | ||||||
|  | 			} | ||||||
|  | 			x = uint(x1) | ||||||
|  | 			fieldValue.Set(reflect.ValueOf(&x).Convert(fieldType)) | ||||||
|  | 		// case "*uint32": | ||||||
|  | 		case core.Uint32Type.Kind(): | ||||||
|  | 			var x uint32 | ||||||
|  | 			x1, err := strconv.ParseUint(string(data), 10, 64) | ||||||
|  | 			if err != nil { | ||||||
|  | 				return fmt.Errorf("arg %v as int: %s", key, err.Error()) | ||||||
|  | 			} | ||||||
|  | 			x = uint32(x1) | ||||||
|  | 			fieldValue.Set(reflect.ValueOf(&x).Convert(fieldType)) | ||||||
|  | 		// case "*uint8": | ||||||
|  | 		case core.Uint8Type.Kind(): | ||||||
|  | 			var x uint8 | ||||||
|  | 			x1, err := strconv.ParseUint(string(data), 10, 64) | ||||||
|  | 			if err != nil { | ||||||
|  | 				return fmt.Errorf("arg %v as int: %s", key, err.Error()) | ||||||
|  | 			} | ||||||
|  | 			x = uint8(x1) | ||||||
|  | 			fieldValue.Set(reflect.ValueOf(&x).Convert(fieldType)) | ||||||
|  | 		// case "*uint16": | ||||||
|  | 		case core.Uint16Type.Kind(): | ||||||
|  | 			var x uint16 | ||||||
|  | 			x1, err := strconv.ParseUint(string(data), 10, 64) | ||||||
|  | 			if err != nil { | ||||||
|  | 				return fmt.Errorf("arg %v as int: %s", key, err.Error()) | ||||||
|  | 			} | ||||||
|  | 			x = uint16(x1) | ||||||
|  | 			fieldValue.Set(reflect.ValueOf(&x).Convert(fieldType)) | ||||||
|  | 		// case "*int64": | ||||||
|  | 		case core.Int64Type.Kind(): | ||||||
|  | 			sdata := string(data) | ||||||
|  | 			var x int64 | ||||||
|  | 			var err error | ||||||
|  | 			// for mysql, when use bit, it returned \x01 | ||||||
|  | 			if col.SQLType.Name == core.Bit && | ||||||
|  | 				strings.Contains(session.Engine.DriverName(), "mysql") { | ||||||
|  | 				if len(data) == 1 { | ||||||
|  | 					x = int64(data[0]) | ||||||
|  | 				} else { | ||||||
|  | 					x = 0 | ||||||
|  | 				} | ||||||
|  | 			} else if strings.HasPrefix(sdata, "0x") { | ||||||
|  | 				x, err = strconv.ParseInt(sdata, 16, 64) | ||||||
|  | 			} else if strings.HasPrefix(sdata, "0") { | ||||||
|  | 				x, err = strconv.ParseInt(sdata, 8, 64) | ||||||
|  | 			} else { | ||||||
|  | 				x, err = strconv.ParseInt(sdata, 10, 64) | ||||||
|  | 			} | ||||||
|  | 			if err != nil { | ||||||
|  | 				return fmt.Errorf("arg %v as int: %s", key, err.Error()) | ||||||
|  | 			} | ||||||
|  | 			fieldValue.Set(reflect.ValueOf(&x).Convert(fieldType)) | ||||||
|  | 		// case "*int": | ||||||
|  | 		case core.IntType.Kind(): | ||||||
|  | 			sdata := string(data) | ||||||
|  | 			var x int | ||||||
|  | 			var x1 int64 | ||||||
|  | 			var err error | ||||||
|  | 			// for mysql, when use bit, it returned \x01 | ||||||
|  | 			if col.SQLType.Name == core.Bit && | ||||||
|  | 				strings.Contains(session.Engine.DriverName(), "mysql") { | ||||||
|  | 				if len(data) == 1 { | ||||||
|  | 					x = int(data[0]) | ||||||
|  | 				} else { | ||||||
|  | 					x = 0 | ||||||
|  | 				} | ||||||
|  | 			} else if strings.HasPrefix(sdata, "0x") { | ||||||
|  | 				x1, err = strconv.ParseInt(sdata, 16, 64) | ||||||
|  | 				x = int(x1) | ||||||
|  | 			} else if strings.HasPrefix(sdata, "0") { | ||||||
|  | 				x1, err = strconv.ParseInt(sdata, 8, 64) | ||||||
|  | 				x = int(x1) | ||||||
|  | 			} else { | ||||||
|  | 				x1, err = strconv.ParseInt(sdata, 10, 64) | ||||||
|  | 				x = int(x1) | ||||||
|  | 			} | ||||||
|  | 			if err != nil { | ||||||
|  | 				return fmt.Errorf("arg %v as int: %s", key, err.Error()) | ||||||
|  | 			} | ||||||
|  | 			fieldValue.Set(reflect.ValueOf(&x).Convert(fieldType)) | ||||||
|  | 		// case "*int32": | ||||||
|  | 		case core.Int32Type.Kind(): | ||||||
|  | 			sdata := string(data) | ||||||
|  | 			var x int32 | ||||||
|  | 			var x1 int64 | ||||||
|  | 			var err error | ||||||
|  | 			// for mysql, when use bit, it returned \x01 | ||||||
|  | 			if col.SQLType.Name == core.Bit && | ||||||
|  | 				session.Engine.dialect.DBType() == core.MYSQL { | ||||||
|  | 				if len(data) == 1 { | ||||||
|  | 					x = int32(data[0]) | ||||||
|  | 				} else { | ||||||
|  | 					x = 0 | ||||||
|  | 				} | ||||||
|  | 			} else if strings.HasPrefix(sdata, "0x") { | ||||||
|  | 				x1, err = strconv.ParseInt(sdata, 16, 64) | ||||||
|  | 				x = int32(x1) | ||||||
|  | 			} else if strings.HasPrefix(sdata, "0") { | ||||||
|  | 				x1, err = strconv.ParseInt(sdata, 8, 64) | ||||||
|  | 				x = int32(x1) | ||||||
|  | 			} else { | ||||||
|  | 				x1, err = strconv.ParseInt(sdata, 10, 64) | ||||||
|  | 				x = int32(x1) | ||||||
|  | 			} | ||||||
|  | 			if err != nil { | ||||||
|  | 				return fmt.Errorf("arg %v as int: %s", key, err.Error()) | ||||||
|  | 			} | ||||||
|  | 			fieldValue.Set(reflect.ValueOf(&x).Convert(fieldType)) | ||||||
|  | 		// case "*int8": | ||||||
|  | 		case core.Int8Type.Kind(): | ||||||
|  | 			sdata := string(data) | ||||||
|  | 			var x int8 | ||||||
|  | 			var x1 int64 | ||||||
|  | 			var err error | ||||||
|  | 			// for mysql, when use bit, it returned \x01 | ||||||
|  | 			if col.SQLType.Name == core.Bit && | ||||||
|  | 				strings.Contains(session.Engine.DriverName(), "mysql") { | ||||||
|  | 				if len(data) == 1 { | ||||||
|  | 					x = int8(data[0]) | ||||||
|  | 				} else { | ||||||
|  | 					x = 0 | ||||||
|  | 				} | ||||||
|  | 			} else if strings.HasPrefix(sdata, "0x") { | ||||||
|  | 				x1, err = strconv.ParseInt(sdata, 16, 64) | ||||||
|  | 				x = int8(x1) | ||||||
|  | 			} else if strings.HasPrefix(sdata, "0") { | ||||||
|  | 				x1, err = strconv.ParseInt(sdata, 8, 64) | ||||||
|  | 				x = int8(x1) | ||||||
|  | 			} else { | ||||||
|  | 				x1, err = strconv.ParseInt(sdata, 10, 64) | ||||||
|  | 				x = int8(x1) | ||||||
|  | 			} | ||||||
|  | 			if err != nil { | ||||||
|  | 				return fmt.Errorf("arg %v as int: %s", key, err.Error()) | ||||||
|  | 			} | ||||||
|  | 			fieldValue.Set(reflect.ValueOf(&x).Convert(fieldType)) | ||||||
|  | 		// case "*int16": | ||||||
|  | 		case core.Int16Type.Kind(): | ||||||
|  | 			sdata := string(data) | ||||||
|  | 			var x int16 | ||||||
|  | 			var x1 int64 | ||||||
|  | 			var err error | ||||||
|  | 			// for mysql, when use bit, it returned \x01 | ||||||
|  | 			if col.SQLType.Name == core.Bit && | ||||||
|  | 				strings.Contains(session.Engine.DriverName(), "mysql") { | ||||||
|  | 				if len(data) == 1 { | ||||||
|  | 					x = int16(data[0]) | ||||||
|  | 				} else { | ||||||
|  | 					x = 0 | ||||||
|  | 				} | ||||||
|  | 			} else if strings.HasPrefix(sdata, "0x") { | ||||||
|  | 				x1, err = strconv.ParseInt(sdata, 16, 64) | ||||||
|  | 				x = int16(x1) | ||||||
|  | 			} else if strings.HasPrefix(sdata, "0") { | ||||||
|  | 				x1, err = strconv.ParseInt(sdata, 8, 64) | ||||||
|  | 				x = int16(x1) | ||||||
|  | 			} else { | ||||||
|  | 				x1, err = strconv.ParseInt(sdata, 10, 64) | ||||||
|  | 				x = int16(x1) | ||||||
|  | 			} | ||||||
|  | 			if err != nil { | ||||||
|  | 				return fmt.Errorf("arg %v as int: %s", key, err.Error()) | ||||||
|  | 			} | ||||||
|  | 			fieldValue.Set(reflect.ValueOf(&x).Convert(fieldType)) | ||||||
|  | 		// case "*SomeStruct": | ||||||
|  | 		case reflect.Struct: | ||||||
|  | 			switch fieldType { | ||||||
|  | 			// case "*.time.Time": | ||||||
|  | 			case core.PtrTimeType: | ||||||
|  | 				x, err := session.byte2Time(col, data) | ||||||
|  | 				if err != nil { | ||||||
|  | 					return err | ||||||
|  | 				} | ||||||
|  | 				v = x | ||||||
|  | 				fieldValue.Set(reflect.ValueOf(&x)) | ||||||
|  | 			default: | ||||||
|  | 				if session.Statement.UseCascade { | ||||||
|  | 					structInter := reflect.New(fieldType.Elem()) | ||||||
|  | 					table, err := session.Engine.autoMapType(structInter.Elem()) | ||||||
|  | 					if err != nil { | ||||||
|  | 						return err | ||||||
|  | 					} | ||||||
|  |  | ||||||
|  | 					if len(table.PrimaryKeys) > 1 { | ||||||
|  | 						panic("unsupported composited primary key cascade") | ||||||
|  | 					} | ||||||
|  | 					var pk = make(core.PK, len(table.PrimaryKeys)) | ||||||
|  | 					rawValueType := table.ColumnType(table.PKColumns()[0].FieldName) | ||||||
|  | 					pk[0], err = str2PK(string(data), rawValueType) | ||||||
|  | 					if err != nil { | ||||||
|  | 						return err | ||||||
|  | 					} | ||||||
|  |  | ||||||
|  | 					if !isPKZero(pk) { | ||||||
|  | 						// !nashtsai! TODO for hasOne relationship, it's preferred to use join query for eager fetch | ||||||
|  | 						// however, also need to consider adding a 'lazy' attribute to xorm tag which allow hasOne | ||||||
|  | 						// property to be fetched lazily | ||||||
|  | 						newsession := session.Engine.NewSession() | ||||||
|  | 						defer newsession.Close() | ||||||
|  | 						has, err := newsession.Id(pk).NoCascade().Get(structInter.Interface()) | ||||||
|  | 						if err != nil { | ||||||
|  | 							return err | ||||||
|  | 						} | ||||||
|  | 						if has { | ||||||
|  | 							v = structInter.Interface() | ||||||
|  | 							fieldValue.Set(reflect.ValueOf(v)) | ||||||
|  | 						} else { | ||||||
|  | 							return errors.New("cascade obj is not exist") | ||||||
|  | 						} | ||||||
|  | 					} | ||||||
|  | 				} else { | ||||||
|  | 					return fmt.Errorf("unsupported struct type in Scan: %s", fieldValue.Type().String()) | ||||||
|  | 				} | ||||||
|  | 			} | ||||||
|  | 		default: | ||||||
|  | 			return fmt.Errorf("unsupported type in Scan: %s", fieldValue.Type().String()) | ||||||
|  | 		} | ||||||
|  | 	default: | ||||||
|  | 		return fmt.Errorf("unsupported type in Scan: %s", fieldValue.Type().String()) | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	return nil | ||||||
|  | } | ||||||
|  |  | ||||||
|  | // convert a field value of a struct to interface for put into db | ||||||
|  | func (session *Session) value2Interface(col *core.Column, fieldValue reflect.Value) (interface{}, error) { | ||||||
|  | 	if fieldValue.CanAddr() { | ||||||
|  | 		if fieldConvert, ok := fieldValue.Addr().Interface().(core.Conversion); ok { | ||||||
|  | 			data, err := fieldConvert.ToDB() | ||||||
|  | 			if err != nil { | ||||||
|  | 				return 0, err | ||||||
|  | 			} | ||||||
|  | 			if col.SQLType.IsBlob() { | ||||||
|  | 				return data, nil | ||||||
|  | 			} | ||||||
|  | 			return string(data), nil | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	if fieldConvert, ok := fieldValue.Interface().(core.Conversion); ok { | ||||||
|  | 		data, err := fieldConvert.ToDB() | ||||||
|  | 		if err != nil { | ||||||
|  | 			return 0, err | ||||||
|  | 		} | ||||||
|  | 		if col.SQLType.IsBlob() { | ||||||
|  | 			return data, nil | ||||||
|  | 		} | ||||||
|  | 		return string(data), nil | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	fieldType := fieldValue.Type() | ||||||
|  | 	k := fieldType.Kind() | ||||||
|  | 	if k == reflect.Ptr { | ||||||
|  | 		if fieldValue.IsNil() { | ||||||
|  | 			return nil, nil | ||||||
|  | 		} else if !fieldValue.IsValid() { | ||||||
|  | 			session.Engine.logger.Warn("the field[", col.FieldName, "] is invalid") | ||||||
|  | 			return nil, nil | ||||||
|  | 		} else { | ||||||
|  | 			// !nashtsai! deference pointer type to instance type | ||||||
|  | 			fieldValue = fieldValue.Elem() | ||||||
|  | 			fieldType = fieldValue.Type() | ||||||
|  | 			k = fieldType.Kind() | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	switch k { | ||||||
|  | 	case reflect.Bool: | ||||||
|  | 		return fieldValue.Bool(), nil | ||||||
|  | 	case reflect.String: | ||||||
|  | 		return fieldValue.String(), nil | ||||||
|  | 	case reflect.Struct: | ||||||
|  | 		if fieldType.ConvertibleTo(core.TimeType) { | ||||||
|  | 			t := fieldValue.Convert(core.TimeType).Interface().(time.Time) | ||||||
|  | 			if session.Engine.dialect.DBType() == core.MSSQL { | ||||||
|  | 				if t.IsZero() { | ||||||
|  | 					return nil, nil | ||||||
|  | 				} | ||||||
|  | 			} | ||||||
|  | 			tf := session.Engine.FormatTime(col.SQLType.Name, t) | ||||||
|  | 			return tf, nil | ||||||
|  | 		} | ||||||
|  |  | ||||||
|  | 		if !col.SQLType.IsJson() { | ||||||
|  | 			// !<winxxp>! 增加支持driver.Valuer接口的结构,如sql.NullString | ||||||
|  | 			if v, ok := fieldValue.Interface().(driver.Valuer); ok { | ||||||
|  | 				return v.Value() | ||||||
|  | 			} | ||||||
|  |  | ||||||
|  | 			fieldTable, err := session.Engine.autoMapType(fieldValue) | ||||||
|  | 			if err != nil { | ||||||
|  | 				return nil, err | ||||||
|  | 			} | ||||||
|  | 			if len(fieldTable.PrimaryKeys) == 1 { | ||||||
|  | 				pkField := reflect.Indirect(fieldValue).FieldByName(fieldTable.PKColumns()[0].FieldName) | ||||||
|  | 				return pkField.Interface(), nil | ||||||
|  | 			} | ||||||
|  | 			return 0, fmt.Errorf("no primary key for col %v", col.Name) | ||||||
|  | 		} | ||||||
|  |  | ||||||
|  | 		if col.SQLType.IsText() { | ||||||
|  | 			bytes, err := json.Marshal(fieldValue.Interface()) | ||||||
|  | 			if err != nil { | ||||||
|  | 				session.Engine.logger.Error(err) | ||||||
|  | 				return 0, err | ||||||
|  | 			} | ||||||
|  | 			return string(bytes), nil | ||||||
|  | 		} else if col.SQLType.IsBlob() { | ||||||
|  | 			bytes, err := json.Marshal(fieldValue.Interface()) | ||||||
|  | 			if err != nil { | ||||||
|  | 				session.Engine.logger.Error(err) | ||||||
|  | 				return 0, err | ||||||
|  | 			} | ||||||
|  | 			return bytes, nil | ||||||
|  | 		} | ||||||
|  | 		return nil, fmt.Errorf("Unsupported type %v", fieldValue.Type()) | ||||||
|  | 	case reflect.Complex64, reflect.Complex128: | ||||||
|  | 		bytes, err := json.Marshal(fieldValue.Interface()) | ||||||
|  | 		if err != nil { | ||||||
|  | 			session.Engine.logger.Error(err) | ||||||
|  | 			return 0, err | ||||||
|  | 		} | ||||||
|  | 		return string(bytes), nil | ||||||
|  | 	case reflect.Array, reflect.Slice, reflect.Map: | ||||||
|  | 		if !fieldValue.IsValid() { | ||||||
|  | 			return fieldValue.Interface(), nil | ||||||
|  | 		} | ||||||
|  |  | ||||||
|  | 		if col.SQLType.IsText() { | ||||||
|  | 			bytes, err := json.Marshal(fieldValue.Interface()) | ||||||
|  | 			if err != nil { | ||||||
|  | 				session.Engine.logger.Error(err) | ||||||
|  | 				return 0, err | ||||||
|  | 			} | ||||||
|  | 			return string(bytes), nil | ||||||
|  | 		} else if col.SQLType.IsBlob() { | ||||||
|  | 			var bytes []byte | ||||||
|  | 			var err error | ||||||
|  | 			if (k == reflect.Array || k == reflect.Slice) && | ||||||
|  | 				(fieldValue.Type().Elem().Kind() == reflect.Uint8) { | ||||||
|  | 				bytes = fieldValue.Bytes() | ||||||
|  | 			} else { | ||||||
|  | 				bytes, err = json.Marshal(fieldValue.Interface()) | ||||||
|  | 				if err != nil { | ||||||
|  | 					session.Engine.logger.Error(err) | ||||||
|  | 					return 0, err | ||||||
|  | 				} | ||||||
|  | 			} | ||||||
|  | 			return bytes, nil | ||||||
|  | 		} | ||||||
|  | 		return nil, ErrUnSupportedType | ||||||
|  | 	case reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uint: | ||||||
|  | 		return int64(fieldValue.Uint()), nil | ||||||
|  | 	default: | ||||||
|  | 		return fieldValue.Interface(), nil | ||||||
|  | 	} | ||||||
|  | } | ||||||
							
								
								
									
										102
									
								
								vendor/github.com/go-xorm/xorm/session_find.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										102
									
								
								vendor/github.com/go-xorm/xorm/session_find.go
									
									
									
										generated
									
									
										vendored
									
									
								
							| @@ -169,31 +169,43 @@ func (session *Session) noCacheFind(table *core.Table, containerValue reflect.Va | |||||||
| 		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 { | 		isPointer = true | ||||||
| 			return reflect.New(elemType.Elem()) | 		elemType = elemType.Elem() | ||||||
| 		} | 	} | ||||||
| 	} else { | 	if elemType.Kind() == reflect.Ptr { | ||||||
| 		newElemFunc = func() reflect.Value { | 		return errors.New("pointer to pointer is not supported") | ||||||
| 			return reflect.New(elemType) | 	} | ||||||
|  |  | ||||||
|  | 	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 { | ||||||
| 			containerValueSetFunc = func(newValue *reflect.Value, pk core.PK) error { | 			if isPointer { | ||||||
| 				containerValue.Set(reflect.Append(containerValue, reflect.ValueOf(newValue.Interface()))) | 				containerValue.Set(reflect.Append(containerValue, newValue.Elem().Addr())) | ||||||
| 				return nil | 			} else { | ||||||
| 			} | 				containerValue.Set(reflect.Append(containerValue, newValue.Elem())) | ||||||
| 		} else { |  | ||||||
| 			containerValueSetFunc = func(newValue *reflect.Value, pk core.PK) error { |  | ||||||
| 				containerValue.Set(reflect.Append(containerValue, reflect.Indirect(reflect.ValueOf(newValue.Interface())))) |  | ||||||
| 				return nil |  | ||||||
| 			} | 			} | ||||||
|  | 			return nil | ||||||
| 		} | 		} | ||||||
| 	} else { | 	} else { | ||||||
| 		keyType := containerValue.Type().Key() | 		keyType := containerValue.Type().Key() | ||||||
| @@ -204,40 +216,45 @@ func (session *Session) noCacheFind(table *core.Table, containerValue reflect.Va | |||||||
| 			return errors.New("don't support multiple primary key's map has non-slice key type") | 			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 { | ||||||
| 			containerValueSetFunc = func(newValue *reflect.Value, pk core.PK) error { | 			keyValue := reflect.New(keyType) | ||||||
| 				keyValue := reflect.New(keyType) | 			err := convertPKToValue(table, keyValue.Interface(), pk) | ||||||
| 				err := convertPKToValue(table, keyValue.Interface(), pk) | 			if err != nil { | ||||||
| 				if err != nil { | 				return err | ||||||
| 					return err |  | ||||||
| 				} |  | ||||||
| 				containerValue.SetMapIndex(keyValue.Elem(), reflect.ValueOf(newValue.Interface())) |  | ||||||
| 				return nil |  | ||||||
| 			} | 			} | ||||||
| 		} else { | 			if isPointer { | ||||||
| 			containerValueSetFunc = func(newValue *reflect.Value, pk core.PK) error { | 				containerValue.SetMapIndex(keyValue.Elem(), newValue.Elem().Addr()) | ||||||
| 				keyValue := reflect.New(keyType) | 			} else { | ||||||
| 				err := convertPKToValue(table, keyValue.Interface(), pk) | 				containerValue.SetMapIndex(keyValue.Elem(), newValue.Elem()) | ||||||
| 				if err != nil { |  | ||||||
| 					return err |  | ||||||
| 				} |  | ||||||
| 				containerValue.SetMapIndex(keyValue.Elem(), reflect.Indirect(reflect.ValueOf(newValue.Interface()))) |  | ||||||
| 				return nil |  | ||||||
| 			} | 			} | ||||||
|  | 			return nil | ||||||
| 		} | 		} | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	var newValue = newElemFunc() | 	if elemType.Kind() == reflect.Struct { | ||||||
| 	dataStruct := rValue(newValue.Interface()) | 		var newValue = newElemFunc(fields) | ||||||
| 	if dataStruct.Kind() == reflect.Struct { | 		dataStruct := rValue(newValue.Interface()) | ||||||
| 		return session.rows2Beans(rawRows, fields, len(fields), session.Engine.autoMapType(dataStruct), newElemFunc, containerValueSetFunc) | 		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 | ||||||
| 		} | 		} | ||||||
|  |  | ||||||
| @@ -394,7 +411,10 @@ func (session *Session) cacheFind(t reflect.Type, sqlStr string, rowsSlicePtr in | |||||||
| 			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 | ||||||
|   | |||||||
							
								
								
									
										52
									
								
								vendor/github.com/go-xorm/xorm/session_get.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										52
									
								
								vendor/github.com/go-xorm/xorm/session_get.go
									
									
									
										generated
									
									
										vendored
									
									
								
							| @@ -20,7 +20,14 @@ func (session *Session) Get(bean interface{}) (bool, error) { | |||||||
| 		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{} | ||||||
| @@ -36,7 +43,7 @@ func (session *Session) Get(bean interface{}) (bool, error) { | |||||||
| 		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...) | ||||||
| @@ -46,13 +53,14 @@ func (session *Session) Get(bean interface{}) (bool, error) { | |||||||
| 		} | 		} | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	return session.nocacheGet(bean, sqlStr, args...) | 	return session.nocacheGet(beanValue.Elem().Kind(), bean, sqlStr, args...) | ||||||
| } | } | ||||||
|  |  | ||||||
| func (session *Session) nocacheGet(bean interface{}, sqlStr string, args ...interface{}) (bool, error) { | func (session *Session) nocacheGet(beanKind reflect.Kind, bean interface{}, sqlStr string, args ...interface{}) (bool, error) { | ||||||
|  | 	session.queryPreprocess(&sqlStr, args...) | ||||||
|  |  | ||||||
| 	var rawRows *core.Rows | 	var 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 { | ||||||
| @@ -65,10 +73,24 @@ func (session *Session) nocacheGet(bean interface{}, sqlStr string, args ...inte | |||||||
| 	defer rawRows.Close() | 	defer rawRows.Close() | ||||||
|  |  | ||||||
| 	if rawRows.Next() { | 	if rawRows.Next() { | ||||||
| 		fields, err := rawRows.Columns() | 		switch beanKind { | ||||||
| 		if err == nil { | 		case reflect.Struct: | ||||||
| 			_, err = session.row2Bean(rawRows, fields, len(fields), bean) | 			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 | ||||||
| @@ -145,20 +167,8 @@ func (session *Session) cacheGet(bean interface{}, sqlStr string, args ...interf | |||||||
| 		} | 		} | ||||||
| 		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 | ||||||
| 			} | 			} | ||||||
|   | |||||||
							
								
								
									
										38
									
								
								vendor/github.com/go-xorm/xorm/session_insert.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										38
									
								
								vendor/github.com/go-xorm/xorm/session_insert.go
									
									
									
										generated
									
									
										vendored
									
									
								
							| @@ -210,13 +210,29 @@ func (session *Session) innerInsertMulti(rowsSlicePtr interface{}) (int64, error | |||||||
| 	} | 	} | ||||||
| 	cleanupProcessorsClosures(&session.beforeClosures) | 	cleanupProcessorsClosures(&session.beforeClosures) | ||||||
|  |  | ||||||
| 	statement := fmt.Sprintf("INSERT INTO %s (%v%v%v) VALUES (%v)", | 	var sql = "INSERT INTO %s (%v%v%v) VALUES (%v)" | ||||||
| 		session.Engine.Quote(session.Statement.TableName()), | 	var statement string | ||||||
| 		session.Engine.QuoteStr(), | 	if session.Engine.dialect.DBType() == core.ORACLE { | ||||||
| 		strings.Join(colNames, session.Engine.QuoteStr()+", "+session.Engine.QuoteStr()), | 		sql = "INSERT ALL INTO %s (%v%v%v) VALUES (%v) SELECT 1 FROM DUAL" | ||||||
| 		session.Engine.QuoteStr(), | 		temp := fmt.Sprintf(") INTO %s (%v%v%v) VALUES (", | ||||||
| 		strings.Join(colMultiPlaces, "),(")) | 			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 | ||||||
| @@ -309,8 +325,8 @@ func (session *Session) innerInsert(bean interface{}) (int64, error) { | |||||||
| 		// 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:]...) | 				colNames = append(colNames[:i], colNames[i + 1:]...) | ||||||
| 				args = append(args[:i], args[i+1:]...) | 				args = append(args[:i], args[i + 1:]...) | ||||||
| 			} | 			} | ||||||
| 		} | 		} | ||||||
|  |  | ||||||
| @@ -319,11 +335,11 @@ func (session *Session) innerInsert(bean interface{}) (int64, error) { | |||||||
| 		exprColVals = append(exprColVals, v.expr) | 		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)", | ||||||
|   | |||||||
							
								
								
									
										11
									
								
								vendor/github.com/go-xorm/xorm/session_raw.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										11
									
								
								vendor/github.com/go-xorm/xorm/session_raw.go
									
									
									
										generated
									
									
										vendored
									
									
								
							| @@ -70,7 +70,7 @@ func (session *Session) innerQuery2(sqlStr string, params ...interface{}) ([]map | |||||||
| 	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 { | ||||||
| @@ -80,6 +80,15 @@ func (session *Session) Query(sqlStr string, paramStr ...interface{}) (resultsSl | |||||||
| 	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 | ||||||
| // ============================= | // ============================= | ||||||
|   | |||||||
							
								
								
									
										5
									
								
								vendor/github.com/go-xorm/xorm/session_schema.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										5
									
								
								vendor/github.com/go-xorm/xorm/session_schema.go
									
									
									
										generated
									
									
										vendored
									
									
								
							| @@ -306,7 +306,10 @@ func (session *Session) Sync2(beans ...interface{}) error { | |||||||
|  |  | ||||||
| 	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) | ||||||
|  |  | ||||||
|   | |||||||
							
								
								
									
										2
									
								
								vendor/github.com/go-xorm/xorm/session_sum.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										2
									
								
								vendor/github.com/go-xorm/xorm/session_sum.go
									
									
									
										generated
									
									
										vendored
									
									
								
							| @@ -123,7 +123,7 @@ func (session *Session) SumsInt(bean interface{}, columnNames ...string) ([]int6 | |||||||
| 	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 { | ||||||
|   | |||||||
							
								
								
									
										77
									
								
								vendor/github.com/go-xorm/xorm/session_update.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										77
									
								
								vendor/github.com/go-xorm/xorm/session_update.go
									
									
									
										generated
									
									
										vendored
									
									
								
							| @@ -253,48 +253,59 @@ func (session *Session) Update(bean interface{}, condiBean ...interface{}) (int6 | |||||||
| 	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) | 		colNames = append(colNames, session.Engine.Quote(table.Version)+" = "+session.Engine.Quote(table.Version)+" + 1") | ||||||
|  |  | ||||||
| 		if len(condSQL) > 0 { |  | ||||||
| 			condSQL = "WHERE " + condSQL |  | ||||||
| 		} |  | ||||||
|  |  | ||||||
| 		if st.LimitN > 0 { |  | ||||||
| 			condSQL = condSQL + fmt.Sprintf(" LIMIT %d", st.LimitN) |  | ||||||
| 		} |  | ||||||
|  |  | ||||||
| 		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) |  | ||||||
|  |  | ||||||
| 		doIncVer = true |  | ||||||
| 	} else { |  | ||||||
| 		condSQL, condArgs, _ = builder.ToSQL(cond) |  | ||||||
| 		if len(condSQL) > 0 { |  | ||||||
| 			condSQL = "WHERE " + condSQL |  | ||||||
| 		} |  | ||||||
|  |  | ||||||
| 		if st.LimitN > 0 { |  | ||||||
| 			condSQL = condSQL + fmt.Sprintf(" LIMIT %d", st.LimitN) |  | ||||||
| 		} |  | ||||||
|  |  | ||||||
| 		sqlStr = fmt.Sprintf("UPDATE %v SET %v %v", |  | ||||||
| 			session.Engine.Quote(session.Statement.TableName()), |  | ||||||
| 			strings.Join(colNames, ", "), |  | ||||||
| 			condSQL) |  | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
|  | 	condSQL, condArgs, _ = builder.ToSQL(cond) | ||||||
|  | 	if len(condSQL) > 0 { | ||||||
|  | 		condSQL = "WHERE " + condSQL | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	if st.OrderStr != "" { | ||||||
|  | 		condSQL = condSQL + fmt.Sprintf(" ORDER BY %v", st.OrderStr) | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	// TODO: Oracle support needed | ||||||
|  | 	var top string | ||||||
|  | 	if st.LimitN > 0 { | ||||||
|  | 		if st.Engine.dialect.DBType() == core.MYSQL { | ||||||
|  | 			condSQL = condSQL + fmt.Sprintf(" LIMIT %d", st.LimitN) | ||||||
|  | 		} else if st.Engine.dialect.DBType() == core.SQLITE { | ||||||
|  | 			tempCondSQL := condSQL + fmt.Sprintf(" LIMIT %d", st.LimitN) | ||||||
|  | 			cond = cond.And(builder.Expr(fmt.Sprintf("rowid IN (SELECT rowid FROM %v %v)", | ||||||
|  | 				session.Engine.Quote(session.Statement.TableName()), tempCondSQL), condArgs...)) | ||||||
|  | 			condSQL, condArgs, _ = builder.ToSQL(cond) | ||||||
|  | 			if len(condSQL) > 0 { | ||||||
|  | 				condSQL = "WHERE " + condSQL | ||||||
|  | 			} | ||||||
|  | 		} else if st.Engine.dialect.DBType() == core.POSTGRES { | ||||||
|  | 			tempCondSQL := condSQL + fmt.Sprintf(" LIMIT %d", st.LimitN) | ||||||
|  | 			cond = cond.And(builder.Expr(fmt.Sprintf("CTID IN (SELECT CTID FROM %v %v)", | ||||||
|  | 				session.Engine.Quote(session.Statement.TableName()), tempCondSQL), condArgs...)) | ||||||
|  | 			condSQL, condArgs, _ = builder.ToSQL(cond) | ||||||
|  | 			if len(condSQL) > 0 { | ||||||
|  | 				condSQL = "WHERE " + condSQL | ||||||
|  | 			} | ||||||
|  | 		} else if st.Engine.dialect.DBType() == core.MSSQL { | ||||||
|  | 			top = fmt.Sprintf("top (%d) ", st.LimitN) | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	sqlStr = fmt.Sprintf("UPDATE %v%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 | ||||||
|   | |||||||
							
								
								
									
										20
									
								
								vendor/github.com/go-xorm/xorm/sqlite3_driver.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										20
									
								
								vendor/github.com/go-xorm/xorm/sqlite3_driver.go
									
									
									
										generated
									
									
										vendored
									
									
								
							| @@ -1,20 +0,0 @@ | |||||||
| // Copyright 2015 The Xorm Authors. All rights reserved. |  | ||||||
| // Use of this source code is governed by a BSD-style |  | ||||||
| // license that can be found in the LICENSE file. |  | ||||||
|  |  | ||||||
| package xorm |  | ||||||
|  |  | ||||||
| import ( |  | ||||||
| 	"github.com/go-xorm/core" |  | ||||||
| ) |  | ||||||
|  |  | ||||||
| // func init() { |  | ||||||
| // 	core.RegisterDriver("sqlite3", &sqlite3Driver{}) |  | ||||||
| // } |  | ||||||
|  |  | ||||||
| type sqlite3Driver struct { |  | ||||||
| } |  | ||||||
|  |  | ||||||
| func (p *sqlite3Driver) Parse(driverName, dataSourceName string) (*core.Uri, error) { |  | ||||||
| 	return &core.Uri{DbType: core.SQLITE, DbName: dataSourceName}, nil |  | ||||||
| } |  | ||||||
							
								
								
									
										94
									
								
								vendor/github.com/go-xorm/xorm/statement.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										94
									
								
								vendor/github.com/go-xorm/xorm/statement.go
									
									
									
										generated
									
									
										vendored
									
									
								
							| @@ -39,7 +39,7 @@ type Statement struct { | |||||||
| 	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{} | ||||||
| @@ -91,7 +91,7 @@ func (statement *Statement) Init() { | |||||||
| 	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 | ||||||
| @@ -195,29 +195,26 @@ func (statement *Statement) Or(query interface{}, args ...interface{}) *Statemen | |||||||
|  |  | ||||||
| // 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 { | 	in := builder.In(statement.Engine.Quote(column), args...) | ||||||
| 		return statement |  | ||||||
| 	} |  | ||||||
|  |  | ||||||
| 	in := builder.In(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 { | 	notIn := builder.NotIn(statement.Engine.Quote(column), args...) | ||||||
| 		return statement | 	statement.cond = statement.cond.And(notIn) | ||||||
| 	} |  | ||||||
|  |  | ||||||
| 	in := builder.NotIn(column, args...) |  | ||||||
| 	statement.cond = statement.cond.And(in) |  | ||||||
| 	return statement | 	return statement | ||||||
| } | } | ||||||
|  |  | ||||||
| func (statement *Statement) setRefValue(v reflect.Value) { | func (statement *Statement) setRefValue(v reflect.Value) error { | ||||||
| 	statement.RefTable = statement.Engine.autoMapType(reflect.Indirect(v)) | 	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 | ||||||
| @@ -227,7 +224,12 @@ func (statement *Statement) Table(tableNameOrBean interface{}) *Statement { | |||||||
| 	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 | ||||||
| @@ -418,7 +420,11 @@ func buildUpdates(engine *Engine, table *core.Table, bean interface{}, | |||||||
| 				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 | ||||||
| 				} | 				} | ||||||
| 			} | 			} | ||||||
| @@ -433,13 +439,16 @@ func buildUpdates(engine *Engine, table *core.Table, bean interface{}, | |||||||
| 			} 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 { | ||||||
| @@ -651,7 +660,9 @@ func buildConds(engine *Engine, table *core.Table, bean interface{}, | |||||||
| 					} | 					} | ||||||
| 				} | 				} | ||||||
| 			} | 			} | ||||||
| 		case reflect.Array, reflect.Slice, reflect.Map: | 		case reflect.Array: | ||||||
|  | 			continue | ||||||
|  | 		case reflect.Slice, reflect.Map: | ||||||
| 			if fieldValue == reflect.Zero(fieldType) { | 			if fieldValue == reflect.Zero(fieldType) { | ||||||
| 				continue | 				continue | ||||||
| 			} | 			} | ||||||
| @@ -706,13 +717,6 @@ func (statement *Statement) TableName() string { | |||||||
| 	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) | ||||||
| @@ -721,23 +725,23 @@ func (statement *Statement) ID(id interface{}) *Statement { | |||||||
| 	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 | ||||||
| } | } | ||||||
|  |  | ||||||
| @@ -1120,7 +1124,11 @@ func (statement *Statement) genConds(bean interface{}) (string, []interface{}, e | |||||||
| } | } | ||||||
|  |  | ||||||
| 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 { | ||||||
| @@ -1139,14 +1147,22 @@ func (statement *Statement) genGetSQL(bean interface{}) (string, []interface{}) | |||||||
| 			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...) | ||||||
| } | } | ||||||
| @@ -1172,7 +1188,7 @@ func (statement *Statement) genSumSQL(bean interface{}, columns ...string) (stri | |||||||
|  |  | ||||||
| 	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) | ||||||
| @@ -1182,7 +1198,7 @@ func (statement *Statement) genSumSQL(bean interface{}, columns ...string) (stri | |||||||
|  |  | ||||||
| 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 " | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| @@ -1289,14 +1305,14 @@ func (statement *Statement) genSelectSQL(columnStr, condSQL string) (a string) { | |||||||
| } | } | ||||||
|  |  | ||||||
| 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)) { | 		if i < len(*(statement.idParam)) { | ||||||
| 			statement.cond = statement.cond.And(builder.Eq{colName: (*(statement.IdParam))[i]}) | 			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
									
								
								vendor/github.com/go-xorm/xorm/tag.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										281
									
								
								vendor/github.com/go-xorm/xorm/tag.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,281 @@ | |||||||
|  | // Copyright 2017 The Xorm Authors. All rights reserved. | ||||||
|  | // Use of this source code is governed by a BSD-style | ||||||
|  | // license that can be found in the LICENSE file. | ||||||
|  |  | ||||||
|  | package xorm | ||||||
|  |  | ||||||
|  | import ( | ||||||
|  | 	"fmt" | ||||||
|  | 	"reflect" | ||||||
|  | 	"strconv" | ||||||
|  | 	"strings" | ||||||
|  | 	"time" | ||||||
|  |  | ||||||
|  | 	"github.com/go-xorm/core" | ||||||
|  | ) | ||||||
|  |  | ||||||
|  | type tagContext struct { | ||||||
|  | 	tagName         string | ||||||
|  | 	params          []string | ||||||
|  | 	preTag, nextTag string | ||||||
|  | 	table           *core.Table | ||||||
|  | 	col             *core.Column | ||||||
|  | 	fieldValue      reflect.Value | ||||||
|  | 	isIndex         bool | ||||||
|  | 	isUnique        bool | ||||||
|  | 	indexNames      map[string]int | ||||||
|  | 	engine          *Engine | ||||||
|  | 	hasCacheTag     bool | ||||||
|  | 	hasNoCacheTag   bool | ||||||
|  | 	ignoreNext      bool | ||||||
|  | } | ||||||
|  |  | ||||||
|  | // tagHandler describes tag handler for XORM | ||||||
|  | type tagHandler func(ctx *tagContext) error | ||||||
|  |  | ||||||
|  | var ( | ||||||
|  | 	// defaultTagHandlers enumerates all the default tag handler | ||||||
|  | 	defaultTagHandlers = map[string]tagHandler{ | ||||||
|  | 		"<-":       OnlyFromDBTagHandler, | ||||||
|  | 		"->":       OnlyToDBTagHandler, | ||||||
|  | 		"PK":       PKTagHandler, | ||||||
|  | 		"NULL":     NULLTagHandler, | ||||||
|  | 		"NOT":      IgnoreTagHandler, | ||||||
|  | 		"AUTOINCR": AutoIncrTagHandler, | ||||||
|  | 		"DEFAULT":  DefaultTagHandler, | ||||||
|  | 		"CREATED":  CreatedTagHandler, | ||||||
|  | 		"UPDATED":  UpdatedTagHandler, | ||||||
|  | 		"DELETED":  DeletedTagHandler, | ||||||
|  | 		"VERSION":  VersionTagHandler, | ||||||
|  | 		"UTC":      UTCTagHandler, | ||||||
|  | 		"LOCAL":    LocalTagHandler, | ||||||
|  | 		"NOTNULL":  NotNullTagHandler, | ||||||
|  | 		"INDEX":    IndexTagHandler, | ||||||
|  | 		"UNIQUE":   UniqueTagHandler, | ||||||
|  | 		"CACHE":    CacheTagHandler, | ||||||
|  | 		"NOCACHE":  NoCacheTagHandler, | ||||||
|  | 	} | ||||||
|  | ) | ||||||
|  |  | ||||||
|  | func init() { | ||||||
|  | 	for k := range core.SqlTypes { | ||||||
|  | 		defaultTagHandlers[k] = SQLTypeTagHandler | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  |  | ||||||
|  | // IgnoreTagHandler describes ignored tag handler | ||||||
|  | func IgnoreTagHandler(ctx *tagContext) error { | ||||||
|  | 	return nil | ||||||
|  | } | ||||||
|  |  | ||||||
|  | // OnlyFromDBTagHandler describes mapping direction tag handler | ||||||
|  | func OnlyFromDBTagHandler(ctx *tagContext) error { | ||||||
|  | 	ctx.col.MapType = core.ONLYFROMDB | ||||||
|  | 	return nil | ||||||
|  | } | ||||||
|  |  | ||||||
|  | // OnlyToDBTagHandler describes mapping direction tag handler | ||||||
|  | func OnlyToDBTagHandler(ctx *tagContext) error { | ||||||
|  | 	ctx.col.MapType = core.ONLYTODB | ||||||
|  | 	return nil | ||||||
|  | } | ||||||
|  |  | ||||||
|  | // PKTagHandler decribes primary key tag handler | ||||||
|  | func PKTagHandler(ctx *tagContext) error { | ||||||
|  | 	ctx.col.IsPrimaryKey = true | ||||||
|  | 	ctx.col.Nullable = false | ||||||
|  | 	return nil | ||||||
|  | } | ||||||
|  |  | ||||||
|  | // NULLTagHandler describes null tag handler | ||||||
|  | func NULLTagHandler(ctx *tagContext) error { | ||||||
|  | 	ctx.col.Nullable = (strings.ToUpper(ctx.preTag) != "NOT") | ||||||
|  | 	return nil | ||||||
|  | } | ||||||
|  |  | ||||||
|  | // NotNullTagHandler describes notnull tag handler | ||||||
|  | func NotNullTagHandler(ctx *tagContext) error { | ||||||
|  | 	ctx.col.Nullable = false | ||||||
|  | 	return nil | ||||||
|  | } | ||||||
|  |  | ||||||
|  | // AutoIncrTagHandler describes autoincr tag handler | ||||||
|  | func AutoIncrTagHandler(ctx *tagContext) error { | ||||||
|  | 	ctx.col.IsAutoIncrement = true | ||||||
|  | 	/* | ||||||
|  | 		if len(ctx.params) > 0 { | ||||||
|  | 			autoStartInt, err := strconv.Atoi(ctx.params[0]) | ||||||
|  | 			if err != nil { | ||||||
|  | 				return err | ||||||
|  | 			} | ||||||
|  | 			ctx.col.AutoIncrStart = autoStartInt | ||||||
|  | 		} else { | ||||||
|  | 			ctx.col.AutoIncrStart = 1 | ||||||
|  | 		} | ||||||
|  | 	*/ | ||||||
|  | 	return nil | ||||||
|  | } | ||||||
|  |  | ||||||
|  | // DefaultTagHandler describes default tag handler | ||||||
|  | func DefaultTagHandler(ctx *tagContext) error { | ||||||
|  | 	if len(ctx.params) > 0 { | ||||||
|  | 		ctx.col.Default = ctx.params[0] | ||||||
|  | 	} else { | ||||||
|  | 		ctx.col.Default = ctx.nextTag | ||||||
|  | 		ctx.ignoreNext = true | ||||||
|  | 	} | ||||||
|  | 	return nil | ||||||
|  | } | ||||||
|  |  | ||||||
|  | // CreatedTagHandler describes created tag handler | ||||||
|  | func CreatedTagHandler(ctx *tagContext) error { | ||||||
|  | 	ctx.col.IsCreated = true | ||||||
|  | 	return nil | ||||||
|  | } | ||||||
|  |  | ||||||
|  | // VersionTagHandler describes version tag handler | ||||||
|  | func VersionTagHandler(ctx *tagContext) error { | ||||||
|  | 	ctx.col.IsVersion = true | ||||||
|  | 	ctx.col.Default = "1" | ||||||
|  | 	return nil | ||||||
|  | } | ||||||
|  |  | ||||||
|  | // UTCTagHandler describes utc tag handler | ||||||
|  | func UTCTagHandler(ctx *tagContext) error { | ||||||
|  | 	ctx.col.TimeZone = time.UTC | ||||||
|  | 	return nil | ||||||
|  | } | ||||||
|  |  | ||||||
|  | // LocalTagHandler describes local tag handler | ||||||
|  | func LocalTagHandler(ctx *tagContext) error { | ||||||
|  | 	if len(ctx.params) == 0 { | ||||||
|  | 		ctx.col.TimeZone = time.Local | ||||||
|  | 	} else { | ||||||
|  | 		var err error | ||||||
|  | 		ctx.col.TimeZone, err = time.LoadLocation(ctx.params[0]) | ||||||
|  | 		if err != nil { | ||||||
|  | 			return err | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | 	return nil | ||||||
|  | } | ||||||
|  |  | ||||||
|  | // UpdatedTagHandler describes updated tag handler | ||||||
|  | func UpdatedTagHandler(ctx *tagContext) error { | ||||||
|  | 	ctx.col.IsUpdated = true | ||||||
|  | 	return nil | ||||||
|  | } | ||||||
|  |  | ||||||
|  | // DeletedTagHandler describes deleted tag handler | ||||||
|  | func DeletedTagHandler(ctx *tagContext) error { | ||||||
|  | 	ctx.col.IsDeleted = true | ||||||
|  | 	return nil | ||||||
|  | } | ||||||
|  |  | ||||||
|  | // IndexTagHandler describes index tag handler | ||||||
|  | func IndexTagHandler(ctx *tagContext) error { | ||||||
|  | 	if len(ctx.params) > 0 { | ||||||
|  | 		ctx.indexNames[ctx.params[0]] = core.IndexType | ||||||
|  | 	} else { | ||||||
|  | 		ctx.isIndex = true | ||||||
|  | 	} | ||||||
|  | 	return nil | ||||||
|  | } | ||||||
|  |  | ||||||
|  | // UniqueTagHandler describes unique tag handler | ||||||
|  | func UniqueTagHandler(ctx *tagContext) error { | ||||||
|  | 	if len(ctx.params) > 0 { | ||||||
|  | 		ctx.indexNames[ctx.params[0]] = core.UniqueType | ||||||
|  | 	} else { | ||||||
|  | 		ctx.isUnique = true | ||||||
|  | 	} | ||||||
|  | 	return nil | ||||||
|  | } | ||||||
|  |  | ||||||
|  | // SQLTypeTagHandler describes SQL Type tag handler | ||||||
|  | func SQLTypeTagHandler(ctx *tagContext) error { | ||||||
|  | 	ctx.col.SQLType = core.SQLType{Name: ctx.tagName} | ||||||
|  | 	if len(ctx.params) > 0 { | ||||||
|  | 		if ctx.tagName == core.Enum { | ||||||
|  | 			ctx.col.EnumOptions = make(map[string]int) | ||||||
|  | 			for k, v := range ctx.params { | ||||||
|  | 				v = strings.TrimSpace(v) | ||||||
|  | 				v = strings.Trim(v, "'") | ||||||
|  | 				ctx.col.EnumOptions[v] = k | ||||||
|  | 			} | ||||||
|  | 		} else if ctx.tagName == core.Set { | ||||||
|  | 			ctx.col.SetOptions = make(map[string]int) | ||||||
|  | 			for k, v := range ctx.params { | ||||||
|  | 				v = strings.TrimSpace(v) | ||||||
|  | 				v = strings.Trim(v, "'") | ||||||
|  | 				ctx.col.SetOptions[v] = k | ||||||
|  | 			} | ||||||
|  | 		} else { | ||||||
|  | 			var err error | ||||||
|  | 			if len(ctx.params) == 2 { | ||||||
|  | 				ctx.col.Length, err = strconv.Atoi(ctx.params[0]) | ||||||
|  | 				if err != nil { | ||||||
|  | 					return err | ||||||
|  | 				} | ||||||
|  | 				ctx.col.Length2, err = strconv.Atoi(ctx.params[1]) | ||||||
|  | 				if err != nil { | ||||||
|  | 					return err | ||||||
|  | 				} | ||||||
|  | 			} else if len(ctx.params) == 1 { | ||||||
|  | 				ctx.col.Length, err = strconv.Atoi(ctx.params[0]) | ||||||
|  | 				if err != nil { | ||||||
|  | 					return err | ||||||
|  | 				} | ||||||
|  | 			} | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | 	return nil | ||||||
|  | } | ||||||
|  |  | ||||||
|  | // ExtendsTagHandler describes extends tag handler | ||||||
|  | func ExtendsTagHandler(ctx *tagContext) error { | ||||||
|  | 	var fieldValue = ctx.fieldValue | ||||||
|  | 	switch fieldValue.Kind() { | ||||||
|  | 	case reflect.Ptr: | ||||||
|  | 		f := fieldValue.Type().Elem() | ||||||
|  | 		if f.Kind() == reflect.Struct { | ||||||
|  | 			fieldPtr := fieldValue | ||||||
|  | 			fieldValue = fieldValue.Elem() | ||||||
|  | 			if !fieldValue.IsValid() || fieldPtr.IsNil() { | ||||||
|  | 				fieldValue = reflect.New(f).Elem() | ||||||
|  | 			} | ||||||
|  | 		} | ||||||
|  | 		fallthrough | ||||||
|  | 	case reflect.Struct: | ||||||
|  | 		parentTable, err := ctx.engine.mapType(fieldValue) | ||||||
|  | 		if err != nil { | ||||||
|  | 			return err | ||||||
|  | 		} | ||||||
|  | 		for _, col := range parentTable.Columns() { | ||||||
|  | 			col.FieldName = fmt.Sprintf("%v.%v", ctx.col.FieldName, col.FieldName) | ||||||
|  | 			ctx.table.AddColumn(col) | ||||||
|  | 			for indexName, indexType := range col.Indexes { | ||||||
|  | 				addIndex(indexName, ctx.table, col, indexType) | ||||||
|  | 			} | ||||||
|  | 		} | ||||||
|  | 	default: | ||||||
|  | 		//TODO: warning | ||||||
|  | 	} | ||||||
|  | 	return nil | ||||||
|  | } | ||||||
|  |  | ||||||
|  | // CacheTagHandler describes cache tag handler | ||||||
|  | func CacheTagHandler(ctx *tagContext) error { | ||||||
|  | 	if !ctx.hasCacheTag { | ||||||
|  | 		ctx.hasCacheTag = true | ||||||
|  | 	} | ||||||
|  | 	return nil | ||||||
|  | } | ||||||
|  |  | ||||||
|  | // NoCacheTagHandler describes nocache tag handler | ||||||
|  | func NoCacheTagHandler(ctx *tagContext) error { | ||||||
|  | 	if !ctx.hasNoCacheTag { | ||||||
|  | 		ctx.hasNoCacheTag = true | ||||||
|  | 	} | ||||||
|  | 	return nil | ||||||
|  | } | ||||||
							
								
								
									
										3
									
								
								vendor/github.com/go-xorm/xorm/xorm.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										3
									
								
								vendor/github.com/go-xorm/xorm/xorm.go
									
									
									
										generated
									
									
										vendored
									
									
								
							| @@ -17,7 +17,7 @@ import ( | |||||||
|  |  | ||||||
| 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 { | ||||||
| @@ -86,6 +86,7 @@ func NewEngine(driverName string, dataSourceName string) (*Engine, error) { | |||||||
| 		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) | ||||||
|   | |||||||
							
								
								
									
										6
									
								
								vendor/vendor.json
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										6
									
								
								vendor/vendor.json
									
									
									
									
										vendored
									
									
								
							| @@ -455,10 +455,10 @@ | |||||||
| 			"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", | 			"revision": "7e70eb82224bc950d4fb936036e925a51947c245", | ||||||
| 			"revisionTime": "2017-02-20T09:51:59Z" | 			"revisionTime": "2017-04-02T10:02:47Z" | ||||||
| 		}, | 		}, | ||||||
| 		{ | 		{ | ||||||
| 			"checksumSHA1": "1ft/4j5MFa7C9dPI9whL03HSUzk=", | 			"checksumSHA1": "1ft/4j5MFa7C9dPI9whL03HSUzk=", | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user
	 Lunny Xiao
					Lunny Xiao