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