github.com/insionng/yougam@v0.0.0-20170714101924-2bc18d833463/libraries/go-xorm/xorm/session.go (about)

     1  // Copyright 2015 The Xorm Authors. All rights reserved.
     2  // Use of this source code is governed by a BSD-style
     3  // license that can be found in the LICENSE file.
     4  
     5  package xorm
     6  
     7  import (
     8  	"database/sql"
     9  	"database/sql/driver"
    10  	"encoding/json"
    11  	"errors"
    12  	"fmt"
    13  	"hash/crc32"
    14  	"reflect"
    15  	"strconv"
    16  	"strings"
    17  	"time"
    18  
    19  	"github.com/insionng/yougam/libraries/go-xorm/builder"
    20  	"github.com/insionng/yougam/libraries/go-xorm/core"
    21  )
    22  
    23  // Session keep a pointer to sql.DB and provides all execution of all
    24  // kind of database operations.
    25  type Session struct {
    26  	db                     *core.DB
    27  	Engine                 *Engine
    28  	Tx                     *core.Tx
    29  	Statement              Statement
    30  	IsAutoCommit           bool
    31  	IsCommitedOrRollbacked bool
    32  	TransType              string
    33  	IsAutoClose            bool
    34  
    35  	// Automatically reset the statement after operations that execute a SQL
    36  	// query such as Count(), Find(), Get(), ...
    37  	AutoResetStatement bool
    38  
    39  	// !nashtsai! storing these beans due to yet committed tx
    40  	afterInsertBeans map[interface{}]*[]func(interface{})
    41  	afterUpdateBeans map[interface{}]*[]func(interface{})
    42  	afterDeleteBeans map[interface{}]*[]func(interface{})
    43  	// --
    44  
    45  	beforeClosures []func(interface{})
    46  	afterClosures  []func(interface{})
    47  
    48  	prepareStmt bool
    49  	stmtCache   map[uint32]*core.Stmt //key: hash.Hash32 of (queryStr, len(queryStr))
    50  	cascadeDeep int
    51  
    52  	// !evalphobia! stored the last executed query on this session
    53  	//beforeSQLExec func(string, ...interface{})
    54  	lastSQL     string
    55  	lastSQLArgs []interface{}
    56  }
    57  
    58  // Clone copy all the session's content and return a new session
    59  func (session *Session) Clone() *Session {
    60  	var sess = *session
    61  	return &sess
    62  }
    63  
    64  // Init reset the session as the init status.
    65  func (session *Session) Init() {
    66  	session.Statement.Init()
    67  	session.Statement.Engine = session.Engine
    68  	session.IsAutoCommit = true
    69  	session.IsCommitedOrRollbacked = false
    70  	session.IsAutoClose = false
    71  	session.AutoResetStatement = true
    72  	session.prepareStmt = false
    73  
    74  	// !nashtsai! is lazy init better?
    75  	session.afterInsertBeans = make(map[interface{}]*[]func(interface{}), 0)
    76  	session.afterUpdateBeans = make(map[interface{}]*[]func(interface{}), 0)
    77  	session.afterDeleteBeans = make(map[interface{}]*[]func(interface{}), 0)
    78  	session.beforeClosures = make([]func(interface{}), 0)
    79  	session.afterClosures = make([]func(interface{}), 0)
    80  
    81  	session.lastSQL = ""
    82  	session.lastSQLArgs = []interface{}{}
    83  }
    84  
    85  // Close release the connection from pool
    86  func (session *Session) Close() {
    87  	for _, v := range session.stmtCache {
    88  		v.Close()
    89  	}
    90  
    91  	if session.db != nil {
    92  		// When Close be called, if session is a transaction and do not call
    93  		// Commit or Rollback, then call Rollback.
    94  		if session.Tx != nil && !session.IsCommitedOrRollbacked {
    95  			session.Rollback()
    96  		}
    97  		session.Tx = nil
    98  		session.stmtCache = nil
    99  		session.Init()
   100  		session.db = nil
   101  	}
   102  }
   103  
   104  func (session *Session) resetStatement() {
   105  	if session.AutoResetStatement {
   106  		session.Statement.Init()
   107  	}
   108  }
   109  
   110  // Prepare set a flag to session that should be prepare statment before execute query
   111  func (session *Session) Prepare() *Session {
   112  	session.prepareStmt = true
   113  	return session
   114  }
   115  
   116  // Sql !DEPRECIATED! will be deprecated, please use SQL instead.
   117  func (session *Session) Sql(query string, args ...interface{}) *Session {
   118  	return session.SQL(query, args...)
   119  }
   120  
   121  // SQL provides raw sql input parameter. When you have a complex SQL statement
   122  // and cannot use Where, Id, In and etc. Methods to describe, you can use SQL.
   123  func (session *Session) SQL(query interface{}, args ...interface{}) *Session {
   124  	session.Statement.SQL(query, args...)
   125  	return session
   126  }
   127  
   128  // Where provides custom query condition.
   129  func (session *Session) Where(query interface{}, args ...interface{}) *Session {
   130  	session.Statement.Where(query, args...)
   131  	return session
   132  }
   133  
   134  // And provides custom query condition.
   135  func (session *Session) And(query interface{}, args ...interface{}) *Session {
   136  	session.Statement.And(query, args...)
   137  	return session
   138  }
   139  
   140  // Or provides custom query condition.
   141  func (session *Session) Or(query interface{}, args ...interface{}) *Session {
   142  	session.Statement.Or(query, args...)
   143  	return session
   144  }
   145  
   146  // Id will be deprecated, please use ID instead
   147  func (session *Session) Id(id interface{}) *Session {
   148  	session.Statement.Id(id)
   149  	return session
   150  }
   151  
   152  // ID provides converting id as a query condition
   153  func (session *Session) ID(id interface{}) *Session {
   154  	session.Statement.Id(id)
   155  	return session
   156  }
   157  
   158  // Before Apply before Processor, affected bean is passed to closure arg
   159  func (session *Session) Before(closures func(interface{})) *Session {
   160  	if closures != nil {
   161  		session.beforeClosures = append(session.beforeClosures, closures)
   162  	}
   163  	return session
   164  }
   165  
   166  // After Apply after Processor, affected bean is passed to closure arg
   167  func (session *Session) After(closures func(interface{})) *Session {
   168  	if closures != nil {
   169  		session.afterClosures = append(session.afterClosures, closures)
   170  	}
   171  	return session
   172  }
   173  
   174  // Table can input a string or pointer to struct for special a table to operate.
   175  func (session *Session) Table(tableNameOrBean interface{}) *Session {
   176  	session.Statement.Table(tableNameOrBean)
   177  	return session
   178  }
   179  
   180  // Alias set the table alias
   181  func (session *Session) Alias(alias string) *Session {
   182  	session.Statement.Alias(alias)
   183  	return session
   184  }
   185  
   186  // In provides a query string like "id in (1, 2, 3)"
   187  func (session *Session) In(column string, args ...interface{}) *Session {
   188  	session.Statement.In(column, args...)
   189  	return session
   190  }
   191  
   192  // NotIn provides a query string like "id in (1, 2, 3)"
   193  func (session *Session) NotIn(column string, args ...interface{}) *Session {
   194  	session.Statement.NotIn(column, args...)
   195  	return session
   196  }
   197  
   198  // Incr provides a query string like "count = count + 1"
   199  func (session *Session) Incr(column string, arg ...interface{}) *Session {
   200  	session.Statement.Incr(column, arg...)
   201  	return session
   202  }
   203  
   204  // Decr provides a query string like "count = count - 1"
   205  func (session *Session) Decr(column string, arg ...interface{}) *Session {
   206  	session.Statement.Decr(column, arg...)
   207  	return session
   208  }
   209  
   210  // SetExpr provides a query string like "column = {expression}"
   211  func (session *Session) SetExpr(column string, expression string) *Session {
   212  	session.Statement.SetExpr(column, expression)
   213  	return session
   214  }
   215  
   216  // Select provides some columns to special
   217  func (session *Session) Select(str string) *Session {
   218  	session.Statement.Select(str)
   219  	return session
   220  }
   221  
   222  // Cols provides some columns to special
   223  func (session *Session) Cols(columns ...string) *Session {
   224  	session.Statement.Cols(columns...)
   225  	return session
   226  }
   227  
   228  // AllCols ask all columns
   229  func (session *Session) AllCols() *Session {
   230  	session.Statement.AllCols()
   231  	return session
   232  }
   233  
   234  // MustCols specify some columns must use even if they are empty
   235  func (session *Session) MustCols(columns ...string) *Session {
   236  	session.Statement.MustCols(columns...)
   237  	return session
   238  }
   239  
   240  // NoCascade indicate that no cascade load child object
   241  func (session *Session) NoCascade() *Session {
   242  	session.Statement.UseCascade = false
   243  	return session
   244  }
   245  
   246  // UseBool automatically retrieve condition according struct, but
   247  // if struct has bool field, it will ignore them. So use UseBool
   248  // to tell system to do not ignore them.
   249  // If no paramters, it will use all the bool field of struct, or
   250  // it will use paramters's columns
   251  func (session *Session) UseBool(columns ...string) *Session {
   252  	session.Statement.UseBool(columns...)
   253  	return session
   254  }
   255  
   256  // Distinct use for distinct columns. Caution: when you are using cache,
   257  // distinct will not be cached because cache system need id,
   258  // but distinct will not provide id
   259  func (session *Session) Distinct(columns ...string) *Session {
   260  	session.Statement.Distinct(columns...)
   261  	return session
   262  }
   263  
   264  // ForUpdate Set Read/Write locking for UPDATE
   265  func (session *Session) ForUpdate() *Session {
   266  	session.Statement.IsForUpdate = true
   267  	return session
   268  }
   269  
   270  // Omit Only not use the paramters as select or update columns
   271  func (session *Session) Omit(columns ...string) *Session {
   272  	session.Statement.Omit(columns...)
   273  	return session
   274  }
   275  
   276  // Nullable Set null when column is zero-value and nullable for update
   277  func (session *Session) Nullable(columns ...string) *Session {
   278  	session.Statement.Nullable(columns...)
   279  	return session
   280  }
   281  
   282  // NoAutoTime means do not automatically give created field and updated field
   283  // the current time on the current session temporarily
   284  func (session *Session) NoAutoTime() *Session {
   285  	session.Statement.UseAutoTime = false
   286  	return session
   287  }
   288  
   289  // NoAutoCondition disable generate SQL condition from beans
   290  func (session *Session) NoAutoCondition(no ...bool) *Session {
   291  	session.Statement.NoAutoCondition(no...)
   292  	return session
   293  }
   294  
   295  // Limit provide limit and offset query condition
   296  func (session *Session) Limit(limit int, start ...int) *Session {
   297  	session.Statement.Limit(limit, start...)
   298  	return session
   299  }
   300  
   301  // OrderBy provide order by query condition, the input parameter is the content
   302  // after order by on a sql statement.
   303  func (session *Session) OrderBy(order string) *Session {
   304  	session.Statement.OrderBy(order)
   305  	return session
   306  }
   307  
   308  // Desc provide desc order by query condition, the input parameters are columns.
   309  func (session *Session) Desc(colNames ...string) *Session {
   310  	session.Statement.Desc(colNames...)
   311  	return session
   312  }
   313  
   314  // Asc provide asc order by query condition, the input parameters are columns.
   315  func (session *Session) Asc(colNames ...string) *Session {
   316  	session.Statement.Asc(colNames...)
   317  	return session
   318  }
   319  
   320  // StoreEngine is only avialble mysql dialect currently
   321  func (session *Session) StoreEngine(storeEngine string) *Session {
   322  	session.Statement.StoreEngine = storeEngine
   323  	return session
   324  }
   325  
   326  // Charset is only avialble mysql dialect currently
   327  func (session *Session) Charset(charset string) *Session {
   328  	session.Statement.Charset = charset
   329  	return session
   330  }
   331  
   332  // Cascade indicates if loading sub Struct
   333  func (session *Session) Cascade(trueOrFalse ...bool) *Session {
   334  	if len(trueOrFalse) >= 1 {
   335  		session.Statement.UseCascade = trueOrFalse[0]
   336  	}
   337  	return session
   338  }
   339  
   340  // NoCache ask this session do not retrieve data from cache system and
   341  // get data from database directly.
   342  func (session *Session) NoCache() *Session {
   343  	session.Statement.UseCache = false
   344  	return session
   345  }
   346  
   347  // Join join_operator should be one of INNER, LEFT OUTER, CROSS etc - this will be prepended to JOIN
   348  func (session *Session) Join(joinOperator string, tablename interface{}, condition string, args ...interface{}) *Session {
   349  	session.Statement.Join(joinOperator, tablename, condition, args...)
   350  	return session
   351  }
   352  
   353  // GroupBy Generate Group By statement
   354  func (session *Session) GroupBy(keys string) *Session {
   355  	session.Statement.GroupBy(keys)
   356  	return session
   357  }
   358  
   359  // Having Generate Having statement
   360  func (session *Session) Having(conditions string) *Session {
   361  	session.Statement.Having(conditions)
   362  	return session
   363  }
   364  
   365  // DB db return the wrapper of sql.DB
   366  func (session *Session) DB() *core.DB {
   367  	if session.db == nil {
   368  		session.db = session.Engine.db
   369  		session.stmtCache = make(map[uint32]*core.Stmt, 0)
   370  	}
   371  	return session.db
   372  }
   373  
   374  // Conds returns session query conditions
   375  func (session *Session) Conds() builder.Cond {
   376  	return session.Statement.cond
   377  }
   378  
   379  // Begin a transaction
   380  func (session *Session) Begin() error {
   381  	if session.IsAutoCommit {
   382  		tx, err := session.DB().Begin()
   383  		if err != nil {
   384  			return err
   385  		}
   386  		session.IsAutoCommit = false
   387  		session.IsCommitedOrRollbacked = false
   388  		session.Tx = tx
   389  		session.saveLastSQL("BEGIN TRANSACTION")
   390  	}
   391  	return nil
   392  }
   393  
   394  // Rollback When using transaction, you can rollback if any error
   395  func (session *Session) Rollback() error {
   396  	if !session.IsAutoCommit && !session.IsCommitedOrRollbacked {
   397  		session.saveLastSQL(session.Engine.dialect.RollBackStr())
   398  		session.IsCommitedOrRollbacked = true
   399  		return session.Tx.Rollback()
   400  	}
   401  	return nil
   402  }
   403  
   404  // Commit When using transaction, Commit will commit all operations.
   405  func (session *Session) Commit() error {
   406  	if !session.IsAutoCommit && !session.IsCommitedOrRollbacked {
   407  		session.saveLastSQL("COMMIT")
   408  		session.IsCommitedOrRollbacked = true
   409  		var err error
   410  		if err = session.Tx.Commit(); err == nil {
   411  			// handle processors after tx committed
   412  
   413  			closureCallFunc := func(closuresPtr *[]func(interface{}), bean interface{}) {
   414  
   415  				if closuresPtr != nil {
   416  					for _, closure := range *closuresPtr {
   417  						closure(bean)
   418  					}
   419  				}
   420  			}
   421  
   422  			for bean, closuresPtr := range session.afterInsertBeans {
   423  				closureCallFunc(closuresPtr, bean)
   424  
   425  				if processor, ok := interface{}(bean).(AfterInsertProcessor); ok {
   426  					processor.AfterInsert()
   427  				}
   428  			}
   429  			for bean, closuresPtr := range session.afterUpdateBeans {
   430  				closureCallFunc(closuresPtr, bean)
   431  
   432  				if processor, ok := interface{}(bean).(AfterUpdateProcessor); ok {
   433  					processor.AfterUpdate()
   434  				}
   435  			}
   436  			for bean, closuresPtr := range session.afterDeleteBeans {
   437  				closureCallFunc(closuresPtr, bean)
   438  
   439  				if processor, ok := interface{}(bean).(AfterDeleteProcessor); ok {
   440  					processor.AfterDelete()
   441  				}
   442  			}
   443  			cleanUpFunc := func(slices *map[interface{}]*[]func(interface{})) {
   444  				if len(*slices) > 0 {
   445  					*slices = make(map[interface{}]*[]func(interface{}), 0)
   446  				}
   447  			}
   448  			cleanUpFunc(&session.afterInsertBeans)
   449  			cleanUpFunc(&session.afterUpdateBeans)
   450  			cleanUpFunc(&session.afterDeleteBeans)
   451  		}
   452  		return err
   453  	}
   454  	return nil
   455  }
   456  
   457  func cleanupProcessorsClosures(slices *[]func(interface{})) {
   458  	if len(*slices) > 0 {
   459  		*slices = make([]func(interface{}), 0)
   460  	}
   461  }
   462  
   463  func (session *Session) scanMapIntoStruct(obj interface{}, objMap map[string][]byte) error {
   464  	dataStruct := rValue(obj)
   465  	if dataStruct.Kind() != reflect.Struct {
   466  		return errors.New("Expected a pointer to a struct")
   467  	}
   468  
   469  	var col *core.Column
   470  	session.Statement.setRefValue(dataStruct)
   471  	table := session.Statement.RefTable
   472  	tableName := session.Statement.tableName
   473  
   474  	for key, data := range objMap {
   475  		if col = table.GetColumn(key); col == nil {
   476  			session.Engine.logger.Warnf("struct %v's has not field %v. %v",
   477  				table.Type.Name(), key, table.ColumnsSeq())
   478  			continue
   479  		}
   480  
   481  		fieldName := col.FieldName
   482  		fieldPath := strings.Split(fieldName, ".")
   483  		var fieldValue reflect.Value
   484  		if len(fieldPath) > 2 {
   485  			session.Engine.logger.Error("Unsupported mutliderive", fieldName)
   486  			continue
   487  		} else if len(fieldPath) == 2 {
   488  			parentField := dataStruct.FieldByName(fieldPath[0])
   489  			if parentField.IsValid() {
   490  				fieldValue = parentField.FieldByName(fieldPath[1])
   491  			}
   492  		} else {
   493  			fieldValue = dataStruct.FieldByName(fieldName)
   494  		}
   495  		if !fieldValue.IsValid() || !fieldValue.CanSet() {
   496  			session.Engine.logger.Warnf("table %v's column %v is not valid or cannot set", tableName, key)
   497  			continue
   498  		}
   499  
   500  		err := session.bytes2Value(col, &fieldValue, data)
   501  		if err != nil {
   502  			return err
   503  		}
   504  	}
   505  
   506  	return nil
   507  }
   508  
   509  // Execute sql
   510  func (session *Session) innerExec(sqlStr string, args ...interface{}) (sql.Result, error) {
   511  	if session.prepareStmt {
   512  		stmt, err := session.doPrepare(sqlStr)
   513  		if err != nil {
   514  			return nil, err
   515  		}
   516  
   517  		res, err := stmt.Exec(args...)
   518  		if err != nil {
   519  			return nil, err
   520  		}
   521  		return res, nil
   522  	}
   523  
   524  	return session.DB().Exec(sqlStr, args...)
   525  }
   526  
   527  func (session *Session) exec(sqlStr string, args ...interface{}) (sql.Result, error) {
   528  	for _, filter := range session.Engine.dialect.Filters() {
   529  		// TODO: for table name, it's no need to RefTable
   530  		sqlStr = filter.Do(sqlStr, session.Engine.dialect, session.Statement.RefTable)
   531  	}
   532  
   533  	session.saveLastSQL(sqlStr, args...)
   534  
   535  	return session.Engine.logSQLExecutionTime(sqlStr, args, func() (sql.Result, error) {
   536  		if session.IsAutoCommit {
   537  			// FIXME: oci8 can not auto commit (github.com/mattn/go-oci8)
   538  			if session.Engine.dialect.DBType() == core.ORACLE {
   539  				session.Begin()
   540  				r, err := session.Tx.Exec(sqlStr, args...)
   541  				session.Commit()
   542  				return r, err
   543  			}
   544  			return session.innerExec(sqlStr, args...)
   545  		}
   546  		return session.Tx.Exec(sqlStr, args...)
   547  	})
   548  }
   549  
   550  // Exec raw sql
   551  func (session *Session) Exec(sqlStr string, args ...interface{}) (sql.Result, error) {
   552  	defer session.resetStatement()
   553  	if session.IsAutoClose {
   554  		defer session.Close()
   555  	}
   556  
   557  	return session.exec(sqlStr, args...)
   558  }
   559  
   560  // CreateTable create a table according a bean
   561  func (session *Session) CreateTable(bean interface{}) error {
   562  	v := rValue(bean)
   563  	session.Statement.setRefValue(v)
   564  
   565  	defer session.resetStatement()
   566  	if session.IsAutoClose {
   567  		defer session.Close()
   568  	}
   569  
   570  	return session.createOneTable()
   571  }
   572  
   573  // CreateIndexes create indexes
   574  func (session *Session) CreateIndexes(bean interface{}) error {
   575  	v := rValue(bean)
   576  	session.Statement.setRefValue(v)
   577  
   578  	defer session.resetStatement()
   579  	if session.IsAutoClose {
   580  		defer session.Close()
   581  	}
   582  
   583  	sqls := session.Statement.genIndexSQL()
   584  	for _, sqlStr := range sqls {
   585  		_, err := session.exec(sqlStr)
   586  		if err != nil {
   587  			return err
   588  		}
   589  	}
   590  	return nil
   591  }
   592  
   593  // CreateUniques create uniques
   594  func (session *Session) CreateUniques(bean interface{}) error {
   595  	v := rValue(bean)
   596  	session.Statement.setRefValue(v)
   597  
   598  	defer session.resetStatement()
   599  	if session.IsAutoClose {
   600  		defer session.Close()
   601  	}
   602  
   603  	sqls := session.Statement.genUniqueSQL()
   604  	for _, sqlStr := range sqls {
   605  		_, err := session.exec(sqlStr)
   606  		if err != nil {
   607  			return err
   608  		}
   609  	}
   610  	return nil
   611  }
   612  
   613  func (session *Session) createOneTable() error {
   614  	sqlStr := session.Statement.genCreateTableSQL()
   615  	_, err := session.exec(sqlStr)
   616  	return err
   617  }
   618  
   619  // to be deleted
   620  func (session *Session) createAll() error {
   621  	if session.IsAutoClose {
   622  		defer session.Close()
   623  	}
   624  
   625  	for _, table := range session.Engine.Tables {
   626  		session.Statement.RefTable = table
   627  		session.Statement.tableName = table.Name
   628  		err := session.createOneTable()
   629  		session.resetStatement()
   630  		if err != nil {
   631  			return err
   632  		}
   633  	}
   634  	return nil
   635  }
   636  
   637  // DropIndexes drop indexes
   638  func (session *Session) DropIndexes(bean interface{}) error {
   639  	v := rValue(bean)
   640  	session.Statement.setRefValue(v)
   641  
   642  	defer session.resetStatement()
   643  	if session.IsAutoClose {
   644  		defer session.Close()
   645  	}
   646  
   647  	sqls := session.Statement.genDelIndexSQL()
   648  	for _, sqlStr := range sqls {
   649  		_, err := session.exec(sqlStr)
   650  		if err != nil {
   651  			return err
   652  		}
   653  	}
   654  	return nil
   655  }
   656  
   657  // DropTable drop table will drop table if exist, if drop failed, it will return error
   658  func (session *Session) DropTable(beanOrTableName interface{}) error {
   659  	tableName, err := session.Engine.tableName(beanOrTableName)
   660  	if err != nil {
   661  		return err
   662  	}
   663  
   664  	var needDrop = true
   665  	if !session.Engine.dialect.SupportDropIfExists() {
   666  		sqlStr, args := session.Engine.dialect.TableCheckSql(tableName)
   667  		results, err := session.query(sqlStr, args...)
   668  		if err != nil {
   669  			return err
   670  		}
   671  		needDrop = len(results) > 0
   672  	}
   673  
   674  	if needDrop {
   675  		sqlStr := session.Engine.Dialect().DropTableSql(tableName)
   676  		_, err = session.exec(sqlStr)
   677  		return err
   678  	}
   679  	return nil
   680  }
   681  
   682  func (session *Session) canCache() bool {
   683  	if session.Statement.RefTable == nil ||
   684  		session.Statement.JoinStr != "" ||
   685  		session.Statement.RawSQL != "" ||
   686  		!session.Statement.UseCache ||
   687  		session.Tx != nil ||
   688  		len(session.Statement.selectStr) > 0 {
   689  		return false
   690  	}
   691  	return true
   692  }
   693  
   694  func (session *Session) cacheGet(bean interface{}, sqlStr string, args ...interface{}) (has bool, err error) {
   695  	// if has no reftable, then don't use cache currently
   696  	if !session.canCache() {
   697  		return false, ErrCacheFailed
   698  	}
   699  
   700  	for _, filter := range session.Engine.dialect.Filters() {
   701  		sqlStr = filter.Do(sqlStr, session.Engine.dialect, session.Statement.RefTable)
   702  	}
   703  	newsql := session.Statement.convertIDSQL(sqlStr)
   704  	if newsql == "" {
   705  		return false, ErrCacheFailed
   706  	}
   707  
   708  	cacher := session.Engine.getCacher2(session.Statement.RefTable)
   709  	tableName := session.Statement.TableName()
   710  	session.Engine.logger.Debug("[cacheGet] find sql:", newsql, args)
   711  	ids, err := core.GetCacheSql(cacher, tableName, newsql, args)
   712  	table := session.Statement.RefTable
   713  	if err != nil {
   714  		var res = make([]string, len(table.PrimaryKeys))
   715  		rows, err := session.DB().Query(newsql, args...)
   716  		if err != nil {
   717  			return false, err
   718  		}
   719  		defer rows.Close()
   720  
   721  		if rows.Next() {
   722  			err = rows.ScanSlice(&res)
   723  			if err != nil {
   724  				return false, err
   725  			}
   726  		} else {
   727  			return false, ErrCacheFailed
   728  		}
   729  
   730  		var pk core.PK = make([]interface{}, len(table.PrimaryKeys))
   731  		for i, col := range table.PKColumns() {
   732  			if col.SQLType.IsText() {
   733  				pk[i] = res[i]
   734  			} else if col.SQLType.IsNumeric() {
   735  				n, err := strconv.ParseInt(res[i], 10, 64)
   736  				if err != nil {
   737  					return false, err
   738  				}
   739  				pk[i] = n
   740  			} else {
   741  				return false, errors.New("unsupported")
   742  			}
   743  		}
   744  
   745  		ids = []core.PK{pk}
   746  		session.Engine.logger.Debug("[cacheGet] cache ids:", newsql, ids)
   747  		err = core.PutCacheSql(cacher, ids, tableName, newsql, args)
   748  		if err != nil {
   749  			return false, err
   750  		}
   751  	} else {
   752  		session.Engine.logger.Debug("[cacheGet] cache hit sql:", newsql)
   753  	}
   754  
   755  	if len(ids) > 0 {
   756  		structValue := reflect.Indirect(reflect.ValueOf(bean))
   757  		id := ids[0]
   758  		session.Engine.logger.Debug("[cacheGet] get bean:", tableName, id)
   759  		sid, err := id.ToString()
   760  		if err != nil {
   761  			return false, err
   762  		}
   763  		cacheBean := cacher.GetBean(tableName, sid)
   764  		if cacheBean == nil {
   765  			/*newSession := session.Engine.NewSession()
   766  			defer newSession.Close()
   767  			cacheBean = reflect.New(structValue.Type()).Interface()
   768  			newSession.Id(id).NoCache()
   769  			if session.Statement.AltTableName != "" {
   770  				newSession.Table(session.Statement.AltTableName)
   771  			}
   772  			if !session.Statement.UseCascade {
   773  				newSession.NoCascade()
   774  			}
   775  			has, err = newSession.Get(cacheBean)
   776  			*/
   777  			cacheBean = bean
   778  			has, err = session.nocacheGet(cacheBean, sqlStr, args...)
   779  			if err != nil || !has {
   780  				return has, err
   781  			}
   782  
   783  			session.Engine.logger.Debug("[cacheGet] cache bean:", tableName, id, cacheBean)
   784  			cacher.PutBean(tableName, sid, cacheBean)
   785  		} else {
   786  			session.Engine.logger.Debug("[cacheGet] cache hit bean:", tableName, id, cacheBean)
   787  			has = true
   788  		}
   789  		structValue.Set(reflect.Indirect(reflect.ValueOf(cacheBean)))
   790  
   791  		return has, nil
   792  	}
   793  	return false, nil
   794  }
   795  
   796  func (session *Session) cacheFind(t reflect.Type, sqlStr string, rowsSlicePtr interface{}, args ...interface{}) (err error) {
   797  	if !session.canCache() ||
   798  		indexNoCase(sqlStr, "having") != -1 ||
   799  		indexNoCase(sqlStr, "group by") != -1 {
   800  		return ErrCacheFailed
   801  	}
   802  
   803  	for _, filter := range session.Engine.dialect.Filters() {
   804  		sqlStr = filter.Do(sqlStr, session.Engine.dialect, session.Statement.RefTable)
   805  	}
   806  
   807  	newsql := session.Statement.convertIDSQL(sqlStr)
   808  	if newsql == "" {
   809  		return ErrCacheFailed
   810  	}
   811  
   812  	tableName := session.Statement.TableName()
   813  
   814  	table := session.Statement.RefTable
   815  	cacher := session.Engine.getCacher2(table)
   816  	ids, err := core.GetCacheSql(cacher, tableName, newsql, args)
   817  	if err != nil {
   818  		rows, err := session.DB().Query(newsql, args...)
   819  		if err != nil {
   820  			return err
   821  		}
   822  		defer rows.Close()
   823  
   824  		var i int
   825  		ids = make([]core.PK, 0)
   826  		for rows.Next() {
   827  			i++
   828  			if i > 500 {
   829  				session.Engine.logger.Debug("[cacheFind] ids length > 500, no cache")
   830  				return ErrCacheFailed
   831  			}
   832  			var res = make([]string, len(table.PrimaryKeys))
   833  			err = rows.ScanSlice(&res)
   834  			if err != nil {
   835  				return err
   836  			}
   837  
   838  			var pk core.PK = make([]interface{}, len(table.PrimaryKeys))
   839  			for i, col := range table.PKColumns() {
   840  				if col.SQLType.IsNumeric() {
   841  					n, err := strconv.ParseInt(res[i], 10, 64)
   842  					if err != nil {
   843  						return err
   844  					}
   845  					pk[i] = n
   846  				} else if col.SQLType.IsText() {
   847  					pk[i] = res[i]
   848  				} else {
   849  					return errors.New("not supported")
   850  				}
   851  			}
   852  
   853  			ids = append(ids, pk)
   854  		}
   855  
   856  		session.Engine.logger.Debug("[cacheFind] cache sql:", ids, tableName, newsql, args)
   857  		err = core.PutCacheSql(cacher, ids, tableName, newsql, args)
   858  		if err != nil {
   859  			return err
   860  		}
   861  	} else {
   862  		session.Engine.logger.Debug("[cacheFind] cache hit sql:", newsql, args)
   863  	}
   864  
   865  	sliceValue := reflect.Indirect(reflect.ValueOf(rowsSlicePtr))
   866  
   867  	ididxes := make(map[string]int)
   868  	var ides []core.PK
   869  	var temps = make([]interface{}, len(ids))
   870  
   871  	for idx, id := range ids {
   872  		sid, err := id.ToString()
   873  		if err != nil {
   874  			return err
   875  		}
   876  		bean := cacher.GetBean(tableName, sid)
   877  		if bean == nil {
   878  			ides = append(ides, id)
   879  			ididxes[sid] = idx
   880  		} else {
   881  			session.Engine.logger.Debug("[cacheFind] cache hit bean:", tableName, id, bean)
   882  
   883  			pk := session.Engine.IdOf(bean)
   884  			xid, err := pk.ToString()
   885  			if err != nil {
   886  				return err
   887  			}
   888  
   889  			if sid != xid {
   890  				session.Engine.logger.Error("[cacheFind] error cache", xid, sid, bean)
   891  				return ErrCacheFailed
   892  			}
   893  			temps[idx] = bean
   894  		}
   895  	}
   896  
   897  	if len(ides) > 0 {
   898  		newSession := session.Engine.NewSession()
   899  		defer newSession.Close()
   900  
   901  		slices := reflect.New(reflect.SliceOf(t))
   902  		beans := slices.Interface()
   903  
   904  		if len(table.PrimaryKeys) == 1 {
   905  			ff := make([]interface{}, 0, len(ides))
   906  			for _, ie := range ides {
   907  				ff = append(ff, ie[0])
   908  			}
   909  
   910  			newSession.In("`"+table.PrimaryKeys[0]+"`", ff...)
   911  		} else {
   912  			for _, ie := range ides {
   913  				cond := builder.NewCond()
   914  				for i, name := range table.PrimaryKeys {
   915  					cond = cond.And(builder.Eq{"`" + name + "`": ie[i]})
   916  				}
   917  				newSession.Or(cond)
   918  			}
   919  		}
   920  
   921  		err = newSession.NoCache().Find(beans)
   922  		if err != nil {
   923  			return err
   924  		}
   925  
   926  		vs := reflect.Indirect(reflect.ValueOf(beans))
   927  		for i := 0; i < vs.Len(); i++ {
   928  			rv := vs.Index(i)
   929  			if rv.Kind() != reflect.Ptr {
   930  				rv = rv.Addr()
   931  			}
   932  			id := session.Engine.IdOfV(rv)
   933  			sid, err := id.ToString()
   934  			if err != nil {
   935  				return err
   936  			}
   937  
   938  			bean := rv.Interface()
   939  			temps[ididxes[sid]] = bean
   940  			session.Engine.logger.Debug("[cacheFind] cache bean:", tableName, id, bean, temps)
   941  			cacher.PutBean(tableName, sid, bean)
   942  		}
   943  	}
   944  
   945  	for j := 0; j < len(temps); j++ {
   946  		bean := temps[j]
   947  		if bean == nil {
   948  			session.Engine.logger.Warn("[cacheFind] cache no hit:", tableName, ids[j], temps)
   949  			// return errors.New("cache error") // !nashtsai! no need to return error, but continue instead
   950  			continue
   951  		}
   952  		if sliceValue.Kind() == reflect.Slice {
   953  			if t.Kind() == reflect.Ptr {
   954  				sliceValue.Set(reflect.Append(sliceValue, reflect.ValueOf(bean)))
   955  			} else {
   956  				sliceValue.Set(reflect.Append(sliceValue, reflect.Indirect(reflect.ValueOf(bean))))
   957  			}
   958  		} else if sliceValue.Kind() == reflect.Map {
   959  			var key = ids[j]
   960  			keyType := sliceValue.Type().Key()
   961  			var ikey interface{}
   962  			if len(key) == 1 {
   963  				ikey, err = str2PK(fmt.Sprintf("%v", key[0]), keyType)
   964  				if err != nil {
   965  					return err
   966  				}
   967  			} else {
   968  				if keyType.Kind() != reflect.Slice {
   969  					return errors.New("table have multiple primary keys, key is not core.PK or slice")
   970  				}
   971  				ikey = key
   972  			}
   973  
   974  			if t.Kind() == reflect.Ptr {
   975  				sliceValue.SetMapIndex(reflect.ValueOf(ikey), reflect.ValueOf(bean))
   976  			} else {
   977  				sliceValue.SetMapIndex(reflect.ValueOf(ikey), reflect.Indirect(reflect.ValueOf(bean)))
   978  			}
   979  		}
   980  	}
   981  
   982  	return nil
   983  }
   984  
   985  // IterFunc only use by Iterate
   986  type IterFunc func(idx int, bean interface{}) error
   987  
   988  // Rows return sql.Rows compatible Rows obj, as a forward Iterator object for iterating record by record, bean's non-empty fields
   989  // are conditions.
   990  func (session *Session) Rows(bean interface{}) (*Rows, error) {
   991  	return newRows(session, bean)
   992  }
   993  
   994  // Iterate record by record handle records from table, condiBeans's non-empty fields
   995  // are conditions. beans could be []Struct, []*Struct, map[int64]Struct
   996  // map[int64]*Struct
   997  func (session *Session) Iterate(bean interface{}, fun IterFunc) error {
   998  	rows, err := session.Rows(bean)
   999  	if err != nil {
  1000  		return err
  1001  	}
  1002  	defer rows.Close()
  1003  
  1004  	i := 0
  1005  	for rows.Next() {
  1006  		b := reflect.New(rows.beanType).Interface()
  1007  		err = rows.Scan(b)
  1008  		if err != nil {
  1009  			return err
  1010  		}
  1011  		err = fun(i, b)
  1012  		if err != nil {
  1013  			return err
  1014  		}
  1015  		i++
  1016  	}
  1017  	return err
  1018  }
  1019  
  1020  func (session *Session) doPrepare(sqlStr string) (stmt *core.Stmt, err error) {
  1021  	crc := crc32.ChecksumIEEE([]byte(sqlStr))
  1022  	// TODO try hash(sqlStr+len(sqlStr))
  1023  	var has bool
  1024  	stmt, has = session.stmtCache[crc]
  1025  	if !has {
  1026  		stmt, err = session.DB().Prepare(sqlStr)
  1027  		if err != nil {
  1028  			return nil, err
  1029  		}
  1030  		session.stmtCache[crc] = stmt
  1031  	}
  1032  	return
  1033  }
  1034  
  1035  func (session *Session) nocacheGet(bean interface{}, sqlStr string, args ...interface{}) (bool, error) {
  1036  	var rawRows *core.Rows
  1037  	var err error
  1038  	session.queryPreprocess(&sqlStr, args...)
  1039  	if session.IsAutoCommit {
  1040  		_, rawRows, err = session.innerQuery(sqlStr, args...)
  1041  	} else {
  1042  		rawRows, err = session.Tx.Query(sqlStr, args...)
  1043  	}
  1044  	if err != nil {
  1045  		return false, err
  1046  	}
  1047  
  1048  	defer rawRows.Close()
  1049  
  1050  	if rawRows.Next() {
  1051  		if fields, err := rawRows.Columns(); err == nil {
  1052  			err = session.row2Bean(rawRows, fields, len(fields), bean)
  1053  		}
  1054  		return true, err
  1055  	}
  1056  	return false, nil
  1057  }
  1058  
  1059  // Get retrieve one record from database, bean's non-empty fields
  1060  // will be as conditions
  1061  func (session *Session) Get(bean interface{}) (bool, error) {
  1062  	defer session.resetStatement()
  1063  	if session.IsAutoClose {
  1064  		defer session.Close()
  1065  	}
  1066  
  1067  	session.Statement.setRefValue(rValue(bean))
  1068  
  1069  	var sqlStr string
  1070  	var args []interface{}
  1071  
  1072  	if session.Statement.RawSQL == "" {
  1073  		if len(session.Statement.TableName()) <= 0 {
  1074  			return false, ErrTableNotFound
  1075  		}
  1076  		session.Statement.Limit(1)
  1077  		sqlStr, args = session.Statement.genGetSQL(bean)
  1078  	} else {
  1079  		sqlStr = session.Statement.RawSQL
  1080  		args = session.Statement.RawParams
  1081  	}
  1082  
  1083  	if session.canCache() {
  1084  		if cacher := session.Engine.getCacher2(session.Statement.RefTable); cacher != nil &&
  1085  			!session.Statement.unscoped {
  1086  			has, err := session.cacheGet(bean, sqlStr, args...)
  1087  			if err != ErrCacheFailed {
  1088  				return has, err
  1089  			}
  1090  		}
  1091  	}
  1092  
  1093  	return session.nocacheGet(bean, sqlStr, args...)
  1094  }
  1095  
  1096  // Count counts the records. bean's non-empty fields
  1097  // are conditions.
  1098  func (session *Session) Count(bean interface{}) (int64, error) {
  1099  	defer session.resetStatement()
  1100  	if session.IsAutoClose {
  1101  		defer session.Close()
  1102  	}
  1103  
  1104  	var sqlStr string
  1105  	var args []interface{}
  1106  	if session.Statement.RawSQL == "" {
  1107  		sqlStr, args = session.Statement.genCountSQL(bean)
  1108  	} else {
  1109  		sqlStr = session.Statement.RawSQL
  1110  		args = session.Statement.RawParams
  1111  	}
  1112  
  1113  	session.queryPreprocess(&sqlStr, args...)
  1114  
  1115  	var err error
  1116  	var total int64
  1117  	if session.IsAutoCommit {
  1118  		err = session.DB().QueryRow(sqlStr, args...).Scan(&total)
  1119  	} else {
  1120  		err = session.Tx.QueryRow(sqlStr, args...).Scan(&total)
  1121  	}
  1122  
  1123  	if err == sql.ErrNoRows || err == nil {
  1124  		return total, nil
  1125  	}
  1126  
  1127  	return 0, err
  1128  }
  1129  
  1130  // Sum call sum some column. bean's non-empty fields are conditions.
  1131  func (session *Session) Sum(bean interface{}, columnName string) (float64, error) {
  1132  	defer session.resetStatement()
  1133  	if session.IsAutoClose {
  1134  		defer session.Close()
  1135  	}
  1136  
  1137  	var sqlStr string
  1138  	var args []interface{}
  1139  	if len(session.Statement.RawSQL) == 0 {
  1140  		sqlStr, args = session.Statement.genSumSQL(bean, columnName)
  1141  	} else {
  1142  		sqlStr = session.Statement.RawSQL
  1143  		args = session.Statement.RawParams
  1144  	}
  1145  
  1146  	session.queryPreprocess(&sqlStr, args...)
  1147  
  1148  	var err error
  1149  	var res float64
  1150  	if session.IsAutoCommit {
  1151  		err = session.DB().QueryRow(sqlStr, args...).Scan(&res)
  1152  	} else {
  1153  		err = session.Tx.QueryRow(sqlStr, args...).Scan(&res)
  1154  	}
  1155  
  1156  	if err == sql.ErrNoRows || err == nil {
  1157  		return res, nil
  1158  	}
  1159  	return 0, err
  1160  }
  1161  
  1162  // Sums call sum some columns. bean's non-empty fields are conditions.
  1163  func (session *Session) Sums(bean interface{}, columnNames ...string) ([]float64, error) {
  1164  	defer session.resetStatement()
  1165  	if session.IsAutoClose {
  1166  		defer session.Close()
  1167  	}
  1168  
  1169  	var sqlStr string
  1170  	var args []interface{}
  1171  	if len(session.Statement.RawSQL) == 0 {
  1172  		sqlStr, args = session.Statement.genSumSQL(bean, columnNames...)
  1173  	} else {
  1174  		sqlStr = session.Statement.RawSQL
  1175  		args = session.Statement.RawParams
  1176  	}
  1177  
  1178  	session.queryPreprocess(&sqlStr, args...)
  1179  
  1180  	var err error
  1181  	var res = make([]float64, len(columnNames), len(columnNames))
  1182  	if session.IsAutoCommit {
  1183  		err = session.DB().QueryRow(sqlStr, args...).ScanSlice(&res)
  1184  	} else {
  1185  		err = session.Tx.QueryRow(sqlStr, args...).ScanSlice(&res)
  1186  	}
  1187  
  1188  	if err == sql.ErrNoRows || err == nil {
  1189  		return res, nil
  1190  	}
  1191  	return nil, err
  1192  }
  1193  
  1194  // SumsInt sum specify columns and return as []int64 instead of []float64
  1195  func (session *Session) SumsInt(bean interface{}, columnNames ...string) ([]int64, error) {
  1196  	defer session.resetStatement()
  1197  	if session.IsAutoClose {
  1198  		defer session.Close()
  1199  	}
  1200  
  1201  	var sqlStr string
  1202  	var args []interface{}
  1203  	if len(session.Statement.RawSQL) == 0 {
  1204  		sqlStr, args = session.Statement.genSumSQL(bean, columnNames...)
  1205  	} else {
  1206  		sqlStr = session.Statement.RawSQL
  1207  		args = session.Statement.RawParams
  1208  	}
  1209  
  1210  	session.queryPreprocess(&sqlStr, args...)
  1211  
  1212  	var err error
  1213  	var res = make([]int64, 0, len(columnNames))
  1214  	if session.IsAutoCommit {
  1215  		err = session.DB().QueryRow(sqlStr, args...).ScanSlice(&res)
  1216  	} else {
  1217  		err = session.Tx.QueryRow(sqlStr, args...).ScanSlice(&res)
  1218  	}
  1219  
  1220  	if err == sql.ErrNoRows || err == nil {
  1221  		return res, nil
  1222  	}
  1223  	return nil, err
  1224  }
  1225  
  1226  func (session *Session) noCacheFind(sliceValue reflect.Value, sqlStr string, args ...interface{}) error {
  1227  	var rawRows *core.Rows
  1228  	var err error
  1229  
  1230  	session.queryPreprocess(&sqlStr, args...)
  1231  	if session.IsAutoCommit {
  1232  		_, rawRows, err = session.innerQuery(sqlStr, args...)
  1233  	} else {
  1234  		rawRows, err = session.Tx.Query(sqlStr, args...)
  1235  	}
  1236  	if err != nil {
  1237  		return err
  1238  	}
  1239  	defer rawRows.Close()
  1240  
  1241  	fields, err := rawRows.Columns()
  1242  	if err != nil {
  1243  		return err
  1244  	}
  1245  
  1246  	var newElemFunc func() reflect.Value
  1247  	sliceElementType := sliceValue.Type().Elem()
  1248  	if sliceElementType.Kind() == reflect.Ptr {
  1249  		newElemFunc = func() reflect.Value {
  1250  			return reflect.New(sliceElementType.Elem())
  1251  		}
  1252  	} else {
  1253  		newElemFunc = func() reflect.Value {
  1254  			return reflect.New(sliceElementType)
  1255  		}
  1256  	}
  1257  
  1258  	var sliceValueSetFunc func(*reflect.Value)
  1259  
  1260  	if sliceValue.Kind() == reflect.Slice {
  1261  		if sliceElementType.Kind() == reflect.Ptr {
  1262  			sliceValueSetFunc = func(newValue *reflect.Value) {
  1263  				sliceValue.Set(reflect.Append(sliceValue, reflect.ValueOf(newValue.Interface())))
  1264  			}
  1265  		} else {
  1266  			sliceValueSetFunc = func(newValue *reflect.Value) {
  1267  				sliceValue.Set(reflect.Append(sliceValue, reflect.Indirect(reflect.ValueOf(newValue.Interface()))))
  1268  			}
  1269  		}
  1270  	}
  1271  
  1272  	var newValue = newElemFunc()
  1273  	dataStruct := rValue(newValue.Interface())
  1274  	if dataStruct.Kind() != reflect.Struct {
  1275  		return errors.New("Expected a pointer to a struct")
  1276  	}
  1277  
  1278  	return session.rows2Beans(rawRows, fields, len(fields), session.Engine.autoMapType(dataStruct), newElemFunc, sliceValueSetFunc)
  1279  }
  1280  
  1281  // Find retrieve records from table, condiBeans's non-empty fields
  1282  // are conditions. beans could be []Struct, []*Struct, map[int64]Struct
  1283  // map[int64]*Struct
  1284  func (session *Session) Find(rowsSlicePtr interface{}, condiBean ...interface{}) error {
  1285  	defer session.resetStatement()
  1286  	if session.IsAutoClose {
  1287  		defer session.Close()
  1288  	}
  1289  
  1290  	sliceValue := reflect.Indirect(reflect.ValueOf(rowsSlicePtr))
  1291  	if sliceValue.Kind() != reflect.Slice && sliceValue.Kind() != reflect.Map {
  1292  		return errors.New("needs a pointer to a slice or a map")
  1293  	}
  1294  
  1295  	sliceElementType := sliceValue.Type().Elem()
  1296  
  1297  	if session.Statement.RefTable == nil {
  1298  		if sliceElementType.Kind() == reflect.Ptr {
  1299  			if sliceElementType.Elem().Kind() == reflect.Struct {
  1300  				pv := reflect.New(sliceElementType.Elem())
  1301  				session.Statement.setRefValue(pv.Elem())
  1302  			} else {
  1303  				return errors.New("slice type")
  1304  			}
  1305  		} else if sliceElementType.Kind() == reflect.Struct {
  1306  			pv := reflect.New(sliceElementType)
  1307  			session.Statement.setRefValue(pv.Elem())
  1308  		} else {
  1309  			return errors.New("slice type")
  1310  		}
  1311  	}
  1312  
  1313  	var table = session.Statement.RefTable
  1314  
  1315  	var addedTableName = (len(session.Statement.JoinStr) > 0)
  1316  	var autoCond builder.Cond
  1317  	if !session.Statement.noAutoCondition && len(condiBean) > 0 {
  1318  		var err error
  1319  		autoCond, err = session.Statement.buildConds(table, condiBean[0], true, true, false, true, addedTableName)
  1320  		if err != nil {
  1321  			panic(err)
  1322  		}
  1323  	} else {
  1324  		// !oinume! Add "<col> IS NULL" to WHERE whatever condiBean is given.
  1325  		// See https://yougam/libraries/xorm/issues/179
  1326  		if col := table.DeletedColumn(); col != nil && !session.Statement.unscoped { // tag "deleted" is enabled
  1327  			var colName = session.Engine.Quote(col.Name)
  1328  			if addedTableName {
  1329  				var nm = session.Statement.TableName()
  1330  				if len(session.Statement.TableAlias) > 0 {
  1331  					nm = session.Statement.TableAlias
  1332  				}
  1333  				colName = session.Engine.Quote(nm) + "." + colName
  1334  			}
  1335  			autoCond = builder.IsNull{colName}.Or(builder.Eq{colName: "0001-01-01 00:00:00"})
  1336  		}
  1337  	}
  1338  
  1339  	var sqlStr string
  1340  	var args []interface{}
  1341  	if session.Statement.RawSQL == "" {
  1342  		if len(session.Statement.TableName()) <= 0 {
  1343  			return ErrTableNotFound
  1344  		}
  1345  
  1346  		var columnStr = session.Statement.ColumnStr
  1347  		if len(session.Statement.selectStr) > 0 {
  1348  			columnStr = session.Statement.selectStr
  1349  		} else {
  1350  			if session.Statement.JoinStr == "" {
  1351  				if columnStr == "" {
  1352  					if session.Statement.GroupByStr != "" {
  1353  						columnStr = session.Statement.Engine.Quote(strings.Replace(session.Statement.GroupByStr, ",", session.Engine.Quote(","), -1))
  1354  					} else {
  1355  						columnStr = session.Statement.genColumnStr()
  1356  					}
  1357  				}
  1358  			} else {
  1359  				if columnStr == "" {
  1360  					if session.Statement.GroupByStr != "" {
  1361  						columnStr = session.Statement.Engine.Quote(strings.Replace(session.Statement.GroupByStr, ",", session.Engine.Quote(","), -1))
  1362  					} else {
  1363  						columnStr = "*"
  1364  					}
  1365  				}
  1366  			}
  1367  		}
  1368  
  1369  		condSQL, condArgs, _ := builder.ToSQL(session.Statement.cond.And(autoCond))
  1370  
  1371  		args = append(session.Statement.joinArgs, condArgs...)
  1372  		sqlStr = session.Statement.genSelectSQL(columnStr, condSQL)
  1373  		// for mssql and use limit
  1374  		qs := strings.Count(sqlStr, "?")
  1375  		if len(args)*2 == qs {
  1376  			args = append(args, args...)
  1377  		}
  1378  	} else {
  1379  		sqlStr = session.Statement.RawSQL
  1380  		args = session.Statement.RawParams
  1381  	}
  1382  
  1383  	var err error
  1384  	if session.canCache() {
  1385  		if cacher := session.Engine.getCacher2(table); cacher != nil &&
  1386  			!session.Statement.IsDistinct &&
  1387  			!session.Statement.unscoped {
  1388  			err = session.cacheFind(sliceElementType, sqlStr, rowsSlicePtr, args...)
  1389  			if err != ErrCacheFailed {
  1390  				return err
  1391  			}
  1392  			err = nil // !nashtsai! reset err to nil for ErrCacheFailed
  1393  			session.Engine.logger.Warn("Cache Find Failed")
  1394  		}
  1395  	}
  1396  
  1397  	if sliceValue.Kind() != reflect.Map {
  1398  		return session.noCacheFind(sliceValue, sqlStr, args...)
  1399  	}
  1400  
  1401  	resultsSlice, err := session.query(sqlStr, args...)
  1402  	if err != nil {
  1403  		return err
  1404  	}
  1405  
  1406  	keyType := sliceValue.Type().Key()
  1407  
  1408  	for _, results := range resultsSlice {
  1409  		var newValue reflect.Value
  1410  		if sliceElementType.Kind() == reflect.Ptr {
  1411  			newValue = reflect.New(sliceElementType.Elem())
  1412  		} else {
  1413  			newValue = reflect.New(sliceElementType)
  1414  		}
  1415  		err := session.scanMapIntoStruct(newValue.Interface(), results)
  1416  		if err != nil {
  1417  			return err
  1418  		}
  1419  		var key interface{}
  1420  		// if there is only one pk, we can put the id as map key.
  1421  		if len(table.PrimaryKeys) == 1 {
  1422  			key, err = str2PK(string(results[table.PrimaryKeys[0]]), keyType)
  1423  			if err != nil {
  1424  				return err
  1425  			}
  1426  		} else {
  1427  			if keyType.Kind() != reflect.Slice {
  1428  				panic("don't support multiple primary key's map has non-slice key type")
  1429  			} else {
  1430  				var keys core.PK = make([]interface{}, 0, len(table.PrimaryKeys))
  1431  				for _, pk := range table.PrimaryKeys {
  1432  					skey, err := str2PK(string(results[pk]), keyType)
  1433  					if err != nil {
  1434  						return err
  1435  					}
  1436  					keys = append(keys, skey)
  1437  				}
  1438  				key = keys
  1439  			}
  1440  		}
  1441  
  1442  		if sliceElementType.Kind() == reflect.Ptr {
  1443  			sliceValue.SetMapIndex(reflect.ValueOf(key), reflect.ValueOf(newValue.Interface()))
  1444  		} else {
  1445  			sliceValue.SetMapIndex(reflect.ValueOf(key), reflect.Indirect(reflect.ValueOf(newValue.Interface())))
  1446  		}
  1447  	}
  1448  
  1449  	return nil
  1450  }
  1451  
  1452  // Ping test if database is ok
  1453  func (session *Session) Ping() error {
  1454  	defer session.resetStatement()
  1455  	if session.IsAutoClose {
  1456  		defer session.Close()
  1457  	}
  1458  
  1459  	return session.DB().Ping()
  1460  }
  1461  
  1462  // IsTableExist if a table is exist
  1463  func (session *Session) IsTableExist(beanOrTableName interface{}) (bool, error) {
  1464  	tableName, err := session.Engine.tableName(beanOrTableName)
  1465  	if err != nil {
  1466  		return false, err
  1467  	}
  1468  
  1469  	return session.isTableExist(tableName)
  1470  }
  1471  
  1472  func (session *Session) isTableExist(tableName string) (bool, error) {
  1473  	defer session.resetStatement()
  1474  	if session.IsAutoClose {
  1475  		defer session.Close()
  1476  	}
  1477  	sqlStr, args := session.Engine.dialect.TableCheckSql(tableName)
  1478  	results, err := session.query(sqlStr, args...)
  1479  	return len(results) > 0, err
  1480  }
  1481  
  1482  // IsTableEmpty if table have any records
  1483  func (session *Session) IsTableEmpty(bean interface{}) (bool, error) {
  1484  	v := rValue(bean)
  1485  	t := v.Type()
  1486  
  1487  	if t.Kind() == reflect.String {
  1488  		return session.isTableEmpty(bean.(string))
  1489  	} else if t.Kind() == reflect.Struct {
  1490  		rows, err := session.Count(bean)
  1491  		return rows == 0, err
  1492  	}
  1493  	return false, errors.New("bean should be a struct or struct's point")
  1494  }
  1495  
  1496  func (session *Session) isTableEmpty(tableName string) (bool, error) {
  1497  	defer session.resetStatement()
  1498  	if session.IsAutoClose {
  1499  		defer session.Close()
  1500  	}
  1501  
  1502  	var total int64
  1503  	sqlStr := fmt.Sprintf("select count(*) from %s", session.Engine.Quote(tableName))
  1504  	err := session.DB().QueryRow(sqlStr).Scan(&total)
  1505  	session.saveLastSQL(sqlStr)
  1506  	if err != nil {
  1507  		if err == sql.ErrNoRows {
  1508  			err = nil
  1509  		}
  1510  		return true, err
  1511  	}
  1512  
  1513  	return total == 0, nil
  1514  }
  1515  
  1516  func (session *Session) isIndexExist(tableName, idxName string, unique bool) (bool, error) {
  1517  	defer session.resetStatement()
  1518  	if session.IsAutoClose {
  1519  		defer session.Close()
  1520  	}
  1521  	var idx string
  1522  	if unique {
  1523  		idx = uniqueName(tableName, idxName)
  1524  	} else {
  1525  		idx = indexName(tableName, idxName)
  1526  	}
  1527  	sqlStr, args := session.Engine.dialect.IndexCheckSql(tableName, idx)
  1528  	results, err := session.query(sqlStr, args...)
  1529  	return len(results) > 0, err
  1530  }
  1531  
  1532  // find if index is exist according cols
  1533  func (session *Session) isIndexExist2(tableName string, cols []string, unique bool) (bool, error) {
  1534  	defer session.resetStatement()
  1535  	if session.IsAutoClose {
  1536  		defer session.Close()
  1537  	}
  1538  
  1539  	indexes, err := session.Engine.dialect.GetIndexes(tableName)
  1540  	if err != nil {
  1541  		return false, err
  1542  	}
  1543  
  1544  	for _, index := range indexes {
  1545  		if sliceEq(index.Cols, cols) {
  1546  			if unique {
  1547  				return index.Type == core.UniqueType, nil
  1548  			}
  1549  			return index.Type == core.IndexType, nil
  1550  		}
  1551  	}
  1552  	return false, nil
  1553  }
  1554  
  1555  func (session *Session) addColumn(colName string) error {
  1556  	defer session.resetStatement()
  1557  	if session.IsAutoClose {
  1558  		defer session.Close()
  1559  	}
  1560  
  1561  	col := session.Statement.RefTable.GetColumn(colName)
  1562  	sql, args := session.Statement.genAddColumnStr(col)
  1563  	_, err := session.exec(sql, args...)
  1564  	return err
  1565  }
  1566  
  1567  func (session *Session) addIndex(tableName, idxName string) error {
  1568  	defer session.resetStatement()
  1569  	if session.IsAutoClose {
  1570  		defer session.Close()
  1571  	}
  1572  	index := session.Statement.RefTable.Indexes[idxName]
  1573  	sqlStr := session.Engine.dialect.CreateIndexSql(tableName, index)
  1574  
  1575  	_, err := session.exec(sqlStr)
  1576  	return err
  1577  }
  1578  
  1579  func (session *Session) addUnique(tableName, uqeName string) error {
  1580  	defer session.resetStatement()
  1581  	if session.IsAutoClose {
  1582  		defer session.Close()
  1583  	}
  1584  	index := session.Statement.RefTable.Indexes[uqeName]
  1585  	sqlStr := session.Engine.dialect.CreateIndexSql(tableName, index)
  1586  	_, err := session.exec(sqlStr)
  1587  	return err
  1588  }
  1589  
  1590  // To be deleted
  1591  func (session *Session) dropAll() error {
  1592  	defer session.resetStatement()
  1593  	if session.IsAutoClose {
  1594  		defer session.Close()
  1595  	}
  1596  
  1597  	for _, table := range session.Engine.Tables {
  1598  		session.Statement.Init()
  1599  		session.Statement.RefTable = table
  1600  		sqlStr := session.Engine.Dialect().DropTableSql(session.Statement.TableName())
  1601  		_, err := session.exec(sqlStr)
  1602  		if err != nil {
  1603  			return err
  1604  		}
  1605  	}
  1606  	return nil
  1607  }
  1608  
  1609  func (session *Session) getField(dataStruct *reflect.Value, key string, table *core.Table, idx int) *reflect.Value {
  1610  	var col *core.Column
  1611  	if col = table.GetColumnIdx(key, idx); col == nil {
  1612  		//session.Engine.logger.Warnf("table %v has no column %v. %v", table.Name, key, table.ColumnsSeq())
  1613  		return nil
  1614  	}
  1615  
  1616  	fieldValue, err := col.ValueOfV(dataStruct)
  1617  	if err != nil {
  1618  		session.Engine.logger.Error(err)
  1619  		return nil
  1620  	}
  1621  
  1622  	if !fieldValue.IsValid() || !fieldValue.CanSet() {
  1623  		session.Engine.logger.Warnf("table %v's column %v is not valid or cannot set", table.Name, key)
  1624  		return nil
  1625  	}
  1626  	return fieldValue
  1627  }
  1628  
  1629  // Cell cell is a result of one column field
  1630  type Cell *interface{}
  1631  
  1632  func (session *Session) rows2Beans(rows *core.Rows, fields []string, fieldsCount int,
  1633  	table *core.Table, newElemFunc func() reflect.Value,
  1634  	sliceValueSetFunc func(*reflect.Value)) error {
  1635  	for rows.Next() {
  1636  		var newValue = newElemFunc()
  1637  		bean := newValue.Interface()
  1638  		dataStruct := rValue(bean)
  1639  		err := session._row2Bean(rows, fields, fieldsCount, bean, &dataStruct, table)
  1640  		if err != nil {
  1641  			return err
  1642  		}
  1643  		sliceValueSetFunc(&newValue)
  1644  	}
  1645  	return nil
  1646  }
  1647  
  1648  func (session *Session) row2Bean(rows *core.Rows, fields []string, fieldsCount int, bean interface{}) error {
  1649  	dataStruct := rValue(bean)
  1650  	if dataStruct.Kind() != reflect.Struct {
  1651  		return errors.New("Expected a pointer to a struct")
  1652  	}
  1653  
  1654  	session.Statement.setRefValue(dataStruct)
  1655  
  1656  	return session._row2Bean(rows, fields, fieldsCount, bean, &dataStruct, session.Statement.RefTable)
  1657  }
  1658  
  1659  func (session *Session) _row2Bean(rows *core.Rows, fields []string, fieldsCount int, bean interface{}, dataStruct *reflect.Value, table *core.Table) error {
  1660  	scanResults := make([]interface{}, fieldsCount)
  1661  	for i := 0; i < len(fields); i++ {
  1662  		var cell interface{}
  1663  		scanResults[i] = &cell
  1664  	}
  1665  	if err := rows.Scan(scanResults...); err != nil {
  1666  		return err
  1667  	}
  1668  
  1669  	if b, hasBeforeSet := bean.(BeforeSetProcessor); hasBeforeSet {
  1670  		for ii, key := range fields {
  1671  			b.BeforeSet(key, Cell(scanResults[ii].(*interface{})))
  1672  		}
  1673  	}
  1674  
  1675  	defer func() {
  1676  		if b, hasAfterSet := bean.(AfterSetProcessor); hasAfterSet {
  1677  			for ii, key := range fields {
  1678  				b.AfterSet(key, Cell(scanResults[ii].(*interface{})))
  1679  			}
  1680  		}
  1681  	}()
  1682  
  1683  	var tempMap = make(map[string]int)
  1684  	for ii, key := range fields {
  1685  		var idx int
  1686  		var ok bool
  1687  		var lKey = strings.ToLower(key)
  1688  		if idx, ok = tempMap[lKey]; !ok {
  1689  			idx = 0
  1690  		} else {
  1691  			idx = idx + 1
  1692  		}
  1693  		tempMap[lKey] = idx
  1694  
  1695  		if fieldValue := session.getField(dataStruct, key, table, idx); fieldValue != nil {
  1696  			rawValue := reflect.Indirect(reflect.ValueOf(scanResults[ii]))
  1697  
  1698  			// if row is null then ignore
  1699  			if rawValue.Interface() == nil {
  1700  				continue
  1701  			}
  1702  
  1703  			if fieldValue.CanAddr() {
  1704  				if structConvert, ok := fieldValue.Addr().Interface().(core.Conversion); ok {
  1705  					if data, err := value2Bytes(&rawValue); err == nil {
  1706  						structConvert.FromDB(data)
  1707  					} else {
  1708  						session.Engine.logger.Error(err)
  1709  					}
  1710  					continue
  1711  				}
  1712  			}
  1713  
  1714  			if _, ok := fieldValue.Interface().(core.Conversion); ok {
  1715  				if data, err := value2Bytes(&rawValue); err == nil {
  1716  					if fieldValue.Kind() == reflect.Ptr && fieldValue.IsNil() {
  1717  						fieldValue.Set(reflect.New(fieldValue.Type().Elem()))
  1718  					}
  1719  					fieldValue.Interface().(core.Conversion).FromDB(data)
  1720  				} else {
  1721  					session.Engine.logger.Error(err)
  1722  				}
  1723  				continue
  1724  			}
  1725  
  1726  			rawValueType := reflect.TypeOf(rawValue.Interface())
  1727  			vv := reflect.ValueOf(rawValue.Interface())
  1728  
  1729  			fieldType := fieldValue.Type()
  1730  			hasAssigned := false
  1731  			col := table.GetColumnIdx(key, idx)
  1732  
  1733  			if col.SQLType.IsJson() {
  1734  				var bs []byte
  1735  				if rawValueType.Kind() == reflect.String {
  1736  					bs = []byte(vv.String())
  1737  				} else if rawValueType.ConvertibleTo(core.BytesType) {
  1738  					bs = vv.Bytes()
  1739  				} else {
  1740  					return fmt.Errorf("unsupported database data type: %s %v", key, rawValueType.Kind())
  1741  				}
  1742  
  1743  				hasAssigned = true
  1744  
  1745  				if len(bs) > 0 {
  1746  					if fieldValue.CanAddr() {
  1747  						err := json.Unmarshal(bs, fieldValue.Addr().Interface())
  1748  						if err != nil {
  1749  							session.Engine.logger.Error(key, err)
  1750  							return err
  1751  						}
  1752  					} else {
  1753  						x := reflect.New(fieldType)
  1754  						err := json.Unmarshal(bs, x.Interface())
  1755  						if err != nil {
  1756  							session.Engine.logger.Error(key, err)
  1757  							return err
  1758  						}
  1759  						fieldValue.Set(x.Elem())
  1760  					}
  1761  				}
  1762  
  1763  				continue
  1764  			}
  1765  
  1766  			switch fieldType.Kind() {
  1767  			case reflect.Complex64, reflect.Complex128:
  1768  				// TODO: reimplement this
  1769  				var bs []byte
  1770  				if rawValueType.Kind() == reflect.String {
  1771  					bs = []byte(vv.String())
  1772  				} else if rawValueType.ConvertibleTo(core.BytesType) {
  1773  					bs = vv.Bytes()
  1774  				}
  1775  
  1776  				hasAssigned = true
  1777  				if len(bs) > 0 {
  1778  					if fieldValue.CanAddr() {
  1779  						err := json.Unmarshal(bs, fieldValue.Addr().Interface())
  1780  						if err != nil {
  1781  							session.Engine.logger.Error(err)
  1782  							return err
  1783  						}
  1784  					} else {
  1785  						x := reflect.New(fieldType)
  1786  						err := json.Unmarshal(bs, x.Interface())
  1787  						if err != nil {
  1788  							session.Engine.logger.Error(err)
  1789  							return err
  1790  						}
  1791  						fieldValue.Set(x.Elem())
  1792  					}
  1793  				}
  1794  			case reflect.Slice, reflect.Array:
  1795  				switch rawValueType.Kind() {
  1796  				case reflect.Slice, reflect.Array:
  1797  					switch rawValueType.Elem().Kind() {
  1798  					case reflect.Uint8:
  1799  						if fieldType.Elem().Kind() == reflect.Uint8 {
  1800  							hasAssigned = true
  1801  							fieldValue.Set(vv)
  1802  						}
  1803  					}
  1804  				}
  1805  			case reflect.String:
  1806  				if rawValueType.Kind() == reflect.String {
  1807  					hasAssigned = true
  1808  					fieldValue.SetString(vv.String())
  1809  				}
  1810  			case reflect.Bool:
  1811  				if rawValueType.Kind() == reflect.Bool {
  1812  					hasAssigned = true
  1813  					fieldValue.SetBool(vv.Bool())
  1814  				}
  1815  			case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
  1816  				switch rawValueType.Kind() {
  1817  				case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
  1818  					hasAssigned = true
  1819  					fieldValue.SetInt(vv.Int())
  1820  				}
  1821  			case reflect.Float32, reflect.Float64:
  1822  				switch rawValueType.Kind() {
  1823  				case reflect.Float32, reflect.Float64:
  1824  					hasAssigned = true
  1825  					fieldValue.SetFloat(vv.Float())
  1826  				}
  1827  			case reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uint:
  1828  				switch rawValueType.Kind() {
  1829  				case reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uint:
  1830  					hasAssigned = true
  1831  					fieldValue.SetUint(vv.Uint())
  1832  				case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
  1833  					hasAssigned = true
  1834  					fieldValue.SetUint(uint64(vv.Int()))
  1835  				}
  1836  			case reflect.Struct:
  1837  				if fieldType.ConvertibleTo(core.TimeType) {
  1838  					if rawValueType == core.TimeType {
  1839  						hasAssigned = true
  1840  
  1841  						t := vv.Convert(core.TimeType).Interface().(time.Time)
  1842  						z, _ := t.Zone()
  1843  						if len(z) == 0 || t.Year() == 0 { // !nashtsai! HACK tmp work around for lib/pq doesn't properly time with location
  1844  							dbTZ := session.Engine.DatabaseTZ
  1845  							if dbTZ == nil {
  1846  								dbTZ = time.Local
  1847  							}
  1848  							session.Engine.logger.Debugf("empty zone key[%v] : %v | zone: %v | location: %+v\n", key, t, z, *t.Location())
  1849  							t = time.Date(t.Year(), t.Month(), t.Day(), t.Hour(),
  1850  								t.Minute(), t.Second(), t.Nanosecond(), dbTZ)
  1851  						}
  1852  						// !nashtsai! convert to engine location
  1853  						if col.TimeZone == nil {
  1854  							t = t.In(session.Engine.TZLocation)
  1855  						} else {
  1856  							t = t.In(col.TimeZone)
  1857  						}
  1858  						fieldValue.Set(reflect.ValueOf(t).Convert(fieldType))
  1859  
  1860  						// t = fieldValue.Interface().(time.Time)
  1861  						// z, _ = t.Zone()
  1862  						// session.Engine.LogDebug("fieldValue key[%v]: %v | zone: %v | location: %+v\n", key, t, z, *t.Location())
  1863  					} else if rawValueType == core.IntType || rawValueType == core.Int64Type ||
  1864  						rawValueType == core.Int32Type {
  1865  						hasAssigned = true
  1866  						var tz *time.Location
  1867  						if col.TimeZone == nil {
  1868  							tz = session.Engine.TZLocation
  1869  						} else {
  1870  							tz = col.TimeZone
  1871  						}
  1872  						t := time.Unix(vv.Int(), 0).In(tz)
  1873  						//vv = reflect.ValueOf(t)
  1874  						fieldValue.Set(reflect.ValueOf(t).Convert(fieldType))
  1875  					} else {
  1876  						if d, ok := vv.Interface().([]uint8); ok {
  1877  							hasAssigned = true
  1878  							t, err := session.byte2Time(col, d)
  1879  							if err != nil {
  1880  								session.Engine.logger.Error("byte2Time error:", err.Error())
  1881  								hasAssigned = false
  1882  							} else {
  1883  								fieldValue.Set(reflect.ValueOf(t).Convert(fieldType))
  1884  							}
  1885  						} else if d, ok := vv.Interface().(string); ok {
  1886  							hasAssigned = true
  1887  							t, err := session.str2Time(col, d)
  1888  							if err != nil {
  1889  								session.Engine.logger.Error("byte2Time error:", err.Error())
  1890  								hasAssigned = false
  1891  							} else {
  1892  								fieldValue.Set(reflect.ValueOf(t).Convert(fieldType))
  1893  							}
  1894  						} else {
  1895  							panic(fmt.Sprintf("rawValueType is %v, value is %v", rawValueType, vv.Interface()))
  1896  						}
  1897  					}
  1898  				} else if nulVal, ok := fieldValue.Addr().Interface().(sql.Scanner); ok {
  1899  					// !<winxxp>! 增加支持sql.Scanner接口的结构,如sql.NullString
  1900  					hasAssigned = true
  1901  					if err := nulVal.Scan(vv.Interface()); err != nil {
  1902  						session.Engine.logger.Error("sql.Sanner error:", err.Error())
  1903  						hasAssigned = false
  1904  					}
  1905  				} else if col.SQLType.IsJson() {
  1906  					if rawValueType.Kind() == reflect.String {
  1907  						hasAssigned = true
  1908  						x := reflect.New(fieldType)
  1909  						if len([]byte(vv.String())) > 0 {
  1910  							err := json.Unmarshal([]byte(vv.String()), x.Interface())
  1911  							if err != nil {
  1912  								session.Engine.logger.Error(err)
  1913  								return err
  1914  							}
  1915  							fieldValue.Set(x.Elem())
  1916  						}
  1917  					} else if rawValueType.Kind() == reflect.Slice {
  1918  						hasAssigned = true
  1919  						x := reflect.New(fieldType)
  1920  						if len(vv.Bytes()) > 0 {
  1921  							err := json.Unmarshal(vv.Bytes(), x.Interface())
  1922  							if err != nil {
  1923  								session.Engine.logger.Error(err)
  1924  								return err
  1925  							}
  1926  							fieldValue.Set(x.Elem())
  1927  						}
  1928  					}
  1929  				} else if session.Statement.UseCascade {
  1930  					table := session.Engine.autoMapType(*fieldValue)
  1931  					if table != nil {
  1932  						hasAssigned = true
  1933  						if len(table.PrimaryKeys) != 1 {
  1934  							panic("unsupported non or composited primary key cascade")
  1935  						}
  1936  						var pk = make(core.PK, len(table.PrimaryKeys))
  1937  
  1938  						switch rawValueType.Kind() {
  1939  						case reflect.Int64:
  1940  							pk[0] = vv.Int()
  1941  						case reflect.Int:
  1942  							pk[0] = int(vv.Int())
  1943  						case reflect.Int32:
  1944  							pk[0] = int32(vv.Int())
  1945  						case reflect.Int16:
  1946  							pk[0] = int16(vv.Int())
  1947  						case reflect.Int8:
  1948  							pk[0] = int8(vv.Int())
  1949  						case reflect.Uint64:
  1950  							pk[0] = vv.Uint()
  1951  						case reflect.Uint:
  1952  							pk[0] = uint(vv.Uint())
  1953  						case reflect.Uint32:
  1954  							pk[0] = uint32(vv.Uint())
  1955  						case reflect.Uint16:
  1956  							pk[0] = uint16(vv.Uint())
  1957  						case reflect.Uint8:
  1958  							pk[0] = uint8(vv.Uint())
  1959  						case reflect.String:
  1960  							pk[0] = vv.String()
  1961  						case reflect.Slice:
  1962  							pk[0], _ = strconv.ParseInt(string(rawValue.Interface().([]byte)), 10, 64)
  1963  						default:
  1964  							panic(fmt.Sprintf("unsupported primary key type: %v, %v", rawValueType, fieldValue))
  1965  						}
  1966  
  1967  						if !isPKZero(pk) {
  1968  							// !nashtsai! TODO for hasOne relationship, it's preferred to use join query for eager fetch
  1969  							// however, also need to consider adding a 'lazy' attribute to xorm tag which allow hasOne
  1970  							// property to be fetched lazily
  1971  							structInter := reflect.New(fieldValue.Type())
  1972  							newsession := session.Engine.NewSession()
  1973  							defer newsession.Close()
  1974  							has, err := newsession.Id(pk).NoCascade().Get(structInter.Interface())
  1975  							if err != nil {
  1976  								return err
  1977  							}
  1978  							if has {
  1979  								//v := structInter.Elem().Interface()
  1980  								//fieldValue.Set(reflect.ValueOf(v))
  1981  								fieldValue.Set(structInter.Elem())
  1982  							} else {
  1983  								return errors.New("cascade obj is not exist")
  1984  							}
  1985  						}
  1986  					} else {
  1987  						session.Engine.logger.Error("unsupported struct type in Scan: ", fieldValue.Type().String())
  1988  					}
  1989  				}
  1990  			case reflect.Ptr:
  1991  				// !nashtsai! TODO merge duplicated codes above
  1992  				//typeStr := fieldType.String()
  1993  				switch fieldType {
  1994  				// following types case matching ptr's native type, therefore assign ptr directly
  1995  				case core.PtrStringType:
  1996  					if rawValueType.Kind() == reflect.String {
  1997  						x := vv.String()
  1998  						hasAssigned = true
  1999  						fieldValue.Set(reflect.ValueOf(&x))
  2000  					}
  2001  				case core.PtrBoolType:
  2002  					if rawValueType.Kind() == reflect.Bool {
  2003  						x := vv.Bool()
  2004  						hasAssigned = true
  2005  						fieldValue.Set(reflect.ValueOf(&x))
  2006  					}
  2007  				case core.PtrTimeType:
  2008  					if rawValueType == core.PtrTimeType {
  2009  						hasAssigned = true
  2010  						var x = rawValue.Interface().(time.Time)
  2011  						fieldValue.Set(reflect.ValueOf(&x))
  2012  					}
  2013  				case core.PtrFloat64Type:
  2014  					if rawValueType.Kind() == reflect.Float64 {
  2015  						x := vv.Float()
  2016  						hasAssigned = true
  2017  						fieldValue.Set(reflect.ValueOf(&x))
  2018  					}
  2019  				case core.PtrUint64Type:
  2020  					if rawValueType.Kind() == reflect.Int64 {
  2021  						var x = uint64(vv.Int())
  2022  						hasAssigned = true
  2023  						fieldValue.Set(reflect.ValueOf(&x))
  2024  					}
  2025  				case core.PtrInt64Type:
  2026  					if rawValueType.Kind() == reflect.Int64 {
  2027  						x := vv.Int()
  2028  						hasAssigned = true
  2029  						fieldValue.Set(reflect.ValueOf(&x))
  2030  					}
  2031  				case core.PtrFloat32Type:
  2032  					if rawValueType.Kind() == reflect.Float64 {
  2033  						var x = float32(vv.Float())
  2034  						hasAssigned = true
  2035  						fieldValue.Set(reflect.ValueOf(&x))
  2036  					}
  2037  				case core.PtrIntType:
  2038  					if rawValueType.Kind() == reflect.Int64 {
  2039  						var x = int(vv.Int())
  2040  						hasAssigned = true
  2041  						fieldValue.Set(reflect.ValueOf(&x))
  2042  					}
  2043  				case core.PtrInt32Type:
  2044  					if rawValueType.Kind() == reflect.Int64 {
  2045  						var x = int32(vv.Int())
  2046  						hasAssigned = true
  2047  						fieldValue.Set(reflect.ValueOf(&x))
  2048  					}
  2049  				case core.PtrInt8Type:
  2050  					if rawValueType.Kind() == reflect.Int64 {
  2051  						var x = int8(vv.Int())
  2052  						hasAssigned = true
  2053  						fieldValue.Set(reflect.ValueOf(&x))
  2054  					}
  2055  				case core.PtrInt16Type:
  2056  					if rawValueType.Kind() == reflect.Int64 {
  2057  						var x = int16(vv.Int())
  2058  						hasAssigned = true
  2059  						fieldValue.Set(reflect.ValueOf(&x))
  2060  					}
  2061  				case core.PtrUintType:
  2062  					if rawValueType.Kind() == reflect.Int64 {
  2063  						var x = uint(vv.Int())
  2064  						hasAssigned = true
  2065  						fieldValue.Set(reflect.ValueOf(&x))
  2066  					}
  2067  				case core.PtrUint32Type:
  2068  					if rawValueType.Kind() == reflect.Int64 {
  2069  						var x = uint32(vv.Int())
  2070  						hasAssigned = true
  2071  						fieldValue.Set(reflect.ValueOf(&x))
  2072  					}
  2073  				case core.Uint8Type:
  2074  					if rawValueType.Kind() == reflect.Int64 {
  2075  						var x = uint8(vv.Int())
  2076  						hasAssigned = true
  2077  						fieldValue.Set(reflect.ValueOf(&x))
  2078  					}
  2079  				case core.Uint16Type:
  2080  					if rawValueType.Kind() == reflect.Int64 {
  2081  						var x = uint16(vv.Int())
  2082  						hasAssigned = true
  2083  						fieldValue.Set(reflect.ValueOf(&x))
  2084  					}
  2085  				case core.Complex64Type:
  2086  					var x complex64
  2087  					if len([]byte(vv.String())) > 0 {
  2088  						err := json.Unmarshal([]byte(vv.String()), &x)
  2089  						if err != nil {
  2090  							session.Engine.logger.Error(err)
  2091  						} else {
  2092  							fieldValue.Set(reflect.ValueOf(&x))
  2093  						}
  2094  					}
  2095  					hasAssigned = true
  2096  				case core.Complex128Type:
  2097  					var x complex128
  2098  					if len([]byte(vv.String())) > 0 {
  2099  						err := json.Unmarshal([]byte(vv.String()), &x)
  2100  						if err != nil {
  2101  							session.Engine.logger.Error(err)
  2102  						} else {
  2103  							fieldValue.Set(reflect.ValueOf(&x))
  2104  						}
  2105  					}
  2106  					hasAssigned = true
  2107  				} // switch fieldType
  2108  				// default:
  2109  				// 	session.Engine.LogError("unsupported type in Scan: ", reflect.TypeOf(v).String())
  2110  			} // switch fieldType.Kind()
  2111  
  2112  			// !nashtsai! for value can't be assigned directly fallback to convert to []byte then back to value
  2113  			if !hasAssigned {
  2114  				data, err := value2Bytes(&rawValue)
  2115  				if err == nil {
  2116  					session.bytes2Value(col, fieldValue, data)
  2117  				} else {
  2118  					session.Engine.logger.Error(err.Error())
  2119  				}
  2120  			}
  2121  		}
  2122  	}
  2123  	return nil
  2124  
  2125  }
  2126  
  2127  func (session *Session) queryPreprocess(sqlStr *string, paramStr ...interface{}) {
  2128  	for _, filter := range session.Engine.dialect.Filters() {
  2129  		*sqlStr = filter.Do(*sqlStr, session.Engine.dialect, session.Statement.RefTable)
  2130  	}
  2131  
  2132  	session.saveLastSQL(*sqlStr, paramStr...)
  2133  }
  2134  
  2135  func (session *Session) query(sqlStr string, paramStr ...interface{}) (resultsSlice []map[string][]byte, err error) {
  2136  
  2137  	session.queryPreprocess(&sqlStr, paramStr...)
  2138  
  2139  	if session.IsAutoCommit {
  2140  		return session.innerQuery2(sqlStr, paramStr...)
  2141  	}
  2142  	return session.txQuery(session.Tx, sqlStr, paramStr...)
  2143  }
  2144  
  2145  func (session *Session) txQuery(tx *core.Tx, sqlStr string, params ...interface{}) (resultsSlice []map[string][]byte, err error) {
  2146  	rows, err := tx.Query(sqlStr, params...)
  2147  	if err != nil {
  2148  		return nil, err
  2149  	}
  2150  	defer rows.Close()
  2151  
  2152  	return rows2maps(rows)
  2153  }
  2154  
  2155  func (session *Session) innerQuery(sqlStr string, params ...interface{}) (*core.Stmt, *core.Rows, error) {
  2156  	var callback func() (*core.Stmt, *core.Rows, error)
  2157  	if session.prepareStmt {
  2158  		callback = func() (*core.Stmt, *core.Rows, error) {
  2159  			stmt, err := session.doPrepare(sqlStr)
  2160  			if err != nil {
  2161  				return nil, nil, err
  2162  			}
  2163  			rows, err := stmt.Query(params...)
  2164  			if err != nil {
  2165  				return nil, nil, err
  2166  			}
  2167  			return stmt, rows, nil
  2168  		}
  2169  	} else {
  2170  		callback = func() (*core.Stmt, *core.Rows, error) {
  2171  			rows, err := session.DB().Query(sqlStr, params...)
  2172  			if err != nil {
  2173  				return nil, nil, err
  2174  			}
  2175  			return nil, rows, err
  2176  		}
  2177  	}
  2178  	stmt, rows, err := session.Engine.logSQLQueryTime(sqlStr, params, callback)
  2179  	if err != nil {
  2180  		return nil, nil, err
  2181  	}
  2182  	return stmt, rows, nil
  2183  }
  2184  
  2185  func (session *Session) innerQuery2(sqlStr string, params ...interface{}) ([]map[string][]byte, error) {
  2186  	_, rows, err := session.innerQuery(sqlStr, params...)
  2187  	if rows != nil {
  2188  		defer rows.Close()
  2189  	}
  2190  	if err != nil {
  2191  		return nil, err
  2192  	}
  2193  	return rows2maps(rows)
  2194  }
  2195  
  2196  // Query a raw sql and return records as []map[string][]byte
  2197  func (session *Session) Query(sqlStr string, paramStr ...interface{}) (resultsSlice []map[string][]byte, err error) {
  2198  	defer session.resetStatement()
  2199  	if session.IsAutoClose {
  2200  		defer session.Close()
  2201  	}
  2202  
  2203  	return session.query(sqlStr, paramStr...)
  2204  }
  2205  
  2206  // =============================
  2207  // for string
  2208  // =============================
  2209  func (session *Session) query2(sqlStr string, paramStr ...interface{}) (resultsSlice []map[string]string, err error) {
  2210  	session.queryPreprocess(&sqlStr, paramStr...)
  2211  
  2212  	if session.IsAutoCommit {
  2213  		return query2(session.DB(), sqlStr, paramStr...)
  2214  	}
  2215  	return txQuery2(session.Tx, sqlStr, paramStr...)
  2216  }
  2217  
  2218  // Insert insert one or more beans
  2219  func (session *Session) Insert(beans ...interface{}) (int64, error) {
  2220  	var affected int64
  2221  	var err error
  2222  
  2223  	if session.IsAutoClose {
  2224  		defer session.Close()
  2225  	}
  2226  
  2227  	for _, bean := range beans {
  2228  		sliceValue := reflect.Indirect(reflect.ValueOf(bean))
  2229  		if sliceValue.Kind() == reflect.Slice {
  2230  			size := sliceValue.Len()
  2231  			if size > 0 {
  2232  				if session.Engine.SupportInsertMany() {
  2233  					cnt, err := session.innerInsertMulti(bean)
  2234  					//session.resetStatement()
  2235  					if err != nil {
  2236  						return affected, err
  2237  					}
  2238  					affected += cnt
  2239  				} else {
  2240  					for i := 0; i < size; i++ {
  2241  						cnt, err := session.innerInsert(sliceValue.Index(i).Interface())
  2242  						//session.resetStatement()
  2243  						if err != nil {
  2244  							return affected, err
  2245  						}
  2246  						affected += cnt
  2247  					}
  2248  				}
  2249  			}
  2250  		} else {
  2251  			cnt, err := session.innerInsert(bean)
  2252  			//session.resetStatement()
  2253  			if err != nil {
  2254  				return affected, err
  2255  			}
  2256  			affected += cnt
  2257  		}
  2258  	}
  2259  
  2260  	return affected, err
  2261  }
  2262  
  2263  func (session *Session) innerInsertMulti(rowsSlicePtr interface{}) (int64, error) {
  2264  	sliceValue := reflect.Indirect(reflect.ValueOf(rowsSlicePtr))
  2265  	if sliceValue.Kind() != reflect.Slice {
  2266  		return 0, errors.New("needs a pointer to a slice")
  2267  	}
  2268  
  2269  	if sliceValue.Len() <= 0 {
  2270  		return 0, errors.New("could not insert a empty slice")
  2271  	}
  2272  
  2273  	session.Statement.setRefValue(sliceValue.Index(0))
  2274  
  2275  	if len(session.Statement.TableName()) <= 0 {
  2276  		return 0, ErrTableNotFound
  2277  	}
  2278  
  2279  	table := session.Statement.RefTable
  2280  	size := sliceValue.Len()
  2281  
  2282  	var colNames []string
  2283  	var colMultiPlaces []string
  2284  	var args []interface{}
  2285  	var cols []*core.Column
  2286  
  2287  	for i := 0; i < size; i++ {
  2288  		v := sliceValue.Index(i)
  2289  		vv := reflect.Indirect(v)
  2290  		elemValue := v.Interface()
  2291  		var colPlaces []string
  2292  
  2293  		// handle BeforeInsertProcessor
  2294  		// !nashtsai! does user expect it's same slice to passed closure when using Before()/After() when insert multi??
  2295  		for _, closure := range session.beforeClosures {
  2296  			closure(elemValue)
  2297  		}
  2298  
  2299  		if processor, ok := interface{}(elemValue).(BeforeInsertProcessor); ok {
  2300  			processor.BeforeInsert()
  2301  		}
  2302  		// --
  2303  
  2304  		if i == 0 {
  2305  			for _, col := range table.Columns() {
  2306  				ptrFieldValue, err := col.ValueOfV(&vv)
  2307  				if err != nil {
  2308  					return 0, err
  2309  				}
  2310  				fieldValue := *ptrFieldValue
  2311  				if col.IsAutoIncrement && isZero(fieldValue.Interface()) {
  2312  					continue
  2313  				}
  2314  				if col.MapType == core.ONLYFROMDB {
  2315  					continue
  2316  				}
  2317  				if col.IsDeleted {
  2318  					continue
  2319  				}
  2320  				if session.Statement.ColumnStr != "" {
  2321  					if _, ok := getFlagForColumn(session.Statement.columnMap, col); !ok {
  2322  						continue
  2323  					}
  2324  				}
  2325  				if session.Statement.OmitStr != "" {
  2326  					if _, ok := getFlagForColumn(session.Statement.columnMap, col); ok {
  2327  						continue
  2328  					}
  2329  				}
  2330  				if (col.IsCreated || col.IsUpdated) && session.Statement.UseAutoTime {
  2331  					val, t := session.Engine.NowTime2(col.SQLType.Name)
  2332  					args = append(args, val)
  2333  
  2334  					var colName = col.Name
  2335  					session.afterClosures = append(session.afterClosures, func(bean interface{}) {
  2336  						col := table.GetColumn(colName)
  2337  						setColumnTime(bean, col, t)
  2338  					})
  2339  				} else if col.IsVersion && session.Statement.checkVersion {
  2340  					args = append(args, 1)
  2341  					var colName = col.Name
  2342  					session.afterClosures = append(session.afterClosures, func(bean interface{}) {
  2343  						col := table.GetColumn(colName)
  2344  						setColumnInt(bean, col, 1)
  2345  					})
  2346  				} else {
  2347  					arg, err := session.value2Interface(col, fieldValue)
  2348  					if err != nil {
  2349  						return 0, err
  2350  					}
  2351  					args = append(args, arg)
  2352  				}
  2353  
  2354  				colNames = append(colNames, col.Name)
  2355  				cols = append(cols, col)
  2356  				colPlaces = append(colPlaces, "?")
  2357  			}
  2358  		} else {
  2359  			for _, col := range cols {
  2360  				ptrFieldValue, err := col.ValueOfV(&vv)
  2361  				if err != nil {
  2362  					return 0, err
  2363  				}
  2364  				fieldValue := *ptrFieldValue
  2365  
  2366  				if col.IsAutoIncrement && isZero(fieldValue.Interface()) {
  2367  					continue
  2368  				}
  2369  				if col.MapType == core.ONLYFROMDB {
  2370  					continue
  2371  				}
  2372  				if col.IsDeleted {
  2373  					continue
  2374  				}
  2375  				if session.Statement.ColumnStr != "" {
  2376  					if _, ok := getFlagForColumn(session.Statement.columnMap, col); !ok {
  2377  						continue
  2378  					}
  2379  				}
  2380  				if session.Statement.OmitStr != "" {
  2381  					if _, ok := getFlagForColumn(session.Statement.columnMap, col); ok {
  2382  						continue
  2383  					}
  2384  				}
  2385  				if (col.IsCreated || col.IsUpdated) && session.Statement.UseAutoTime {
  2386  					val, t := session.Engine.NowTime2(col.SQLType.Name)
  2387  					args = append(args, val)
  2388  
  2389  					var colName = col.Name
  2390  					session.afterClosures = append(session.afterClosures, func(bean interface{}) {
  2391  						col := table.GetColumn(colName)
  2392  						setColumnTime(bean, col, t)
  2393  					})
  2394  				} else if col.IsVersion && session.Statement.checkVersion {
  2395  					args = append(args, 1)
  2396  					var colName = col.Name
  2397  					session.afterClosures = append(session.afterClosures, func(bean interface{}) {
  2398  						col := table.GetColumn(colName)
  2399  						setColumnInt(bean, col, 1)
  2400  					})
  2401  				} else {
  2402  					arg, err := session.value2Interface(col, fieldValue)
  2403  					if err != nil {
  2404  						return 0, err
  2405  					}
  2406  					args = append(args, arg)
  2407  				}
  2408  
  2409  				colPlaces = append(colPlaces, "?")
  2410  			}
  2411  		}
  2412  		colMultiPlaces = append(colMultiPlaces, strings.Join(colPlaces, ", "))
  2413  	}
  2414  	cleanupProcessorsClosures(&session.beforeClosures)
  2415  
  2416  	statement := fmt.Sprintf("INSERT INTO %s (%v%v%v) VALUES (%v)",
  2417  		session.Engine.Quote(session.Statement.TableName()),
  2418  		session.Engine.QuoteStr(),
  2419  		strings.Join(colNames, session.Engine.QuoteStr()+", "+session.Engine.QuoteStr()),
  2420  		session.Engine.QuoteStr(),
  2421  		strings.Join(colMultiPlaces, "),("))
  2422  
  2423  	res, err := session.exec(statement, args...)
  2424  	if err != nil {
  2425  		return 0, err
  2426  	}
  2427  
  2428  	if cacher := session.Engine.getCacher2(table); cacher != nil && session.Statement.UseCache {
  2429  		session.cacheInsert(session.Statement.TableName())
  2430  	}
  2431  
  2432  	lenAfterClosures := len(session.afterClosures)
  2433  	for i := 0; i < size; i++ {
  2434  		elemValue := reflect.Indirect(sliceValue.Index(i)).Addr().Interface()
  2435  
  2436  		// handle AfterInsertProcessor
  2437  		if session.IsAutoCommit {
  2438  			// !nashtsai! does user expect it's same slice to passed closure when using Before()/After() when insert multi??
  2439  			for _, closure := range session.afterClosures {
  2440  				closure(elemValue)
  2441  			}
  2442  			if processor, ok := interface{}(elemValue).(AfterInsertProcessor); ok {
  2443  				processor.AfterInsert()
  2444  			}
  2445  		} else {
  2446  			if lenAfterClosures > 0 {
  2447  				if value, has := session.afterInsertBeans[elemValue]; has && value != nil {
  2448  					*value = append(*value, session.afterClosures...)
  2449  				} else {
  2450  					afterClosures := make([]func(interface{}), lenAfterClosures)
  2451  					copy(afterClosures, session.afterClosures)
  2452  					session.afterInsertBeans[elemValue] = &afterClosures
  2453  				}
  2454  			} else {
  2455  				if _, ok := interface{}(elemValue).(AfterInsertProcessor); ok {
  2456  					session.afterInsertBeans[elemValue] = nil
  2457  				}
  2458  			}
  2459  		}
  2460  	}
  2461  
  2462  	cleanupProcessorsClosures(&session.afterClosures)
  2463  	return res.RowsAffected()
  2464  }
  2465  
  2466  // InsertMulti insert multiple records
  2467  func (session *Session) InsertMulti(rowsSlicePtr interface{}) (int64, error) {
  2468  	defer session.resetStatement()
  2469  	if session.IsAutoClose {
  2470  		defer session.Close()
  2471  	}
  2472  
  2473  	sliceValue := reflect.Indirect(reflect.ValueOf(rowsSlicePtr))
  2474  	if sliceValue.Kind() != reflect.Slice {
  2475  		return 0, ErrParamsType
  2476  
  2477  	}
  2478  
  2479  	if sliceValue.Len() <= 0 {
  2480  		return 0, nil
  2481  	}
  2482  
  2483  	return session.innerInsertMulti(rowsSlicePtr)
  2484  }
  2485  
  2486  func (session *Session) str2Time(col *core.Column, data string) (outTime time.Time, outErr error) {
  2487  	sdata := strings.TrimSpace(data)
  2488  	var x time.Time
  2489  	var err error
  2490  
  2491  	if sdata == "0000-00-00 00:00:00" ||
  2492  		sdata == "0001-01-01 00:00:00" {
  2493  	} else if !strings.ContainsAny(sdata, "- :") { // !nashtsai! has only found that mymysql driver is using this for time type column
  2494  		// time stamp
  2495  		sd, err := strconv.ParseInt(sdata, 10, 64)
  2496  		if err == nil {
  2497  			x = time.Unix(sd, 0)
  2498  			// !nashtsai! HACK mymysql driver is casuing Local location being change to CHAT and cause wrong time conversion
  2499  			if col.TimeZone == nil {
  2500  				x = x.In(session.Engine.TZLocation)
  2501  			} else {
  2502  				x = x.In(col.TimeZone)
  2503  			}
  2504  			session.Engine.logger.Debugf("time(0) key[%v]: %+v | sdata: [%v]\n", col.FieldName, x, sdata)
  2505  		} else {
  2506  			session.Engine.logger.Debugf("time(0) err key[%v]: %+v | sdata: [%v]\n", col.FieldName, x, sdata)
  2507  		}
  2508  	} else if len(sdata) > 19 && strings.Contains(sdata, "-") {
  2509  		x, err = time.ParseInLocation(time.RFC3339Nano, sdata, session.Engine.TZLocation)
  2510  		session.Engine.logger.Debugf("time(1) key[%v]: %+v | sdata: [%v]\n", col.FieldName, x, sdata)
  2511  		if err != nil {
  2512  			x, err = time.ParseInLocation("2006-01-02 15:04:05.999999999", sdata, session.Engine.TZLocation)
  2513  			session.Engine.logger.Debugf("time(2) key[%v]: %+v | sdata: [%v]\n", col.FieldName, x, sdata)
  2514  		}
  2515  		if err != nil {
  2516  			x, err = time.ParseInLocation("2006-01-02 15:04:05.9999999 Z07:00", sdata, session.Engine.TZLocation)
  2517  			session.Engine.logger.Debugf("time(3) key[%v]: %+v | sdata: [%v]\n", col.FieldName, x, sdata)
  2518  		}
  2519  
  2520  	} else if len(sdata) == 19 && strings.Contains(sdata, "-") {
  2521  		x, err = time.ParseInLocation("2006-01-02 15:04:05", sdata, session.Engine.TZLocation)
  2522  		session.Engine.logger.Debugf("time(4) key[%v]: %+v | sdata: [%v]\n", col.FieldName, x, sdata)
  2523  	} else if len(sdata) == 10 && sdata[4] == '-' && sdata[7] == '-' {
  2524  		x, err = time.ParseInLocation("2006-01-02", sdata, session.Engine.TZLocation)
  2525  		session.Engine.logger.Debugf("time(5) key[%v]: %+v | sdata: [%v]\n", col.FieldName, x, sdata)
  2526  	} else if col.SQLType.Name == core.Time {
  2527  		if strings.Contains(sdata, " ") {
  2528  			ssd := strings.Split(sdata, " ")
  2529  			sdata = ssd[1]
  2530  		}
  2531  
  2532  		sdata = strings.TrimSpace(sdata)
  2533  		if session.Engine.dialect.DBType() == core.MYSQL && len(sdata) > 8 {
  2534  			sdata = sdata[len(sdata)-8:]
  2535  		}
  2536  
  2537  		st := fmt.Sprintf("2006-01-02 %v", sdata)
  2538  		x, err = time.ParseInLocation("2006-01-02 15:04:05", st, session.Engine.TZLocation)
  2539  		session.Engine.logger.Debugf("time(6) key[%v]: %+v | sdata: [%v]\n", col.FieldName, x, sdata)
  2540  	} else {
  2541  		outErr = fmt.Errorf("unsupported time format %v", sdata)
  2542  		return
  2543  	}
  2544  	if err != nil {
  2545  		outErr = fmt.Errorf("unsupported time format %v: %v", sdata, err)
  2546  		return
  2547  	}
  2548  	outTime = x
  2549  	return
  2550  }
  2551  
  2552  func (session *Session) byte2Time(col *core.Column, data []byte) (outTime time.Time, outErr error) {
  2553  	return session.str2Time(col, string(data))
  2554  }
  2555  
  2556  // convert a db data([]byte) to a field value
  2557  func (session *Session) bytes2Value(col *core.Column, fieldValue *reflect.Value, data []byte) error {
  2558  	if structConvert, ok := fieldValue.Addr().Interface().(core.Conversion); ok {
  2559  		return structConvert.FromDB(data)
  2560  	}
  2561  
  2562  	if structConvert, ok := fieldValue.Interface().(core.Conversion); ok {
  2563  		return structConvert.FromDB(data)
  2564  	}
  2565  
  2566  	var v interface{}
  2567  	key := col.Name
  2568  	fieldType := fieldValue.Type()
  2569  
  2570  	switch fieldType.Kind() {
  2571  	case reflect.Complex64, reflect.Complex128:
  2572  		x := reflect.New(fieldType)
  2573  		if len(data) > 0 {
  2574  			err := json.Unmarshal(data, x.Interface())
  2575  			if err != nil {
  2576  				session.Engine.logger.Error(err)
  2577  				return err
  2578  			}
  2579  			fieldValue.Set(x.Elem())
  2580  		}
  2581  	case reflect.Slice, reflect.Array, reflect.Map:
  2582  		v = data
  2583  		t := fieldType.Elem()
  2584  		k := t.Kind()
  2585  		if col.SQLType.IsText() {
  2586  			x := reflect.New(fieldType)
  2587  			if len(data) > 0 {
  2588  				err := json.Unmarshal(data, x.Interface())
  2589  				if err != nil {
  2590  					session.Engine.logger.Error(err)
  2591  					return err
  2592  				}
  2593  				fieldValue.Set(x.Elem())
  2594  			}
  2595  		} else if col.SQLType.IsBlob() {
  2596  			if k == reflect.Uint8 {
  2597  				fieldValue.Set(reflect.ValueOf(v))
  2598  			} else {
  2599  				x := reflect.New(fieldType)
  2600  				if len(data) > 0 {
  2601  					err := json.Unmarshal(data, x.Interface())
  2602  					if err != nil {
  2603  						session.Engine.logger.Error(err)
  2604  						return err
  2605  					}
  2606  					fieldValue.Set(x.Elem())
  2607  				}
  2608  			}
  2609  		} else {
  2610  			return ErrUnSupportedType
  2611  		}
  2612  	case reflect.String:
  2613  		fieldValue.SetString(string(data))
  2614  	case reflect.Bool:
  2615  		d := string(data)
  2616  		v, err := strconv.ParseBool(d)
  2617  		if err != nil {
  2618  			return fmt.Errorf("arg %v as bool: %s", key, err.Error())
  2619  		}
  2620  		fieldValue.Set(reflect.ValueOf(v))
  2621  	case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
  2622  		sdata := string(data)
  2623  		var x int64
  2624  		var err error
  2625  		// for mysql, when use bit, it returned \x01
  2626  		if col.SQLType.Name == core.Bit &&
  2627  			session.Engine.dialect.DBType() == core.MYSQL { // !nashtsai! TODO dialect needs to provide conversion interface API
  2628  			if len(data) == 1 {
  2629  				x = int64(data[0])
  2630  			} else {
  2631  				x = 0
  2632  			}
  2633  		} else if strings.HasPrefix(sdata, "0x") {
  2634  			x, err = strconv.ParseInt(sdata, 16, 64)
  2635  		} else if strings.HasPrefix(sdata, "0") {
  2636  			x, err = strconv.ParseInt(sdata, 8, 64)
  2637  		} else if strings.EqualFold(sdata, "true") {
  2638  			x = 1
  2639  		} else if strings.EqualFold(sdata, "false") {
  2640  			x = 0
  2641  		} else {
  2642  			x, err = strconv.ParseInt(sdata, 10, 64)
  2643  		}
  2644  		if err != nil {
  2645  			return fmt.Errorf("arg %v as int: %s", key, err.Error())
  2646  		}
  2647  		fieldValue.SetInt(x)
  2648  	case reflect.Float32, reflect.Float64:
  2649  		x, err := strconv.ParseFloat(string(data), 64)
  2650  		if err != nil {
  2651  			return fmt.Errorf("arg %v as float64: %s", key, err.Error())
  2652  		}
  2653  		fieldValue.SetFloat(x)
  2654  	case reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uint:
  2655  		x, err := strconv.ParseUint(string(data), 10, 64)
  2656  		if err != nil {
  2657  			return fmt.Errorf("arg %v as int: %s", key, err.Error())
  2658  		}
  2659  		fieldValue.SetUint(x)
  2660  	//Currently only support Time type
  2661  	case reflect.Struct:
  2662  		// !<winxxp>! 增加支持sql.Scanner接口的结构,如sql.NullString
  2663  		if nulVal, ok := fieldValue.Addr().Interface().(sql.Scanner); ok {
  2664  			if err := nulVal.Scan(data); err != nil {
  2665  				return fmt.Errorf("sql.Scan(%v) failed: %s ", data, err.Error())
  2666  			}
  2667  		} else {
  2668  			if fieldType.ConvertibleTo(core.TimeType) {
  2669  				x, err := session.byte2Time(col, data)
  2670  				if err != nil {
  2671  					return err
  2672  				}
  2673  				v = x
  2674  				fieldValue.Set(reflect.ValueOf(v).Convert(fieldType))
  2675  			} else if session.Statement.UseCascade {
  2676  				table := session.Engine.autoMapType(*fieldValue)
  2677  				if table != nil {
  2678  					// TODO: current only support 1 primary key
  2679  					if len(table.PrimaryKeys) > 1 {
  2680  						panic("unsupported composited primary key cascade")
  2681  					}
  2682  					var pk = make(core.PK, len(table.PrimaryKeys))
  2683  					rawValueType := table.ColumnType(table.PKColumns()[0].FieldName)
  2684  					var err error
  2685  					pk[0], err = str2PK(string(data), rawValueType)
  2686  					if err != nil {
  2687  						return err
  2688  					}
  2689  
  2690  					if !isPKZero(pk) {
  2691  						// !nashtsai! TODO for hasOne relationship, it's preferred to use join query for eager fetch
  2692  						// however, also need to consider adding a 'lazy' attribute to xorm tag which allow hasOne
  2693  						// property to be fetched lazily
  2694  						structInter := reflect.New(fieldValue.Type())
  2695  						newsession := session.Engine.NewSession()
  2696  						defer newsession.Close()
  2697  						has, err := newsession.Id(pk).NoCascade().Get(structInter.Interface())
  2698  						if err != nil {
  2699  							return err
  2700  						}
  2701  						if has {
  2702  							v = structInter.Elem().Interface()
  2703  							fieldValue.Set(reflect.ValueOf(v))
  2704  						} else {
  2705  							return errors.New("cascade obj is not exist")
  2706  						}
  2707  					}
  2708  				} else {
  2709  					return fmt.Errorf("unsupported struct type in Scan: %s", fieldValue.Type().String())
  2710  				}
  2711  			}
  2712  		}
  2713  	case reflect.Ptr:
  2714  		// !nashtsai! TODO merge duplicated codes above
  2715  		//typeStr := fieldType.String()
  2716  		switch fieldType.Elem().Kind() {
  2717  		// case "*string":
  2718  		case core.StringType.Kind():
  2719  			x := string(data)
  2720  			fieldValue.Set(reflect.ValueOf(&x).Convert(fieldType))
  2721  		// case "*bool":
  2722  		case core.BoolType.Kind():
  2723  			d := string(data)
  2724  			v, err := strconv.ParseBool(d)
  2725  			if err != nil {
  2726  				return fmt.Errorf("arg %v as bool: %s", key, err.Error())
  2727  			}
  2728  			fieldValue.Set(reflect.ValueOf(&v).Convert(fieldType))
  2729  		// case "*complex64":
  2730  		case core.Complex64Type.Kind():
  2731  			var x complex64
  2732  			if len(data) > 0 {
  2733  				err := json.Unmarshal(data, &x)
  2734  				if err != nil {
  2735  					session.Engine.logger.Error(err)
  2736  					return err
  2737  				}
  2738  				fieldValue.Set(reflect.ValueOf(&x).Convert(fieldType))
  2739  			}
  2740  		// case "*complex128":
  2741  		case core.Complex128Type.Kind():
  2742  			var x complex128
  2743  			if len(data) > 0 {
  2744  				err := json.Unmarshal(data, &x)
  2745  				if err != nil {
  2746  					session.Engine.logger.Error(err)
  2747  					return err
  2748  				}
  2749  				fieldValue.Set(reflect.ValueOf(&x).Convert(fieldType))
  2750  			}
  2751  		// case "*float64":
  2752  		case core.Float64Type.Kind():
  2753  			x, err := strconv.ParseFloat(string(data), 64)
  2754  			if err != nil {
  2755  				return fmt.Errorf("arg %v as float64: %s", key, err.Error())
  2756  			}
  2757  			fieldValue.Set(reflect.ValueOf(&x).Convert(fieldType))
  2758  		// case "*float32":
  2759  		case core.Float32Type.Kind():
  2760  			var x float32
  2761  			x1, err := strconv.ParseFloat(string(data), 32)
  2762  			if err != nil {
  2763  				return fmt.Errorf("arg %v as float32: %s", key, err.Error())
  2764  			}
  2765  			x = float32(x1)
  2766  			fieldValue.Set(reflect.ValueOf(&x).Convert(fieldType))
  2767  		// case "*uint64":
  2768  		case core.Uint64Type.Kind():
  2769  			var x uint64
  2770  			x, err := strconv.ParseUint(string(data), 10, 64)
  2771  			if err != nil {
  2772  				return fmt.Errorf("arg %v as int: %s", key, err.Error())
  2773  			}
  2774  			fieldValue.Set(reflect.ValueOf(&x).Convert(fieldType))
  2775  		// case "*uint":
  2776  		case core.UintType.Kind():
  2777  			var x uint
  2778  			x1, err := strconv.ParseUint(string(data), 10, 64)
  2779  			if err != nil {
  2780  				return fmt.Errorf("arg %v as int: %s", key, err.Error())
  2781  			}
  2782  			x = uint(x1)
  2783  			fieldValue.Set(reflect.ValueOf(&x).Convert(fieldType))
  2784  		// case "*uint32":
  2785  		case core.Uint32Type.Kind():
  2786  			var x uint32
  2787  			x1, err := strconv.ParseUint(string(data), 10, 64)
  2788  			if err != nil {
  2789  				return fmt.Errorf("arg %v as int: %s", key, err.Error())
  2790  			}
  2791  			x = uint32(x1)
  2792  			fieldValue.Set(reflect.ValueOf(&x).Convert(fieldType))
  2793  		// case "*uint8":
  2794  		case core.Uint8Type.Kind():
  2795  			var x uint8
  2796  			x1, err := strconv.ParseUint(string(data), 10, 64)
  2797  			if err != nil {
  2798  				return fmt.Errorf("arg %v as int: %s", key, err.Error())
  2799  			}
  2800  			x = uint8(x1)
  2801  			fieldValue.Set(reflect.ValueOf(&x).Convert(fieldType))
  2802  		// case "*uint16":
  2803  		case core.Uint16Type.Kind():
  2804  			var x uint16
  2805  			x1, err := strconv.ParseUint(string(data), 10, 64)
  2806  			if err != nil {
  2807  				return fmt.Errorf("arg %v as int: %s", key, err.Error())
  2808  			}
  2809  			x = uint16(x1)
  2810  			fieldValue.Set(reflect.ValueOf(&x).Convert(fieldType))
  2811  		// case "*int64":
  2812  		case core.Int64Type.Kind():
  2813  			sdata := string(data)
  2814  			var x int64
  2815  			var err error
  2816  			// for mysql, when use bit, it returned \x01
  2817  			if col.SQLType.Name == core.Bit &&
  2818  				strings.Contains(session.Engine.DriverName(), "mysql") {
  2819  				if len(data) == 1 {
  2820  					x = int64(data[0])
  2821  				} else {
  2822  					x = 0
  2823  				}
  2824  			} else if strings.HasPrefix(sdata, "0x") {
  2825  				x, err = strconv.ParseInt(sdata, 16, 64)
  2826  			} else if strings.HasPrefix(sdata, "0") {
  2827  				x, err = strconv.ParseInt(sdata, 8, 64)
  2828  			} else {
  2829  				x, err = strconv.ParseInt(sdata, 10, 64)
  2830  			}
  2831  			if err != nil {
  2832  				return fmt.Errorf("arg %v as int: %s", key, err.Error())
  2833  			}
  2834  			fieldValue.Set(reflect.ValueOf(&x).Convert(fieldType))
  2835  		// case "*int":
  2836  		case core.IntType.Kind():
  2837  			sdata := string(data)
  2838  			var x int
  2839  			var x1 int64
  2840  			var err error
  2841  			// for mysql, when use bit, it returned \x01
  2842  			if col.SQLType.Name == core.Bit &&
  2843  				strings.Contains(session.Engine.DriverName(), "mysql") {
  2844  				if len(data) == 1 {
  2845  					x = int(data[0])
  2846  				} else {
  2847  					x = 0
  2848  				}
  2849  			} else if strings.HasPrefix(sdata, "0x") {
  2850  				x1, err = strconv.ParseInt(sdata, 16, 64)
  2851  				x = int(x1)
  2852  			} else if strings.HasPrefix(sdata, "0") {
  2853  				x1, err = strconv.ParseInt(sdata, 8, 64)
  2854  				x = int(x1)
  2855  			} else {
  2856  				x1, err = strconv.ParseInt(sdata, 10, 64)
  2857  				x = int(x1)
  2858  			}
  2859  			if err != nil {
  2860  				return fmt.Errorf("arg %v as int: %s", key, err.Error())
  2861  			}
  2862  			fieldValue.Set(reflect.ValueOf(&x).Convert(fieldType))
  2863  		// case "*int32":
  2864  		case core.Int32Type.Kind():
  2865  			sdata := string(data)
  2866  			var x int32
  2867  			var x1 int64
  2868  			var err error
  2869  			// for mysql, when use bit, it returned \x01
  2870  			if col.SQLType.Name == core.Bit &&
  2871  				session.Engine.dialect.DBType() == core.MYSQL {
  2872  				if len(data) == 1 {
  2873  					x = int32(data[0])
  2874  				} else {
  2875  					x = 0
  2876  				}
  2877  			} else if strings.HasPrefix(sdata, "0x") {
  2878  				x1, err = strconv.ParseInt(sdata, 16, 64)
  2879  				x = int32(x1)
  2880  			} else if strings.HasPrefix(sdata, "0") {
  2881  				x1, err = strconv.ParseInt(sdata, 8, 64)
  2882  				x = int32(x1)
  2883  			} else {
  2884  				x1, err = strconv.ParseInt(sdata, 10, 64)
  2885  				x = int32(x1)
  2886  			}
  2887  			if err != nil {
  2888  				return fmt.Errorf("arg %v as int: %s", key, err.Error())
  2889  			}
  2890  			fieldValue.Set(reflect.ValueOf(&x).Convert(fieldType))
  2891  		// case "*int8":
  2892  		case core.Int8Type.Kind():
  2893  			sdata := string(data)
  2894  			var x int8
  2895  			var x1 int64
  2896  			var err error
  2897  			// for mysql, when use bit, it returned \x01
  2898  			if col.SQLType.Name == core.Bit &&
  2899  				strings.Contains(session.Engine.DriverName(), "mysql") {
  2900  				if len(data) == 1 {
  2901  					x = int8(data[0])
  2902  				} else {
  2903  					x = 0
  2904  				}
  2905  			} else if strings.HasPrefix(sdata, "0x") {
  2906  				x1, err = strconv.ParseInt(sdata, 16, 64)
  2907  				x = int8(x1)
  2908  			} else if strings.HasPrefix(sdata, "0") {
  2909  				x1, err = strconv.ParseInt(sdata, 8, 64)
  2910  				x = int8(x1)
  2911  			} else {
  2912  				x1, err = strconv.ParseInt(sdata, 10, 64)
  2913  				x = int8(x1)
  2914  			}
  2915  			if err != nil {
  2916  				return fmt.Errorf("arg %v as int: %s", key, err.Error())
  2917  			}
  2918  			fieldValue.Set(reflect.ValueOf(&x).Convert(fieldType))
  2919  		// case "*int16":
  2920  		case core.Int16Type.Kind():
  2921  			sdata := string(data)
  2922  			var x int16
  2923  			var x1 int64
  2924  			var err error
  2925  			// for mysql, when use bit, it returned \x01
  2926  			if col.SQLType.Name == core.Bit &&
  2927  				strings.Contains(session.Engine.DriverName(), "mysql") {
  2928  				if len(data) == 1 {
  2929  					x = int16(data[0])
  2930  				} else {
  2931  					x = 0
  2932  				}
  2933  			} else if strings.HasPrefix(sdata, "0x") {
  2934  				x1, err = strconv.ParseInt(sdata, 16, 64)
  2935  				x = int16(x1)
  2936  			} else if strings.HasPrefix(sdata, "0") {
  2937  				x1, err = strconv.ParseInt(sdata, 8, 64)
  2938  				x = int16(x1)
  2939  			} else {
  2940  				x1, err = strconv.ParseInt(sdata, 10, 64)
  2941  				x = int16(x1)
  2942  			}
  2943  			if err != nil {
  2944  				return fmt.Errorf("arg %v as int: %s", key, err.Error())
  2945  			}
  2946  			fieldValue.Set(reflect.ValueOf(&x).Convert(fieldType))
  2947  		// case "*SomeStruct":
  2948  		case reflect.Struct:
  2949  			switch fieldType {
  2950  			// case "*.time.Time":
  2951  			case core.PtrTimeType:
  2952  				x, err := session.byte2Time(col, data)
  2953  				if err != nil {
  2954  					return err
  2955  				}
  2956  				v = x
  2957  				fieldValue.Set(reflect.ValueOf(&x))
  2958  			default:
  2959  				if session.Statement.UseCascade {
  2960  					structInter := reflect.New(fieldType.Elem())
  2961  					table := session.Engine.autoMapType(structInter.Elem())
  2962  					if table != nil {
  2963  						if len(table.PrimaryKeys) > 1 {
  2964  							panic("unsupported composited primary key cascade")
  2965  						}
  2966  						var pk = make(core.PK, len(table.PrimaryKeys))
  2967  						var err error
  2968  						rawValueType := table.ColumnType(table.PKColumns()[0].FieldName)
  2969  						pk[0], err = str2PK(string(data), rawValueType)
  2970  						if err != nil {
  2971  							return err
  2972  						}
  2973  
  2974  						if !isPKZero(pk) {
  2975  							// !nashtsai! TODO for hasOne relationship, it's preferred to use join query for eager fetch
  2976  							// however, also need to consider adding a 'lazy' attribute to xorm tag which allow hasOne
  2977  							// property to be fetched lazily
  2978  							newsession := session.Engine.NewSession()
  2979  							defer newsession.Close()
  2980  							has, err := newsession.Id(pk).NoCascade().Get(structInter.Interface())
  2981  							if err != nil {
  2982  								return err
  2983  							}
  2984  							if has {
  2985  								v = structInter.Interface()
  2986  								fieldValue.Set(reflect.ValueOf(v))
  2987  							} else {
  2988  								return errors.New("cascade obj is not exist")
  2989  							}
  2990  						}
  2991  					}
  2992  				} else {
  2993  					return fmt.Errorf("unsupported struct type in Scan: %s", fieldValue.Type().String())
  2994  				}
  2995  			}
  2996  		default:
  2997  			return fmt.Errorf("unsupported type in Scan: %s", fieldValue.Type().String())
  2998  		}
  2999  	default:
  3000  		return fmt.Errorf("unsupported type in Scan: %s", fieldValue.Type().String())
  3001  	}
  3002  
  3003  	return nil
  3004  }
  3005  
  3006  // convert a field value of a struct to interface for put into db
  3007  func (session *Session) value2Interface(col *core.Column, fieldValue reflect.Value) (interface{}, error) {
  3008  	if fieldValue.CanAddr() {
  3009  		if fieldConvert, ok := fieldValue.Addr().Interface().(core.Conversion); ok {
  3010  			data, err := fieldConvert.ToDB()
  3011  			if err != nil {
  3012  				return 0, err
  3013  			}
  3014  			return string(data), nil
  3015  		}
  3016  	}
  3017  
  3018  	if fieldConvert, ok := fieldValue.Interface().(core.Conversion); ok {
  3019  		data, err := fieldConvert.ToDB()
  3020  		if err != nil {
  3021  			return 0, err
  3022  		}
  3023  		return string(data), nil
  3024  	}
  3025  
  3026  	fieldType := fieldValue.Type()
  3027  	k := fieldType.Kind()
  3028  	if k == reflect.Ptr {
  3029  		if fieldValue.IsNil() {
  3030  			return nil, nil
  3031  		} else if !fieldValue.IsValid() {
  3032  			session.Engine.logger.Warn("the field[", col.FieldName, "] is invalid")
  3033  			return nil, nil
  3034  		} else {
  3035  			// !nashtsai! deference pointer type to instance type
  3036  			fieldValue = fieldValue.Elem()
  3037  			fieldType = fieldValue.Type()
  3038  			k = fieldType.Kind()
  3039  		}
  3040  	}
  3041  
  3042  	switch k {
  3043  	case reflect.Bool:
  3044  		return fieldValue.Bool(), nil
  3045  	case reflect.String:
  3046  		return fieldValue.String(), nil
  3047  	case reflect.Struct:
  3048  		if fieldType.ConvertibleTo(core.TimeType) {
  3049  			t := fieldValue.Convert(core.TimeType).Interface().(time.Time)
  3050  			if session.Engine.dialect.DBType() == core.MSSQL {
  3051  				if t.IsZero() {
  3052  					return nil, nil
  3053  				}
  3054  			}
  3055  			tf := session.Engine.FormatTime(col.SQLType.Name, t)
  3056  			return tf, nil
  3057  		}
  3058  
  3059  		if !col.SQLType.IsJson() {
  3060  			// !<winxxp>! 增加支持driver.Valuer接口的结构,如sql.NullString
  3061  			if v, ok := fieldValue.Interface().(driver.Valuer); ok {
  3062  				return v.Value()
  3063  			}
  3064  
  3065  			fieldTable := session.Engine.autoMapType(fieldValue)
  3066  			if len(fieldTable.PrimaryKeys) == 1 {
  3067  				pkField := reflect.Indirect(fieldValue).FieldByName(fieldTable.PKColumns()[0].FieldName)
  3068  				return pkField.Interface(), nil
  3069  			}
  3070  			return 0, fmt.Errorf("no primary key for col %v", col.Name)
  3071  		}
  3072  
  3073  		if col.SQLType.IsText() {
  3074  			bytes, err := json.Marshal(fieldValue.Interface())
  3075  			if err != nil {
  3076  				session.Engine.logger.Error(err)
  3077  				return 0, err
  3078  			}
  3079  			return string(bytes), nil
  3080  		} else if col.SQLType.IsBlob() {
  3081  			bytes, err := json.Marshal(fieldValue.Interface())
  3082  			if err != nil {
  3083  				session.Engine.logger.Error(err)
  3084  				return 0, err
  3085  			}
  3086  			return bytes, nil
  3087  		}
  3088  		return nil, fmt.Errorf("Unsupported type %v", fieldValue.Type())
  3089  	case reflect.Complex64, reflect.Complex128:
  3090  		bytes, err := json.Marshal(fieldValue.Interface())
  3091  		if err != nil {
  3092  			session.Engine.logger.Error(err)
  3093  			return 0, err
  3094  		}
  3095  		return string(bytes), nil
  3096  	case reflect.Array, reflect.Slice, reflect.Map:
  3097  		if !fieldValue.IsValid() {
  3098  			return fieldValue.Interface(), nil
  3099  		}
  3100  
  3101  		if col.SQLType.IsText() {
  3102  			bytes, err := json.Marshal(fieldValue.Interface())
  3103  			if err != nil {
  3104  				session.Engine.logger.Error(err)
  3105  				return 0, err
  3106  			}
  3107  			return string(bytes), nil
  3108  		} else if col.SQLType.IsBlob() {
  3109  			var bytes []byte
  3110  			var err error
  3111  			if (k == reflect.Array || k == reflect.Slice) &&
  3112  				(fieldValue.Type().Elem().Kind() == reflect.Uint8) {
  3113  				bytes = fieldValue.Bytes()
  3114  			} else {
  3115  				bytes, err = json.Marshal(fieldValue.Interface())
  3116  				if err != nil {
  3117  					session.Engine.logger.Error(err)
  3118  					return 0, err
  3119  				}
  3120  			}
  3121  			return bytes, nil
  3122  		}
  3123  		return nil, ErrUnSupportedType
  3124  	case reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uint:
  3125  		return int64(fieldValue.Uint()), nil
  3126  	default:
  3127  		return fieldValue.Interface(), nil
  3128  	}
  3129  }
  3130  
  3131  func (session *Session) innerInsert(bean interface{}) (int64, error) {
  3132  	session.Statement.setRefValue(rValue(bean))
  3133  	if len(session.Statement.TableName()) <= 0 {
  3134  		return 0, ErrTableNotFound
  3135  	}
  3136  
  3137  	table := session.Statement.RefTable
  3138  
  3139  	// handle BeforeInsertProcessor
  3140  	for _, closure := range session.beforeClosures {
  3141  		closure(bean)
  3142  	}
  3143  	cleanupProcessorsClosures(&session.beforeClosures) // cleanup after used
  3144  
  3145  	if processor, ok := interface{}(bean).(BeforeInsertProcessor); ok {
  3146  		processor.BeforeInsert()
  3147  	}
  3148  	// --
  3149  	colNames, args, err := genCols(session.Statement.RefTable, session, bean, false, false)
  3150  	if err != nil {
  3151  		return 0, err
  3152  	}
  3153  	// insert expr columns, override if exists
  3154  	exprColumns := session.Statement.getExpr()
  3155  	exprColVals := make([]string, 0, len(exprColumns))
  3156  	for _, v := range exprColumns {
  3157  		// remove the expr columns
  3158  		for i, colName := range colNames {
  3159  			if colName == v.colName {
  3160  				colNames = append(colNames[:i], colNames[i+1:]...)
  3161  				args = append(args[:i], args[i+1:]...)
  3162  			}
  3163  		}
  3164  
  3165  		// append expr column to the end
  3166  		colNames = append(colNames, v.colName)
  3167  		exprColVals = append(exprColVals, v.expr)
  3168  	}
  3169  
  3170  	colPlaces := strings.Repeat("?, ", len(colNames)-len(exprColumns))
  3171  	if len(exprColVals) > 0 {
  3172  		colPlaces = colPlaces + strings.Join(exprColVals, ", ")
  3173  	} else {
  3174  		colPlaces = colPlaces[0 : len(colPlaces)-2]
  3175  	}
  3176  
  3177  	sqlStr := fmt.Sprintf("INSERT INTO %s (%v%v%v) VALUES (%v)",
  3178  		session.Engine.Quote(session.Statement.TableName()),
  3179  		session.Engine.QuoteStr(),
  3180  		strings.Join(colNames, session.Engine.Quote(", ")),
  3181  		session.Engine.QuoteStr(),
  3182  		colPlaces)
  3183  
  3184  	handleAfterInsertProcessorFunc := func(bean interface{}) {
  3185  		if session.IsAutoCommit {
  3186  			for _, closure := range session.afterClosures {
  3187  				closure(bean)
  3188  			}
  3189  			if processor, ok := interface{}(bean).(AfterInsertProcessor); ok {
  3190  				processor.AfterInsert()
  3191  			}
  3192  		} else {
  3193  			lenAfterClosures := len(session.afterClosures)
  3194  			if lenAfterClosures > 0 {
  3195  				if value, has := session.afterInsertBeans[bean]; has && value != nil {
  3196  					*value = append(*value, session.afterClosures...)
  3197  				} else {
  3198  					afterClosures := make([]func(interface{}), lenAfterClosures)
  3199  					copy(afterClosures, session.afterClosures)
  3200  					session.afterInsertBeans[bean] = &afterClosures
  3201  				}
  3202  
  3203  			} else {
  3204  				if _, ok := interface{}(bean).(AfterInsertProcessor); ok {
  3205  					session.afterInsertBeans[bean] = nil
  3206  				}
  3207  			}
  3208  		}
  3209  		cleanupProcessorsClosures(&session.afterClosures) // cleanup after used
  3210  	}
  3211  
  3212  	// for postgres, many of them didn't implement lastInsertId, so we should
  3213  	// implemented it ourself.
  3214  	if session.Engine.dialect.DBType() == core.ORACLE && len(table.AutoIncrement) > 0 {
  3215  		//assert table.AutoIncrement != ""
  3216  		res, err := session.query("select seq_atable.currval from dual", args...)
  3217  		if err != nil {
  3218  			return 0, err
  3219  		}
  3220  
  3221  		handleAfterInsertProcessorFunc(bean)
  3222  
  3223  		if cacher := session.Engine.getCacher2(table); cacher != nil && session.Statement.UseCache {
  3224  			session.cacheInsert(session.Statement.TableName())
  3225  		}
  3226  
  3227  		if table.Version != "" && session.Statement.checkVersion {
  3228  			verValue, err := table.VersionColumn().ValueOf(bean)
  3229  			if err != nil {
  3230  				session.Engine.logger.Error(err)
  3231  			} else if verValue.IsValid() && verValue.CanSet() {
  3232  				verValue.SetInt(1)
  3233  			}
  3234  		}
  3235  
  3236  		if len(res) < 1 {
  3237  			return 0, errors.New("insert no error but not returned id")
  3238  		}
  3239  
  3240  		idByte := res[0][table.AutoIncrement]
  3241  		id, err := strconv.ParseInt(string(idByte), 10, 64)
  3242  		if err != nil || id <= 0 {
  3243  			return 1, err
  3244  		}
  3245  
  3246  		aiValue, err := table.AutoIncrColumn().ValueOf(bean)
  3247  		if err != nil {
  3248  			session.Engine.logger.Error(err)
  3249  		}
  3250  
  3251  		if aiValue == nil || !aiValue.IsValid() || !aiValue.CanSet() {
  3252  			return 1, nil
  3253  		}
  3254  
  3255  		aiValue.Set(int64ToIntValue(id, aiValue.Type()))
  3256  
  3257  		return 1, nil
  3258  	} else if session.Engine.dialect.DBType() == core.POSTGRES && len(table.AutoIncrement) > 0 {
  3259  		//assert table.AutoIncrement != ""
  3260  		sqlStr = sqlStr + " RETURNING " + session.Engine.Quote(table.AutoIncrement)
  3261  		res, err := session.query(sqlStr, args...)
  3262  
  3263  		if err != nil {
  3264  			return 0, err
  3265  		}
  3266  		handleAfterInsertProcessorFunc(bean)
  3267  
  3268  		if cacher := session.Engine.getCacher2(table); cacher != nil && session.Statement.UseCache {
  3269  			session.cacheInsert(session.Statement.TableName())
  3270  		}
  3271  
  3272  		if table.Version != "" && session.Statement.checkVersion {
  3273  			verValue, err := table.VersionColumn().ValueOf(bean)
  3274  			if err != nil {
  3275  				session.Engine.logger.Error(err)
  3276  			} else if verValue.IsValid() && verValue.CanSet() {
  3277  				verValue.SetInt(1)
  3278  			}
  3279  		}
  3280  
  3281  		if len(res) < 1 {
  3282  			return 0, errors.New("insert no error but not returned id")
  3283  		}
  3284  
  3285  		idByte := res[0][table.AutoIncrement]
  3286  		id, err := strconv.ParseInt(string(idByte), 10, 64)
  3287  		if err != nil || id <= 0 {
  3288  			return 1, err
  3289  		}
  3290  
  3291  		aiValue, err := table.AutoIncrColumn().ValueOf(bean)
  3292  		if err != nil {
  3293  			session.Engine.logger.Error(err)
  3294  		}
  3295  
  3296  		if aiValue == nil || !aiValue.IsValid() || !aiValue.CanSet() {
  3297  			return 1, nil
  3298  		}
  3299  
  3300  		aiValue.Set(int64ToIntValue(id, aiValue.Type()))
  3301  
  3302  		return 1, nil
  3303  	} else {
  3304  		res, err := session.exec(sqlStr, args...)
  3305  		if err != nil {
  3306  			return 0, err
  3307  		}
  3308  
  3309  		defer handleAfterInsertProcessorFunc(bean)
  3310  
  3311  		if cacher := session.Engine.getCacher2(table); cacher != nil && session.Statement.UseCache {
  3312  			session.cacheInsert(session.Statement.TableName())
  3313  		}
  3314  
  3315  		if table.Version != "" && session.Statement.checkVersion {
  3316  			verValue, err := table.VersionColumn().ValueOf(bean)
  3317  			if err != nil {
  3318  				session.Engine.logger.Error(err)
  3319  			} else if verValue.IsValid() && verValue.CanSet() {
  3320  				verValue.SetInt(1)
  3321  			}
  3322  		}
  3323  
  3324  		if table.AutoIncrement == "" {
  3325  			return res.RowsAffected()
  3326  		}
  3327  
  3328  		var id int64
  3329  		id, err = res.LastInsertId()
  3330  		if err != nil || id <= 0 {
  3331  			return res.RowsAffected()
  3332  		}
  3333  
  3334  		aiValue, err := table.AutoIncrColumn().ValueOf(bean)
  3335  		if err != nil {
  3336  			session.Engine.logger.Error(err)
  3337  		}
  3338  
  3339  		if aiValue == nil || !aiValue.IsValid() || !aiValue.CanSet() {
  3340  			return res.RowsAffected()
  3341  		}
  3342  
  3343  		aiValue.Set(int64ToIntValue(id, aiValue.Type()))
  3344  
  3345  		return res.RowsAffected()
  3346  	}
  3347  }
  3348  
  3349  // InsertOne insert only one struct into database as a record.
  3350  // The in parameter bean must a struct or a point to struct. The return
  3351  // parameter is inserted and error
  3352  func (session *Session) InsertOne(bean interface{}) (int64, error) {
  3353  	defer session.resetStatement()
  3354  	if session.IsAutoClose {
  3355  		defer session.Close()
  3356  	}
  3357  
  3358  	return session.innerInsert(bean)
  3359  }
  3360  
  3361  func (session *Session) cacheInsert(tables ...string) error {
  3362  	if session.Statement.RefTable == nil {
  3363  		return ErrCacheFailed
  3364  	}
  3365  
  3366  	table := session.Statement.RefTable
  3367  	cacher := session.Engine.getCacher2(table)
  3368  
  3369  	for _, t := range tables {
  3370  		session.Engine.logger.Debug("[cache] clear sql:", t)
  3371  		cacher.ClearIds(t)
  3372  	}
  3373  
  3374  	return nil
  3375  }
  3376  
  3377  func (session *Session) cacheUpdate(sqlStr string, args ...interface{}) error {
  3378  	if session.Statement.RefTable == nil ||
  3379  		session.Tx != nil {
  3380  		return ErrCacheFailed
  3381  	}
  3382  
  3383  	oldhead, newsql := session.Statement.convertUpdateSQL(sqlStr)
  3384  	if newsql == "" {
  3385  		return ErrCacheFailed
  3386  	}
  3387  	for _, filter := range session.Engine.dialect.Filters() {
  3388  		newsql = filter.Do(newsql, session.Engine.dialect, session.Statement.RefTable)
  3389  	}
  3390  	session.Engine.logger.Debug("[cacheUpdate] new sql", oldhead, newsql)
  3391  
  3392  	var nStart int
  3393  	if len(args) > 0 {
  3394  		if strings.Index(sqlStr, "?") > -1 {
  3395  			nStart = strings.Count(oldhead, "?")
  3396  		} else {
  3397  			// only for pq, TODO: if any other databse?
  3398  			nStart = strings.Count(oldhead, "$")
  3399  		}
  3400  	}
  3401  	table := session.Statement.RefTable
  3402  	cacher := session.Engine.getCacher2(table)
  3403  	tableName := session.Statement.TableName()
  3404  	session.Engine.logger.Debug("[cacheUpdate] get cache sql", newsql, args[nStart:])
  3405  	ids, err := core.GetCacheSql(cacher, tableName, newsql, args[nStart:])
  3406  	if err != nil {
  3407  		rows, err := session.DB().Query(newsql, args[nStart:]...)
  3408  		if err != nil {
  3409  			return err
  3410  		}
  3411  		defer rows.Close()
  3412  
  3413  		ids = make([]core.PK, 0)
  3414  		for rows.Next() {
  3415  			var res = make([]string, len(table.PrimaryKeys))
  3416  			err = rows.ScanSlice(&res)
  3417  			if err != nil {
  3418  				return err
  3419  			}
  3420  			var pk core.PK = make([]interface{}, len(table.PrimaryKeys))
  3421  			for i, col := range table.PKColumns() {
  3422  				if col.SQLType.IsNumeric() {
  3423  					n, err := strconv.ParseInt(res[i], 10, 64)
  3424  					if err != nil {
  3425  						return err
  3426  					}
  3427  					pk[i] = n
  3428  				} else if col.SQLType.IsText() {
  3429  					pk[i] = res[i]
  3430  				} else {
  3431  					return errors.New("not supported")
  3432  				}
  3433  			}
  3434  
  3435  			ids = append(ids, pk)
  3436  		}
  3437  		session.Engine.logger.Debug("[cacheUpdate] find updated id", ids)
  3438  	} /*else {
  3439  	    session.Engine.LogDebug("[xorm:cacheUpdate] del cached sql:", tableName, newsql, args)
  3440  	    cacher.DelIds(tableName, genSqlKey(newsql, args))
  3441  	}*/
  3442  
  3443  	for _, id := range ids {
  3444  		sid, err := id.ToString()
  3445  		if err != nil {
  3446  			return err
  3447  		}
  3448  		if bean := cacher.GetBean(tableName, sid); bean != nil {
  3449  			sqls := splitNNoCase(sqlStr, "where", 2)
  3450  			if len(sqls) == 0 || len(sqls) > 2 {
  3451  				return ErrCacheFailed
  3452  			}
  3453  
  3454  			sqls = splitNNoCase(sqls[0], "set", 2)
  3455  			if len(sqls) != 2 {
  3456  				return ErrCacheFailed
  3457  			}
  3458  			kvs := strings.Split(strings.TrimSpace(sqls[1]), ",")
  3459  			for idx, kv := range kvs {
  3460  				sps := strings.SplitN(kv, "=", 2)
  3461  				sps2 := strings.Split(sps[0], ".")
  3462  				colName := sps2[len(sps2)-1]
  3463  				if strings.Contains(colName, "`") {
  3464  					colName = strings.TrimSpace(strings.Replace(colName, "`", "", -1))
  3465  				} else if strings.Contains(colName, session.Engine.QuoteStr()) {
  3466  					colName = strings.TrimSpace(strings.Replace(colName, session.Engine.QuoteStr(), "", -1))
  3467  				} else {
  3468  					session.Engine.logger.Debug("[cacheUpdate] cannot find column", tableName, colName)
  3469  					return ErrCacheFailed
  3470  				}
  3471  
  3472  				if col := table.GetColumn(colName); col != nil {
  3473  					fieldValue, err := col.ValueOf(bean)
  3474  					if err != nil {
  3475  						session.Engine.logger.Error(err)
  3476  					} else {
  3477  						session.Engine.logger.Debug("[cacheUpdate] set bean field", bean, colName, fieldValue.Interface())
  3478  						if col.IsVersion && session.Statement.checkVersion {
  3479  							fieldValue.SetInt(fieldValue.Int() + 1)
  3480  						} else {
  3481  							fieldValue.Set(reflect.ValueOf(args[idx]))
  3482  						}
  3483  					}
  3484  				} else {
  3485  					session.Engine.logger.Errorf("[cacheUpdate] ERROR: column %v is not table %v's",
  3486  						colName, table.Name)
  3487  				}
  3488  			}
  3489  
  3490  			session.Engine.logger.Debug("[cacheUpdate] update cache", tableName, id, bean)
  3491  			cacher.PutBean(tableName, sid, bean)
  3492  		}
  3493  	}
  3494  	session.Engine.logger.Debug("[cacheUpdate] clear cached table sql:", tableName)
  3495  	cacher.ClearIds(tableName)
  3496  	return nil
  3497  }
  3498  
  3499  // Update records, bean's non-empty fields are updated contents,
  3500  // condiBean' non-empty filds are conditions
  3501  // CAUTION:
  3502  //        1.bool will defaultly be updated content nor conditions
  3503  //         You should call UseBool if you have bool to use.
  3504  //        2.float32 & float64 may be not inexact as conditions
  3505  func (session *Session) Update(bean interface{}, condiBean ...interface{}) (int64, error) {
  3506  	defer session.resetStatement()
  3507  	if session.IsAutoClose {
  3508  		defer session.Close()
  3509  	}
  3510  
  3511  	v := rValue(bean)
  3512  	t := v.Type()
  3513  
  3514  	var colNames []string
  3515  	var args []interface{}
  3516  
  3517  	// handle before update processors
  3518  	for _, closure := range session.beforeClosures {
  3519  		closure(bean)
  3520  	}
  3521  	cleanupProcessorsClosures(&session.beforeClosures) // cleanup after used
  3522  	if processor, ok := interface{}(bean).(BeforeUpdateProcessor); ok {
  3523  		processor.BeforeUpdate()
  3524  	}
  3525  	// --
  3526  
  3527  	var err error
  3528  	var isMap = t.Kind() == reflect.Map
  3529  	var isStruct = t.Kind() == reflect.Struct
  3530  	if isStruct {
  3531  		session.Statement.setRefValue(v)
  3532  
  3533  		if len(session.Statement.TableName()) <= 0 {
  3534  			return 0, ErrTableNotFound
  3535  		}
  3536  
  3537  		if session.Statement.ColumnStr == "" {
  3538  			colNames, args = buildUpdates(session.Engine, session.Statement.RefTable, bean, false, false,
  3539  				false, false, session.Statement.allUseBool, session.Statement.useAllCols,
  3540  				session.Statement.mustColumnMap, session.Statement.nullableMap,
  3541  				session.Statement.columnMap, true, session.Statement.unscoped)
  3542  		} else {
  3543  			colNames, args, err = genCols(session.Statement.RefTable, session, bean, true, true)
  3544  			if err != nil {
  3545  				return 0, err
  3546  			}
  3547  		}
  3548  	} else if isMap {
  3549  		colNames = make([]string, 0)
  3550  		args = make([]interface{}, 0)
  3551  		bValue := reflect.Indirect(reflect.ValueOf(bean))
  3552  
  3553  		for _, v := range bValue.MapKeys() {
  3554  			colNames = append(colNames, session.Engine.Quote(v.String())+" = ?")
  3555  			args = append(args, bValue.MapIndex(v).Interface())
  3556  		}
  3557  	} else {
  3558  		return 0, ErrParamsType
  3559  	}
  3560  
  3561  	table := session.Statement.RefTable
  3562  
  3563  	if session.Statement.UseAutoTime && table != nil && table.Updated != "" {
  3564  		colNames = append(colNames, session.Engine.Quote(table.Updated)+" = ?")
  3565  		col := table.UpdatedColumn()
  3566  		val, t := session.Engine.NowTime2(col.SQLType.Name)
  3567  		args = append(args, val)
  3568  
  3569  		var colName = col.Name
  3570  		if isStruct {
  3571  			session.afterClosures = append(session.afterClosures, func(bean interface{}) {
  3572  				col := table.GetColumn(colName)
  3573  				setColumnTime(bean, col, t)
  3574  			})
  3575  		}
  3576  	}
  3577  
  3578  	//for update action to like "column = column + ?"
  3579  	incColumns := session.Statement.getInc()
  3580  	for _, v := range incColumns {
  3581  		colNames = append(colNames, session.Engine.Quote(v.colName)+" = "+session.Engine.Quote(v.colName)+" + ?")
  3582  		args = append(args, v.arg)
  3583  	}
  3584  	//for update action to like "column = column - ?"
  3585  	decColumns := session.Statement.getDec()
  3586  	for _, v := range decColumns {
  3587  		colNames = append(colNames, session.Engine.Quote(v.colName)+" = "+session.Engine.Quote(v.colName)+" - ?")
  3588  		args = append(args, v.arg)
  3589  	}
  3590  	//for update action to like "column = expression"
  3591  	exprColumns := session.Statement.getExpr()
  3592  	for _, v := range exprColumns {
  3593  		colNames = append(colNames, session.Engine.Quote(v.colName)+" = "+v.expr)
  3594  	}
  3595  
  3596  	session.Statement.processIdParam()
  3597  
  3598  	var autoCond builder.Cond
  3599  	if !session.Statement.noAutoCondition && len(condiBean) > 0 {
  3600  		var err error
  3601  		autoCond, err = session.Statement.buildConds(session.Statement.RefTable, condiBean[0], true, true, false, true, false)
  3602  		if err != nil {
  3603  			return 0, err
  3604  		}
  3605  	}
  3606  
  3607  	st := session.Statement
  3608  	defer session.resetStatement()
  3609  
  3610  	var sqlStr string
  3611  	var condArgs []interface{}
  3612  	var condSQL string
  3613  	cond := session.Statement.cond.And(autoCond)
  3614  
  3615  	doIncVer := false
  3616  	var verValue *reflect.Value
  3617  	if table != nil && table.Version != "" && session.Statement.checkVersion {
  3618  		verValue, err = table.VersionColumn().ValueOf(bean)
  3619  		if err != nil {
  3620  			return 0, err
  3621  		}
  3622  
  3623  		cond = cond.And(builder.Eq{session.Engine.Quote(table.Version): verValue.Interface()})
  3624  		condSQL, condArgs, _ = builder.ToSQL(cond)
  3625  
  3626  		if len(condSQL) > 0 {
  3627  			condSQL = "WHERE " + condSQL
  3628  		}
  3629  
  3630  		if st.LimitN > 0 {
  3631  			condSQL = condSQL + fmt.Sprintf(" LIMIT %d", st.LimitN)
  3632  		}
  3633  
  3634  		sqlStr = fmt.Sprintf("UPDATE %v SET %v, %v %v",
  3635  			session.Engine.Quote(session.Statement.TableName()),
  3636  			strings.Join(colNames, ", "),
  3637  			session.Engine.Quote(table.Version)+" = "+session.Engine.Quote(table.Version)+" + 1",
  3638  			condSQL)
  3639  
  3640  		doIncVer = true
  3641  	} else {
  3642  		condSQL, condArgs, _ = builder.ToSQL(cond)
  3643  		if len(condSQL) > 0 {
  3644  			condSQL = "WHERE " + condSQL
  3645  		}
  3646  
  3647  		if st.LimitN > 0 {
  3648  			condSQL = condSQL + fmt.Sprintf(" LIMIT %d", st.LimitN)
  3649  		}
  3650  
  3651  		sqlStr = fmt.Sprintf("UPDATE %v SET %v %v",
  3652  			session.Engine.Quote(session.Statement.TableName()),
  3653  			strings.Join(colNames, ", "),
  3654  			condSQL)
  3655  	}
  3656  
  3657  	res, err := session.exec(sqlStr, append(args, condArgs...)...)
  3658  	if err != nil {
  3659  		return 0, err
  3660  	} else if doIncVer {
  3661  		if verValue != nil && verValue.IsValid() && verValue.CanSet() {
  3662  			verValue.SetInt(verValue.Int() + 1)
  3663  		}
  3664  	}
  3665  
  3666  	if table != nil {
  3667  		if cacher := session.Engine.getCacher2(table); cacher != nil && session.Statement.UseCache {
  3668  			cacher.ClearIds(session.Statement.TableName())
  3669  			cacher.ClearBeans(session.Statement.TableName())
  3670  		}
  3671  	}
  3672  
  3673  	// handle after update processors
  3674  	if session.IsAutoCommit {
  3675  		for _, closure := range session.afterClosures {
  3676  			closure(bean)
  3677  		}
  3678  		if processor, ok := interface{}(bean).(AfterUpdateProcessor); ok {
  3679  			session.Engine.logger.Debug("[event]", session.Statement.TableName(), " has after update processor")
  3680  			processor.AfterUpdate()
  3681  		}
  3682  	} else {
  3683  		lenAfterClosures := len(session.afterClosures)
  3684  		if lenAfterClosures > 0 {
  3685  			if value, has := session.afterUpdateBeans[bean]; has && value != nil {
  3686  				*value = append(*value, session.afterClosures...)
  3687  			} else {
  3688  				afterClosures := make([]func(interface{}), lenAfterClosures)
  3689  				copy(afterClosures, session.afterClosures)
  3690  				// FIXME: if bean is a map type, it will panic because map cannot be as map key
  3691  				session.afterUpdateBeans[bean] = &afterClosures
  3692  			}
  3693  
  3694  		} else {
  3695  			if _, ok := interface{}(bean).(AfterInsertProcessor); ok {
  3696  				session.afterUpdateBeans[bean] = nil
  3697  			}
  3698  		}
  3699  	}
  3700  	cleanupProcessorsClosures(&session.afterClosures) // cleanup after used
  3701  	// --
  3702  
  3703  	return res.RowsAffected()
  3704  }
  3705  
  3706  func (session *Session) cacheDelete(sqlStr string, args ...interface{}) error {
  3707  	if session.Statement.RefTable == nil ||
  3708  		session.Tx != nil {
  3709  		return ErrCacheFailed
  3710  	}
  3711  
  3712  	for _, filter := range session.Engine.dialect.Filters() {
  3713  		sqlStr = filter.Do(sqlStr, session.Engine.dialect, session.Statement.RefTable)
  3714  	}
  3715  
  3716  	newsql := session.Statement.convertIDSQL(sqlStr)
  3717  	if newsql == "" {
  3718  		return ErrCacheFailed
  3719  	}
  3720  
  3721  	cacher := session.Engine.getCacher2(session.Statement.RefTable)
  3722  	tableName := session.Statement.TableName()
  3723  	ids, err := core.GetCacheSql(cacher, tableName, newsql, args)
  3724  	if err != nil {
  3725  		resultsSlice, err := session.query(newsql, args...)
  3726  		if err != nil {
  3727  			return err
  3728  		}
  3729  		ids = make([]core.PK, 0)
  3730  		if len(resultsSlice) > 0 {
  3731  			for _, data := range resultsSlice {
  3732  				var id int64
  3733  				var pk core.PK = make([]interface{}, 0)
  3734  				for _, col := range session.Statement.RefTable.PKColumns() {
  3735  					if v, ok := data[col.Name]; !ok {
  3736  						return errors.New("no id")
  3737  					} else if col.SQLType.IsText() {
  3738  						pk = append(pk, string(v))
  3739  					} else if col.SQLType.IsNumeric() {
  3740  						id, err = strconv.ParseInt(string(v), 10, 64)
  3741  						if err != nil {
  3742  							return err
  3743  						}
  3744  						pk = append(pk, id)
  3745  					} else {
  3746  						return errors.New("not supported primary key type")
  3747  					}
  3748  				}
  3749  				ids = append(ids, pk)
  3750  			}
  3751  		}
  3752  	} /*else {
  3753  	    session.Engine.LogDebug("delete cache sql %v", newsql)
  3754  	    cacher.DelIds(tableName, genSqlKey(newsql, args))
  3755  	}*/
  3756  
  3757  	for _, id := range ids {
  3758  		session.Engine.logger.Debug("[cacheDelete] delete cache obj", tableName, id)
  3759  		sid, err := id.ToString()
  3760  		if err != nil {
  3761  			return err
  3762  		}
  3763  		cacher.DelBean(tableName, sid)
  3764  	}
  3765  	session.Engine.logger.Debug("[cacheDelete] clear cache sql", tableName)
  3766  	cacher.ClearIds(tableName)
  3767  	return nil
  3768  }
  3769  
  3770  // Delete records, bean's non-empty fields are conditions
  3771  func (session *Session) Delete(bean interface{}) (int64, error) {
  3772  	defer session.resetStatement()
  3773  	if session.IsAutoClose {
  3774  		defer session.Close()
  3775  	}
  3776  
  3777  	session.Statement.setRefValue(rValue(bean))
  3778  	var table = session.Statement.RefTable
  3779  
  3780  	// handle before delete processors
  3781  	for _, closure := range session.beforeClosures {
  3782  		closure(bean)
  3783  	}
  3784  	cleanupProcessorsClosures(&session.beforeClosures)
  3785  
  3786  	if processor, ok := interface{}(bean).(BeforeDeleteProcessor); ok {
  3787  		processor.BeforeDelete()
  3788  	}
  3789  
  3790  	// --
  3791  	condSQL, condArgs, _ := session.Statement.genConds(bean)
  3792  	if len(condSQL) == 0 && session.Statement.LimitN == 0 {
  3793  		return 0, ErrNeedDeletedCond
  3794  	}
  3795  
  3796  	var tableName = session.Engine.Quote(session.Statement.TableName())
  3797  	var deleteSQL string
  3798  	if len(condSQL) > 0 {
  3799  		deleteSQL = fmt.Sprintf("DELETE FROM %v WHERE %v", tableName, condSQL)
  3800  	} else {
  3801  		deleteSQL = fmt.Sprintf("DELETE FROM %v", tableName)
  3802  	}
  3803  
  3804  	var orderSQL string
  3805  	if len(session.Statement.OrderStr) > 0 {
  3806  		orderSQL += fmt.Sprintf(" ORDER BY %s", session.Statement.OrderStr)
  3807  	}
  3808  	if session.Statement.LimitN > 0 {
  3809  		orderSQL += fmt.Sprintf(" LIMIT %d", session.Statement.LimitN)
  3810  	}
  3811  
  3812  	if len(orderSQL) > 0 {
  3813  		switch session.Engine.dialect.DBType() {
  3814  		case core.POSTGRES:
  3815  			inSQL := fmt.Sprintf("ctid IN (SELECT ctid FROM %s%s)", tableName, orderSQL)
  3816  			if len(condSQL) > 0 {
  3817  				deleteSQL += " AND " + inSQL
  3818  			} else {
  3819  				deleteSQL += " WHERE " + inSQL
  3820  			}
  3821  		case core.SQLITE:
  3822  			inSQL := fmt.Sprintf("rowid IN (SELECT rowid FROM %s%s)", tableName, orderSQL)
  3823  			if len(condSQL) > 0 {
  3824  				deleteSQL += " AND " + inSQL
  3825  			} else {
  3826  				deleteSQL += " WHERE " + inSQL
  3827  			}
  3828  		// TODO: how to handle delete limit on mssql?
  3829  		case core.MSSQL:
  3830  			return 0, ErrNotImplemented
  3831  		default:
  3832  			deleteSQL += orderSQL
  3833  		}
  3834  	}
  3835  
  3836  	var realSQL string
  3837  	argsForCache := make([]interface{}, 0, len(condArgs)*2)
  3838  	if session.Statement.unscoped || table.DeletedColumn() == nil { // tag "deleted" is disabled
  3839  		realSQL = deleteSQL
  3840  		copy(argsForCache, condArgs)
  3841  		argsForCache = append(condArgs, argsForCache...)
  3842  	} else {
  3843  		// !oinume! sqlStrForCache and argsForCache is needed to behave as executing "DELETE FROM ..." for cache.
  3844  		copy(argsForCache, condArgs)
  3845  		argsForCache = append(condArgs, argsForCache...)
  3846  
  3847  		deletedColumn := table.DeletedColumn()
  3848  		realSQL = fmt.Sprintf("UPDATE %v SET %v = ? WHERE %v",
  3849  			session.Engine.Quote(session.Statement.TableName()),
  3850  			session.Engine.Quote(deletedColumn.Name),
  3851  			condSQL)
  3852  
  3853  		if len(orderSQL) > 0 {
  3854  			switch session.Engine.dialect.DBType() {
  3855  			case core.POSTGRES:
  3856  				inSQL := fmt.Sprintf("ctid IN (SELECT ctid FROM %s%s)", tableName, orderSQL)
  3857  				if len(condSQL) > 0 {
  3858  					realSQL += " AND " + inSQL
  3859  				} else {
  3860  					realSQL += " WHERE " + inSQL
  3861  				}
  3862  			case core.SQLITE:
  3863  				inSQL := fmt.Sprintf("rowid IN (SELECT rowid FROM %s%s)", tableName, orderSQL)
  3864  				if len(condSQL) > 0 {
  3865  					realSQL += " AND " + inSQL
  3866  				} else {
  3867  					realSQL += " WHERE " + inSQL
  3868  				}
  3869  			// TODO: how to handle delete limit on mssql?
  3870  			case core.MSSQL:
  3871  				return 0, ErrNotImplemented
  3872  			default:
  3873  				realSQL += orderSQL
  3874  			}
  3875  		}
  3876  
  3877  		// !oinume! Insert NowTime to the head of session.Statement.Params
  3878  		condArgs = append(condArgs, "")
  3879  		paramsLen := len(condArgs)
  3880  		copy(condArgs[1:paramsLen], condArgs[0:paramsLen-1])
  3881  
  3882  		val, t := session.Engine.NowTime2(deletedColumn.SQLType.Name)
  3883  		condArgs[0] = val
  3884  
  3885  		var colName = deletedColumn.Name
  3886  		session.afterClosures = append(session.afterClosures, func(bean interface{}) {
  3887  			col := table.GetColumn(colName)
  3888  			setColumnTime(bean, col, t)
  3889  		})
  3890  	}
  3891  
  3892  	if cacher := session.Engine.getCacher2(session.Statement.RefTable); cacher != nil && session.Statement.UseCache {
  3893  		session.cacheDelete(deleteSQL, argsForCache...)
  3894  	}
  3895  
  3896  	res, err := session.exec(realSQL, condArgs...)
  3897  	if err != nil {
  3898  		return 0, err
  3899  	}
  3900  
  3901  	// handle after delete processors
  3902  	if session.IsAutoCommit {
  3903  		for _, closure := range session.afterClosures {
  3904  			closure(bean)
  3905  		}
  3906  		if processor, ok := interface{}(bean).(AfterDeleteProcessor); ok {
  3907  			processor.AfterDelete()
  3908  		}
  3909  	} else {
  3910  		lenAfterClosures := len(session.afterClosures)
  3911  		if lenAfterClosures > 0 {
  3912  			if value, has := session.afterDeleteBeans[bean]; has && value != nil {
  3913  				*value = append(*value, session.afterClosures...)
  3914  			} else {
  3915  				afterClosures := make([]func(interface{}), lenAfterClosures)
  3916  				copy(afterClosures, session.afterClosures)
  3917  				session.afterDeleteBeans[bean] = &afterClosures
  3918  			}
  3919  		} else {
  3920  			if _, ok := interface{}(bean).(AfterInsertProcessor); ok {
  3921  				session.afterDeleteBeans[bean] = nil
  3922  			}
  3923  		}
  3924  	}
  3925  	cleanupProcessorsClosures(&session.afterClosures)
  3926  	// --
  3927  
  3928  	return res.RowsAffected()
  3929  }
  3930  
  3931  // saveLastSQL stores executed query information
  3932  func (session *Session) saveLastSQL(sql string, args ...interface{}) {
  3933  	session.lastSQL = sql
  3934  	session.lastSQLArgs = args
  3935  	session.Engine.logSQL(sql, args...)
  3936  }
  3937  
  3938  // LastSQL returns last query information
  3939  func (session *Session) LastSQL() (string, []interface{}) {
  3940  	return session.lastSQL, session.lastSQLArgs
  3941  }
  3942  
  3943  // tbName get some table's table name
  3944  func (session *Session) tbNameNoSchema(table *core.Table) string {
  3945  	if len(session.Statement.AltTableName) > 0 {
  3946  		return session.Statement.AltTableName
  3947  	}
  3948  
  3949  	return table.Name
  3950  }
  3951  
  3952  // Sync2 synchronize structs to database tables
  3953  func (session *Session) Sync2(beans ...interface{}) error {
  3954  	engine := session.Engine
  3955  
  3956  	tables, err := engine.DBMetas()
  3957  	if err != nil {
  3958  		return err
  3959  	}
  3960  
  3961  	var structTables []*core.Table
  3962  
  3963  	for _, bean := range beans {
  3964  		v := rValue(bean)
  3965  		table := engine.mapType(v)
  3966  		structTables = append(structTables, table)
  3967  		var tbName = session.tbNameNoSchema(table)
  3968  
  3969  		var oriTable *core.Table
  3970  		for _, tb := range tables {
  3971  			if strings.EqualFold(tb.Name, tbName) {
  3972  				oriTable = tb
  3973  				break
  3974  			}
  3975  		}
  3976  
  3977  		if oriTable == nil {
  3978  			err = session.StoreEngine(session.Statement.StoreEngine).CreateTable(bean)
  3979  			if err != nil {
  3980  				return err
  3981  			}
  3982  
  3983  			err = session.CreateUniques(bean)
  3984  			if err != nil {
  3985  				return err
  3986  			}
  3987  
  3988  			err = session.CreateIndexes(bean)
  3989  			if err != nil {
  3990  				return err
  3991  			}
  3992  		} else {
  3993  			for _, col := range table.Columns() {
  3994  				var oriCol *core.Column
  3995  				for _, col2 := range oriTable.Columns() {
  3996  					if strings.EqualFold(col.Name, col2.Name) {
  3997  						oriCol = col2
  3998  						break
  3999  					}
  4000  				}
  4001  
  4002  				if oriCol != nil {
  4003  					expectedType := engine.dialect.SqlType(col)
  4004  					curType := engine.dialect.SqlType(oriCol)
  4005  					if expectedType != curType {
  4006  						if expectedType == core.Text &&
  4007  							strings.HasPrefix(curType, core.Varchar) {
  4008  							// currently only support mysql & postgres
  4009  							if engine.dialect.DBType() == core.MYSQL ||
  4010  								engine.dialect.DBType() == core.POSTGRES {
  4011  								engine.logger.Infof("Table %s column %s change type from %s to %s\n",
  4012  									tbName, col.Name, curType, expectedType)
  4013  								_, err = engine.Exec(engine.dialect.ModifyColumnSql(table.Name, col))
  4014  							} else {
  4015  								engine.logger.Warnf("Table %s column %s db type is %s, struct type is %s\n",
  4016  									tbName, col.Name, curType, expectedType)
  4017  							}
  4018  						} else if strings.HasPrefix(curType, core.Varchar) && strings.HasPrefix(expectedType, core.Varchar) {
  4019  							if engine.dialect.DBType() == core.MYSQL {
  4020  								if oriCol.Length < col.Length {
  4021  									engine.logger.Infof("Table %s column %s change type from varchar(%d) to varchar(%d)\n",
  4022  										tbName, col.Name, oriCol.Length, col.Length)
  4023  									_, err = engine.Exec(engine.dialect.ModifyColumnSql(table.Name, col))
  4024  								}
  4025  							}
  4026  						} else {
  4027  							if !(strings.HasPrefix(curType, expectedType) && curType[len(expectedType)] == '(') {
  4028  								engine.logger.Warnf("Table %s column %s db type is %s, struct type is %s",
  4029  									tbName, col.Name, curType, expectedType)
  4030  							}
  4031  						}
  4032  					} else if expectedType == core.Varchar {
  4033  						if engine.dialect.DBType() == core.MYSQL {
  4034  							if oriCol.Length < col.Length {
  4035  								engine.logger.Infof("Table %s column %s change type from varchar(%d) to varchar(%d)\n",
  4036  									tbName, col.Name, oriCol.Length, col.Length)
  4037  								_, err = engine.Exec(engine.dialect.ModifyColumnSql(table.Name, col))
  4038  							}
  4039  						}
  4040  					}
  4041  					if col.Default != oriCol.Default {
  4042  						engine.logger.Warnf("Table %s Column %s db default is %s, struct default is %s",
  4043  							tbName, col.Name, oriCol.Default, col.Default)
  4044  					}
  4045  					if col.Nullable != oriCol.Nullable {
  4046  						engine.logger.Warnf("Table %s Column %s db nullable is %v, struct nullable is %v",
  4047  							tbName, col.Name, oriCol.Nullable, col.Nullable)
  4048  					}
  4049  				} else {
  4050  					session := engine.NewSession()
  4051  					session.Statement.RefTable = table
  4052  					session.Statement.tableName = tbName
  4053  					defer session.Close()
  4054  					err = session.addColumn(col.Name)
  4055  				}
  4056  				if err != nil {
  4057  					return err
  4058  				}
  4059  			}
  4060  
  4061  			var foundIndexNames = make(map[string]bool)
  4062  			var addedNames = make(map[string]*core.Index)
  4063  
  4064  			for name, index := range table.Indexes {
  4065  				var oriIndex *core.Index
  4066  				for name2, index2 := range oriTable.Indexes {
  4067  					if index.Equal(index2) {
  4068  						oriIndex = index2
  4069  						foundIndexNames[name2] = true
  4070  						break
  4071  					}
  4072  				}
  4073  
  4074  				if oriIndex != nil {
  4075  					if oriIndex.Type != index.Type {
  4076  						sql := engine.dialect.DropIndexSql(tbName, oriIndex)
  4077  						_, err = engine.Exec(sql)
  4078  						if err != nil {
  4079  							return err
  4080  						}
  4081  						oriIndex = nil
  4082  					}
  4083  				}
  4084  
  4085  				if oriIndex == nil {
  4086  					addedNames[name] = index
  4087  				}
  4088  			}
  4089  
  4090  			for name2, index2 := range oriTable.Indexes {
  4091  				if _, ok := foundIndexNames[name2]; !ok {
  4092  					sql := engine.dialect.DropIndexSql(tbName, index2)
  4093  					_, err = engine.Exec(sql)
  4094  					if err != nil {
  4095  						return err
  4096  					}
  4097  				}
  4098  			}
  4099  
  4100  			for name, index := range addedNames {
  4101  				if index.Type == core.UniqueType {
  4102  					session := engine.NewSession()
  4103  					session.Statement.RefTable = table
  4104  					session.Statement.tableName = tbName
  4105  					defer session.Close()
  4106  					err = session.addUnique(tbName, name)
  4107  				} else if index.Type == core.IndexType {
  4108  					session := engine.NewSession()
  4109  					session.Statement.RefTable = table
  4110  					session.Statement.tableName = tbName
  4111  					defer session.Close()
  4112  					err = session.addIndex(tbName, name)
  4113  				}
  4114  				if err != nil {
  4115  					return err
  4116  				}
  4117  			}
  4118  		}
  4119  	}
  4120  
  4121  	for _, table := range tables {
  4122  		var oriTable *core.Table
  4123  		for _, structTable := range structTables {
  4124  			if strings.EqualFold(table.Name, session.tbNameNoSchema(structTable)) {
  4125  				oriTable = structTable
  4126  				break
  4127  			}
  4128  		}
  4129  
  4130  		if oriTable == nil {
  4131  			//engine.LogWarnf("Table %s has no struct to mapping it", table.Name)
  4132  			continue
  4133  		}
  4134  
  4135  		for _, colName := range table.ColumnsSeq() {
  4136  			if oriTable.GetColumn(colName) == nil {
  4137  				engine.logger.Warnf("Table %s has column %s but struct has not related field", table.Name, colName)
  4138  			}
  4139  		}
  4140  	}
  4141  	return nil
  4142  }
  4143  
  4144  // Unscoped always disable struct tag "deleted"
  4145  func (session *Session) Unscoped() *Session {
  4146  	session.Statement.Unscoped()
  4147  	return session
  4148  }