Просмотр исходного кода

pin versions of xorm to resolve sql tests

Resolves issue with postgres tests.
Also sets timezone of test instance and database to utc to resolve
mysql tests.
Closes #12065
Marcus Efraimsson 7 лет назад
Родитель
Сommit
5a96863eed
33 измененных файлов с 1017 добавлено и 1355 удалено
  1. 5 5
      Gopkg.lock
  2. 2 2
      Gopkg.toml
  3. 2 2
      pkg/services/sqlstore/sqlstore.go
  4. 4 4
      vendor/github.com/go-xorm/core/cache.go
  5. 8 8
      vendor/github.com/go-xorm/core/column.go
  6. 12 45
      vendor/github.com/go-xorm/core/db.go
  7. 1 6
      vendor/github.com/go-xorm/core/dialect.go
  8. 3 3
      vendor/github.com/go-xorm/core/filter.go
  9. 0 2
      vendor/github.com/go-xorm/core/index.go
  10. 61 3
      vendor/github.com/go-xorm/core/rows.go
  11. 0 3
      vendor/github.com/go-xorm/core/scan.go
  12. 16 20
      vendor/github.com/go-xorm/core/type.go
  13. 0 74
      vendor/github.com/go-xorm/xorm/dialect_mysql.go
  14. 26 70
      vendor/github.com/go-xorm/xorm/dialect_postgres.go
  15. 106 64
      vendor/github.com/go-xorm/xorm/engine.go
  16. 1 4
      vendor/github.com/go-xorm/xorm/engine_cond.go
  17. 0 113
      vendor/github.com/go-xorm/xorm/engine_table.go
  18. 0 13
      vendor/github.com/go-xorm/xorm/error.go
  19. 162 0
      vendor/github.com/go-xorm/xorm/helpers.go
  20. 0 6
      vendor/github.com/go-xorm/xorm/interface.go
  21. 3 3
      vendor/github.com/go-xorm/xorm/rows.go
  22. 356 353
      vendor/github.com/go-xorm/xorm/session.go
  23. 0 107
      vendor/github.com/go-xorm/xorm/session_cols.go
  24. 3 3
      vendor/github.com/go-xorm/xorm/session_delete.go
  25. 3 12
      vendor/github.com/go-xorm/xorm/session_exist.go
  26. 6 43
      vendor/github.com/go-xorm/xorm/session_find.go
  27. 3 12
      vendor/github.com/go-xorm/xorm/session_get.go
  28. 43 115
      vendor/github.com/go-xorm/xorm/session_insert.go
  29. 2 16
      vendor/github.com/go-xorm/xorm/session_query.go
  30. 51 36
      vendor/github.com/go-xorm/xorm/session_schema.go
  31. 14 101
      vendor/github.com/go-xorm/xorm/session_update.go
  32. 123 98
      vendor/github.com/go-xorm/xorm/statement.go
  33. 1 9
      vendor/github.com/go-xorm/xorm/xorm.go

+ 5 - 5
Gopkg.lock

@@ -186,14 +186,14 @@
 [[projects]]
   name = "github.com/go-xorm/core"
   packages = ["."]
-  revision = "f43c33d9a48db006417a7ac4c16b08897e3e1458"
-  version = "v0.5.8"
+  revision = "da1adaf7a28ca792961721a34e6e04945200c890"
+  version = "v0.5.7"
 
 [[projects]]
   name = "github.com/go-xorm/xorm"
   packages = ["."]
-  revision = "fc1b13e0d8e240788213230aa5747eb557f80f41"
-  version = "v0.6.6"
+  revision = "1933dd69e294c0a26c0266637067f24dbb25770c"
+  version = "v0.6.4"
 
 [[projects]]
   branch = "master"
@@ -670,6 +670,6 @@
 [solve-meta]
   analyzer-name = "dep"
   analyzer-version = 1
-  inputs-digest = "cdeb99713eda72e1ea84b5e6b110819785823cec9bc38b147efa0b86949ecff0"
+  inputs-digest = "6c7ae4bcbe7fa4430d3bdbf204df1b7c59cba88151fbcefa167ce15e6351b6d3"
   solver-name = "gps-cdcl"
   solver-version = 1

+ 2 - 2
Gopkg.toml

@@ -85,11 +85,11 @@ ignored = [
 
 [[constraint]]
   name = "github.com/go-xorm/core"
-  version = "0.5.7"
+  version = "=0.5.7"
 
 [[constraint]]
   name = "github.com/go-xorm/xorm"
-  version = "0.6.4"
+  version = "=0.6.4"
 
 [[constraint]]
   name = "github.com/gorilla/websocket"

+ 2 - 2
pkg/services/sqlstore/sqlstore.go

@@ -277,8 +277,8 @@ func InitTestDB(t *testing.T) *SqlStore {
 		t.Fatalf("Failed to init test database: %v", err)
 	}
 
-	//// sqlstore.engine.DatabaseTZ = time.UTC
-	//// sqlstore.engine.TZLocation = time.UTC
+	sqlstore.engine.DatabaseTZ = time.UTC
+	sqlstore.engine.TZLocation = time.UTC
 
 	return sqlstore
 }

+ 4 - 4
vendor/github.com/go-xorm/core/cache.go

@@ -1,12 +1,11 @@
 package core
 
 import (
-	"bytes"
-	"encoding/gob"
 	"errors"
 	"fmt"
-	"strings"
 	"time"
+	"bytes"
+	"encoding/gob"
 )
 
 const (
@@ -56,10 +55,11 @@ func encodeIds(ids []PK) (string, error) {
 	return buf.String(), err
 }
 
+
 func decodeIds(s string) ([]PK, error) {
 	pks := make([]PK, 0)
 
-	dec := gob.NewDecoder(strings.NewReader(s))
+	dec := gob.NewDecoder(bytes.NewBufferString(s))
 	err := dec.Decode(&pks)
 
 	return pks, err

+ 8 - 8
vendor/github.com/go-xorm/core/column.go

@@ -79,10 +79,6 @@ func (col *Column) String(d Dialect) string {
 		}
 	}
 
-	if col.Default != "" {
-		sql += "DEFAULT " + col.Default + " "
-	}
-
 	if d.ShowCreateNull() {
 		if col.Nullable {
 			sql += "NULL "
@@ -91,6 +87,10 @@ func (col *Column) String(d Dialect) string {
 		}
 	}
 
+	if col.Default != "" {
+		sql += "DEFAULT " + col.Default + " "
+	}
+
 	return sql
 }
 
@@ -99,10 +99,6 @@ 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 "
@@ -111,6 +107,10 @@ func (col *Column) StringNoPk(d Dialect) string {
 		}
 	}
 
+	if col.Default != "" {
+		sql += "DEFAULT " + col.Default + " "
+	}
+
 	return sql
 }
 

+ 12 - 45
vendor/github.com/go-xorm/core/db.go

@@ -7,11 +7,6 @@ import (
 	"fmt"
 	"reflect"
 	"regexp"
-	"sync"
-)
-
-var (
-	DefaultCacheSize = 200
 )
 
 func MapToSlice(query string, mp interface{}) (string, []interface{}, error) {
@@ -63,16 +58,9 @@ func StructToSlice(query string, st interface{}) (string, []interface{}, error)
 	return query, args, nil
 }
 
-type cacheStruct struct {
-	value reflect.Value
-	idx   int
-}
-
 type DB struct {
 	*sql.DB
-	Mapper            IMapper
-	reflectCache      map[reflect.Type]*cacheStruct
-	reflectCacheMutex sync.RWMutex
+	Mapper IMapper
 }
 
 func Open(driverName, dataSourceName string) (*DB, error) {
@@ -80,32 +68,11 @@ func Open(driverName, dataSourceName string) (*DB, error) {
 	if err != nil {
 		return nil, err
 	}
-	return &DB{
-		DB:           db,
-		Mapper:       NewCacheMapper(&SnakeMapper{}),
-		reflectCache: make(map[reflect.Type]*cacheStruct),
-	}, nil
+	return &DB{db, NewCacheMapper(&SnakeMapper{})}, nil
 }
 
 func FromDB(db *sql.DB) *DB {
-	return &DB{
-		DB:           db,
-		Mapper:       NewCacheMapper(&SnakeMapper{}),
-		reflectCache: make(map[reflect.Type]*cacheStruct),
-	}
-}
-
-func (db *DB) reflectNew(typ reflect.Type) reflect.Value {
-	db.reflectCacheMutex.Lock()
-	defer db.reflectCacheMutex.Unlock()
-	cs, ok := db.reflectCache[typ]
-	if !ok || cs.idx+1 > DefaultCacheSize-1 {
-		cs = &cacheStruct{reflect.MakeSlice(reflect.SliceOf(typ), DefaultCacheSize, DefaultCacheSize), 0}
-		db.reflectCache[typ] = cs
-	} else {
-		cs.idx = cs.idx + 1
-	}
-	return cs.value.Index(cs.idx).Addr()
+	return &DB{db, NewCacheMapper(&SnakeMapper{})}
 }
 
 func (db *DB) Query(query string, args ...interface{}) (*Rows, error) {
@@ -116,7 +83,7 @@ func (db *DB) Query(query string, args ...interface{}) (*Rows, error) {
 		}
 		return nil, err
 	}
-	return &Rows{rows, db}, nil
+	return &Rows{rows, db.Mapper}, nil
 }
 
 func (db *DB) QueryMap(query string, mp interface{}) (*Rows, error) {
@@ -161,8 +128,8 @@ func (db *DB) QueryRowStruct(query string, st interface{}) *Row {
 
 type Stmt struct {
 	*sql.Stmt
-	db    *DB
-	names map[string]int
+	Mapper IMapper
+	names  map[string]int
 }
 
 func (db *DB) Prepare(query string) (*Stmt, error) {
@@ -178,7 +145,7 @@ func (db *DB) Prepare(query string) (*Stmt, error) {
 	if err != nil {
 		return nil, err
 	}
-	return &Stmt{stmt, db, names}, nil
+	return &Stmt{stmt, db.Mapper, names}, nil
 }
 
 func (s *Stmt) ExecMap(mp interface{}) (sql.Result, error) {
@@ -212,7 +179,7 @@ func (s *Stmt) Query(args ...interface{}) (*Rows, error) {
 	if err != nil {
 		return nil, err
 	}
-	return &Rows{rows, s.db}, nil
+	return &Rows{rows, s.Mapper}, nil
 }
 
 func (s *Stmt) QueryMap(mp interface{}) (*Rows, error) {
@@ -307,7 +274,7 @@ func (EmptyScanner) Scan(src interface{}) error {
 
 type Tx struct {
 	*sql.Tx
-	db *DB
+	Mapper IMapper
 }
 
 func (db *DB) Begin() (*Tx, error) {
@@ -315,7 +282,7 @@ func (db *DB) Begin() (*Tx, error) {
 	if err != nil {
 		return nil, err
 	}
-	return &Tx{tx, db}, nil
+	return &Tx{tx, db.Mapper}, nil
 }
 
 func (tx *Tx) Prepare(query string) (*Stmt, error) {
@@ -331,7 +298,7 @@ func (tx *Tx) Prepare(query string) (*Stmt, error) {
 	if err != nil {
 		return nil, err
 	}
-	return &Stmt{stmt, tx.db, names}, nil
+	return &Stmt{stmt, tx.Mapper, names}, nil
 }
 
 func (tx *Tx) Stmt(stmt *Stmt) *Stmt {
@@ -360,7 +327,7 @@ func (tx *Tx) Query(query string, args ...interface{}) (*Rows, error) {
 	if err != nil {
 		return nil, err
 	}
-	return &Rows{rows, tx.db}, nil
+	return &Rows{rows, tx.Mapper}, nil
 }
 
 func (tx *Tx) QueryMap(query string, mp interface{}) (*Rows, error) {

+ 1 - 6
vendor/github.com/go-xorm/core/dialect.go

@@ -74,7 +74,6 @@ type Dialect interface {
 	GetIndexes(tableName string) (map[string]*Index, error)
 
 	Filters() []Filter
-	SetParams(params map[string]string)
 }
 
 func OpenDialect(dialect Dialect) (*DB, error) {
@@ -149,8 +148,7 @@ func (db *Base) SupportDropIfExists() bool {
 }
 
 func (db *Base) DropTableSql(tableName string) string {
-	quote := db.dialect.Quote
-	return fmt.Sprintf("DROP TABLE IF EXISTS %s", quote(tableName))
+	return fmt.Sprintf("DROP TABLE IF EXISTS `%s`", tableName)
 }
 
 func (db *Base) HasRecords(query string, args ...interface{}) (bool, error) {
@@ -291,9 +289,6 @@ func (b *Base) LogSQL(sql string, args []interface{}) {
 	}
 }
 
-func (b *Base) SetParams(params map[string]string) {
-}
-
 var (
 	dialects = map[string]func() Dialect{}
 )

+ 3 - 3
vendor/github.com/go-xorm/core/filter.go

@@ -37,9 +37,9 @@ func (q *Quoter) Quote(content string) string {
 func (i *IdFilter) Do(sql string, dialect Dialect, table *Table) string {
 	quoter := NewQuoter(dialect)
 	if table != nil && len(table.PrimaryKeys) == 1 {
-		sql = strings.Replace(sql, " `(id)` ", " "+quoter.Quote(table.PrimaryKeys[0])+" ", -1)
-		sql = strings.Replace(sql, " "+quoter.Quote("(id)")+" ", " "+quoter.Quote(table.PrimaryKeys[0])+" ", -1)
-		return strings.Replace(sql, " (id) ", " "+quoter.Quote(table.PrimaryKeys[0])+" ", -1)
+		sql = strings.Replace(sql, "`(id)`", quoter.Quote(table.PrimaryKeys[0]), -1)
+		sql = strings.Replace(sql, quoter.Quote("(id)"), quoter.Quote(table.PrimaryKeys[0]), -1)
+		return strings.Replace(sql, "(id)", quoter.Quote(table.PrimaryKeys[0]), -1)
 	}
 	return sql
 }

+ 0 - 2
vendor/github.com/go-xorm/core/index.go

@@ -22,8 +22,6 @@ type Index struct {
 func (index *Index) XName(tableName string) string {
 	if !strings.HasPrefix(index.Name, "UQE_") &&
 		!strings.HasPrefix(index.Name, "IDX_") {
-		tableName = strings.Replace(tableName, `"`, "", -1)
-		tableName = strings.Replace(tableName, `.`, "_", -1)
 		if index.Type == UniqueType {
 			return fmt.Sprintf("UQE_%v_%v", tableName, index.Name)
 		}

+ 61 - 3
vendor/github.com/go-xorm/core/rows.go

@@ -9,7 +9,7 @@ import (
 
 type Rows struct {
 	*sql.Rows
-	db *DB
+	Mapper IMapper
 }
 
 func (rs *Rows) ToMapString() ([]map[string]string, error) {
@@ -105,7 +105,7 @@ func (rs *Rows) ScanStructByName(dest interface{}) error {
 	newDest := make([]interface{}, len(cols))
 	var v EmptyScanner
 	for j, name := range cols {
-		f := fieldByName(vv.Elem(), rs.db.Mapper.Table2Obj(name))
+		f := fieldByName(vv.Elem(), rs.Mapper.Table2Obj(name))
 		if f.IsValid() {
 			newDest[j] = f.Addr().Interface()
 		} else {
@@ -116,6 +116,36 @@ func (rs *Rows) ScanStructByName(dest interface{}) error {
 	return rs.Rows.Scan(newDest...)
 }
 
+type cacheStruct struct {
+	value reflect.Value
+	idx   int
+}
+
+var (
+	reflectCache      = make(map[reflect.Type]*cacheStruct)
+	reflectCacheMutex sync.RWMutex
+)
+
+func ReflectNew(typ reflect.Type) reflect.Value {
+	reflectCacheMutex.RLock()
+	cs, ok := reflectCache[typ]
+	reflectCacheMutex.RUnlock()
+
+	const newSize = 200
+
+	if !ok || cs.idx+1 > newSize-1 {
+		cs = &cacheStruct{reflect.MakeSlice(reflect.SliceOf(typ), newSize, newSize), 0}
+		reflectCacheMutex.Lock()
+		reflectCache[typ] = cs
+		reflectCacheMutex.Unlock()
+	} else {
+		reflectCacheMutex.Lock()
+		cs.idx = cs.idx + 1
+		reflectCacheMutex.Unlock()
+	}
+	return cs.value.Index(cs.idx).Addr()
+}
+
 // scan data to a slice's pointer, slice's length should equal to columns' number
 func (rs *Rows) ScanSlice(dest interface{}) error {
 	vv := reflect.ValueOf(dest)
@@ -167,7 +197,9 @@ func (rs *Rows) ScanMap(dest interface{}) error {
 	vvv := vv.Elem()
 
 	for i, _ := range cols {
-		newDest[i] = rs.db.reflectNew(vvv.Type().Elem()).Interface()
+		newDest[i] = ReflectNew(vvv.Type().Elem()).Interface()
+		//v := reflect.New(vvv.Type().Elem())
+		//newDest[i] = v.Interface()
 	}
 
 	err = rs.Rows.Scan(newDest...)
@@ -183,6 +215,32 @@ func (rs *Rows) ScanMap(dest interface{}) error {
 	return nil
 }
 
+/*func (rs *Rows) ScanMap(dest interface{}) error {
+	vv := reflect.ValueOf(dest)
+	if vv.Kind() != reflect.Ptr || vv.Elem().Kind() != reflect.Map {
+		return errors.New("dest should be a map's pointer")
+	}
+
+	cols, err := rs.Columns()
+	if err != nil {
+		return err
+	}
+
+	newDest := make([]interface{}, len(cols))
+	err = rs.ScanSlice(newDest)
+	if err != nil {
+		return err
+	}
+
+	vvv := vv.Elem()
+
+	for i, name := range cols {
+		vname := reflect.ValueOf(name)
+		vvv.SetMapIndex(vname, reflect.ValueOf(newDest[i]).Elem())
+	}
+
+	return nil
+}*/
 type Row struct {
 	rows *Rows
 	// One of these two will be non-nil:

+ 0 - 3
vendor/github.com/go-xorm/core/scan.go

@@ -44,9 +44,6 @@ 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)

+ 16 - 20
vendor/github.com/go-xorm/core/type.go

@@ -69,17 +69,15 @@ var (
 	Enum = "ENUM"
 	Set  = "SET"
 
-	Char             = "CHAR"
-	Varchar          = "VARCHAR"
-	NVarchar         = "NVARCHAR"
-	TinyText         = "TINYTEXT"
-	Text             = "TEXT"
-	Clob             = "CLOB"
-	MediumText       = "MEDIUMTEXT"
-	LongText         = "LONGTEXT"
-	Uuid             = "UUID"
-	UniqueIdentifier = "UNIQUEIDENTIFIER"
-	SysName          = "SYSNAME"
+	Char       = "CHAR"
+	Varchar    = "VARCHAR"
+	NVarchar   = "NVARCHAR"
+	TinyText   = "TINYTEXT"
+	Text       = "TEXT"
+	Clob       = "CLOB"
+	MediumText = "MEDIUMTEXT"
+	LongText   = "LONGTEXT"
+	Uuid       = "UUID"
 
 	Date       = "DATE"
 	DateTime   = "DATETIME"
@@ -134,7 +132,6 @@ var (
 		LongText:   TEXT_TYPE,
 		Uuid:       TEXT_TYPE,
 		Clob:       TEXT_TYPE,
-		SysName:    TEXT_TYPE,
 
 		Date:       TIME_TYPE,
 		DateTime:   TIME_TYPE,
@@ -151,12 +148,11 @@ var (
 		Binary:    BLOB_TYPE,
 		VarBinary: BLOB_TYPE,
 
-		TinyBlob:         BLOB_TYPE,
-		Blob:             BLOB_TYPE,
-		MediumBlob:       BLOB_TYPE,
-		LongBlob:         BLOB_TYPE,
-		Bytea:            BLOB_TYPE,
-		UniqueIdentifier: BLOB_TYPE,
+		TinyBlob:   BLOB_TYPE,
+		Blob:       BLOB_TYPE,
+		MediumBlob: BLOB_TYPE,
+		LongBlob:   BLOB_TYPE,
+		Bytea:      BLOB_TYPE,
 
 		Bool: NUMERIC_TYPE,
 
@@ -293,9 +289,9 @@ func SQLType2Type(st SQLType) reflect.Type {
 		return reflect.TypeOf(float32(1))
 	case Double:
 		return reflect.TypeOf(float64(1))
-	case Char, Varchar, NVarchar, TinyText, Text, MediumText, LongText, Enum, Set, Uuid, Clob, SysName:
+	case Char, Varchar, NVarchar, TinyText, Text, MediumText, LongText, Enum, Set, Uuid, Clob:
 		return reflect.TypeOf("")
-	case TinyBlob, Blob, LongBlob, Bytea, Binary, MediumBlob, VarBinary, UniqueIdentifier:
+	case TinyBlob, Blob, LongBlob, Bytea, Binary, MediumBlob, VarBinary:
 		return reflect.TypeOf([]byte{})
 	case Bool:
 		return reflect.TypeOf(true)

+ 0 - 74
vendor/github.com/go-xorm/xorm/dialect_mysql.go

@@ -172,33 +172,12 @@ type mysql struct {
 	allowAllFiles     bool
 	allowOldPasswords bool
 	clientFoundRows   bool
-	rowFormat         string
 }
 
 func (db *mysql) Init(d *core.DB, uri *core.Uri, drivername, dataSourceName string) error {
 	return db.Base.Init(d, db, uri, drivername, dataSourceName)
 }
 
-func (db *mysql) SetParams(params map[string]string) {
-	rowFormat, ok := params["rowFormat"]
-	if ok {
-		var t = strings.ToUpper(rowFormat)
-		switch t {
-		case "COMPACT":
-			fallthrough
-		case "REDUNDANT":
-			fallthrough
-		case "DYNAMIC":
-			fallthrough
-		case "COMPRESSED":
-			db.rowFormat = t
-			break
-		default:
-			break
-		}
-	}
-}
-
 func (db *mysql) SqlType(c *core.Column) string {
 	var res string
 	switch t := c.SQLType.Name; t {
@@ -508,59 +487,6 @@ func (db *mysql) GetIndexes(tableName string) (map[string]*core.Index, error) {
 	return indexes, nil
 }
 
-func (db *mysql) CreateTableSql(table *core.Table, tableName, storeEngine, charset string) string {
-	var sql string
-	sql = "CREATE TABLE IF NOT EXISTS "
-	if tableName == "" {
-		tableName = table.Name
-	}
-
-	sql += db.Quote(tableName)
-	sql += " ("
-
-	if len(table.ColumnsSeq()) > 0 {
-		pkList := table.PrimaryKeys
-
-		for _, colName := range table.ColumnsSeq() {
-			col := table.GetColumn(colName)
-			if col.IsPrimaryKey && len(pkList) == 1 {
-				sql += col.String(db)
-			} else {
-				sql += col.StringNoPk(db)
-			}
-			sql = strings.TrimSpace(sql)
-			if len(col.Comment) > 0 {
-				sql += " COMMENT '" + col.Comment + "'"
-			}
-			sql += ", "
-		}
-
-		if len(pkList) > 1 {
-			sql += "PRIMARY KEY ( "
-			sql += db.Quote(strings.Join(pkList, db.Quote(",")))
-			sql += " ), "
-		}
-
-		sql = sql[:len(sql)-2]
-	}
-	sql += ")"
-
-	if storeEngine != "" {
-		sql += " ENGINE=" + storeEngine
-	}
-
-	if len(charset) == 0 {
-		charset = db.URI().Charset
-	} else if len(charset) > 0 {
-		sql += " DEFAULT CHARSET " + charset
-	}
-
-	if db.rowFormat != "" {
-		sql += " ROW_FORMAT=" + db.rowFormat
-	}
-	return sql
-}
-
 func (db *mysql) Filters() []core.Filter {
 	return []core.Filter{&core.IdFilter{}}
 }

+ 26 - 70
vendor/github.com/go-xorm/xorm/dialect_postgres.go

@@ -764,26 +764,14 @@ var (
 		"YES":                       true,
 		"ZONE":                      true,
 	}
-
-	// DefaultPostgresSchema default postgres schema
-	DefaultPostgresSchema = "public"
 )
 
-const postgresPublicSchema = "public"
-
 type postgres struct {
 	core.Base
 }
 
 func (db *postgres) Init(d *core.DB, uri *core.Uri, drivername, dataSourceName string) error {
-	err := db.Base.Init(d, db, uri, drivername, dataSourceName)
-	if err != nil {
-		return err
-	}
-	if db.Schema == "" {
-		db.Schema = DefaultPostgresSchema
-	}
-	return nil
+	return db.Base.Init(d, db, uri, drivername, dataSourceName)
 }
 
 func (db *postgres) SqlType(c *core.Column) string {
@@ -880,42 +868,32 @@ func (db *postgres) IndexOnTable() bool {
 }
 
 func (db *postgres) IndexCheckSql(tableName, idxName string) (string, []interface{}) {
-	if len(db.Schema) == 0 {
-		args := []interface{}{tableName, idxName}
-		return `SELECT indexname FROM pg_indexes WHERE tablename = ? AND indexname = ?`, args
-	}
-
-	args := []interface{}{db.Schema, tableName, idxName}
+	args := []interface{}{tableName, idxName}
 	return `SELECT indexname FROM pg_indexes ` +
-		`WHERE schemaname = ? AND tablename = ? AND indexname = ?`, args
+		`WHERE tablename = ? AND indexname = ?`, args
 }
 
 func (db *postgres) TableCheckSql(tableName string) (string, []interface{}) {
-	if len(db.Schema) == 0 {
-		args := []interface{}{tableName}
-		return `SELECT tablename FROM pg_tables WHERE tablename = ?`, args
-	}
-
-	args := []interface{}{db.Schema, tableName}
-	return `SELECT tablename FROM pg_tables WHERE schemaname = ? AND tablename = ?`, args
+	args := []interface{}{tableName}
+	return `SELECT tablename FROM pg_tables WHERE tablename = ?`, args
 }
 
+/*func (db *postgres) ColumnCheckSql(tableName, colName string) (string, []interface{}) {
+	args := []interface{}{tableName, colName}
+	return "SELECT column_name FROM INFORMATION_SCHEMA.COLUMNS WHERE table_name = ?" +
+		" AND column_name = ?", args
+}*/
+
 func (db *postgres) ModifyColumnSql(tableName string, col *core.Column) string {
-	if len(db.Schema) == 0 {
-		return fmt.Sprintf("alter table %s ALTER COLUMN %s TYPE %s",
-			tableName, col.Name, db.SqlType(col))
-	}
-	return fmt.Sprintf("alter table %s.%s ALTER COLUMN %s TYPE %s",
-		db.Schema, tableName, col.Name, db.SqlType(col))
+	return fmt.Sprintf("alter table %s ALTER COLUMN %s TYPE %s",
+		tableName, col.Name, db.SqlType(col))
 }
 
 func (db *postgres) DropIndexSql(tableName string, index *core.Index) string {
+	//var unique string
 	quote := db.Quote
 	idxName := index.Name
 
-	tableName = strings.Replace(tableName, `"`, "", -1)
-	tableName = strings.Replace(tableName, `.`, "_", -1)
-
 	if !strings.HasPrefix(idxName, "UQE_") &&
 		!strings.HasPrefix(idxName, "IDX_") {
 		if index.Type == core.UniqueType {
@@ -924,21 +902,13 @@ func (db *postgres) DropIndexSql(tableName string, index *core.Index) string {
 			idxName = fmt.Sprintf("IDX_%v_%v", tableName, index.Name)
 		}
 	}
-	if db.Uri.Schema != "" {
-		idxName = db.Uri.Schema + "." + idxName
-	}
 	return fmt.Sprintf("DROP INDEX %v", quote(idxName))
 }
 
 func (db *postgres) IsColumnExist(tableName, colName string) (bool, error) {
-	args := []interface{}{db.Schema, tableName, colName}
-	query := "SELECT column_name FROM INFORMATION_SCHEMA.COLUMNS WHERE table_schema = $1 AND table_name = $2" +
-		" AND column_name = $3"
-	if len(db.Schema) == 0 {
-		args = []interface{}{tableName, colName}
-		query = "SELECT column_name FROM INFORMATION_SCHEMA.COLUMNS WHERE table_name = $1" +
-			" AND column_name = $2"
-	}
+	args := []interface{}{tableName, colName}
+	query := "SELECT column_name FROM INFORMATION_SCHEMA.COLUMNS WHERE table_name = $1" +
+		" AND column_name = $2"
 	db.LogSQL(query, args)
 
 	rows, err := db.DB().Query(query, args...)
@@ -951,7 +921,8 @@ func (db *postgres) IsColumnExist(tableName, colName string) (bool, error) {
 }
 
 func (db *postgres) GetColumns(tableName string) ([]string, map[string]*core.Column, error) {
-	args := []interface{}{tableName}
+	// FIXME: the schema should be replaced by user custom's
+	args := []interface{}{tableName, "public"}
 	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
@@ -962,15 +933,7 @@ FROM pg_attribute f
     LEFT JOIN pg_constraint p ON p.conrelid = c.oid AND f.attnum = ANY (p.conkey)
     LEFT JOIN pg_class AS g ON p.confrelid = g.oid
     LEFT JOIN INFORMATION_SCHEMA.COLUMNS s ON s.column_name=f.attname AND c.relname=s.table_name
-WHERE c.relkind = 'r'::char AND c.relname = $1%s AND f.attnum > 0 ORDER BY f.attnum;`
-
-	var f string
-	if len(db.Schema) != 0 {
-		args = append(args, db.Schema)
-		f = " AND s.table_schema = $2"
-	}
-	s = fmt.Sprintf(s, f)
-
+WHERE c.relkind = 'r'::char AND c.relname = $1 AND s.table_schema = $2 AND f.attnum > 0 ORDER BY f.attnum;`
 	db.LogSQL(s, args)
 
 	rows, err := db.DB().Query(s, args...)
@@ -1060,13 +1023,9 @@ WHERE c.relkind = 'r'::char AND c.relname = $1%s AND f.attnum > 0 ORDER BY f.att
 }
 
 func (db *postgres) GetTables() ([]*core.Table, error) {
-	args := []interface{}{}
-	s := "SELECT tablename FROM pg_tables"
-	if len(db.Schema) != 0 {
-		args = append(args, db.Schema)
-		s = s + " WHERE schemaname = $1"
-	}
-
+	// FIXME: replace public to user customrize schema
+	args := []interface{}{"public"}
+	s := fmt.Sprintf("SELECT tablename FROM pg_tables WHERE schemaname = $1")
 	db.LogSQL(s, args)
 
 	rows, err := db.DB().Query(s, args...)
@@ -1090,12 +1049,9 @@ func (db *postgres) GetTables() ([]*core.Table, error) {
 }
 
 func (db *postgres) GetIndexes(tableName string) (map[string]*core.Index, error) {
-	args := []interface{}{tableName}
-	s := fmt.Sprintf("SELECT indexname, indexdef FROM pg_indexes WHERE tablename=$1")
-	if len(db.Schema) != 0 {
-		args = append(args, db.Schema)
-		s = s + " AND schemaname=$2"
-	}
+	// FIXME: replace the public schema to user specify schema
+	args := []interface{}{"public", tableName}
+	s := fmt.Sprintf("SELECT indexname, indexdef FROM pg_indexes WHERE schemaname=$1 AND tablename=$2")
 	db.LogSQL(s, args)
 
 	rows, err := db.DB().Query(s, args...)

+ 106 - 64
vendor/github.com/go-xorm/xorm/engine.go

@@ -49,35 +49,6 @@ type Engine struct {
 	tagHandlers map[string]tagHandler
 
 	engineGroup *EngineGroup
-
-	cachers    map[string]core.Cacher
-	cacherLock sync.RWMutex
-}
-
-func (engine *Engine) setCacher(tableName string, cacher core.Cacher) {
-	engine.cacherLock.Lock()
-	engine.cachers[tableName] = cacher
-	engine.cacherLock.Unlock()
-}
-
-func (engine *Engine) SetCacher(tableName string, cacher core.Cacher) {
-	engine.setCacher(tableName, cacher)
-}
-
-func (engine *Engine) getCacher(tableName string) core.Cacher {
-	var cacher core.Cacher
-	var ok bool
-	engine.cacherLock.RLock()
-	cacher, ok = engine.cachers[tableName]
-	engine.cacherLock.RUnlock()
-	if !ok && !engine.disableGlobalCache {
-		cacher = engine.Cacher
-	}
-	return cacher
-}
-
-func (engine *Engine) GetCacher(tableName string) core.Cacher {
-	return engine.getCacher(tableName)
 }
 
 // BufferSize sets buffer size for iterate
@@ -274,7 +245,13 @@ func (engine *Engine) NoCascade() *Session {
 
 // MapCacher Set a table use a special cacher
 func (engine *Engine) MapCacher(bean interface{}, cacher core.Cacher) error {
-	engine.setCacher(engine.TableName(bean, true), cacher)
+	v := rValue(bean)
+	tb, err := engine.autoMapType(v)
+	if err != nil {
+		return err
+	}
+
+	tb.Cacher = cacher
 	return nil
 }
 
@@ -559,6 +536,33 @@ func (engine *Engine) dumpTables(tables []*core.Table, w io.Writer, tp ...core.D
 	return nil
 }
 
+func (engine *Engine) tableName(beanOrTableName interface{}) (string, error) {
+	v := rValue(beanOrTableName)
+	if v.Type().Kind() == reflect.String {
+		return beanOrTableName.(string), nil
+	} else if v.Type().Kind() == reflect.Struct {
+		return engine.tbName(v), nil
+	}
+	return "", errors.New("bean should be a struct or struct's point")
+}
+
+func (engine *Engine) tbName(v reflect.Value) string {
+	if tb, ok := v.Interface().(TableName); ok {
+		return tb.TableName()
+	}
+
+	if v.Type().Kind() == reflect.Ptr {
+		if tb, ok := reflect.Indirect(v).Interface().(TableName); ok {
+			return tb.TableName()
+		}
+	} else if v.CanAddr() {
+		if tb, ok := v.Addr().Interface().(TableName); ok {
+			return tb.TableName()
+		}
+	}
+	return engine.TableMapper.Obj2Table(reflect.Indirect(v).Type().Name())
+}
+
 // Cascade use cascade or not
 func (engine *Engine) Cascade(trueOrFalse ...bool) *Session {
 	session := engine.NewSession()
@@ -842,7 +846,7 @@ func (engine *Engine) TableInfo(bean interface{}) *Table {
 	if err != nil {
 		engine.logger.Error(err)
 	}
-	return &Table{tb, engine.TableName(bean)}
+	return &Table{tb, engine.tbName(v)}
 }
 
 func addIndex(indexName string, table *core.Table, col *core.Column, indexType int) {
@@ -857,6 +861,15 @@ func addIndex(indexName string, table *core.Table, col *core.Column, indexType i
 	}
 }
 
+func (engine *Engine) newTable() *core.Table {
+	table := core.NewEmptyTable()
+
+	if !engine.disableGlobalCache {
+		table.Cacher = engine.Cacher
+	}
+	return table
+}
+
 // TableName table name interface to define customerize table name
 type TableName interface {
 	TableName() string
@@ -868,9 +881,21 @@ var (
 
 func (engine *Engine) mapType(v reflect.Value) (*core.Table, error) {
 	t := v.Type()
-	table := core.NewEmptyTable()
+	table := engine.newTable()
+	if tb, ok := v.Interface().(TableName); ok {
+		table.Name = tb.TableName()
+	} else {
+		if v.CanAddr() {
+			if tb, ok = v.Addr().Interface().(TableName); ok {
+				table.Name = tb.TableName()
+			}
+		}
+		if table.Name == "" {
+			table.Name = engine.TableMapper.Obj2Table(t.Name())
+		}
+	}
+
 	table.Type = t
-	table.Name = engine.tbNameForMap(v)
 
 	var idFieldColName string
 	var hasCacheTag, hasNoCacheTag bool
@@ -1024,15 +1049,15 @@ func (engine *Engine) mapType(v reflect.Value) (*core.Table, error) {
 	if hasCacheTag {
 		if engine.Cacher != nil { // !nash! use engine's cacher if provided
 			engine.logger.Info("enable cache on table:", table.Name)
-			engine.setCacher(table.Name, engine.Cacher)
+			table.Cacher = engine.Cacher
 		} else {
 			engine.logger.Info("enable LRU cache on table:", table.Name)
-			engine.setCacher(table.Name, NewLRUCacher2(NewMemoryStore(), time.Hour, 10000))
+			table.Cacher = NewLRUCacher2(NewMemoryStore(), time.Hour, 10000) // !nashtsai! HACK use LRU cacher for now
 		}
 	}
 	if hasNoCacheTag {
-		engine.logger.Info("disable cache on table:", table.Name)
-		engine.setCacher(table.Name, nil)
+		engine.logger.Info("no cache on table:", table.Name)
+		table.Cacher = nil
 	}
 
 	return table, nil
@@ -1137,10 +1162,26 @@ func (engine *Engine) CreateUniques(bean interface{}) error {
 	return session.CreateUniques(bean)
 }
 
+func (engine *Engine) getCacher2(table *core.Table) core.Cacher {
+	return table.Cacher
+}
+
 // ClearCacheBean if enabled cache, clear the cache bean
 func (engine *Engine) ClearCacheBean(bean interface{}, id string) error {
-	tableName := engine.TableName(bean)
-	cacher := engine.getCacher(tableName)
+	v := rValue(bean)
+	t := v.Type()
+	if t.Kind() != reflect.Struct {
+		return errors.New("error params")
+	}
+	tableName := engine.tbName(v)
+	table, err := engine.autoMapType(v)
+	if err != nil {
+		return err
+	}
+	cacher := table.Cacher
+	if cacher == nil {
+		cacher = engine.Cacher
+	}
 	if cacher != nil {
 		cacher.ClearIds(tableName)
 		cacher.DelBean(tableName, id)
@@ -1151,8 +1192,21 @@ func (engine *Engine) ClearCacheBean(bean interface{}, id string) error {
 // ClearCache if enabled cache, clear some tables' cache
 func (engine *Engine) ClearCache(beans ...interface{}) error {
 	for _, bean := range beans {
-		tableName := engine.TableName(bean)
-		cacher := engine.getCacher(tableName)
+		v := rValue(bean)
+		t := v.Type()
+		if t.Kind() != reflect.Struct {
+			return errors.New("error params")
+		}
+		tableName := engine.tbName(v)
+		table, err := engine.autoMapType(v)
+		if err != nil {
+			return err
+		}
+
+		cacher := table.Cacher
+		if cacher == nil {
+			cacher = engine.Cacher
+		}
 		if cacher != nil {
 			cacher.ClearIds(tableName)
 			cacher.ClearBeans(tableName)
@@ -1170,13 +1224,13 @@ func (engine *Engine) Sync(beans ...interface{}) error {
 
 	for _, bean := range beans {
 		v := rValue(bean)
-		tableNameNoSchema := engine.tbNameNoSchema(v.Interface())
+		tableName := engine.tbName(v)
 		table, err := engine.autoMapType(v)
 		if err != nil {
 			return err
 		}
 
-		isExist, err := session.Table(bean).isTableExist(tableNameNoSchema)
+		isExist, err := session.Table(bean).isTableExist(tableName)
 		if err != nil {
 			return err
 		}
@@ -1202,12 +1256,12 @@ func (engine *Engine) Sync(beans ...interface{}) error {
 			}
 		} else {
 			for _, col := range table.Columns() {
-				isExist, err := engine.dialect.IsColumnExist(tableNameNoSchema, col.Name)
+				isExist, err := engine.dialect.IsColumnExist(tableName, col.Name)
 				if err != nil {
 					return err
 				}
 				if !isExist {
-					if err := session.statement.setRefBean(bean); err != nil {
+					if err := session.statement.setRefValue(v); err != nil {
 						return err
 					}
 					err = session.addColumn(col.Name)
@@ -1218,35 +1272,35 @@ func (engine *Engine) Sync(beans ...interface{}) error {
 			}
 
 			for name, index := range table.Indexes {
-				if err := session.statement.setRefBean(bean); err != nil {
+				if err := session.statement.setRefValue(v); err != nil {
 					return err
 				}
 				if index.Type == core.UniqueType {
-					isExist, err := session.isIndexExist2(tableNameNoSchema, index.Cols, true)
+					isExist, err := session.isIndexExist2(tableName, index.Cols, true)
 					if err != nil {
 						return err
 					}
 					if !isExist {
-						if err := session.statement.setRefBean(bean); err != nil {
+						if err := session.statement.setRefValue(v); err != nil {
 							return err
 						}
 
-						err = session.addUnique(tableNameNoSchema, name)
+						err = session.addUnique(tableName, name)
 						if err != nil {
 							return err
 						}
 					}
 				} else if index.Type == core.IndexType {
-					isExist, err := session.isIndexExist2(tableNameNoSchema, index.Cols, false)
+					isExist, err := session.isIndexExist2(tableName, index.Cols, false)
 					if err != nil {
 						return err
 					}
 					if !isExist {
-						if err := session.statement.setRefBean(bean); err != nil {
+						if err := session.statement.setRefValue(v); err != nil {
 							return err
 						}
 
-						err = session.addIndex(tableNameNoSchema, name)
+						err = session.addIndex(tableName, name)
 						if err != nil {
 							return err
 						}
@@ -1399,13 +1453,6 @@ func (engine *Engine) Find(beans interface{}, condiBeans ...interface{}) error {
 	return session.Find(beans, condiBeans...)
 }
 
-// FindAndCount find the results and also return the counts
-func (engine *Engine) FindAndCount(rowsSlicePtr interface{}, condiBean ...interface{}) (int64, error) {
-	session := engine.NewSession()
-	defer session.Close()
-	return session.FindAndCount(rowsSlicePtr, condiBean...)
-}
-
 // Iterate record by record handle records from table, bean's non-empty fields
 // are conditions.
 func (engine *Engine) Iterate(bean interface{}, fun IterFunc) error {
@@ -1582,11 +1629,6 @@ func (engine *Engine) SetTZDatabase(tz *time.Location) {
 	engine.DatabaseTZ = tz
 }
 
-// SetSchema sets the schema of database
-func (engine *Engine) SetSchema(schema string) {
-	engine.dialect.URI().Schema = schema
-}
-
 // Unscoped always disable struct tag "deleted"
 func (engine *Engine) Unscoped() *Session {
 	session := engine.NewSession()

+ 1 - 4
vendor/github.com/go-xorm/xorm/engine_cond.go

@@ -9,7 +9,6 @@ import (
 	"encoding/json"
 	"fmt"
 	"reflect"
-	"strings"
 	"time"
 
 	"github.com/go-xorm/builder"
@@ -52,9 +51,7 @@ func (engine *Engine) buildConds(table *core.Table, bean interface{},
 
 		fieldValuePtr, err := col.ValueOf(bean)
 		if err != nil {
-			if !strings.Contains(err.Error(), "is not valid") {
-				engine.logger.Warn(err)
-			}
+			engine.logger.Error(err)
 			continue
 		}
 

+ 0 - 113
vendor/github.com/go-xorm/xorm/engine_table.go

@@ -1,113 +0,0 @@
-// Copyright 2018 The Xorm Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-package xorm
-
-import (
-	"fmt"
-	"reflect"
-	"strings"
-
-	"github.com/go-xorm/core"
-)
-
-// TableNameWithSchema will automatically add schema prefix on table name
-func (engine *Engine) tbNameWithSchema(v string) string {
-	// Add schema name as prefix of table name.
-	// Only for postgres database.
-	if engine.dialect.DBType() == core.POSTGRES &&
-		engine.dialect.URI().Schema != "" &&
-		engine.dialect.URI().Schema != postgresPublicSchema &&
-		strings.Index(v, ".") == -1 {
-		return engine.dialect.URI().Schema + "." + v
-	}
-	return v
-}
-
-// TableName returns table name with schema prefix if has
-func (engine *Engine) TableName(bean interface{}, includeSchema ...bool) string {
-	tbName := engine.tbNameNoSchema(bean)
-	if len(includeSchema) > 0 && includeSchema[0] {
-		tbName = engine.tbNameWithSchema(tbName)
-	}
-
-	return tbName
-}
-
-// tbName get some table's table name
-func (session *Session) tbNameNoSchema(table *core.Table) string {
-	if len(session.statement.AltTableName) > 0 {
-		return session.statement.AltTableName
-	}
-
-	return table.Name
-}
-
-func (engine *Engine) tbNameForMap(v reflect.Value) string {
-	if v.Type().Implements(tpTableName) {
-		return v.Interface().(TableName).TableName()
-	}
-	if v.Kind() == reflect.Ptr {
-		v = v.Elem()
-		if v.Type().Implements(tpTableName) {
-			return v.Interface().(TableName).TableName()
-		}
-	}
-
-	return engine.TableMapper.Obj2Table(v.Type().Name())
-}
-
-func (engine *Engine) tbNameNoSchema(tablename interface{}) string {
-	switch tablename.(type) {
-	case []string:
-		t := tablename.([]string)
-		if len(t) > 1 {
-			return fmt.Sprintf("%v AS %v", engine.Quote(t[0]), engine.Quote(t[1]))
-		} else if len(t) == 1 {
-			return engine.Quote(t[0])
-		}
-	case []interface{}:
-		t := tablename.([]interface{})
-		l := len(t)
-		var table string
-		if l > 0 {
-			f := t[0]
-			switch f.(type) {
-			case string:
-				table = f.(string)
-			case TableName:
-				table = f.(TableName).TableName()
-			default:
-				v := rValue(f)
-				t := v.Type()
-				if t.Kind() == reflect.Struct {
-					table = engine.tbNameForMap(v)
-				} else {
-					table = engine.Quote(fmt.Sprintf("%v", f))
-				}
-			}
-		}
-		if l > 1 {
-			return fmt.Sprintf("%v AS %v", engine.Quote(table),
-				engine.Quote(fmt.Sprintf("%v", t[1])))
-		} else if l == 1 {
-			return engine.Quote(table)
-		}
-	case TableName:
-		return tablename.(TableName).TableName()
-	case string:
-		return tablename.(string)
-	case reflect.Value:
-		v := tablename.(reflect.Value)
-		return engine.tbNameForMap(v)
-	default:
-		v := rValue(tablename)
-		t := v.Type()
-		if t.Kind() == reflect.Struct {
-			return engine.tbNameForMap(v)
-		}
-		return engine.Quote(fmt.Sprintf("%v", tablename))
-	}
-	return ""
-}

+ 0 - 13
vendor/github.com/go-xorm/xorm/error.go

@@ -6,7 +6,6 @@ package xorm
 
 import (
 	"errors"
-	"fmt"
 )
 
 var (
@@ -26,16 +25,4 @@ var (
 	ErrNotImplemented = errors.New("Not implemented")
 	// ErrConditionType condition type unsupported
 	ErrConditionType = errors.New("Unsupported conditon type")
-	// ErrColumnIsNotExist columns is not exist
-	ErrFieldIsNotExist = errors.New("Field is not exist")
 )
-
-// ErrFieldIsNotValid is not valid
-type ErrFieldIsNotValid struct {
-	FieldName string
-	TableName string
-}
-
-func (e ErrFieldIsNotValid) Error() string {
-	return fmt.Sprintf("field %s is not valid on table %s", e.FieldName, e.TableName)
-}

+ 162 - 0
vendor/github.com/go-xorm/xorm/helpers.go

@@ -11,6 +11,7 @@ import (
 	"sort"
 	"strconv"
 	"strings"
+	"time"
 
 	"github.com/go-xorm/core"
 )
@@ -292,6 +293,19 @@ func structName(v reflect.Type) string {
 	return v.Name()
 }
 
+func col2NewCols(columns ...string) []string {
+	newColumns := make([]string, 0, len(columns))
+	for _, col := range columns {
+		col = strings.Replace(col, "`", "", -1)
+		col = strings.Replace(col, `"`, "", -1)
+		ccols := strings.Split(col, ",")
+		for _, c := range ccols {
+			newColumns = append(newColumns, strings.TrimSpace(c))
+		}
+	}
+	return newColumns
+}
+
 func sliceEq(left, right []string) bool {
 	if len(left) != len(right) {
 		return false
@@ -306,6 +320,154 @@ func sliceEq(left, right []string) bool {
 	return true
 }
 
+func setColumnInt(bean interface{}, col *core.Column, t int64) {
+	v, err := col.ValueOf(bean)
+	if err != nil {
+		return
+	}
+	if v.CanSet() {
+		switch v.Type().Kind() {
+		case reflect.Int, reflect.Int64, reflect.Int32:
+			v.SetInt(t)
+		case reflect.Uint, reflect.Uint64, reflect.Uint32:
+			v.SetUint(uint64(t))
+		}
+	}
+}
+
+func setColumnTime(bean interface{}, col *core.Column, t time.Time) {
+	v, err := col.ValueOf(bean)
+	if err != nil {
+		return
+	}
+	if v.CanSet() {
+		switch v.Type().Kind() {
+		case reflect.Struct:
+			v.Set(reflect.ValueOf(t).Convert(v.Type()))
+		case reflect.Int, reflect.Int64, reflect.Int32:
+			v.SetInt(t.Unix())
+		case reflect.Uint, reflect.Uint64, reflect.Uint32:
+			v.SetUint(uint64(t.Unix()))
+		}
+	}
+}
+
+func genCols(table *core.Table, session *Session, bean interface{}, useCol bool, includeQuote bool) ([]string, []interface{}, error) {
+	colNames := make([]string, 0, len(table.ColumnsSeq()))
+	args := make([]interface{}, 0, len(table.ColumnsSeq()))
+
+	for _, col := range table.Columns() {
+		if useCol && !col.IsVersion && !col.IsCreated && !col.IsUpdated {
+			if _, ok := getFlagForColumn(session.statement.columnMap, col); !ok {
+				continue
+			}
+		}
+		if col.MapType == core.ONLYFROMDB {
+			continue
+		}
+
+		fieldValuePtr, err := col.ValueOf(bean)
+		if err != nil {
+			return nil, nil, err
+		}
+		fieldValue := *fieldValuePtr
+
+		if col.IsAutoIncrement {
+			switch fieldValue.Type().Kind() {
+			case reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int, reflect.Int64:
+				if fieldValue.Int() == 0 {
+					continue
+				}
+			case reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint, reflect.Uint64:
+				if fieldValue.Uint() == 0 {
+					continue
+				}
+			case reflect.String:
+				if len(fieldValue.String()) == 0 {
+					continue
+				}
+			case reflect.Ptr:
+				if fieldValue.Pointer() == 0 {
+					continue
+				}
+			}
+		}
+
+		if col.IsDeleted {
+			continue
+		}
+
+		if session.statement.ColumnStr != "" {
+			if _, ok := getFlagForColumn(session.statement.columnMap, col); !ok {
+				continue
+			} else if _, ok := session.statement.incrColumns[col.Name]; ok {
+				continue
+			} else if _, ok := session.statement.decrColumns[col.Name]; ok {
+				continue
+			}
+		}
+		if session.statement.OmitStr != "" {
+			if _, ok := getFlagForColumn(session.statement.columnMap, col); ok {
+				continue
+			}
+		}
+
+		// !evalphobia! set fieldValue as nil when column is nullable and zero-value
+		if _, ok := getFlagForColumn(session.statement.nullableMap, col); ok {
+			if col.Nullable && isZero(fieldValue.Interface()) {
+				var nilValue *int
+				fieldValue = reflect.ValueOf(nilValue)
+			}
+		}
+
+		if (col.IsCreated || col.IsUpdated) && session.statement.UseAutoTime /*&& isZero(fieldValue.Interface())*/ {
+			// if time is non-empty, then set to auto time
+			val, t := session.engine.nowTime(col)
+			args = append(args, val)
+
+			var colName = col.Name
+			session.afterClosures = append(session.afterClosures, func(bean interface{}) {
+				col := table.GetColumn(colName)
+				setColumnTime(bean, col, t)
+			})
+		} else if col.IsVersion && session.statement.checkVersion {
+			args = append(args, 1)
+		} else {
+			arg, err := session.value2Interface(col, fieldValue)
+			if err != nil {
+				return colNames, args, err
+			}
+			args = append(args, arg)
+		}
+
+		if includeQuote {
+			colNames = append(colNames, session.engine.Quote(col.Name)+" = ?")
+		} else {
+			colNames = append(colNames, col.Name)
+		}
+	}
+	return colNames, args, nil
+}
+
 func indexName(tableName, idxName string) string {
 	return fmt.Sprintf("IDX_%v_%v", tableName, idxName)
 }
+
+func getFlagForColumn(m map[string]bool, col *core.Column) (val bool, has bool) {
+	if len(m) == 0 {
+		return false, false
+	}
+
+	n := len(col.Name)
+
+	for mk := range m {
+		if len(mk) != n {
+			continue
+		}
+		if strings.EqualFold(mk, col.Name) {
+			return m[mk], true
+		}
+	}
+
+	return false, false
+}

+ 0 - 6
vendor/github.com/go-xorm/xorm/interface.go

@@ -30,7 +30,6 @@ type Interface interface {
 	Exec(string, ...interface{}) (sql.Result, error)
 	Exist(bean ...interface{}) (bool, error)
 	Find(interface{}, ...interface{}) error
-	FindAndCount(interface{}, ...interface{}) (int64, error)
 	Get(interface{}) (bool, error)
 	GroupBy(keys string) *Session
 	ID(interface{}) *Session
@@ -42,7 +41,6 @@ type Interface interface {
 	IsTableExist(beanOrTableName interface{}) (bool, error)
 	Iterate(interface{}, IterFunc) error
 	Limit(int, ...int) *Session
-	MustCols(columns ...string) *Session
 	NoAutoCondition(...bool) *Session
 	NotIn(string, ...interface{}) *Session
 	Join(joinOperator string, tablename interface{}, condition string, args ...interface{}) *Session
@@ -77,7 +75,6 @@ type EngineInterface interface {
 	Dialect() core.Dialect
 	DropTables(...interface{}) error
 	DumpAllToFile(fp string, tp ...core.DbType) error
-	GetCacher(string) core.Cacher
 	GetColumnMapper() core.IMapper
 	GetDefaultCacher() core.Cacher
 	GetTableMapper() core.IMapper
@@ -86,11 +83,9 @@ type EngineInterface interface {
 	NewSession() *Session
 	NoAutoTime() *Session
 	Quote(string) string
-	SetCacher(string, core.Cacher)
 	SetDefaultCacher(core.Cacher)
 	SetLogLevel(core.LogLevel)
 	SetMapper(core.IMapper)
-	SetSchema(string)
 	SetTZDatabase(tz *time.Location)
 	SetTZLocation(tz *time.Location)
 	ShowSQL(show ...bool)
@@ -98,7 +93,6 @@ type EngineInterface interface {
 	Sync2(...interface{}) error
 	StoreEngine(storeEngine string) *Session
 	TableInfo(bean interface{}) *Table
-	TableName(interface{}, ...bool) string
 	UnMapType(reflect.Type)
 }
 

+ 3 - 3
vendor/github.com/go-xorm/xorm/rows.go

@@ -32,7 +32,7 @@ func newRows(session *Session, bean interface{}) (*Rows, error) {
 	var args []interface{}
 	var err error
 
-	if err = rows.session.statement.setRefBean(bean); err != nil {
+	if err = rows.session.statement.setRefValue(rValue(bean)); err != nil {
 		return nil, err
 	}
 
@@ -94,7 +94,8 @@ func (rows *Rows) Scan(bean interface{}) error {
 		return fmt.Errorf("scan arg is incompatible type to [%v]", rows.beanType)
 	}
 
-	if err := rows.session.statement.setRefBean(bean); err != nil {
+	dataStruct := rValue(bean)
+	if err := rows.session.statement.setRefValue(dataStruct); err != nil {
 		return err
 	}
 
@@ -103,7 +104,6 @@ func (rows *Rows) Scan(bean interface{}) error {
 		return err
 	}
 
-	dataStruct := rValue(bean)
 	_, err = rows.session.slice2Bean(scanResults, rows.fields, bean, &dataStruct, rows.session.statement.RefTable)
 	if err != nil {
 		return err

+ 356 - 353
vendor/github.com/go-xorm/xorm/session.go

@@ -278,22 +278,24 @@ func (session *Session) doPrepare(db *core.DB, sqlStr string) (stmt *core.Stmt,
 	return
 }
 
-func (session *Session) getField(dataStruct *reflect.Value, key string, table *core.Table, idx int) (*reflect.Value, error) {
+func (session *Session) getField(dataStruct *reflect.Value, key string, table *core.Table, idx int) *reflect.Value {
 	var col *core.Column
 	if col = table.GetColumnIdx(key, idx); col == nil {
-		return nil, ErrFieldIsNotExist
+		//session.engine.logger.Warnf("table %v has no column %v. %v", table.Name, key, table.ColumnsSeq())
+		return nil
 	}
 
 	fieldValue, err := col.ValueOfV(dataStruct)
 	if err != nil {
-		return nil, err
+		session.engine.logger.Error(err)
+		return nil
 	}
 
 	if !fieldValue.IsValid() || !fieldValue.CanSet() {
-		return nil, ErrFieldIsNotValid{key, table.Name}
+		session.engine.logger.Warnf("table %v's column %v is not valid or cannot set", table.Name, key)
+		return nil
 	}
-
-	return fieldValue, nil
+	return fieldValue
 }
 
 // Cell cell is a result of one column field
@@ -405,417 +407,409 @@ func (session *Session) slice2Bean(scanResults []interface{}, fields []string, b
 		}
 		tempMap[lKey] = idx
 
-		fieldValue, err := session.getField(dataStruct, key, table, idx)
-		if err != nil {
-			if !strings.Contains(err.Error(), "is not valid") {
-				session.engine.logger.Warn(err)
+		if fieldValue := session.getField(dataStruct, key, table, idx); fieldValue != nil {
+			rawValue := reflect.Indirect(reflect.ValueOf(scanResults[ii]))
+
+			// if row is null then ignore
+			if rawValue.Interface() == nil {
+				continue
 			}
-			continue
-		}
-		if fieldValue == nil {
-			continue
-		}
-		rawValue := reflect.Indirect(reflect.ValueOf(scanResults[ii]))
 
-		// if row is null then ignore
-		if rawValue.Interface() == nil {
-			continue
-		}
+			if fieldValue.CanAddr() {
+				if structConvert, ok := fieldValue.Addr().Interface().(core.Conversion); ok {
+					if data, err := value2Bytes(&rawValue); err == nil {
+						if err := structConvert.FromDB(data); err != nil {
+							return nil, err
+						}
+					} else {
+						return nil, err
+					}
+					continue
+				}
+			}
 
-		if fieldValue.CanAddr() {
-			if structConvert, ok := fieldValue.Addr().Interface().(core.Conversion); ok {
+			if _, ok := fieldValue.Interface().(core.Conversion); ok {
 				if data, err := value2Bytes(&rawValue); err == nil {
-					if err := structConvert.FromDB(data); err != nil {
-						return nil, err
+					if fieldValue.Kind() == reflect.Ptr && fieldValue.IsNil() {
+						fieldValue.Set(reflect.New(fieldValue.Type().Elem()))
 					}
+					fieldValue.Interface().(core.Conversion).FromDB(data)
 				} else {
 					return nil, err
 				}
 				continue
 			}
-		}
 
-		if _, ok := fieldValue.Interface().(core.Conversion); ok {
-			if data, err := value2Bytes(&rawValue); err == nil {
-				if fieldValue.Kind() == reflect.Ptr && fieldValue.IsNil() {
-					fieldValue.Set(reflect.New(fieldValue.Type().Elem()))
-				}
-				fieldValue.Interface().(core.Conversion).FromDB(data)
-			} else {
-				return nil, err
+			rawValueType := reflect.TypeOf(rawValue.Interface())
+			vv := reflect.ValueOf(rawValue.Interface())
+			col := table.GetColumnIdx(key, idx)
+			if col.IsPrimaryKey {
+				pk = append(pk, rawValue.Interface())
 			}
-			continue
-		}
+			fieldType := fieldValue.Type()
+			hasAssigned := false
 
-		rawValueType := reflect.TypeOf(rawValue.Interface())
-		vv := reflect.ValueOf(rawValue.Interface())
-		col := table.GetColumnIdx(key, idx)
-		if col.IsPrimaryKey {
-			pk = append(pk, rawValue.Interface())
-		}
-		fieldType := fieldValue.Type()
-		hasAssigned := false
-
-		if col.SQLType.IsJson() {
-			var bs []byte
-			if rawValueType.Kind() == reflect.String {
-				bs = []byte(vv.String())
-			} else if rawValueType.ConvertibleTo(core.BytesType) {
-				bs = vv.Bytes()
-			} else {
-				return nil, fmt.Errorf("unsupported database data type: %s %v", key, rawValueType.Kind())
-			}
+			if col.SQLType.IsJson() {
+				var bs []byte
+				if rawValueType.Kind() == reflect.String {
+					bs = []byte(vv.String())
+				} else if rawValueType.ConvertibleTo(core.BytesType) {
+					bs = vv.Bytes()
+				} else {
+					return nil, fmt.Errorf("unsupported database data type: %s %v", key, rawValueType.Kind())
+				}
 
-			hasAssigned = true
+				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 {
-						return nil, err
+				if len(bs) > 0 {
+					if fieldType.Kind() == reflect.String {
+						fieldValue.SetString(string(bs))
+						continue
 					}
-				} else {
-					x := reflect.New(fieldType)
-					err := json.Unmarshal(bs, x.Interface())
-					if err != nil {
-						return nil, err
+					if fieldValue.CanAddr() {
+						err := json.Unmarshal(bs, fieldValue.Addr().Interface())
+						if err != nil {
+							return nil, err
+						}
+					} else {
+						x := reflect.New(fieldType)
+						err := json.Unmarshal(bs, x.Interface())
+						if err != nil {
+							return nil, err
+						}
+						fieldValue.Set(x.Elem())
 					}
-					fieldValue.Set(x.Elem())
 				}
-			}
 
-			continue
-		}
-
-		switch fieldType.Kind() {
-		case reflect.Complex64, reflect.Complex128:
-			// TODO: reimplement this
-			var bs []byte
-			if rawValueType.Kind() == reflect.String {
-				bs = []byte(vv.String())
-			} else if rawValueType.ConvertibleTo(core.BytesType) {
-				bs = vv.Bytes()
+				continue
 			}
 
-			hasAssigned = true
-			if len(bs) > 0 {
-				if fieldValue.CanAddr() {
-					err := json.Unmarshal(bs, fieldValue.Addr().Interface())
-					if err != nil {
-						return nil, err
-					}
-				} else {
-					x := reflect.New(fieldType)
-					err := json.Unmarshal(bs, x.Interface())
-					if err != nil {
-						return nil, err
+			switch fieldType.Kind() {
+			case reflect.Complex64, reflect.Complex128:
+				// TODO: reimplement this
+				var bs []byte
+				if rawValueType.Kind() == reflect.String {
+					bs = []byte(vv.String())
+				} else if rawValueType.ConvertibleTo(core.BytesType) {
+					bs = vv.Bytes()
+				}
+
+				hasAssigned = true
+				if len(bs) > 0 {
+					if fieldValue.CanAddr() {
+						err := json.Unmarshal(bs, fieldValue.Addr().Interface())
+						if err != nil {
+							return nil, err
+						}
+					} else {
+						x := reflect.New(fieldType)
+						err := json.Unmarshal(bs, x.Interface())
+						if err != nil {
+							return nil, err
+						}
+						fieldValue.Set(x.Elem())
 					}
-					fieldValue.Set(x.Elem())
 				}
-			}
-		case reflect.Slice, reflect.Array:
-			switch rawValueType.Kind() {
 			case reflect.Slice, reflect.Array:
-				switch rawValueType.Elem().Kind() {
-				case reflect.Uint8:
-					if fieldType.Elem().Kind() == reflect.Uint8 {
-						hasAssigned = true
-						if col.SQLType.IsText() {
-							x := reflect.New(fieldType)
-							err := json.Unmarshal(vv.Bytes(), x.Interface())
-							if err != nil {
-								return nil, err
-							}
-							fieldValue.Set(x.Elem())
-						} else {
-							if fieldValue.Len() > 0 {
-								for i := 0; i < fieldValue.Len(); i++ {
-									if i < vv.Len() {
-										fieldValue.Index(i).Set(vv.Index(i))
-									}
+				switch rawValueType.Kind() {
+				case reflect.Slice, reflect.Array:
+					switch rawValueType.Elem().Kind() {
+					case reflect.Uint8:
+						if fieldType.Elem().Kind() == reflect.Uint8 {
+							hasAssigned = true
+							if col.SQLType.IsText() {
+								x := reflect.New(fieldType)
+								err := json.Unmarshal(vv.Bytes(), x.Interface())
+								if err != nil {
+									return nil, err
 								}
+								fieldValue.Set(x.Elem())
 							} else {
-								for i := 0; i < vv.Len(); i++ {
-									fieldValue.Set(reflect.Append(*fieldValue, vv.Index(i)))
+								if fieldValue.Len() > 0 {
+									for i := 0; i < fieldValue.Len(); i++ {
+										if i < vv.Len() {
+											fieldValue.Index(i).Set(vv.Index(i))
+										}
+									}
+								} else {
+									for i := 0; i < vv.Len(); i++ {
+										fieldValue.Set(reflect.Append(*fieldValue, vv.Index(i)))
+									}
 								}
 							}
 						}
 					}
 				}
-			}
-		case reflect.String:
-			if rawValueType.Kind() == reflect.String {
-				hasAssigned = true
-				fieldValue.SetString(vv.String())
-			}
-		case reflect.Bool:
-			if rawValueType.Kind() == reflect.Bool {
-				hasAssigned = true
-				fieldValue.SetBool(vv.Bool())
-			}
-		case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
-			switch rawValueType.Kind() {
+			case reflect.String:
+				if rawValueType.Kind() == reflect.String {
+					hasAssigned = true
+					fieldValue.SetString(vv.String())
+				}
+			case reflect.Bool:
+				if rawValueType.Kind() == reflect.Bool {
+					hasAssigned = true
+					fieldValue.SetBool(vv.Bool())
+				}
 			case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
-				hasAssigned = true
-				fieldValue.SetInt(vv.Int())
-			}
-		case reflect.Float32, reflect.Float64:
-			switch rawValueType.Kind() {
+				switch rawValueType.Kind() {
+				case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
+					hasAssigned = true
+					fieldValue.SetInt(vv.Int())
+				}
 			case reflect.Float32, reflect.Float64:
-				hasAssigned = true
-				fieldValue.SetFloat(vv.Float())
-			}
-		case reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uint:
-			switch rawValueType.Kind() {
-			case reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uint:
-				hasAssigned = true
-				fieldValue.SetUint(vv.Uint())
-			case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
-				hasAssigned = true
-				fieldValue.SetUint(uint64(vv.Int()))
-			}
-		case reflect.Struct:
-			if fieldType.ConvertibleTo(core.TimeType) {
-				dbTZ := session.engine.DatabaseTZ
-				if col.TimeZone != nil {
-					dbTZ = col.TimeZone
+				switch rawValueType.Kind() {
+				case reflect.Float32, reflect.Float64:
+					hasAssigned = true
+					fieldValue.SetFloat(vv.Float())
 				}
-
-				if rawValueType == core.TimeType {
+			case reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uint:
+				switch rawValueType.Kind() {
+				case reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uint:
+					hasAssigned = true
+					fieldValue.SetUint(vv.Uint())
+				case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
 					hasAssigned = true
+					fieldValue.SetUint(uint64(vv.Int()))
+				}
+			case reflect.Struct:
+				if fieldType.ConvertibleTo(core.TimeType) {
+					dbTZ := session.engine.DatabaseTZ
+					if col.TimeZone != nil {
+						dbTZ = col.TimeZone
+					}
 
-					t := vv.Convert(core.TimeType).Interface().(time.Time)
+					if rawValueType == core.TimeType {
+						hasAssigned = true
 
-					z, _ := t.Zone()
-					// set new location if database don't save timezone or give an incorrect timezone
-					if len(z) == 0 || t.Year() == 0 || t.Location().String() != dbTZ.String() { // !nashtsai! HACK tmp work around for lib/pq doesn't properly time with location
-						session.engine.logger.Debugf("empty zone key[%v] : %v | zone: %v | location: %+v\n", key, t, z, *t.Location())
-						t = time.Date(t.Year(), t.Month(), t.Day(), t.Hour(),
-							t.Minute(), t.Second(), t.Nanosecond(), dbTZ)
-					}
+						t := vv.Convert(core.TimeType).Interface().(time.Time)
 
-					t = t.In(session.engine.TZLocation)
-					fieldValue.Set(reflect.ValueOf(t).Convert(fieldType))
-				} else if rawValueType == core.IntType || rawValueType == core.Int64Type ||
-					rawValueType == core.Int32Type {
-					hasAssigned = true
+						z, _ := t.Zone()
+						// set new location if database don't save timezone or give an incorrect timezone
+						if len(z) == 0 || t.Year() == 0 || t.Location().String() != dbTZ.String() { // !nashtsai! HACK tmp work around for lib/pq doesn't properly time with location
+							session.engine.logger.Debugf("empty zone key[%v] : %v | zone: %v | location: %+v\n", key, t, z, *t.Location())
+							t = time.Date(t.Year(), t.Month(), t.Day(), t.Hour(),
+								t.Minute(), t.Second(), t.Nanosecond(), dbTZ)
+						}
 
-					t := time.Unix(vv.Int(), 0).In(session.engine.TZLocation)
-					fieldValue.Set(reflect.ValueOf(t).Convert(fieldType))
-				} else {
-					if d, ok := vv.Interface().([]uint8); ok {
+						t = t.In(session.engine.TZLocation)
+						fieldValue.Set(reflect.ValueOf(t).Convert(fieldType))
+					} else if rawValueType == core.IntType || rawValueType == core.Int64Type ||
+						rawValueType == core.Int32Type {
 						hasAssigned = true
-						t, err := session.byte2Time(col, d)
-						if err != nil {
-							session.engine.logger.Error("byte2Time error:", err.Error())
-							hasAssigned = false
+
+						t := time.Unix(vv.Int(), 0).In(session.engine.TZLocation)
+						fieldValue.Set(reflect.ValueOf(t).Convert(fieldType))
+					} else {
+						if d, ok := vv.Interface().([]uint8); ok {
+							hasAssigned = true
+							t, err := session.byte2Time(col, d)
+							if err != nil {
+								session.engine.logger.Error("byte2Time error:", err.Error())
+								hasAssigned = false
+							} else {
+								fieldValue.Set(reflect.ValueOf(t).Convert(fieldType))
+							}
+						} else if d, ok := vv.Interface().(string); ok {
+							hasAssigned = true
+							t, err := session.str2Time(col, d)
+							if err != nil {
+								session.engine.logger.Error("byte2Time error:", err.Error())
+								hasAssigned = false
+							} else {
+								fieldValue.Set(reflect.ValueOf(t).Convert(fieldType))
+							}
 						} else {
-							fieldValue.Set(reflect.ValueOf(t).Convert(fieldType))
+							return nil, fmt.Errorf("rawValueType is %v, value is %v", rawValueType, vv.Interface())
+						}
+					}
+				} else if nulVal, ok := fieldValue.Addr().Interface().(sql.Scanner); ok {
+					// !<winxxp>! 增加支持sql.Scanner接口的结构,如sql.NullString
+					hasAssigned = true
+					if err := nulVal.Scan(vv.Interface()); err != nil {
+						session.engine.logger.Error("sql.Sanner error:", err.Error())
+						hasAssigned = false
+					}
+				} else if col.SQLType.IsJson() {
+					if rawValueType.Kind() == reflect.String {
+						hasAssigned = true
+						x := reflect.New(fieldType)
+						if len([]byte(vv.String())) > 0 {
+							err := json.Unmarshal([]byte(vv.String()), x.Interface())
+							if err != nil {
+								return nil, err
+							}
+							fieldValue.Set(x.Elem())
 						}
-					} else if d, ok := vv.Interface().(string); ok {
+					} else if rawValueType.Kind() == reflect.Slice {
 						hasAssigned = true
-						t, err := session.str2Time(col, d)
+						x := reflect.New(fieldType)
+						if len(vv.Bytes()) > 0 {
+							err := json.Unmarshal(vv.Bytes(), x.Interface())
+							if err != nil {
+								return nil, err
+							}
+							fieldValue.Set(x.Elem())
+						}
+					}
+				} else if session.statement.UseCascade {
+					table, err := session.engine.autoMapType(*fieldValue)
+					if err != nil {
+						return nil, err
+					}
+
+					hasAssigned = true
+					if len(table.PrimaryKeys) != 1 {
+						return nil, errors.New("unsupported non or composited primary key cascade")
+					}
+					var pk = make(core.PK, len(table.PrimaryKeys))
+					pk[0], err = asKind(vv, rawValueType)
+					if err != nil {
+						return nil, err
+					}
+
+					if !isPKZero(pk) {
+						// !nashtsai! TODO for hasOne relationship, it's preferred to use join query for eager fetch
+						// however, also need to consider adding a 'lazy' attribute to xorm tag which allow hasOne
+						// property to be fetched lazily
+						structInter := reflect.New(fieldValue.Type())
+						has, err := session.ID(pk).NoCascade().get(structInter.Interface())
 						if err != nil {
-							session.engine.logger.Error("byte2Time error:", err.Error())
-							hasAssigned = false
+							return nil, err
+						}
+						if has {
+							fieldValue.Set(structInter.Elem())
 						} else {
-							fieldValue.Set(reflect.ValueOf(t).Convert(fieldType))
+							return nil, errors.New("cascade obj is not exist")
 						}
-					} else {
-						return nil, fmt.Errorf("rawValueType is %v, value is %v", rawValueType, vv.Interface())
 					}
 				}
-			} else if nulVal, ok := fieldValue.Addr().Interface().(sql.Scanner); ok {
-				// !<winxxp>! 增加支持sql.Scanner接口的结构,如sql.NullString
-				hasAssigned = true
-				if err := nulVal.Scan(vv.Interface()); err != nil {
-					session.engine.logger.Error("sql.Sanner error:", err.Error())
-					hasAssigned = false
-				}
-			} else if col.SQLType.IsJson() {
-				if rawValueType.Kind() == reflect.String {
-					hasAssigned = true
-					x := reflect.New(fieldType)
+			case reflect.Ptr:
+				// !nashtsai! TODO merge duplicated codes above
+				switch fieldType {
+				// following types case matching ptr's native type, therefore assign ptr directly
+				case core.PtrStringType:
+					if rawValueType.Kind() == reflect.String {
+						x := vv.String()
+						hasAssigned = true
+						fieldValue.Set(reflect.ValueOf(&x))
+					}
+				case core.PtrBoolType:
+					if rawValueType.Kind() == reflect.Bool {
+						x := vv.Bool()
+						hasAssigned = true
+						fieldValue.Set(reflect.ValueOf(&x))
+					}
+				case core.PtrTimeType:
+					if rawValueType == core.PtrTimeType {
+						hasAssigned = true
+						var x = rawValue.Interface().(time.Time)
+						fieldValue.Set(reflect.ValueOf(&x))
+					}
+				case core.PtrFloat64Type:
+					if rawValueType.Kind() == reflect.Float64 {
+						x := vv.Float()
+						hasAssigned = true
+						fieldValue.Set(reflect.ValueOf(&x))
+					}
+				case core.PtrUint64Type:
+					if rawValueType.Kind() == reflect.Int64 {
+						var x = uint64(vv.Int())
+						hasAssigned = true
+						fieldValue.Set(reflect.ValueOf(&x))
+					}
+				case core.PtrInt64Type:
+					if rawValueType.Kind() == reflect.Int64 {
+						x := vv.Int()
+						hasAssigned = true
+						fieldValue.Set(reflect.ValueOf(&x))
+					}
+				case core.PtrFloat32Type:
+					if rawValueType.Kind() == reflect.Float64 {
+						var x = float32(vv.Float())
+						hasAssigned = true
+						fieldValue.Set(reflect.ValueOf(&x))
+					}
+				case core.PtrIntType:
+					if rawValueType.Kind() == reflect.Int64 {
+						var x = int(vv.Int())
+						hasAssigned = true
+						fieldValue.Set(reflect.ValueOf(&x))
+					}
+				case core.PtrInt32Type:
+					if rawValueType.Kind() == reflect.Int64 {
+						var x = int32(vv.Int())
+						hasAssigned = true
+						fieldValue.Set(reflect.ValueOf(&x))
+					}
+				case core.PtrInt8Type:
+					if rawValueType.Kind() == reflect.Int64 {
+						var x = int8(vv.Int())
+						hasAssigned = true
+						fieldValue.Set(reflect.ValueOf(&x))
+					}
+				case core.PtrInt16Type:
+					if rawValueType.Kind() == reflect.Int64 {
+						var x = int16(vv.Int())
+						hasAssigned = true
+						fieldValue.Set(reflect.ValueOf(&x))
+					}
+				case core.PtrUintType:
+					if rawValueType.Kind() == reflect.Int64 {
+						var x = uint(vv.Int())
+						hasAssigned = true
+						fieldValue.Set(reflect.ValueOf(&x))
+					}
+				case core.PtrUint32Type:
+					if rawValueType.Kind() == reflect.Int64 {
+						var x = uint32(vv.Int())
+						hasAssigned = true
+						fieldValue.Set(reflect.ValueOf(&x))
+					}
+				case core.Uint8Type:
+					if rawValueType.Kind() == reflect.Int64 {
+						var x = uint8(vv.Int())
+						hasAssigned = true
+						fieldValue.Set(reflect.ValueOf(&x))
+					}
+				case core.Uint16Type:
+					if rawValueType.Kind() == reflect.Int64 {
+						var x = uint16(vv.Int())
+						hasAssigned = true
+						fieldValue.Set(reflect.ValueOf(&x))
+					}
+				case core.Complex64Type:
+					var x complex64
 					if len([]byte(vv.String())) > 0 {
-						err := json.Unmarshal([]byte(vv.String()), x.Interface())
+						err := json.Unmarshal([]byte(vv.String()), &x)
 						if err != nil {
 							return nil, err
 						}
-						fieldValue.Set(x.Elem())
+						fieldValue.Set(reflect.ValueOf(&x))
 					}
-				} else if rawValueType.Kind() == reflect.Slice {
 					hasAssigned = true
-					x := reflect.New(fieldType)
-					if len(vv.Bytes()) > 0 {
-						err := json.Unmarshal(vv.Bytes(), x.Interface())
+				case core.Complex128Type:
+					var x complex128
+					if len([]byte(vv.String())) > 0 {
+						err := json.Unmarshal([]byte(vv.String()), &x)
 						if err != nil {
 							return nil, err
 						}
-						fieldValue.Set(x.Elem())
+						fieldValue.Set(reflect.ValueOf(&x))
 					}
-				}
-			} else if session.statement.UseCascade {
-				table, err := session.engine.autoMapType(*fieldValue)
-				if err != nil {
-					return nil, err
-				}
+					hasAssigned = true
+				} // switch fieldType
+			} // switch fieldType.Kind()
 
-				hasAssigned = true
-				if len(table.PrimaryKeys) != 1 {
-					return nil, errors.New("unsupported non or composited primary key cascade")
-				}
-				var pk = make(core.PK, len(table.PrimaryKeys))
-				pk[0], err = asKind(vv, rawValueType)
+			// !nashtsai! for value can't be assigned directly fallback to convert to []byte then back to value
+			if !hasAssigned {
+				data, err := value2Bytes(&rawValue)
 				if err != nil {
 					return nil, err
 				}
 
-				if !isPKZero(pk) {
-					// !nashtsai! TODO for hasOne relationship, it's preferred to use join query for eager fetch
-					// however, also need to consider adding a 'lazy' attribute to xorm tag which allow hasOne
-					// property to be fetched lazily
-					structInter := reflect.New(fieldValue.Type())
-					has, err := session.ID(pk).NoCascade().get(structInter.Interface())
-					if err != nil {
-						return nil, err
-					}
-					if has {
-						fieldValue.Set(structInter.Elem())
-					} else {
-						return nil, errors.New("cascade obj is not exist")
-					}
-				}
-			}
-		case reflect.Ptr:
-			// !nashtsai! TODO merge duplicated codes above
-			switch fieldType {
-			// following types case matching ptr's native type, therefore assign ptr directly
-			case core.PtrStringType:
-				if rawValueType.Kind() == reflect.String {
-					x := vv.String()
-					hasAssigned = true
-					fieldValue.Set(reflect.ValueOf(&x))
-				}
-			case core.PtrBoolType:
-				if rawValueType.Kind() == reflect.Bool {
-					x := vv.Bool()
-					hasAssigned = true
-					fieldValue.Set(reflect.ValueOf(&x))
-				}
-			case core.PtrTimeType:
-				if rawValueType == core.PtrTimeType {
-					hasAssigned = true
-					var x = rawValue.Interface().(time.Time)
-					fieldValue.Set(reflect.ValueOf(&x))
-				}
-			case core.PtrFloat64Type:
-				if rawValueType.Kind() == reflect.Float64 {
-					x := vv.Float()
-					hasAssigned = true
-					fieldValue.Set(reflect.ValueOf(&x))
-				}
-			case core.PtrUint64Type:
-				if rawValueType.Kind() == reflect.Int64 {
-					var x = uint64(vv.Int())
-					hasAssigned = true
-					fieldValue.Set(reflect.ValueOf(&x))
-				}
-			case core.PtrInt64Type:
-				if rawValueType.Kind() == reflect.Int64 {
-					x := vv.Int()
-					hasAssigned = true
-					fieldValue.Set(reflect.ValueOf(&x))
-				}
-			case core.PtrFloat32Type:
-				if rawValueType.Kind() == reflect.Float64 {
-					var x = float32(vv.Float())
-					hasAssigned = true
-					fieldValue.Set(reflect.ValueOf(&x))
-				}
-			case core.PtrIntType:
-				if rawValueType.Kind() == reflect.Int64 {
-					var x = int(vv.Int())
-					hasAssigned = true
-					fieldValue.Set(reflect.ValueOf(&x))
-				}
-			case core.PtrInt32Type:
-				if rawValueType.Kind() == reflect.Int64 {
-					var x = int32(vv.Int())
-					hasAssigned = true
-					fieldValue.Set(reflect.ValueOf(&x))
-				}
-			case core.PtrInt8Type:
-				if rawValueType.Kind() == reflect.Int64 {
-					var x = int8(vv.Int())
-					hasAssigned = true
-					fieldValue.Set(reflect.ValueOf(&x))
-				}
-			case core.PtrInt16Type:
-				if rawValueType.Kind() == reflect.Int64 {
-					var x = int16(vv.Int())
-					hasAssigned = true
-					fieldValue.Set(reflect.ValueOf(&x))
-				}
-			case core.PtrUintType:
-				if rawValueType.Kind() == reflect.Int64 {
-					var x = uint(vv.Int())
-					hasAssigned = true
-					fieldValue.Set(reflect.ValueOf(&x))
-				}
-			case core.PtrUint32Type:
-				if rawValueType.Kind() == reflect.Int64 {
-					var x = uint32(vv.Int())
-					hasAssigned = true
-					fieldValue.Set(reflect.ValueOf(&x))
-				}
-			case core.Uint8Type:
-				if rawValueType.Kind() == reflect.Int64 {
-					var x = uint8(vv.Int())
-					hasAssigned = true
-					fieldValue.Set(reflect.ValueOf(&x))
-				}
-			case core.Uint16Type:
-				if rawValueType.Kind() == reflect.Int64 {
-					var x = uint16(vv.Int())
-					hasAssigned = true
-					fieldValue.Set(reflect.ValueOf(&x))
-				}
-			case core.Complex64Type:
-				var x complex64
-				if len([]byte(vv.String())) > 0 {
-					err := json.Unmarshal([]byte(vv.String()), &x)
-					if err != nil {
-						return nil, err
-					}
-					fieldValue.Set(reflect.ValueOf(&x))
-				}
-				hasAssigned = true
-			case core.Complex128Type:
-				var x complex128
-				if len([]byte(vv.String())) > 0 {
-					err := json.Unmarshal([]byte(vv.String()), &x)
-					if err != nil {
-						return nil, err
-					}
-					fieldValue.Set(reflect.ValueOf(&x))
+				if err = session.bytes2Value(col, fieldValue, data); err != nil {
+					return nil, err
 				}
-				hasAssigned = true
-			} // switch fieldType
-		} // switch fieldType.Kind()
-
-		// !nashtsai! for value can't be assigned directly fallback to convert to []byte then back to value
-		if !hasAssigned {
-			data, err := value2Bytes(&rawValue)
-			if err != nil {
-				return nil, err
-			}
-
-			if err = session.bytes2Value(col, fieldValue, data); err != nil {
-				return nil, err
 			}
 		}
 	}
@@ -834,6 +828,15 @@ func (session *Session) LastSQL() (string, []interface{}) {
 	return session.lastSQL, session.lastSQLArgs
 }
 
+// tbName get some table's table name
+func (session *Session) tbNameNoSchema(table *core.Table) string {
+	if len(session.statement.AltTableName) > 0 {
+		return session.statement.AltTableName
+	}
+
+	return table.Name
+}
+
 // Unscoped always disable struct tag "deleted"
 func (session *Session) Unscoped() *Session {
 	session.statement.Unscoped()

+ 0 - 107
vendor/github.com/go-xorm/xorm/session_cols.go

@@ -4,113 +4,6 @@
 
 package xorm
 
-import (
-	"reflect"
-	"strings"
-	"time"
-
-	"github.com/go-xorm/core"
-)
-
-type incrParam struct {
-	colName string
-	arg     interface{}
-}
-
-type decrParam struct {
-	colName string
-	arg     interface{}
-}
-
-type exprParam struct {
-	colName string
-	expr    string
-}
-
-type columnMap []string
-
-func (m columnMap) contain(colName string) bool {
-	if len(m) == 0 {
-		return false
-	}
-
-	n := len(colName)
-	for _, mk := range m {
-		if len(mk) != n {
-			continue
-		}
-		if strings.EqualFold(mk, colName) {
-			return true
-		}
-	}
-
-	return false
-}
-
-func setColumnInt(bean interface{}, col *core.Column, t int64) {
-	v, err := col.ValueOf(bean)
-	if err != nil {
-		return
-	}
-	if v.CanSet() {
-		switch v.Type().Kind() {
-		case reflect.Int, reflect.Int64, reflect.Int32:
-			v.SetInt(t)
-		case reflect.Uint, reflect.Uint64, reflect.Uint32:
-			v.SetUint(uint64(t))
-		}
-	}
-}
-
-func setColumnTime(bean interface{}, col *core.Column, t time.Time) {
-	v, err := col.ValueOf(bean)
-	if err != nil {
-		return
-	}
-	if v.CanSet() {
-		switch v.Type().Kind() {
-		case reflect.Struct:
-			v.Set(reflect.ValueOf(t).Convert(v.Type()))
-		case reflect.Int, reflect.Int64, reflect.Int32:
-			v.SetInt(t.Unix())
-		case reflect.Uint, reflect.Uint64, reflect.Uint32:
-			v.SetUint(uint64(t.Unix()))
-		}
-	}
-}
-
-func getFlagForColumn(m map[string]bool, col *core.Column) (val bool, has bool) {
-	if len(m) == 0 {
-		return false, false
-	}
-
-	n := len(col.Name)
-
-	for mk := range m {
-		if len(mk) != n {
-			continue
-		}
-		if strings.EqualFold(mk, col.Name) {
-			return m[mk], true
-		}
-	}
-
-	return false, false
-}
-
-func col2NewCols(columns ...string) []string {
-	newColumns := make([]string, 0, len(columns))
-	for _, col := range columns {
-		col = strings.Replace(col, "`", "", -1)
-		col = strings.Replace(col, `"`, "", -1)
-		ccols := strings.Split(col, ",")
-		for _, c := range ccols {
-			newColumns = append(newColumns, strings.TrimSpace(c))
-		}
-	}
-	return newColumns
-}
-
 // Incr provides a query string like "count = count + 1"
 func (session *Session) Incr(column string, arg ...interface{}) *Session {
 	session.statement.Incr(column, arg...)

+ 3 - 3
vendor/github.com/go-xorm/xorm/session_delete.go

@@ -27,7 +27,7 @@ func (session *Session) cacheDelete(table *core.Table, tableName, sqlStr string,
 		return ErrCacheFailed
 	}
 
-	cacher := session.engine.getCacher(tableName)
+	cacher := session.engine.getCacher2(table)
 	pkColumns := table.PKColumns()
 	ids, err := core.GetCacheSql(cacher, tableName, newsql, args)
 	if err != nil {
@@ -79,7 +79,7 @@ func (session *Session) Delete(bean interface{}) (int64, error) {
 		defer session.Close()
 	}
 
-	if err := session.statement.setRefBean(bean); err != nil {
+	if err := session.statement.setRefValue(rValue(bean)); err != nil {
 		return 0, err
 	}
 
@@ -199,7 +199,7 @@ func (session *Session) Delete(bean interface{}) (int64, error) {
 		})
 	}
 
-	if cacher := session.engine.getCacher(tableName); cacher != nil && session.statement.UseCache {
+	if cacher := session.engine.getCacher2(table); cacher != nil && session.statement.UseCache {
 		session.cacheDelete(table, tableNameNoQuote, deleteSQL, argsForCache...)
 	}
 

+ 3 - 12
vendor/github.com/go-xorm/xorm/session_exist.go

@@ -10,7 +10,6 @@ import (
 	"reflect"
 
 	"github.com/go-xorm/builder"
-	"github.com/go-xorm/core"
 )
 
 // Exist returns true if the record exist otherwise return false
@@ -36,18 +35,10 @@ 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)
-				}
+				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)
-				}
+				sqlStr = fmt.Sprintf("SELECT * FROM %s LIMIT 1", tableName)
 				args = []interface{}{}
 			}
 		} else {
@@ -57,7 +48,7 @@ func (session *Session) Exist(bean ...interface{}) (bool, error) {
 			}
 
 			if beanValue.Elem().Kind() == reflect.Struct {
-				if err := session.statement.setRefBean(bean[0]); err != nil {
+				if err := session.statement.setRefValue(beanValue.Elem()); err != nil {
 					return false, err
 				}
 			}

+ 6 - 43
vendor/github.com/go-xorm/xorm/session_find.go

@@ -29,39 +29,6 @@ func (session *Session) Find(rowsSlicePtr interface{}, condiBean ...interface{})
 	return session.find(rowsSlicePtr, condiBean...)
 }
 
-// FindAndCount find the results and also return the counts
-func (session *Session) FindAndCount(rowsSlicePtr interface{}, condiBean ...interface{}) (int64, error) {
-	if session.isAutoClose {
-		defer session.Close()
-	}
-
-	session.autoResetStatement = false
-	err := session.find(rowsSlicePtr, condiBean...)
-	if err != nil {
-		return 0, err
-	}
-
-	sliceValue := reflect.Indirect(reflect.ValueOf(rowsSlicePtr))
-	if sliceValue.Kind() != reflect.Slice && sliceValue.Kind() != reflect.Map {
-		return 0, errors.New("needs a pointer to a slice or a map")
-	}
-
-	sliceElementType := sliceValue.Type().Elem()
-	if sliceElementType.Kind() == reflect.Ptr {
-		sliceElementType = sliceElementType.Elem()
-	}
-	session.autoResetStatement = true
-
-	if session.statement.selectStr != "" {
-		session.statement.selectStr = ""
-	}
-	if session.statement.OrderStr != "" {
-		session.statement.OrderStr = ""
-	}
-
-	return session.Count(reflect.New(sliceElementType).Interface())
-}
-
 func (session *Session) find(rowsSlicePtr interface{}, condiBean ...interface{}) error {
 	sliceValue := reflect.Indirect(reflect.ValueOf(rowsSlicePtr))
 	if sliceValue.Kind() != reflect.Slice && sliceValue.Kind() != reflect.Map {
@@ -75,7 +42,7 @@ func (session *Session) find(rowsSlicePtr interface{}, condiBean ...interface{})
 		if sliceElementType.Kind() == reflect.Ptr {
 			if sliceElementType.Elem().Kind() == reflect.Struct {
 				pv := reflect.New(sliceElementType.Elem())
-				if err := session.statement.setRefValue(pv); err != nil {
+				if err := session.statement.setRefValue(pv.Elem()); err != nil {
 					return err
 				}
 			} else {
@@ -83,7 +50,7 @@ func (session *Session) find(rowsSlicePtr interface{}, condiBean ...interface{})
 			}
 		} else if sliceElementType.Kind() == reflect.Struct {
 			pv := reflect.New(sliceElementType)
-			if err := session.statement.setRefValue(pv); err != nil {
+			if err := session.statement.setRefValue(pv.Elem()); err != nil {
 				return err
 			}
 		} else {
@@ -161,7 +128,7 @@ func (session *Session) find(rowsSlicePtr interface{}, condiBean ...interface{})
 		}
 
 		args = append(session.statement.joinArgs, condArgs...)
-		sqlStr, err = session.statement.genSelectSQL(columnStr, condSQL, true, true)
+		sqlStr, err = session.statement.genSelectSQL(columnStr, condSQL)
 		if err != nil {
 			return err
 		}
@@ -176,7 +143,7 @@ func (session *Session) find(rowsSlicePtr interface{}, condiBean ...interface{})
 	}
 
 	if session.canCache() {
-		if cacher := session.engine.getCacher(table.Name); cacher != nil &&
+		if cacher := session.engine.getCacher2(table); cacher != nil &&
 			!session.statement.IsDistinct &&
 			!session.statement.unscoped {
 			err = session.cacheFind(sliceElementType, sqlStr, rowsSlicePtr, args...)
@@ -321,12 +288,6 @@ func (session *Session) cacheFind(t reflect.Type, sqlStr string, rowsSlicePtr in
 		return ErrCacheFailed
 	}
 
-	tableName := session.statement.TableName()
-	cacher := session.engine.getCacher(tableName)
-	if cacher == nil {
-		return nil
-	}
-
 	for _, filter := range session.engine.dialect.Filters() {
 		sqlStr = filter.Do(sqlStr, session.engine.dialect, session.statement.RefTable)
 	}
@@ -336,7 +297,9 @@ func (session *Session) cacheFind(t reflect.Type, sqlStr string, rowsSlicePtr in
 		return ErrCacheFailed
 	}
 
+	tableName := session.statement.TableName()
 	table := session.statement.RefTable
+	cacher := session.engine.getCacher2(table)
 	ids, err := core.GetCacheSql(cacher, tableName, newsql, args)
 	if err != nil {
 		rows, err := session.queryRows(newsql, args...)

+ 3 - 12
vendor/github.com/go-xorm/xorm/session_get.go

@@ -5,7 +5,6 @@
 package xorm
 
 import (
-	"database/sql"
 	"errors"
 	"reflect"
 	"strconv"
@@ -31,7 +30,7 @@ func (session *Session) get(bean interface{}) (bool, error) {
 	}
 
 	if beanValue.Elem().Kind() == reflect.Struct {
-		if err := session.statement.setRefBean(bean); err != nil {
+		if err := session.statement.setRefValue(beanValue.Elem()); err != nil {
 			return false, err
 		}
 	}
@@ -57,7 +56,7 @@ func (session *Session) get(bean interface{}) (bool, error) {
 	table := session.statement.RefTable
 
 	if session.canCache() && beanValue.Elem().Kind() == reflect.Struct {
-		if cacher := session.engine.getCacher(table.Name); cacher != nil &&
+		if cacher := session.engine.getCacher2(table); cacher != nil &&
 			!session.statement.unscoped {
 			has, err := session.cacheGet(bean, sqlStr, args...)
 			if err != ErrCacheFailed {
@@ -80,13 +79,6 @@ 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()
@@ -134,9 +126,8 @@ func (session *Session) cacheGet(bean interface{}, sqlStr string, args ...interf
 		return false, ErrCacheFailed
 	}
 
+	cacher := session.engine.getCacher2(session.statement.RefTable)
 	tableName := session.statement.TableName()
-	cacher := session.engine.getCacher(tableName)
-
 	session.engine.logger.Debug("[cacheGet] find sql:", newsql, args)
 	table := session.statement.RefTable
 	ids, err := core.GetCacheSql(cacher, tableName, newsql, args)

+ 43 - 115
vendor/github.com/go-xorm/xorm/session_insert.go

@@ -66,12 +66,11 @@ func (session *Session) innerInsertMulti(rowsSlicePtr interface{}) (int64, error
 		return 0, errors.New("could not insert a empty slice")
 	}
 
-	if err := session.statement.setRefBean(sliceValue.Index(0).Interface()); err != nil {
+	if err := session.statement.setRefValue(reflect.ValueOf(sliceValue.Index(0).Interface())); err != nil {
 		return 0, err
 	}
 
-	tableName := session.statement.TableName()
-	if len(tableName) <= 0 {
+	if len(session.statement.TableName()) <= 0 {
 		return 0, ErrTableNotFound
 	}
 
@@ -116,11 +115,15 @@ func (session *Session) innerInsertMulti(rowsSlicePtr interface{}) (int64, error
 				if col.IsDeleted {
 					continue
 				}
-				if session.statement.omitColumnMap.contain(col.Name) {
-					continue
+				if session.statement.ColumnStr != "" {
+					if _, ok := getFlagForColumn(session.statement.columnMap, col); !ok {
+						continue
+					}
 				}
-				if len(session.statement.columnMap) > 0 && !session.statement.columnMap.contain(col.Name) {
-					continue
+				if session.statement.OmitStr != "" {
+					if _, ok := getFlagForColumn(session.statement.columnMap, col); ok {
+						continue
+					}
 				}
 				if (col.IsCreated || col.IsUpdated) && session.statement.UseAutoTime {
 					val, t := session.engine.nowTime(col)
@@ -167,11 +170,15 @@ func (session *Session) innerInsertMulti(rowsSlicePtr interface{}) (int64, error
 				if col.IsDeleted {
 					continue
 				}
-				if session.statement.omitColumnMap.contain(col.Name) {
-					continue
+				if session.statement.ColumnStr != "" {
+					if _, ok := getFlagForColumn(session.statement.columnMap, col); !ok {
+						continue
+					}
 				}
-				if len(session.statement.columnMap) > 0 && !session.statement.columnMap.contain(col.Name) {
-					continue
+				if session.statement.OmitStr != "" {
+					if _, ok := getFlagForColumn(session.statement.columnMap, col); ok {
+						continue
+					}
 				}
 				if (col.IsCreated || col.IsUpdated) && session.statement.UseAutoTime {
 					val, t := session.engine.nowTime(col)
@@ -206,6 +213,7 @@ func (session *Session) innerInsertMulti(rowsSlicePtr interface{}) (int64, error
 
 	var sql = "INSERT INTO %s (%v%v%v) VALUES (%v)"
 	var statement string
+	var tableName = session.statement.TableName()
 	if session.engine.dialect.DBType() == core.ORACLE {
 		sql = "INSERT ALL INTO %s (%v%v%v) VALUES (%v) SELECT 1 FROM DUAL"
 		temp := fmt.Sprintf(") INTO %s (%v%v%v) VALUES (",
@@ -232,7 +240,9 @@ func (session *Session) innerInsertMulti(rowsSlicePtr interface{}) (int64, error
 		return 0, err
 	}
 
-	session.cacheInsert(tableName)
+	if cacher := session.engine.getCacher2(table); cacher != nil && session.statement.UseCache {
+		session.cacheInsert(table, tableName)
+	}
 
 	lenAfterClosures := len(session.afterClosures)
 	for i := 0; i < size; i++ {
@@ -288,7 +298,7 @@ func (session *Session) InsertMulti(rowsSlicePtr interface{}) (int64, error) {
 }
 
 func (session *Session) innerInsert(bean interface{}) (int64, error) {
-	if err := session.statement.setRefBean(bean); err != nil {
+	if err := session.statement.setRefValue(rValue(bean)); err != nil {
 		return 0, err
 	}
 	if len(session.statement.TableName()) <= 0 {
@@ -306,8 +316,8 @@ func (session *Session) innerInsert(bean interface{}) (int64, error) {
 	if processor, ok := interface{}(bean).(BeforeInsertProcessor); ok {
 		processor.BeforeInsert()
 	}
-
-	colNames, args, err := session.genInsertColumns(bean)
+	// --
+	colNames, args, err := genCols(session.statement.RefTable, session, bean, false, false)
 	if err != nil {
 		return 0, err
 	}
@@ -392,7 +402,9 @@ func (session *Session) innerInsert(bean interface{}) (int64, error) {
 
 		defer handleAfterInsertProcessorFunc(bean)
 
-		session.cacheInsert(tableName)
+		if cacher := session.engine.getCacher2(table); cacher != nil && session.statement.UseCache {
+			session.cacheInsert(table, tableName)
+		}
 
 		if table.Version != "" && session.statement.checkVersion {
 			verValue, err := table.VersionColumn().ValueOf(bean)
@@ -435,7 +447,9 @@ func (session *Session) innerInsert(bean interface{}) (int64, error) {
 		}
 		defer handleAfterInsertProcessorFunc(bean)
 
-		session.cacheInsert(tableName)
+		if cacher := session.engine.getCacher2(table); cacher != nil && session.statement.UseCache {
+			session.cacheInsert(table, tableName)
+		}
 
 		if table.Version != "" && session.statement.checkVersion {
 			verValue, err := table.VersionColumn().ValueOf(bean)
@@ -476,7 +490,9 @@ func (session *Session) innerInsert(bean interface{}) (int64, error) {
 
 		defer handleAfterInsertProcessorFunc(bean)
 
-		session.cacheInsert(tableName)
+		if cacher := session.engine.getCacher2(table); cacher != nil && session.statement.UseCache {
+			session.cacheInsert(table, tableName)
+		}
 
 		if table.Version != "" && session.statement.checkVersion {
 			verValue, err := table.VersionColumn().ValueOf(bean)
@@ -523,104 +539,16 @@ func (session *Session) InsertOne(bean interface{}) (int64, error) {
 	return session.innerInsert(bean)
 }
 
-func (session *Session) cacheInsert(table string) error {
-	if !session.statement.UseCache {
-		return nil
-	}
-	cacher := session.engine.getCacher(table)
-	if cacher == nil {
-		return nil
+func (session *Session) cacheInsert(table *core.Table, tables ...string) error {
+	if table == nil {
+		return ErrCacheFailed
 	}
-	session.engine.logger.Debug("[cache] clear sql:", table)
-	cacher.ClearIds(table)
-	return nil
-}
-
-// genInsertColumns generates insert needed columns
-func (session *Session) genInsertColumns(bean interface{}) ([]string, []interface{}, error) {
-	table := session.statement.RefTable
-	colNames := make([]string, 0, len(table.ColumnsSeq()))
-	args := make([]interface{}, 0, len(table.ColumnsSeq()))
-
-	for _, col := range table.Columns() {
-		if col.MapType == core.ONLYFROMDB {
-			continue
-		}
-
-		if col.IsDeleted {
-			continue
-		}
-
-		if session.statement.omitColumnMap.contain(col.Name) {
-			continue
-		}
-
-		if len(session.statement.columnMap) > 0 && !session.statement.columnMap.contain(col.Name) {
-			continue
-		}
-
-		if _, ok := session.statement.incrColumns[col.Name]; ok {
-			continue
-		} else if _, ok := session.statement.decrColumns[col.Name]; ok {
-			continue
-		}
 
-		fieldValuePtr, err := col.ValueOf(bean)
-		if err != nil {
-			return nil, nil, err
-		}
-		fieldValue := *fieldValuePtr
-
-		if col.IsAutoIncrement {
-			switch fieldValue.Type().Kind() {
-			case reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int, reflect.Int64:
-				if fieldValue.Int() == 0 {
-					continue
-				}
-			case reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint, reflect.Uint64:
-				if fieldValue.Uint() == 0 {
-					continue
-				}
-			case reflect.String:
-				if len(fieldValue.String()) == 0 {
-					continue
-				}
-			case reflect.Ptr:
-				if fieldValue.Pointer() == 0 {
-					continue
-				}
-			}
-		}
-
-		// !evalphobia! set fieldValue as nil when column is nullable and zero-value
-		if _, ok := getFlagForColumn(session.statement.nullableMap, col); ok {
-			if col.Nullable && isZero(fieldValue.Interface()) {
-				var nilValue *int
-				fieldValue = reflect.ValueOf(nilValue)
-			}
-		}
-
-		if (col.IsCreated || col.IsUpdated) && session.statement.UseAutoTime /*&& isZero(fieldValue.Interface())*/ {
-			// if time is non-empty, then set to auto time
-			val, t := session.engine.nowTime(col)
-			args = append(args, val)
-
-			var colName = col.Name
-			session.afterClosures = append(session.afterClosures, func(bean interface{}) {
-				col := table.GetColumn(colName)
-				setColumnTime(bean, col, t)
-			})
-		} else if col.IsVersion && session.statement.checkVersion {
-			args = append(args, 1)
-		} else {
-			arg, err := session.value2Interface(col, fieldValue)
-			if err != nil {
-				return colNames, args, err
-			}
-			args = append(args, arg)
-		}
-
-		colNames = append(colNames, col.Name)
+	cacher := session.engine.getCacher2(table)
+	for _, t := range tables {
+		session.engine.logger.Debug("[cache] clear sql:", t)
+		cacher.ClearIds(t)
 	}
-	return colNames, args, nil
+
+	return nil
 }

+ 2 - 16
vendor/github.com/go-xorm/xorm/session_query.go

@@ -17,17 +17,7 @@ import (
 
 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
-		}
+		return sqlorArgs[0].(string), sqlorArgs[1:], nil
 	}
 
 	if session.statement.RawSQL != "" {
@@ -64,17 +54,13 @@ func (session *Session) genQuerySQL(sqlorArgs ...interface{}) (string, []interfa
 		}
 	}
 
-	if err := session.statement.processIDParam(); err != nil {
-		return "", nil, err
-	}
-
 	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, true, true)
+	sqlStr, err := session.statement.genSelectSQL(columnStr, condSQL)
 	if err != nil {
 		return "", nil, err
 	}

+ 51 - 36
vendor/github.com/go-xorm/xorm/session_schema.go

@@ -6,7 +6,9 @@ package xorm
 
 import (
 	"database/sql"
+	"errors"
 	"fmt"
+	"reflect"
 	"strings"
 
 	"github.com/go-xorm/core"
@@ -32,7 +34,8 @@ func (session *Session) CreateTable(bean interface{}) error {
 }
 
 func (session *Session) createTable(bean interface{}) error {
-	if err := session.statement.setRefBean(bean); err != nil {
+	v := rValue(bean)
+	if err := session.statement.setRefValue(v); err != nil {
 		return err
 	}
 
@@ -51,7 +54,8 @@ func (session *Session) CreateIndexes(bean interface{}) error {
 }
 
 func (session *Session) createIndexes(bean interface{}) error {
-	if err := session.statement.setRefBean(bean); err != nil {
+	v := rValue(bean)
+	if err := session.statement.setRefValue(v); err != nil {
 		return err
 	}
 
@@ -74,7 +78,8 @@ func (session *Session) CreateUniques(bean interface{}) error {
 }
 
 func (session *Session) createUniques(bean interface{}) error {
-	if err := session.statement.setRefBean(bean); err != nil {
+	v := rValue(bean)
+	if err := session.statement.setRefValue(v); err != nil {
 		return err
 	}
 
@@ -98,7 +103,8 @@ func (session *Session) DropIndexes(bean interface{}) error {
 }
 
 func (session *Session) dropIndexes(bean interface{}) error {
-	if err := session.statement.setRefBean(bean); err != nil {
+	v := rValue(bean)
+	if err := session.statement.setRefValue(v); err != nil {
 		return err
 	}
 
@@ -122,7 +128,11 @@ func (session *Session) DropTable(beanOrTableName interface{}) error {
 }
 
 func (session *Session) dropTable(beanOrTableName interface{}) error {
-	tableName := session.engine.tbNameNoSchema(beanOrTableName)
+	tableName, err := session.engine.tableName(beanOrTableName)
+	if err != nil {
+		return err
+	}
+
 	var needDrop = true
 	if !session.engine.dialect.SupportDropIfExists() {
 		sqlStr, args := session.engine.dialect.TableCheckSql(tableName)
@@ -134,8 +144,8 @@ func (session *Session) dropTable(beanOrTableName interface{}) error {
 	}
 
 	if needDrop {
-		sqlStr := session.engine.Dialect().DropTableSql(session.engine.TableName(tableName, true))
-		_, err := session.exec(sqlStr)
+		sqlStr := session.engine.Dialect().DropTableSql(tableName)
+		_, err = session.exec(sqlStr)
 		return err
 	}
 	return nil
@@ -147,7 +157,10 @@ func (session *Session) IsTableExist(beanOrTableName interface{}) (bool, error)
 		defer session.Close()
 	}
 
-	tableName := session.engine.tbNameNoSchema(beanOrTableName)
+	tableName, err := session.engine.tableName(beanOrTableName)
+	if err != nil {
+		return false, err
+	}
 
 	return session.isTableExist(tableName)
 }
@@ -160,15 +173,24 @@ func (session *Session) isTableExist(tableName string) (bool, error) {
 
 // IsTableEmpty if table have any records
 func (session *Session) IsTableEmpty(bean interface{}) (bool, error) {
-	if session.isAutoClose {
-		defer session.Close()
+	v := rValue(bean)
+	t := v.Type()
+
+	if t.Kind() == reflect.String {
+		if session.isAutoClose {
+			defer session.Close()
+		}
+		return session.isTableEmpty(bean.(string))
+	} else if t.Kind() == reflect.Struct {
+		rows, err := session.Count(bean)
+		return rows == 0, err
 	}
-	return session.isTableEmpty(session.engine.tbNameNoSchema(bean))
+	return false, errors.New("bean should be a struct or struct's point")
 }
 
 func (session *Session) isTableEmpty(tableName string) (bool, error) {
 	var total int64
-	sqlStr := fmt.Sprintf("select count(*) from %s", session.engine.Quote(session.engine.TableName(tableName, true)))
+	sqlStr := fmt.Sprintf("select count(*) from %s", session.engine.Quote(tableName))
 	err := session.queryRow(sqlStr).Scan(&total)
 	if err != nil {
 		if err == sql.ErrNoRows {
@@ -233,12 +255,6 @@ func (session *Session) Sync2(beans ...interface{}) error {
 		return err
 	}
 
-	session.autoResetStatement = false
-	defer func() {
-		session.autoResetStatement = true
-		session.resetStatement()
-	}()
-
 	var structTables []*core.Table
 
 	for _, bean := range beans {
@@ -248,8 +264,7 @@ func (session *Session) Sync2(beans ...interface{}) error {
 			return err
 		}
 		structTables = append(structTables, table)
-		tbName := session.tbNameNoSchema(table)
-		tbNameWithSchema := engine.TableName(tbName, true)
+		var tbName = session.tbNameNoSchema(table)
 
 		var oriTable *core.Table
 		for _, tb := range tables {
@@ -294,32 +309,32 @@ func (session *Session) Sync2(beans ...interface{}) error {
 							if engine.dialect.DBType() == core.MYSQL ||
 								engine.dialect.DBType() == core.POSTGRES {
 								engine.logger.Infof("Table %s column %s change type from %s to %s\n",
-									tbNameWithSchema, col.Name, curType, expectedType)
-								_, err = session.exec(engine.dialect.ModifyColumnSql(tbNameWithSchema, col))
+									tbName, col.Name, curType, expectedType)
+								_, err = session.exec(engine.dialect.ModifyColumnSql(table.Name, col))
 							} else {
 								engine.logger.Warnf("Table %s column %s db type is %s, struct type is %s\n",
-									tbNameWithSchema, col.Name, curType, expectedType)
+									tbName, col.Name, curType, expectedType)
 							}
 						} else if strings.HasPrefix(curType, core.Varchar) && strings.HasPrefix(expectedType, core.Varchar) {
 							if engine.dialect.DBType() == core.MYSQL {
 								if oriCol.Length < col.Length {
 									engine.logger.Infof("Table %s column %s change type from varchar(%d) to varchar(%d)\n",
-										tbNameWithSchema, col.Name, oriCol.Length, col.Length)
-									_, err = session.exec(engine.dialect.ModifyColumnSql(tbNameWithSchema, col))
+										tbName, col.Name, oriCol.Length, col.Length)
+									_, err = session.exec(engine.dialect.ModifyColumnSql(table.Name, col))
 								}
 							}
 						} else {
 							if !(strings.HasPrefix(curType, expectedType) && curType[len(expectedType)] == '(') {
 								engine.logger.Warnf("Table %s column %s db type is %s, struct type is %s",
-									tbNameWithSchema, col.Name, curType, expectedType)
+									tbName, col.Name, curType, expectedType)
 							}
 						}
 					} else if expectedType == core.Varchar {
 						if engine.dialect.DBType() == core.MYSQL {
 							if oriCol.Length < col.Length {
 								engine.logger.Infof("Table %s column %s change type from varchar(%d) to varchar(%d)\n",
-									tbNameWithSchema, col.Name, oriCol.Length, col.Length)
-								_, err = session.exec(engine.dialect.ModifyColumnSql(tbNameWithSchema, col))
+									tbName, col.Name, oriCol.Length, col.Length)
+								_, err = session.exec(engine.dialect.ModifyColumnSql(table.Name, col))
 							}
 						}
 					}
@@ -333,7 +348,7 @@ func (session *Session) Sync2(beans ...interface{}) error {
 					}
 				} else {
 					session.statement.RefTable = table
-					session.statement.tableName = tbNameWithSchema
+					session.statement.tableName = tbName
 					err = session.addColumn(col.Name)
 				}
 				if err != nil {
@@ -356,7 +371,7 @@ func (session *Session) Sync2(beans ...interface{}) error {
 
 				if oriIndex != nil {
 					if oriIndex.Type != index.Type {
-						sql := engine.dialect.DropIndexSql(tbNameWithSchema, oriIndex)
+						sql := engine.dialect.DropIndexSql(tbName, oriIndex)
 						_, err = session.exec(sql)
 						if err != nil {
 							return err
@@ -372,7 +387,7 @@ func (session *Session) Sync2(beans ...interface{}) error {
 
 			for name2, index2 := range oriTable.Indexes {
 				if _, ok := foundIndexNames[name2]; !ok {
-					sql := engine.dialect.DropIndexSql(tbNameWithSchema, index2)
+					sql := engine.dialect.DropIndexSql(tbName, index2)
 					_, err = session.exec(sql)
 					if err != nil {
 						return err
@@ -383,12 +398,12 @@ func (session *Session) Sync2(beans ...interface{}) error {
 			for name, index := range addedNames {
 				if index.Type == core.UniqueType {
 					session.statement.RefTable = table
-					session.statement.tableName = tbNameWithSchema
-					err = session.addUnique(tbNameWithSchema, name)
+					session.statement.tableName = tbName
+					err = session.addUnique(tbName, name)
 				} else if index.Type == core.IndexType {
 					session.statement.RefTable = table
-					session.statement.tableName = tbNameWithSchema
-					err = session.addIndex(tbNameWithSchema, name)
+					session.statement.tableName = tbName
+					err = session.addIndex(tbName, name)
 				}
 				if err != nil {
 					return err
@@ -413,7 +428,7 @@ func (session *Session) Sync2(beans ...interface{}) error {
 
 		for _, colName := range table.ColumnsSeq() {
 			if oriTable.GetColumn(colName) == nil {
-				engine.logger.Warnf("Table %s has column %s but struct has not related field", engine.TableName(table.Name, true), colName)
+				engine.logger.Warnf("Table %s has column %s but struct has not related field", table.Name, colName)
 			}
 		}
 	}

+ 14 - 101
vendor/github.com/go-xorm/xorm/session_update.go

@@ -40,7 +40,7 @@ func (session *Session) cacheUpdate(table *core.Table, tableName, sqlStr string,
 		}
 	}
 
-	cacher := session.engine.getCacher(tableName)
+	cacher := session.engine.getCacher2(table)
 	session.engine.logger.Debug("[cacheUpdate] get cache sql", newsql, args[nStart:])
 	ids, err := core.GetCacheSql(cacher, tableName, newsql, args[nStart:])
 	if err != nil {
@@ -167,7 +167,7 @@ func (session *Session) Update(bean interface{}, condiBean ...interface{}) (int6
 	var isMap = t.Kind() == reflect.Map
 	var isStruct = t.Kind() == reflect.Struct
 	if isStruct {
-		if err := session.statement.setRefBean(bean); err != nil {
+		if err := session.statement.setRefValue(v); err != nil {
 			return 0, err
 		}
 
@@ -176,10 +176,12 @@ func (session *Session) Update(bean interface{}, condiBean ...interface{}) (int6
 		}
 
 		if session.statement.ColumnStr == "" {
-			colNames, args = session.statement.buildUpdates(bean, false, false,
-				false, false, true)
+			colNames, args = buildUpdates(session.engine, session.statement.RefTable, bean, false, false,
+				false, false, session.statement.allUseBool, session.statement.useAllCols,
+				session.statement.mustColumnMap, session.statement.nullableMap,
+				session.statement.columnMap, true, session.statement.unscoped)
 		} else {
-			colNames, args, err = session.genUpdateColumns(bean)
+			colNames, args, err = genCols(session.statement.RefTable, session, bean, true, true)
 			if err != nil {
 				return 0, err
 			}
@@ -200,8 +202,7 @@ func (session *Session) Update(bean interface{}, condiBean ...interface{}) (int6
 	table := session.statement.RefTable
 
 	if session.statement.UseAutoTime && table != nil && table.Updated != "" {
-		if !session.statement.columnMap.contain(table.Updated) &&
-			!session.statement.omitColumnMap.contain(table.Updated) {
+		if _, ok := session.statement.columnMap[strings.ToLower(table.Updated)]; !ok {
 			colNames = append(colNames, session.engine.Quote(table.Updated)+" = ?")
 			col := table.UpdatedColumn()
 			val, t := session.engine.nowTime(col)
@@ -361,11 +362,12 @@ func (session *Session) Update(bean interface{}, condiBean ...interface{}) (int6
 		}
 	}
 
-	if cacher := session.engine.getCacher(tableName); cacher != nil && session.statement.UseCache {
-		//session.cacheUpdate(table, tableName, sqlStr, args...)
-		session.engine.logger.Debug("[cacheUpdate] clear table ", tableName)
-		cacher.ClearIds(tableName)
-		cacher.ClearBeans(tableName)
+	if table != nil {
+		if cacher := session.engine.getCacher2(table); cacher != nil && session.statement.UseCache {
+			//session.cacheUpdate(table, tableName, sqlStr, args...)
+			cacher.ClearIds(tableName)
+			cacher.ClearBeans(tableName)
+		}
 	}
 
 	// handle after update processors
@@ -400,92 +402,3 @@ func (session *Session) Update(bean interface{}, condiBean ...interface{}) (int6
 
 	return res.RowsAffected()
 }
-
-func (session *Session) genUpdateColumns(bean interface{}) ([]string, []interface{}, error) {
-	table := session.statement.RefTable
-	colNames := make([]string, 0, len(table.ColumnsSeq()))
-	args := make([]interface{}, 0, len(table.ColumnsSeq()))
-
-	for _, col := range table.Columns() {
-		if !col.IsVersion && !col.IsCreated && !col.IsUpdated {
-			if session.statement.omitColumnMap.contain(col.Name) {
-				continue
-			}
-		}
-		if col.MapType == core.ONLYFROMDB {
-			continue
-		}
-
-		fieldValuePtr, err := col.ValueOf(bean)
-		if err != nil {
-			return nil, nil, err
-		}
-		fieldValue := *fieldValuePtr
-
-		if col.IsAutoIncrement {
-			switch fieldValue.Type().Kind() {
-			case reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int, reflect.Int64:
-				if fieldValue.Int() == 0 {
-					continue
-				}
-			case reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint, reflect.Uint64:
-				if fieldValue.Uint() == 0 {
-					continue
-				}
-			case reflect.String:
-				if len(fieldValue.String()) == 0 {
-					continue
-				}
-			case reflect.Ptr:
-				if fieldValue.Pointer() == 0 {
-					continue
-				}
-			}
-		}
-
-		if col.IsDeleted || col.IsCreated {
-			continue
-		}
-
-		if len(session.statement.columnMap) > 0 {
-			if !session.statement.columnMap.contain(col.Name) {
-				continue
-			} else if _, ok := session.statement.incrColumns[col.Name]; ok {
-				continue
-			} else if _, ok := session.statement.decrColumns[col.Name]; ok {
-				continue
-			}
-		}
-
-		// !evalphobia! set fieldValue as nil when column is nullable and zero-value
-		if _, ok := getFlagForColumn(session.statement.nullableMap, col); ok {
-			if col.Nullable && isZero(fieldValue.Interface()) {
-				var nilValue *int
-				fieldValue = reflect.ValueOf(nilValue)
-			}
-		}
-
-		if col.IsUpdated && session.statement.UseAutoTime /*&& isZero(fieldValue.Interface())*/ {
-			// if time is non-empty, then set to auto time
-			val, t := session.engine.nowTime(col)
-			args = append(args, val)
-
-			var colName = col.Name
-			session.afterClosures = append(session.afterClosures, func(bean interface{}) {
-				col := table.GetColumn(colName)
-				setColumnTime(bean, col, t)
-			})
-		} else if col.IsVersion && session.statement.checkVersion {
-			args = append(args, 1)
-		} else {
-			arg, err := session.value2Interface(col, fieldValue)
-			if err != nil {
-				return colNames, args, err
-			}
-			args = append(args, arg)
-		}
-
-		colNames = append(colNames, session.engine.Quote(col.Name)+" = ?")
-	}
-	return colNames, args, nil
-}

+ 123 - 98
vendor/github.com/go-xorm/xorm/statement.go

@@ -18,6 +18,21 @@ import (
 	"github.com/go-xorm/core"
 )
 
+type incrParam struct {
+	colName string
+	arg     interface{}
+}
+
+type decrParam struct {
+	colName string
+	arg     interface{}
+}
+
+type exprParam struct {
+	colName string
+	expr    string
+}
+
 // Statement save all the sql info for executing SQL
 type Statement struct {
 	RefTable        *core.Table
@@ -32,6 +47,7 @@ type Statement struct {
 	HavingStr       string
 	ColumnStr       string
 	selectStr       string
+	columnMap       map[string]bool
 	useAllCols      bool
 	OmitStr         string
 	AltTableName    string
@@ -51,8 +67,6 @@ type Statement struct {
 	allUseBool      bool
 	checkVersion    bool
 	unscoped        bool
-	columnMap       columnMap
-	omitColumnMap   columnMap
 	mustColumnMap   map[string]bool
 	nullableMap     map[string]bool
 	incrColumns     map[string]incrParam
@@ -75,8 +89,7 @@ func (statement *Statement) Init() {
 	statement.HavingStr = ""
 	statement.ColumnStr = ""
 	statement.OmitStr = ""
-	statement.columnMap = columnMap{}
-	statement.omitColumnMap = columnMap{}
+	statement.columnMap = make(map[string]bool)
 	statement.AltTableName = ""
 	statement.tableName = ""
 	statement.idParam = nil
@@ -208,33 +221,34 @@ func (statement *Statement) setRefValue(v reflect.Value) error {
 	if err != nil {
 		return err
 	}
-	statement.tableName = statement.Engine.TableName(v, true)
+	statement.tableName = statement.Engine.tbName(v)
 	return nil
 }
 
-func (statement *Statement) setRefBean(bean interface{}) error {
-	var err error
-	statement.RefTable, err = statement.Engine.autoMapType(rValue(bean))
-	if err != nil {
-		return err
+// Table tempororily set table name, the parameter could be a string or a pointer of struct
+func (statement *Statement) Table(tableNameOrBean interface{}) *Statement {
+	v := rValue(tableNameOrBean)
+	t := v.Type()
+	if t.Kind() == reflect.String {
+		statement.AltTableName = tableNameOrBean.(string)
+	} else if t.Kind() == reflect.Struct {
+		var err error
+		statement.RefTable, err = statement.Engine.autoMapType(v)
+		if err != nil {
+			statement.Engine.logger.Error(err)
+			return statement
+		}
+		statement.AltTableName = statement.Engine.tbName(v)
 	}
-	statement.tableName = statement.Engine.TableName(bean, true)
-	return nil
+	return statement
 }
 
 // Auto generating update columnes and values according a struct
-func (statement *Statement) buildUpdates(bean interface{},
-	includeVersion, includeUpdated, includeNil,
-	includeAutoIncr, update bool) ([]string, []interface{}) {
-	engine := statement.Engine
-	table := statement.RefTable
-	allUseBool := statement.allUseBool
-	useAllCols := statement.useAllCols
-	mustColumnMap := statement.mustColumnMap
-	nullableMap := statement.nullableMap
-	columnMap := statement.columnMap
-	omitColumnMap := statement.omitColumnMap
-	unscoped := statement.unscoped
+func buildUpdates(engine *Engine, table *core.Table, bean interface{},
+	includeVersion bool, includeUpdated bool, includeNil bool,
+	includeAutoIncr bool, allUseBool bool, useAllCols bool,
+	mustColumnMap map[string]bool, nullableMap map[string]bool,
+	columnMap map[string]bool, update, unscoped bool) ([]string, []interface{}) {
 
 	var colNames = make([]string, 0)
 	var args = make([]interface{}, 0)
@@ -254,10 +268,7 @@ func (statement *Statement) buildUpdates(bean interface{},
 		if col.IsDeleted && !unscoped {
 			continue
 		}
-		if omitColumnMap.contain(col.Name) {
-			continue
-		}
-		if len(columnMap) > 0 && !columnMap.contain(col.Name) {
+		if use, ok := columnMap[strings.ToLower(col.Name)]; ok && !use {
 			continue
 		}
 
@@ -593,10 +604,17 @@ func (statement *Statement) col2NewColsWithQuote(columns ...string) []string {
 }
 
 func (statement *Statement) colmap2NewColsWithQuote() []string {
-	newColumns := make([]string, len(statement.columnMap), len(statement.columnMap))
-	copy(newColumns, statement.columnMap)
-	for i := 0; i < len(statement.columnMap); i++ {
-		newColumns[i] = statement.Engine.Quote(newColumns[i])
+	newColumns := make([]string, 0, len(statement.columnMap))
+	for col := range statement.columnMap {
+		fields := strings.Split(strings.TrimSpace(col), ".")
+		if len(fields) == 1 {
+			newColumns = append(newColumns, statement.Engine.quote(fields[0]))
+		} else if len(fields) == 2 {
+			newColumns = append(newColumns, statement.Engine.quote(fields[0])+"."+
+				statement.Engine.quote(fields[1]))
+		} else {
+			panic(errors.New("unwanted colnames"))
+		}
 	}
 	return newColumns
 }
@@ -624,11 +642,10 @@ func (statement *Statement) Select(str string) *Statement {
 func (statement *Statement) Cols(columns ...string) *Statement {
 	cols := col2NewCols(columns...)
 	for _, nc := range cols {
-		statement.columnMap = append(statement.columnMap, nc)
+		statement.columnMap[strings.ToLower(nc)] = true
 	}
 
 	newColumns := statement.colmap2NewColsWithQuote()
-
 	statement.ColumnStr = strings.Join(newColumns, ", ")
 	statement.ColumnStr = strings.Replace(statement.ColumnStr, statement.Engine.quote("*"), "*", -1)
 	return statement
@@ -663,7 +680,7 @@ func (statement *Statement) UseBool(columns ...string) *Statement {
 func (statement *Statement) Omit(columns ...string) {
 	newColumns := col2NewCols(columns...)
 	for _, nc := range newColumns {
-		statement.omitColumnMap = append(statement.omitColumnMap, nc)
+		statement.columnMap[strings.ToLower(nc)] = false
 	}
 	statement.OmitStr = statement.Engine.Quote(strings.Join(newColumns, statement.Engine.Quote(", ")))
 }
@@ -726,23 +743,6 @@ func (statement *Statement) Asc(colNames ...string) *Statement {
 	return statement
 }
 
-// Table tempororily set table name, the parameter could be a string or a pointer of struct
-func (statement *Statement) Table(tableNameOrBean interface{}) *Statement {
-	v := rValue(tableNameOrBean)
-	t := v.Type()
-	if t.Kind() == reflect.Struct {
-		var err error
-		statement.RefTable, err = statement.Engine.autoMapType(v)
-		if err != nil {
-			statement.Engine.logger.Error(err)
-			return statement
-		}
-	}
-
-	statement.AltTableName = statement.Engine.TableName(tableNameOrBean, true)
-	return statement
-}
-
 // Join The joinOP should be one of INNER, LEFT OUTER, CROSS etc - this will be prepended to JOIN
 func (statement *Statement) Join(joinOP string, tablename interface{}, condition string, args ...interface{}) *Statement {
 	var buf bytes.Buffer
@@ -752,9 +752,39 @@ func (statement *Statement) Join(joinOP string, tablename interface{}, condition
 		fmt.Fprintf(&buf, "%v JOIN ", joinOP)
 	}
 
-	tbName := statement.Engine.TableName(tablename, true)
+	switch tablename.(type) {
+	case []string:
+		t := tablename.([]string)
+		if len(t) > 1 {
+			fmt.Fprintf(&buf, "%v AS %v", statement.Engine.Quote(t[0]), statement.Engine.Quote(t[1]))
+		} else if len(t) == 1 {
+			fmt.Fprintf(&buf, statement.Engine.Quote(t[0]))
+		}
+	case []interface{}:
+		t := tablename.([]interface{})
+		l := len(t)
+		var table string
+		if l > 0 {
+			f := t[0]
+			v := rValue(f)
+			t := v.Type()
+			if t.Kind() == reflect.String {
+				table = f.(string)
+			} else if t.Kind() == reflect.Struct {
+				table = statement.Engine.tbName(v)
+			}
+		}
+		if l > 1 {
+			fmt.Fprintf(&buf, "%v AS %v", statement.Engine.Quote(table),
+				statement.Engine.Quote(fmt.Sprintf("%v", t[1])))
+		} else if l == 1 {
+			fmt.Fprintf(&buf, statement.Engine.Quote(table))
+		}
+	default:
+		fmt.Fprintf(&buf, statement.Engine.Quote(fmt.Sprintf("%v", tablename)))
+	}
 
-	fmt.Fprintf(&buf, "%s ON %v", tbName, condition)
+	fmt.Fprintf(&buf, " ON %v", condition)
 	statement.JoinStr = buf.String()
 	statement.joinArgs = append(statement.joinArgs, args...)
 	return statement
@@ -787,12 +817,10 @@ func (statement *Statement) genColumnStr() string {
 	columns := statement.RefTable.Columns()
 
 	for _, col := range columns {
-		if statement.omitColumnMap.contain(col.Name) {
-			continue
-		}
-
-		if len(statement.columnMap) > 0 && !statement.columnMap.contain(col.Name) {
-			continue
+		if statement.OmitStr != "" {
+			if _, ok := getFlagForColumn(statement.columnMap, col); ok {
+				continue
+			}
 		}
 
 		if col.MapType == core.ONLYTODB {
@@ -803,6 +831,10 @@ func (statement *Statement) genColumnStr() string {
 			buf.WriteString(", ")
 		}
 
+		if col.IsPrimaryKey && statement.Engine.Dialect().DBType() == "ql" {
+			buf.WriteString("id() AS ")
+		}
+
 		if statement.JoinStr != "" {
 			if statement.TableAlias != "" {
 				buf.WriteString(statement.TableAlias)
@@ -827,13 +859,11 @@ func (statement *Statement) genCreateTableSQL() string {
 func (statement *Statement) genIndexSQL() []string {
 	var sqls []string
 	tbName := statement.TableName()
-	for _, index := range statement.RefTable.Indexes {
+	quote := statement.Engine.Quote
+	for idxName, index := range statement.RefTable.Indexes {
 		if index.Type == core.IndexType {
-			sql := statement.Engine.dialect.CreateIndexSql(tbName, index)
-			/*idxTBName := strings.Replace(tbName, ".", "_", -1)
-			idxTBName = strings.Replace(idxTBName, `"`, "", -1)
-			sql := fmt.Sprintf("CREATE INDEX %v ON %v (%v);", quote(indexName(idxTBName, idxName)),
-				quote(tbName), quote(strings.Join(index.Cols, quote(","))))*/
+			sql := fmt.Sprintf("CREATE INDEX %v ON %v (%v);", quote(indexName(tbName, idxName)),
+				quote(tbName), quote(strings.Join(index.Cols, quote(","))))
 			sqls = append(sqls, sql)
 		}
 	}
@@ -859,18 +889,16 @@ func (statement *Statement) genUniqueSQL() []string {
 func (statement *Statement) genDelIndexSQL() []string {
 	var sqls []string
 	tbName := statement.TableName()
-	idxPrefixName := strings.Replace(tbName, `"`, "", -1)
-	idxPrefixName = strings.Replace(idxPrefixName, `.`, "_", -1)
 	for idxName, index := range statement.RefTable.Indexes {
 		var rIdxName string
 		if index.Type == core.UniqueType {
-			rIdxName = uniqueName(idxPrefixName, idxName)
+			rIdxName = uniqueName(tbName, idxName)
 		} else if index.Type == core.IndexType {
-			rIdxName = indexName(idxPrefixName, idxName)
+			rIdxName = indexName(tbName, idxName)
 		}
-		sql := fmt.Sprintf("DROP INDEX %v", statement.Engine.Quote(statement.Engine.TableName(rIdxName, true)))
+		sql := fmt.Sprintf("DROP INDEX %v", statement.Engine.Quote(rIdxName))
 		if statement.Engine.dialect.IndexOnTable() {
-			sql += fmt.Sprintf(" ON %v", statement.Engine.Quote(tbName))
+			sql += fmt.Sprintf(" ON %v", statement.Engine.Quote(statement.TableName()))
 		}
 		sqls = append(sqls, sql)
 	}
@@ -921,7 +949,7 @@ func (statement *Statement) genGetSQL(bean interface{}) (string, []interface{},
 	v := rValue(bean)
 	isStruct := v.Kind() == reflect.Struct
 	if isStruct {
-		statement.setRefBean(bean)
+		statement.setRefValue(v)
 	}
 
 	var columnStr = statement.ColumnStr
@@ -954,17 +982,13 @@ func (statement *Statement) genGetSQL(bean interface{}) (string, []interface{},
 		if err := statement.mergeConds(bean); err != nil {
 			return "", nil, err
 		}
-	} else {
-		if err := statement.processIDParam(); err != nil {
-			return "", nil, err
-		}
 	}
 	condSQL, condArgs, err := builder.ToSQL(statement.cond)
 	if err != nil {
 		return "", nil, err
 	}
 
-	sqlStr, err := statement.genSelectSQL(columnStr, condSQL, true, true)
+	sqlStr, err := statement.genSelectSQL(columnStr, condSQL)
 	if err != nil {
 		return "", nil, err
 	}
@@ -977,7 +1001,7 @@ func (statement *Statement) genCountSQL(beans ...interface{}) (string, []interfa
 	var condArgs []interface{}
 	var err error
 	if len(beans) > 0 {
-		statement.setRefBean(beans[0])
+		statement.setRefValue(rValue(beans[0]))
 		condSQL, condArgs, err = statement.genConds(beans[0])
 	} else {
 		condSQL, condArgs, err = builder.ToSQL(statement.cond)
@@ -994,7 +1018,7 @@ func (statement *Statement) genCountSQL(beans ...interface{}) (string, []interfa
 			selectSQL = "count(*)"
 		}
 	}
-	sqlStr, err := statement.genSelectSQL(selectSQL, condSQL, false, false)
+	sqlStr, err := statement.genSelectSQL(selectSQL, condSQL)
 	if err != nil {
 		return "", nil, err
 	}
@@ -1003,7 +1027,7 @@ func (statement *Statement) genCountSQL(beans ...interface{}) (string, []interfa
 }
 
 func (statement *Statement) genSumSQL(bean interface{}, columns ...string) (string, []interface{}, error) {
-	statement.setRefBean(bean)
+	statement.setRefValue(rValue(bean))
 
 	var sumStrs = make([]string, 0, len(columns))
 	for _, colName := range columns {
@@ -1019,7 +1043,7 @@ func (statement *Statement) genSumSQL(bean interface{}, columns ...string) (stri
 		return "", nil, err
 	}
 
-	sqlStr, err := statement.genSelectSQL(sumSelect, condSQL, true, true)
+	sqlStr, err := statement.genSelectSQL(sumSelect, condSQL)
 	if err != nil {
 		return "", nil, err
 	}
@@ -1027,7 +1051,7 @@ func (statement *Statement) genSumSQL(bean interface{}, columns ...string) (stri
 	return sqlStr, append(statement.joinArgs, condArgs...), nil
 }
 
-func (statement *Statement) genSelectSQL(columnStr, condSQL string, needLimit, needOrderBy bool) (a string, err error) {
+func (statement *Statement) genSelectSQL(columnStr, condSQL string) (a string, err error) {
 	var distinct string
 	if statement.IsDistinct && !strings.HasPrefix(columnStr, "count") {
 		distinct = "DISTINCT "
@@ -1038,6 +1062,10 @@ func (statement *Statement) genSelectSQL(columnStr, condSQL string, needLimit, n
 	var top string
 	var mssqlCondi string
 
+	if err := statement.processIDParam(); err != nil {
+		return "", err
+	}
+
 	var buf bytes.Buffer
 	if len(condSQL) > 0 {
 		fmt.Fprintf(&buf, " WHERE %v", condSQL)
@@ -1090,10 +1118,9 @@ func (statement *Statement) genSelectSQL(columnStr, condSQL string, needLimit, n
 			}
 
 			var orderStr string
-			if needOrderBy && len(statement.OrderStr) > 0 {
+			if len(statement.OrderStr) > 0 {
 				orderStr = " ORDER BY " + statement.OrderStr
 			}
-
 			var groupStr string
 			if len(statement.GroupByStr) > 0 {
 				groupStr = " GROUP BY " + statement.GroupByStr
@@ -1119,20 +1146,18 @@ func (statement *Statement) genSelectSQL(columnStr, condSQL string, needLimit, n
 	if statement.HavingStr != "" {
 		a = fmt.Sprintf("%v %v", a, statement.HavingStr)
 	}
-	if needOrderBy && statement.OrderStr != "" {
+	if statement.OrderStr != "" {
 		a = fmt.Sprintf("%v ORDER BY %v", a, statement.OrderStr)
 	}
-	if needLimit {
-		if dialect.DBType() != core.MSSQL && dialect.DBType() != core.ORACLE {
-			if statement.Start > 0 {
-				a = fmt.Sprintf("%v LIMIT %v OFFSET %v", a, statement.LimitN, statement.Start)
-			} else if statement.LimitN > 0 {
-				a = fmt.Sprintf("%v LIMIT %v", a, statement.LimitN)
-			}
-		} else if dialect.DBType() == core.ORACLE {
-			if statement.Start != 0 || statement.LimitN != 0 {
-				a = fmt.Sprintf("SELECT %v FROM (SELECT %v,ROWNUM RN FROM (%v) at WHERE ROWNUM <= %d) aat WHERE RN > %d", columnStr, columnStr, a, statement.Start+statement.LimitN, statement.Start)
-			}
+	if dialect.DBType() != core.MSSQL && dialect.DBType() != core.ORACLE {
+		if statement.Start > 0 {
+			a = fmt.Sprintf("%v LIMIT %v OFFSET %v", a, statement.LimitN, statement.Start)
+		} else if statement.LimitN > 0 {
+			a = fmt.Sprintf("%v LIMIT %v", a, statement.LimitN)
+		}
+	} else if dialect.DBType() == core.ORACLE {
+		if statement.Start != 0 || statement.LimitN != 0 {
+			a = fmt.Sprintf("SELECT %v FROM (SELECT %v,ROWNUM RN FROM (%v) at WHERE ROWNUM <= %d) aat WHERE RN > %d", columnStr, columnStr, a, statement.Start+statement.LimitN, statement.Start)
 		}
 	}
 	if statement.IsForUpdate {
@@ -1143,7 +1168,7 @@ func (statement *Statement) genSelectSQL(columnStr, condSQL string, needLimit, n
 }
 
 func (statement *Statement) processIDParam() error {
-	if statement.idParam == nil || statement.RefTable == nil {
+	if statement.idParam == nil {
 		return nil
 	}
 

+ 1 - 9
vendor/github.com/go-xorm/xorm/xorm.go

@@ -17,7 +17,7 @@ import (
 
 const (
 	// Version show the xorm's version
-	Version string = "0.6.6.0413"
+	Version string = "0.6.4.0910"
 )
 
 func regDrvsNDialects() bool {
@@ -90,7 +90,6 @@ func NewEngine(driverName string, dataSourceName string) (*Engine, error) {
 		TagIdentifier: "xorm",
 		TZLocation:    time.Local,
 		tagHandlers:   defaultTagHandlers,
-		cachers:       make(map[string]core.Cacher),
 	}
 
 	if uri.DbType == core.SQLITE {
@@ -109,13 +108,6 @@ func NewEngine(driverName string, dataSourceName string) (*Engine, error) {
 	return engine, nil
 }
 
-// NewEngineWithParams new a db manager with params. The params will be passed to dialect.
-func NewEngineWithParams(driverName string, dataSourceName string, params map[string]string) (*Engine, error) {
-	engine, err := NewEngine(driverName, dataSourceName)
-	engine.dialect.SetParams(params)
-	return engine, err
-}
-
 // Clone clone an engine
 func (engine *Engine) Clone() (*Engine, error) {
 	return NewEngine(engine.DriverName(), engine.DataSourceName())