| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177 | // Copyright 2016 The Xorm Authors. All rights reserved.// Use of this source code is governed by a BSD-style// license that can be found in the LICENSE file.package xormimport (	"errors"	"reflect"	"strconv"	"github.com/go-xorm/core")// Get retrieve one record from database, bean's non-empty fields// will be as conditionsfunc (session *Session) Get(bean interface{}) (bool, error) {	defer session.resetStatement()	if session.IsAutoClose {		defer session.Close()	}	session.Statement.setRefValue(rValue(bean))	var sqlStr string	var args []interface{}	if session.Statement.RawSQL == "" {		if len(session.Statement.TableName()) <= 0 {			return false, ErrTableNotFound		}		session.Statement.Limit(1)		sqlStr, args = session.Statement.genGetSQL(bean)	} else {		sqlStr = session.Statement.RawSQL		args = session.Statement.RawParams	}	if session.canCache() {		if cacher := session.Engine.getCacher2(session.Statement.RefTable); cacher != nil &&			!session.Statement.unscoped {			has, err := session.cacheGet(bean, sqlStr, args...)			if err != ErrCacheFailed {				return has, err			}		}	}	return session.nocacheGet(bean, sqlStr, args...)}func (session *Session) nocacheGet(bean interface{}, sqlStr string, args ...interface{}) (bool, error) {	var rawRows *core.Rows	var err error	session.queryPreprocess(&sqlStr, args...)	if session.IsAutoCommit {		_, rawRows, err = session.innerQuery(sqlStr, args...)	} else {		rawRows, err = session.Tx.Query(sqlStr, args...)	}	if err != nil {		return false, err	}	defer rawRows.Close()	if rawRows.Next() {		fields, err := rawRows.Columns()		if err == nil {			err = session.row2Bean(rawRows, fields, len(fields), bean)		}		return true, err	}	return false, nil}func (session *Session) cacheGet(bean interface{}, sqlStr string, args ...interface{}) (has bool, err error) {	// if has no reftable, then don't use cache currently	if !session.canCache() {		return false, ErrCacheFailed	}	for _, filter := range session.Engine.dialect.Filters() {		sqlStr = filter.Do(sqlStr, session.Engine.dialect, session.Statement.RefTable)	}	newsql := session.Statement.convertIDSQL(sqlStr)	if newsql == "" {		return false, ErrCacheFailed	}	cacher := session.Engine.getCacher2(session.Statement.RefTable)	tableName := session.Statement.TableName()	session.Engine.logger.Debug("[cacheGet] find sql:", newsql, args)	ids, err := core.GetCacheSql(cacher, tableName, newsql, args)	table := session.Statement.RefTable	if err != nil {		var res = make([]string, len(table.PrimaryKeys))		rows, err := session.DB().Query(newsql, args...)		if err != nil {			return false, err		}		defer rows.Close()		if rows.Next() {			err = rows.ScanSlice(&res)			if err != nil {				return false, err			}		} else {			return false, ErrCacheFailed		}		var pk core.PK = make([]interface{}, len(table.PrimaryKeys))		for i, col := range table.PKColumns() {			if col.SQLType.IsText() {				pk[i] = res[i]			} else if col.SQLType.IsNumeric() {				n, err := strconv.ParseInt(res[i], 10, 64)				if err != nil {					return false, err				}				pk[i] = n			} else {				return false, errors.New("unsupported")			}		}		ids = []core.PK{pk}		session.Engine.logger.Debug("[cacheGet] cache ids:", newsql, ids)		err = core.PutCacheSql(cacher, ids, tableName, newsql, args)		if err != nil {			return false, err		}	} else {		session.Engine.logger.Debug("[cacheGet] cache hit sql:", newsql)	}	if len(ids) > 0 {		structValue := reflect.Indirect(reflect.ValueOf(bean))		id := ids[0]		session.Engine.logger.Debug("[cacheGet] get bean:", tableName, id)		sid, err := id.ToString()		if err != nil {			return false, err		}		cacheBean := cacher.GetBean(tableName, sid)		if cacheBean == nil {			/*newSession := session.Engine.NewSession()			defer newSession.Close()			cacheBean = reflect.New(structValue.Type()).Interface()			newSession.Id(id).NoCache()			if session.Statement.AltTableName != "" {				newSession.Table(session.Statement.AltTableName)			}			if !session.Statement.UseCascade {				newSession.NoCascade()			}			has, err = newSession.Get(cacheBean)			*/			cacheBean = bean			has, err = session.nocacheGet(cacheBean, sqlStr, args...)			if err != nil || !has {				return has, err			}			session.Engine.logger.Debug("[cacheGet] cache bean:", tableName, id, cacheBean)			cacher.PutBean(tableName, sid, cacheBean)		} else {			session.Engine.logger.Debug("[cacheGet] cache hit bean:", tableName, id, cacheBean)			has = true		}		structValue.Set(reflect.Indirect(reflect.ValueOf(cacheBean)))		return has, nil	}	return false, nil}
 |