fix MSSQL bug on org (#3405)
This commit is contained in:
		
					parent
					
						
							
								a0c397df08
							
						
					
				
			
			
				commit
				
					
						97fe773491
					
				
			
		
					 28 changed files with 1011 additions and 164 deletions
				
			
		
							
								
								
									
										4
									
								
								vendor/github.com/go-xorm/builder/builder_select.go
									
										
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										4
									
								
								vendor/github.com/go-xorm/builder/builder_select.go
									
										
									
										generated
									
									
										vendored
									
									
								
							| 
						 | 
				
			
			@ -45,6 +45,10 @@ func (b *Builder) selectWriteTo(w Writer) error {
 | 
			
		|||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if !b.cond.IsValid() {
 | 
			
		||||
		return nil
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if _, err := fmt.Fprint(w, " WHERE "); err != nil {
 | 
			
		||||
		return err
 | 
			
		||||
	}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										6
									
								
								vendor/github.com/go-xorm/builder/cond_and.go
									
										
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										6
									
								
								vendor/github.com/go-xorm/builder/cond_and.go
									
										
									
										generated
									
									
										vendored
									
									
								
							| 
						 | 
				
			
			@ -25,7 +25,9 @@ func And(conds ...Cond) Cond {
 | 
			
		|||
func (and condAnd) WriteTo(w Writer) error {
 | 
			
		||||
	for i, cond := range and {
 | 
			
		||||
		_, isOr := cond.(condOr)
 | 
			
		||||
		if isOr {
 | 
			
		||||
		_, isExpr := cond.(expr)
 | 
			
		||||
		wrap := isOr || isExpr
 | 
			
		||||
		if wrap {
 | 
			
		||||
			fmt.Fprint(w, "(")
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -34,7 +36,7 @@ func (and condAnd) WriteTo(w Writer) error {
 | 
			
		|||
			return err
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		if isOr {
 | 
			
		||||
		if wrap {
 | 
			
		||||
			fmt.Fprint(w, ")")
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										10
									
								
								vendor/github.com/go-xorm/core/cache.go
									
										
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										10
									
								
								vendor/github.com/go-xorm/core/cache.go
									
										
									
										generated
									
									
										vendored
									
									
								
							| 
						 | 
				
			
			@ -1,11 +1,12 @@
 | 
			
		|||
package core
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"errors"
 | 
			
		||||
	"fmt"
 | 
			
		||||
	"time"
 | 
			
		||||
	"bytes"
 | 
			
		||||
	"encoding/gob"
 | 
			
		||||
	"errors"
 | 
			
		||||
	"fmt"
 | 
			
		||||
	"strings"
 | 
			
		||||
	"time"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
const (
 | 
			
		||||
| 
						 | 
				
			
			@ -55,11 +56,10 @@ func encodeIds(ids []PK) (string, error) {
 | 
			
		|||
	return buf.String(), err
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
func decodeIds(s string) ([]PK, error) {
 | 
			
		||||
	pks := make([]PK, 0)
 | 
			
		||||
 | 
			
		||||
	dec := gob.NewDecoder(bytes.NewBufferString(s))
 | 
			
		||||
	dec := gob.NewDecoder(strings.NewReader(s))
 | 
			
		||||
	err := dec.Decode(&pks)
 | 
			
		||||
 | 
			
		||||
	return pks, err
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										1
									
								
								vendor/github.com/go-xorm/core/circle.yml
									
										
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										1
									
								
								vendor/github.com/go-xorm/core/circle.yml
									
										
									
										generated
									
									
										vendored
									
									
								
							| 
						 | 
				
			
			@ -12,3 +12,4 @@ test:
 | 
			
		|||
  override:
 | 
			
		||||
    # './...' is a relative pattern which means all subdirectories
 | 
			
		||||
    - go test -v -race
 | 
			
		||||
    - go test -v -race --dbtype=sqlite3
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										16
									
								
								vendor/github.com/go-xorm/core/column.go
									
										
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										16
									
								
								vendor/github.com/go-xorm/core/column.go
									
										
									
										generated
									
									
										vendored
									
									
								
							| 
						 | 
				
			
			@ -79,6 +79,10 @@ func (col *Column) String(d Dialect) string {
 | 
			
		|||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if col.Default != "" {
 | 
			
		||||
		sql += "DEFAULT " + col.Default + " "
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if d.ShowCreateNull() {
 | 
			
		||||
		if col.Nullable {
 | 
			
		||||
			sql += "NULL "
 | 
			
		||||
| 
						 | 
				
			
			@ -87,10 +91,6 @@ func (col *Column) String(d Dialect) string {
 | 
			
		|||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if col.Default != "" {
 | 
			
		||||
		sql += "DEFAULT " + col.Default + " "
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return sql
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -99,6 +99,10 @@ func (col *Column) StringNoPk(d Dialect) string {
 | 
			
		|||
 | 
			
		||||
	sql += d.SqlType(col) + " "
 | 
			
		||||
 | 
			
		||||
	if col.Default != "" {
 | 
			
		||||
		sql += "DEFAULT " + col.Default + " "
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if d.ShowCreateNull() {
 | 
			
		||||
		if col.Nullable {
 | 
			
		||||
			sql += "NULL "
 | 
			
		||||
| 
						 | 
				
			
			@ -107,10 +111,6 @@ func (col *Column) StringNoPk(d Dialect) string {
 | 
			
		|||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if col.Default != "" {
 | 
			
		||||
		sql += "DEFAULT " + col.Default + " "
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return sql
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										3
									
								
								vendor/github.com/go-xorm/core/scan.go
									
										
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										3
									
								
								vendor/github.com/go-xorm/core/scan.go
									
										
									
										generated
									
									
										vendored
									
									
								
							| 
						 | 
				
			
			@ -44,6 +44,9 @@ func convertTime(dest *NullTime, src interface{}) error {
 | 
			
		|||
		}
 | 
			
		||||
		*dest = NullTime(t)
 | 
			
		||||
		return nil
 | 
			
		||||
	case time.Time:
 | 
			
		||||
		*dest = NullTime(s)
 | 
			
		||||
		return nil
 | 
			
		||||
	case nil:
 | 
			
		||||
	default:
 | 
			
		||||
		return fmt.Errorf("unsupported driver -> Scan pair: %T -> %T", src, dest)
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										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)
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										4
									
								
								vendor/github.com/go-xorm/xorm/convert.go
									
										
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										4
									
								
								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)
 | 
			
		||||
		}
 | 
			
		||||
	case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
 | 
			
		||||
		s := asString(src)
 | 
			
		||||
		i64, err := strconv.ParseInt(s, 10, dv.Type().Bits())
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										75
									
								
								vendor/github.com/go-xorm/xorm/dialect_postgres.go
									
										
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										75
									
								
								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")
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	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
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										9
									
								
								vendor/github.com/go-xorm/xorm/session_exist.go
									
										
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										9
									
								
								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
 | 
			
		||||
				}
 | 
			
		||||
 | 
			
		||||
				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 {
 | 
			
		||||
				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
 | 
			
		||||
		}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										13
									
								
								vendor/github.com/go-xorm/xorm/session_update.go
									
										
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										13
									
								
								vendor/github.com/go-xorm/xorm/session_update.go
									
										
									
										generated
									
									
										vendored
									
									
								
							| 
						 | 
				
			
			@ -242,11 +242,24 @@ func (session *Session) Update(bean interface{}, condiBean ...interface{}) (int6
 | 
			
		|||
 | 
			
		||||
	var autoCond builder.Cond
 | 
			
		||||
	if !session.statement.noAutoCondition && len(condiBean) > 0 {
 | 
			
		||||
		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
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	st := &session.statement
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										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{}{}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										18
									
								
								vendor/vendor.json
									
										
									
									
										vendored
									
									
								
							
							
						
						
									
										18
									
								
								vendor/vendor.json
									
										
									
									
										vendored
									
									
								
							| 
						 | 
				
			
			@ -462,16 +462,16 @@
 | 
			
		|||
			"revisionTime": "2016-11-01T11:13:14Z"
 | 
			
		||||
		},
 | 
			
		||||
		{
 | 
			
		||||
			"checksumSHA1": "9SXbj96wb1PgppBZzxMIN0axbFQ=",
 | 
			
		||||
			"checksumSHA1": "HsUSlgz1VKEEiZdkXY5qdLzexWU=",
 | 
			
		||||
			"path": "github.com/go-xorm/builder",
 | 
			
		||||
			"revision": "c8871c857d2555fbfbd8524f895be5386d3d8836",
 | 
			
		||||
			"revisionTime": "2017-05-19T03:21:30Z"
 | 
			
		||||
			"revision": "488224409dd8aa2ce7a5baf8d10d55764a913738",
 | 
			
		||||
			"revisionTime": "2018-01-16T06:54:19Z"
 | 
			
		||||
		},
 | 
			
		||||
		{
 | 
			
		||||
			"checksumSHA1": "HMavuxvDhKOwmbbFnYt9hfT6jE0=",
 | 
			
		||||
			"checksumSHA1": "7JjlvSpGfLa49MHElks8NGBUfFA=",
 | 
			
		||||
			"path": "github.com/go-xorm/core",
 | 
			
		||||
			"revision": "da1adaf7a28ca792961721a34e6e04945200c890",
 | 
			
		||||
			"revisionTime": "2017-09-09T08:56:53Z"
 | 
			
		||||
			"revision": "cb1d0ca71f42d3ee1bf4aba7daa16099bc31a7e9",
 | 
			
		||||
			"revisionTime": "2017-12-21T01:38:49Z"
 | 
			
		||||
		},
 | 
			
		||||
		{
 | 
			
		||||
			"checksumSHA1": "k52lEKLp8j5M+jFpe+3u+bIFpxQ=",
 | 
			
		||||
| 
						 | 
				
			
			@ -480,10 +480,10 @@
 | 
			
		|||
			"revisionTime": "2016-08-11T02:11:45Z"
 | 
			
		||||
		},
 | 
			
		||||
		{
 | 
			
		||||
			"checksumSHA1": "+KmPfckyKvrUZPIHBYHylg/7V8o=",
 | 
			
		||||
			"checksumSHA1": "eGBz6F3I/0naVUclZ6GZWc3EzQo=",
 | 
			
		||||
			"path": "github.com/go-xorm/xorm",
 | 
			
		||||
			"revision": "29d4a0330a00b9be468b70e3fb0f74109348c358",
 | 
			
		||||
			"revisionTime": "2017-09-30T01:26:13Z"
 | 
			
		||||
			"revision": "d4149d1eee0c2c488a74a5863fd9caf13d60fd03",
 | 
			
		||||
			"revisionTime": "2018-01-22T13:32:35Z"
 | 
			
		||||
		},
 | 
			
		||||
		{
 | 
			
		||||
			"checksumSHA1": "1ft/4j5MFa7C9dPI9whL03HSUzk=",
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue