Ver código fonte

1.fix bug on cache delete
2.fix cache issues and improve the tests

xormplus 8 anos atrás
pai
commit
69624319c9

+ 12 - 22
cache_lru.go

@@ -15,13 +15,12 @@ import (
 
 // LRUCacher implments cache object facilities
 type LRUCacher struct {
-	idList   *list.List
-	sqlList  *list.List
-	idIndex  map[string]map[string]*list.Element
-	sqlIndex map[string]map[string]*list.Element
-	store    core.CacheStore
-	mutex    sync.Mutex
-	// maxSize    int
+	idList         *list.List
+	sqlList        *list.List
+	idIndex        map[string]map[string]*list.Element
+	sqlIndex       map[string]map[string]*list.Element
+	store          core.CacheStore
+	mutex          sync.Mutex
 	MaxElementSize int
 	Expired        time.Duration
 	GcInterval     time.Duration
@@ -54,8 +53,6 @@ func (m *LRUCacher) RunGC() {
 
 // GC check ids lit and sql list to remove all element expired
 func (m *LRUCacher) GC() {
-	//fmt.Println("begin gc ...")
-	//defer fmt.Println("end gc ...")
 	m.mutex.Lock()
 	defer m.mutex.Unlock()
 	var removedNum int
@@ -64,12 +61,10 @@ func (m *LRUCacher) GC() {
 			time.Now().Sub(e.Value.(*idNode).lastVisit) > m.Expired {
 			removedNum++
 			next := e.Next()
-			//fmt.Println("removing ...", e.Value)
 			node := e.Value.(*idNode)
 			m.delBean(node.tbName, node.id)
 			e = next
 		} else {
-			//fmt.Printf("removing %d cache nodes ..., left %d\n", removedNum, m.idList.Len())
 			break
 		}
 	}
@@ -80,12 +75,10 @@ func (m *LRUCacher) GC() {
 			time.Now().Sub(e.Value.(*sqlNode).lastVisit) > m.Expired {
 			removedNum++
 			next := e.Next()
-			//fmt.Println("removing ...", e.Value)
 			node := e.Value.(*sqlNode)
 			m.delIds(node.tbName, node.sql)
 			e = next
 		} else {
-			//fmt.Printf("removing %d cache nodes ..., left %d\n", removedNum, m.sqlList.Len())
 			break
 		}
 	}
@@ -116,7 +109,6 @@ func (m *LRUCacher) GetIds(tableName, sql string) interface{} {
 	}
 
 	m.delIds(tableName, sql)
-
 	return nil
 }
 
@@ -134,7 +126,6 @@ func (m *LRUCacher) GetBean(tableName string, id string) interface{} {
 			// if expired, remove the node and return nil
 			if time.Now().Sub(lastTime) > m.Expired {
 				m.delBean(tableName, id)
-				//m.clearIds(tableName)
 				return nil
 			}
 			m.idList.MoveToBack(el)
@@ -148,7 +139,6 @@ func (m *LRUCacher) GetBean(tableName string, id string) interface{} {
 
 	// store bean is not exist, then remove memory's index
 	m.delBean(tableName, id)
-	//m.clearIds(tableName)
 	return nil
 }
 
@@ -166,8 +156,8 @@ func (m *LRUCacher) clearIds(tableName string) {
 // ClearIds clears all sql-ids mapping on table tableName from cache
 func (m *LRUCacher) ClearIds(tableName string) {
 	m.mutex.Lock()
-	defer m.mutex.Unlock()
 	m.clearIds(tableName)
+	m.mutex.Unlock()
 }
 
 func (m *LRUCacher) clearBeans(tableName string) {
@@ -184,14 +174,13 @@ func (m *LRUCacher) clearBeans(tableName string) {
 // ClearBeans clears all beans in some table
 func (m *LRUCacher) ClearBeans(tableName string) {
 	m.mutex.Lock()
-	defer m.mutex.Unlock()
 	m.clearBeans(tableName)
+	m.mutex.Unlock()
 }
 
 // PutIds pus ids into table
 func (m *LRUCacher) PutIds(tableName, sql string, ids interface{}) {
 	m.mutex.Lock()
-	defer m.mutex.Unlock()
 	if _, ok := m.sqlIndex[tableName]; !ok {
 		m.sqlIndex[tableName] = make(map[string]*list.Element)
 	}
@@ -207,12 +196,12 @@ func (m *LRUCacher) PutIds(tableName, sql string, ids interface{}) {
 		node := e.Value.(*sqlNode)
 		m.delIds(node.tbName, node.sql)
 	}
+	m.mutex.Unlock()
 }
 
 // PutBean puts beans into table
 func (m *LRUCacher) PutBean(tableName string, id string, obj interface{}) {
 	m.mutex.Lock()
-	defer m.mutex.Unlock()
 	var el *list.Element
 	var ok bool
 
@@ -229,6 +218,7 @@ func (m *LRUCacher) PutBean(tableName string, id string, obj interface{}) {
 		node := e.Value.(*idNode)
 		m.delBean(node.tbName, node.id)
 	}
+	m.mutex.Unlock()
 }
 
 func (m *LRUCacher) delIds(tableName, sql string) {
@@ -244,8 +234,8 @@ func (m *LRUCacher) delIds(tableName, sql string) {
 // DelIds deletes ids
 func (m *LRUCacher) DelIds(tableName, sql string) {
 	m.mutex.Lock()
-	defer m.mutex.Unlock()
 	m.delIds(tableName, sql)
+	m.mutex.Unlock()
 }
 
 func (m *LRUCacher) delBean(tableName string, id string) {
@@ -261,8 +251,8 @@ func (m *LRUCacher) delBean(tableName string, id string) {
 // DelBean deletes beans in some table
 func (m *LRUCacher) DelBean(tableName string, id string) {
 	m.mutex.Lock()
-	defer m.mutex.Unlock()
 	m.delBean(tableName, id)
+	m.mutex.Unlock()
 }
 
 type idNode struct {

+ 52 - 0
cache_lru_test.go

@@ -0,0 +1,52 @@
+// Copyright 2015 The Xorm Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package xorm
+
+import (
+	"testing"
+
+	"github.com/go-xorm/core"
+	"github.com/stretchr/testify/assert"
+)
+
+func TestLRUCache(t *testing.T) {
+	type CacheObject1 struct {
+		Id int64
+	}
+
+	store := NewMemoryStore()
+	cacher := NewLRUCacher(store, 10000)
+
+	tableName := "cache_object1"
+	pks := []core.PK{
+		{1},
+		{2},
+	}
+
+	for _, pk := range pks {
+		sid, err := pk.ToString()
+		assert.NoError(t, err)
+
+		cacher.PutIds(tableName, "select * from cache_object1", sid)
+		ids := cacher.GetIds(tableName, "select * from cache_object1")
+		assert.EqualValues(t, sid, ids)
+
+		cacher.ClearIds(tableName)
+		ids2 := cacher.GetIds(tableName, "select * from cache_object1")
+		assert.Nil(t, ids2)
+
+		obj2 := cacher.GetBean(tableName, sid)
+		assert.Nil(t, obj2)
+
+		var obj = new(CacheObject1)
+		cacher.PutBean(tableName, sid, obj)
+		obj3 := cacher.GetBean(tableName, sid)
+		assert.EqualValues(t, obj, obj3)
+
+		cacher.DelBean(tableName, sid)
+		obj4 := cacher.GetBean(tableName, sid)
+		assert.Nil(t, obj4)
+	}
+}

+ 37 - 0
cache_memory_store_test.go

@@ -0,0 +1,37 @@
+// Copyright 2015 The Xorm Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package xorm
+
+import (
+	"testing"
+
+	"github.com/stretchr/testify/assert"
+)
+
+func TestMemoryStore(t *testing.T) {
+	store := NewMemoryStore()
+	var kvs = map[string]interface{}{
+		"a": "b",
+	}
+	for k, v := range kvs {
+		assert.NoError(t, store.Put(k, v))
+	}
+
+	for k, v := range kvs {
+		val, err := store.Get(k)
+		assert.NoError(t, err)
+		assert.EqualValues(t, v, val)
+	}
+
+	for k, _ := range kvs {
+		err := store.Del(k)
+		assert.NoError(t, err)
+	}
+
+	for k, _ := range kvs {
+		_, err := store.Get(k)
+		assert.EqualValues(t, ErrNotExist, err)
+	}
+}

+ 30 - 3
cache_test.go

@@ -20,6 +20,7 @@ func TestCacheFind(t *testing.T) {
 		Password string
 	}
 
+	oldCacher := testEngine.Cacher
 	cacher := NewLRUCacher2(NewMemoryStore(), time.Hour, 10000)
 	testEngine.SetDefaultCacher(cacher)
 
@@ -58,7 +59,31 @@ func TestCacheFind(t *testing.T) {
 		assert.Equal(t, inserts[i].Password, box.Password)
 	}
 
-	testEngine.SetDefaultCacher(nil)
+	boxes = make([]MailBox, 0, 2)
+	assert.NoError(t, testEngine.Alias("a").Where("a.id > -1").Asc("a.id").Find(&boxes))
+	assert.EqualValues(t, 2, len(boxes))
+	for i, box := range boxes {
+		assert.Equal(t, inserts[i].Id, box.Id)
+		assert.Equal(t, inserts[i].Username, box.Username)
+		assert.Equal(t, inserts[i].Password, box.Password)
+	}
+
+	type MailBox4 struct {
+		Id       int64
+		Username string
+		Password string
+	}
+
+	boxes2 := make([]MailBox4, 0, 2)
+	assert.NoError(t, testEngine.Table("mail_box").Where("mail_box.id > -1").Asc("mail_box.id").Find(&boxes2))
+	assert.EqualValues(t, 2, len(boxes2))
+	for i, box := range boxes2 {
+		assert.Equal(t, inserts[i].Id, box.Id)
+		assert.Equal(t, inserts[i].Username, box.Username)
+		assert.Equal(t, inserts[i].Password, box.Password)
+	}
+
+	testEngine.SetDefaultCacher(oldCacher)
 }
 
 func TestCacheFind2(t *testing.T) {
@@ -70,6 +95,7 @@ func TestCacheFind2(t *testing.T) {
 		Password string
 	}
 
+	oldCacher := testEngine.Cacher
 	cacher := NewLRUCacher2(NewMemoryStore(), time.Hour, 10000)
 	testEngine.SetDefaultCacher(cacher)
 
@@ -108,7 +134,7 @@ func TestCacheFind2(t *testing.T) {
 		assert.Equal(t, inserts[i].Password, box.Password)
 	}
 
-	testEngine.SetDefaultCacher(nil)
+	testEngine.SetDefaultCacher(oldCacher)
 }
 
 func TestCacheGet(t *testing.T) {
@@ -120,6 +146,7 @@ func TestCacheGet(t *testing.T) {
 		Password string
 	}
 
+	oldCacher := testEngine.Cacher
 	cacher := NewLRUCacher2(NewMemoryStore(), time.Hour, 10000)
 	testEngine.SetDefaultCacher(cacher)
 
@@ -148,5 +175,5 @@ func TestCacheGet(t *testing.T) {
 	assert.EqualValues(t, "user1", box2.Username)
 	assert.EqualValues(t, "pass1", box2.Password)
 
-	testEngine.SetDefaultCacher(nil)
+	testEngine.SetDefaultCacher(oldCacher)
 }

+ 5 - 5
processors_test.go

@@ -42,24 +42,24 @@ func TestBefore_Get(t *testing.T) {
 func TestBefore_Find(t *testing.T) {
 	assert.NoError(t, prepareEngine())
 
-	type BeforeTable struct {
+	type BeforeTable2 struct {
 		Id   int64
 		Name string
 		Val  string `xorm:"-"`
 	}
 
-	assert.NoError(t, testEngine.Sync2(new(BeforeTable)))
+	assert.NoError(t, testEngine.Sync2(new(BeforeTable2)))
 
-	cnt, err := testEngine.Insert([]BeforeTable{
+	cnt, err := testEngine.Insert([]BeforeTable2{
 		{Name: "test1"},
 		{Name: "test2"},
 	})
 	assert.NoError(t, err)
 	assert.EqualValues(t, 2, cnt)
 
-	var be []BeforeTable
+	var be []BeforeTable2
 	err = testEngine.Before(func(bean interface{}) {
-		bean.(*BeforeTable).Val = "val"
+		bean.(*BeforeTable2).Val = "val"
 	}).Find(&be)
 	assert.NoError(t, err)
 	assert.Equal(t, 2, len(be))

+ 4 - 4
session_cols_test.go

@@ -14,14 +14,14 @@ import (
 func TestSetExpr(t *testing.T) {
 	assert.NoError(t, prepareEngine())
 
-	type User struct {
+	type UserExpr struct {
 		Id   int64
 		Show bool
 	}
 
-	assert.NoError(t, testEngine.Sync2(new(User)))
+	assert.NoError(t, testEngine.Sync2(new(UserExpr)))
 
-	cnt, err := testEngine.Insert(&User{
+	cnt, err := testEngine.Insert(&UserExpr{
 		Show: true,
 	})
 	assert.NoError(t, err)
@@ -31,7 +31,7 @@ func TestSetExpr(t *testing.T) {
 	if testEngine.dialect.DBType() == core.MSSQL {
 		not = "~"
 	}
-	cnt, err = testEngine.SetExpr("show", not+" `show`").ID(1).Update(new(User))
+	cnt, err = testEngine.SetExpr("show", not+" `show`").ID(1).Update(new(UserExpr))
 	assert.NoError(t, err)
 	assert.EqualValues(t, 1, cnt)
 }

+ 15 - 16
session_delete.go

@@ -12,14 +12,14 @@ import (
 	"github.com/xormplus/core"
 )
 
-func (session *Session) cacheDelete(sqlStr string, args ...interface{}) error {
-	if session.statement.RefTable == nil ||
+func (session *Session) cacheDelete(table *core.Table, tableName, sqlStr string, args ...interface{}) error {
+	if table == nil ||
 		session.tx != nil {
 		return ErrCacheFailed
 	}
 
 	for _, filter := range session.engine.dialect.Filters() {
-		sqlStr = filter.Do(sqlStr, session.engine.dialect, session.statement.RefTable)
+		sqlStr = filter.Do(sqlStr, session.engine.dialect, table)
 	}
 
 	newsql := session.statement.convertIDSQL(sqlStr)
@@ -27,8 +27,8 @@ func (session *Session) cacheDelete(sqlStr string, args ...interface{}) error {
 		return ErrCacheFailed
 	}
 
-	cacher := session.engine.getCacher2(session.statement.RefTable)
-	tableName := session.statement.TableName()
+	cacher := session.engine.getCacher2(table)
+	pkColumns := table.PKColumns()
 	ids, err := core.GetCacheSql(cacher, tableName, newsql, args)
 	if err != nil {
 		resultsSlice, err := session.queryBytes(newsql, args...)
@@ -40,7 +40,7 @@ func (session *Session) cacheDelete(sqlStr string, args ...interface{}) error {
 			for _, data := range resultsSlice {
 				var id int64
 				var pk core.PK = make([]interface{}, 0)
-				for _, col := range session.statement.RefTable.PKColumns() {
+				for _, col := range pkColumns {
 					if v, ok := data[col.Name]; !ok {
 						return errors.New("no id")
 					} else if col.SQLType.IsText() {
@@ -58,20 +58,17 @@ func (session *Session) cacheDelete(sqlStr string, args ...interface{}) error {
 				ids = append(ids, pk)
 			}
 		}
-	} /*else {
-	    session.engine.LogDebug("delete cache sql %v", newsql)
-	    cacher.DelIds(tableName, genSqlKey(newsql, args))
-	}*/
+	}
 
 	for _, id := range ids {
-		session.engine.logger.Debug("[cacheDelete] delete cache obj", tableName, id)
+		session.engine.logger.Debug("[cacheDelete] delete cache obj:", tableName, id)
 		sid, err := id.ToString()
 		if err != nil {
 			return err
 		}
 		cacher.DelBean(tableName, sid)
 	}
-	session.engine.logger.Debug("[cacheDelete] clear cache sql", tableName)
+	session.engine.logger.Debug("[cacheDelete] clear cache table:", tableName)
 	cacher.ClearIds(tableName)
 	return nil
 }
@@ -85,7 +82,6 @@ func (session *Session) Delete(bean interface{}) (int64, error) {
 	if err := session.statement.setRefValue(rValue(bean)); err != nil {
 		return 0, err
 	}
-	var table = session.statement.RefTable
 
 	// handle before delete processors
 	for _, closure := range session.beforeClosures {
@@ -105,7 +101,9 @@ func (session *Session) Delete(bean interface{}) (int64, error) {
 		return 0, ErrNeedDeletedCond
 	}
 
-	var tableName = session.engine.Quote(session.statement.TableName())
+	var tableNameNoQuote = session.statement.TableName()
+	var tableName = session.engine.Quote(tableNameNoQuote)
+	var table = session.statement.RefTable
 	var deleteSQL string
 	if len(condSQL) > 0 {
 		deleteSQL = fmt.Sprintf("DELETE FROM %v WHERE %v", tableName, condSQL)
@@ -201,10 +199,11 @@ func (session *Session) Delete(bean interface{}) (int64, error) {
 		})
 	}
 
-	if cacher := session.engine.getCacher2(session.statement.RefTable); cacher != nil && session.statement.UseCache {
-		session.cacheDelete(deleteSQL, argsForCache...)
+	if cacher := session.engine.getCacher2(table); cacher != nil && session.statement.UseCache {
+		session.cacheDelete(table, tableNameNoQuote, deleteSQL, argsForCache...)
 	}
 
+	session.statement.RefTable = table
 	res, err := session.exec(realSQL, condArgs...)
 	if err != nil {
 		return 0, err

+ 32 - 0
session_delete_test.go

@@ -137,3 +137,35 @@ func TestDeleted(t *testing.T) {
 	assert.NoError(t, err)
 	assert.EqualValues(t, 2, len(records3))
 }
+
+func TestCacheDelete(t *testing.T) {
+	assert.NoError(t, prepareEngine())
+
+	oldCacher := testEngine.Cacher
+	cacher := NewLRUCacher(NewMemoryStore(), 1000)
+	testEngine.SetDefaultCacher(cacher)
+
+	type CacheDeleteStruct struct {
+		Id int64
+	}
+
+	err := testEngine.CreateTables(&CacheDeleteStruct{})
+	assert.NoError(t, err)
+
+	_, err = testEngine.Insert(&CacheDeleteStruct{})
+	assert.NoError(t, err)
+
+	aff, err := testEngine.Delete(&CacheDeleteStruct{
+		Id: 1,
+	})
+	assert.NoError(t, err)
+	assert.EqualValues(t, aff, 1)
+
+	aff, err = testEngine.Unscoped().Delete(&CacheDeleteStruct{
+		Id: 1,
+	})
+	assert.NoError(t, err)
+	assert.EqualValues(t, aff, 0)
+
+	testEngine.SetDefaultCacher(oldCacher)
+}

+ 5 - 7
session_find.go

@@ -179,7 +179,6 @@ func (session *Session) find(rowsSlicePtr interface{}, condiBean ...interface{})
 
 	}
 	return session.noCacheFind(table, sliceValue, sqlStr, args...)
-
 }
 
 func (session *Session) noCacheFind(table *core.Table, containerValue reflect.Value, sqlStr string, args ...interface{}) error {
@@ -317,12 +316,11 @@ func (session *Session) cacheFind(t reflect.Type, sqlStr string, rowsSlicePtr in
 	}
 
 	tableName := session.statement.TableName()
-
 	table := session.statement.RefTable
 	cacher := session.engine.getCacher2(table)
 	ids, err := core.GetCacheSql(cacher, tableName, newsql, args)
 	if err != nil {
-		rows, err := session.NoCache().queryRows(newsql, args...)
+		rows, err := session.queryRows(newsql, args...)
 		if err != nil {
 			return err
 		}
@@ -352,13 +350,13 @@ func (session *Session) cacheFind(t reflect.Type, sqlStr string, rowsSlicePtr in
 			ids = append(ids, pk)
 		}
 
-		session.engine.logger.Debug("[cacheFind] cache sql:", ids, tableName, newsql, args)
+		session.engine.logger.Debug("[cacheFind] cache sql:", ids, tableName, sqlStr, newsql, args)
 		err = core.PutCacheSql(cacher, ids, tableName, newsql, args)
 		if err != nil {
 			return err
 		}
 	} else {
-		session.engine.logger.Debug("[cacheFind] cache hit sql:", newsql, args)
+		session.engine.logger.Debug("[cacheFind] cache hit sql:", tableName, sqlStr, newsql, args)
 	}
 
 	sliceValue := reflect.Indirect(reflect.ValueOf(rowsSlicePtr))
@@ -373,7 +371,7 @@ func (session *Session) cacheFind(t reflect.Type, sqlStr string, rowsSlicePtr in
 			return err
 		}
 		bean := cacher.GetBean(tableName, sid)
-		if bean == nil {
+		if bean == nil || reflect.ValueOf(bean).Elem().Type() != t {
 			ides = append(ides, id)
 			ididxes[sid] = idx
 		} else {
@@ -414,7 +412,7 @@ func (session *Session) cacheFind(t reflect.Type, sqlStr string, rowsSlicePtr in
 			}
 		}
 
-		err = session.NoCache().find(beans)
+		err = session.NoCache().Table(tableName).find(beans)
 		if err != nil {
 			return err
 		}

+ 2 - 2
session_get.go

@@ -136,8 +136,8 @@ func (session *Session) cacheGet(bean interface{}, sqlStr string, args ...interf
 	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
+	ids, err := core.GetCacheSql(cacher, tableName, newsql, args)
 	if err != nil {
 		var res = make([]string, len(table.PrimaryKeys))
 		rows, err := session.NoCache().queryRows(newsql, args...)
@@ -177,7 +177,7 @@ func (session *Session) cacheGet(bean interface{}, sqlStr string, args ...interf
 			return false, err
 		}
 	} else {
-		session.engine.logger.Debug("[cacheGet] cache hit sql:", newsql)
+		session.engine.logger.Debug("[cacheGet] cache hit sql:", newsql, ids)
 	}
 
 	if len(ids) > 0 {

+ 14 - 14
session_insert.go

@@ -213,22 +213,23 @@ func (session *Session) innerInsertMulti(rowsSlicePtr interface{}) (int64, error
 
 	var sql = "INSERT INTO %s (%v%v%v) VALUES (%v)"
 	var statement string
+	var tableName = session.statement.TableName()
 	if session.engine.dialect.DBType() == core.ORACLE {
 		sql = "INSERT ALL INTO %s (%v%v%v) VALUES (%v) SELECT 1 FROM DUAL"
 		temp := fmt.Sprintf(") INTO %s (%v%v%v) VALUES (",
-			session.engine.Quote(session.statement.TableName()),
+			session.engine.Quote(tableName),
 			session.engine.QuoteStr(),
 			strings.Join(colNames, session.engine.QuoteStr()+", "+session.engine.QuoteStr()),
 			session.engine.QuoteStr())
 		statement = fmt.Sprintf(sql,
-			session.engine.Quote(session.statement.TableName()),
+			session.engine.Quote(tableName),
 			session.engine.QuoteStr(),
 			strings.Join(colNames, session.engine.QuoteStr()+", "+session.engine.QuoteStr()),
 			session.engine.QuoteStr(),
 			strings.Join(colMultiPlaces, temp))
 	} else {
 		statement = fmt.Sprintf(sql,
-			session.engine.Quote(session.statement.TableName()),
+			session.engine.Quote(tableName),
 			session.engine.QuoteStr(),
 			strings.Join(colNames, session.engine.QuoteStr()+", "+session.engine.QuoteStr()),
 			session.engine.QuoteStr(),
@@ -240,7 +241,7 @@ func (session *Session) innerInsertMulti(rowsSlicePtr interface{}) (int64, error
 	}
 
 	if cacher := session.engine.getCacher2(table); cacher != nil && session.statement.UseCache {
-		session.cacheInsert(session.statement.TableName())
+		session.cacheInsert(table, tableName)
 	}
 
 	lenAfterClosures := len(session.afterClosures)
@@ -347,18 +348,19 @@ func (session *Session) innerInsert(bean interface{}) (int64, error) {
 	}
 
 	var sqlStr string
+	var tableName = session.statement.TableName()
 	if len(colPlaces) > 0 {
 		sqlStr = fmt.Sprintf("INSERT INTO %s (%v%v%v) VALUES (%v)",
-			session.engine.Quote(session.statement.TableName()),
+			session.engine.Quote(tableName),
 			session.engine.QuoteStr(),
 			strings.Join(colNames, session.engine.Quote(", ")),
 			session.engine.QuoteStr(),
 			colPlaces)
 	} else {
 		if session.engine.dialect.DBType() == core.MYSQL {
-			sqlStr = fmt.Sprintf("INSERT INTO %s VALUES ()", session.engine.Quote(session.statement.TableName()))
+			sqlStr = fmt.Sprintf("INSERT INTO %s VALUES ()", session.engine.Quote(tableName))
 		} else {
-			sqlStr = fmt.Sprintf("INSERT INTO %s DEFAULT VALUES", session.engine.Quote(session.statement.TableName()))
+			sqlStr = fmt.Sprintf("INSERT INTO %s DEFAULT VALUES", session.engine.Quote(tableName))
 		}
 	}
 
@@ -401,7 +403,7 @@ func (session *Session) innerInsert(bean interface{}) (int64, error) {
 		handleAfterInsertProcessorFunc(bean)
 
 		if cacher := session.engine.getCacher2(table); cacher != nil && session.statement.UseCache {
-			session.cacheInsert(session.statement.TableName())
+			session.cacheInsert(table, tableName)
 		}
 
 		if table.Version != "" && session.statement.checkVersion {
@@ -446,7 +448,7 @@ func (session *Session) innerInsert(bean interface{}) (int64, error) {
 		handleAfterInsertProcessorFunc(bean)
 
 		if cacher := session.engine.getCacher2(table); cacher != nil && session.statement.UseCache {
-			session.cacheInsert(session.statement.TableName())
+			session.cacheInsert(table, tableName)
 		}
 
 		if table.Version != "" && session.statement.checkVersion {
@@ -489,7 +491,7 @@ func (session *Session) innerInsert(bean interface{}) (int64, error) {
 		defer handleAfterInsertProcessorFunc(bean)
 
 		if cacher := session.engine.getCacher2(table); cacher != nil && session.statement.UseCache {
-			session.cacheInsert(session.statement.TableName())
+			session.cacheInsert(table, tableName)
 		}
 
 		if table.Version != "" && session.statement.checkVersion {
@@ -537,14 +539,12 @@ func (session *Session) InsertOne(bean interface{}) (int64, error) {
 	return session.innerInsert(bean)
 }
 
-func (session *Session) cacheInsert(tables ...string) error {
-	if session.statement.RefTable == nil {
+func (session *Session) cacheInsert(table *core.Table, tables ...string) error {
+	if table == nil {
 		return ErrCacheFailed
 	}
 
-	table := session.statement.RefTable
 	cacher := session.engine.getCacher2(table)
-
 	for _, t := range tables {
 		session.engine.logger.Debug("[cache] clear sql:", t)
 		cacher.ClearIds(t)

+ 3 - 3
session_insert_test.go

@@ -141,15 +141,15 @@ func TestInsertOneIfPkIsPoint(t *testing.T) {
 func TestInsertOneIfPkIsPointRename(t *testing.T) {
 	assert.NoError(t, prepareEngine())
 	type ID *int64
-	type TestPoint struct {
+	type TestPoint2 struct {
 		Id      ID         `xorm:"autoincr pk notnull 'id'"`
 		Msg     *string    `xorm:"varchar(255)"`
 		Created *time.Time `xorm:"created"`
 	}
 
-	assert.NoError(t, testEngine.Sync2(new(TestPoint)))
+	assert.NoError(t, testEngine.Sync2(new(TestPoint2)))
 	msg := "hi"
-	data := TestPoint{Msg: &msg}
+	data := TestPoint2{Msg: &msg}
 	_, err := testEngine.InsertOne(&data)
 	assert.NoError(t, err)
 }

+ 10 - 20
session_pk_test.go

@@ -764,21 +764,11 @@ func TestCompositeKey(t *testing.T) {
 		t.Error(errors.New("failed to insert CompositeKey{22, 22}"))
 	}
 
-	if testEngine.Cacher != nil {
-		testEngine.Cacher.ClearBeans(testEngine.TableInfo(compositeKeyVal).Name)
-	}
-
 	cps = make([]CompositeKey, 0)
 	err = testEngine.Find(&cps)
-	if err != nil {
-		t.Error(err)
-	}
-	if len(cps) != 2 {
-		t.Error(errors.New("should has two record"))
-	}
-	if cps[0] != compositeKeyVal {
-		t.Error(errors.New("should be equeal"))
-	}
+	assert.NoError(t, err)
+	assert.EqualValues(t, 2, len(cps), "should has two record")
+	assert.EqualValues(t, compositeKeyVal, cps[0], "should be equeal")
 
 	compositeKeyVal = CompositeKey{UpdateStr: "test1"}
 	cnt, err = testEngine.ID(core.PK{11, 22}).Update(&compositeKeyVal)
@@ -796,16 +786,16 @@ func TestCompositeKey(t *testing.T) {
 	}
 }
 
-type User struct {
-	UserId   string `xorm:"varchar(19) not null pk"`
-	NickName string `xorm:"varchar(19) not null"`
-	GameId   uint32 `xorm:"integer pk"`
-	Score    int32  `xorm:"integer"`
-}
-
 func TestCompositeKey2(t *testing.T) {
 	assert.NoError(t, prepareEngine())
 
+	type User struct {
+		UserId   string `xorm:"varchar(19) not null pk"`
+		NickName string `xorm:"varchar(19) not null"`
+		GameId   uint32 `xorm:"integer pk"`
+		Score    int32  `xorm:"integer"`
+	}
+
 	err := testEngine.DropTables(&User{})
 
 	if err != nil {

+ 4 - 4
session_query_test.go

@@ -16,7 +16,7 @@ import (
 func TestQueryString(t *testing.T) {
 	assert.NoError(t, prepareEngine())
 
-	type GetVar struct {
+	type GetVar2 struct {
 		Id      int64  `xorm:"autoincr pk"`
 		Msg     string `xorm:"varchar(255)"`
 		Age     int
@@ -24,9 +24,9 @@ func TestQueryString(t *testing.T) {
 		Created time.Time `xorm:"created"`
 	}
 
-	assert.NoError(t, testEngine.Sync2(new(GetVar)))
+	assert.NoError(t, testEngine.Sync2(new(GetVar2)))
 
-	var data = GetVar{
+	var data = GetVar2{
 		Msg:   "hi",
 		Age:   28,
 		Money: 1.5,
@@ -34,7 +34,7 @@ func TestQueryString(t *testing.T) {
 	_, err := testEngine.InsertOne(data)
 	assert.NoError(t, err)
 
-	records, err := testEngine.QueryString("select * from get_var")
+	records, err := testEngine.QueryString("select * from get_var2")
 	assert.NoError(t, err)
 	assert.Equal(t, 1, len(records))
 	assert.Equal(t, 5, len(records[0]))

+ 3 - 2
session_schema_test.go

@@ -197,8 +197,9 @@ func TestMetaInfo(t *testing.T) {
 	tables, err := testEngine.DBMetas()
 	assert.NoError(t, err)
 	assert.EqualValues(t, 2, len(tables))
-	assert.EqualValues(t, "customtablename", tables[0].Name)
-	assert.EqualValues(t, "index_or_unique", tables[1].Name)
+	tableNames := []string{tables[0].Name, tables[1].Name}
+	assert.Contains(t, tableNames, "customtablename")
+	assert.Contains(t, tableNames, "index_or_unique")
 }
 
 func TestCharst(t *testing.T) {

+ 4 - 4
session_stats_test.go

@@ -76,26 +76,26 @@ func TestSum(t *testing.T) {
 func TestSumCustomColumn(t *testing.T) {
 	assert.NoError(t, prepareEngine())
 
-	type SumStruct struct {
+	type SumStruct2 struct {
 		Int   int
 		Float float32
 	}
 
 	var (
-		cases = []SumStruct{
+		cases = []SumStruct2{
 			{1, 6.2},
 			{2, 5.3},
 			{92, -0.2},
 		}
 	)
 
-	assert.NoError(t, testEngine.Sync2(new(SumStruct)))
+	assert.NoError(t, testEngine.Sync2(new(SumStruct2)))
 
 	cnt, err := testEngine.Insert(cases)
 	assert.NoError(t, err)
 	assert.EqualValues(t, 3, cnt)
 
-	sumInt, err := testEngine.Sum(new(SumStruct),
+	sumInt, err := testEngine.Sum(new(SumStruct2),
 		"CASE WHEN `int` <= 2 THEN `int` ELSE 0 END")
 	assert.NoError(t, err)
 	assert.EqualValues(t, 3, int(sumInt))

+ 13 - 12
session_update.go

@@ -15,8 +15,8 @@ import (
 	"github.com/xormplus/core"
 )
 
-func (session *Session) cacheUpdate(sqlStr string, args ...interface{}) error {
-	if session.statement.RefTable == nil ||
+func (session *Session) cacheUpdate(table *core.Table, tableName, sqlStr string, args ...interface{}) error {
+	if table == nil ||
 		session.tx != nil {
 		return ErrCacheFailed
 	}
@@ -26,7 +26,7 @@ func (session *Session) cacheUpdate(sqlStr string, args ...interface{}) error {
 		return ErrCacheFailed
 	}
 	for _, filter := range session.engine.dialect.Filters() {
-		newsql = filter.Do(newsql, session.engine.dialect, session.statement.RefTable)
+		newsql = filter.Do(newsql, session.engine.dialect, table)
 	}
 	session.engine.logger.Debug("[cacheUpdate] new sql", oldhead, newsql)
 
@@ -39,9 +39,8 @@ func (session *Session) cacheUpdate(sqlStr string, args ...interface{}) error {
 			nStart = strings.Count(oldhead, "$")
 		}
 	}
-	table := session.statement.RefTable
+
 	cacher := session.engine.getCacher2(table)
-	tableName := session.statement.TableName()
 	session.engine.logger.Debug("[cacheUpdate] get cache sql", newsql, args[nStart:])
 	ids, err := core.GetCacheSql(cacher, tableName, newsql, args[nStart:])
 	if err != nil {
@@ -280,6 +279,7 @@ func (session *Session) Update(bean interface{}, condiBean ...interface{}) (int6
 		condSQL = condSQL + fmt.Sprintf(" ORDER BY %v", st.OrderStr)
 	}
 
+	var tableName = session.statement.TableName()
 	// TODO: Oracle support needed
 	var top string
 	if st.LimitN > 0 {
@@ -288,7 +288,7 @@ func (session *Session) Update(bean interface{}, condiBean ...interface{}) (int6
 		} else if st.Engine.dialect.DBType() == core.SQLITE {
 			tempCondSQL := condSQL + fmt.Sprintf(" LIMIT %d", st.LimitN)
 			cond = cond.And(builder.Expr(fmt.Sprintf("rowid IN (SELECT rowid FROM %v %v)",
-				session.engine.Quote(session.statement.TableName()), tempCondSQL), condArgs...))
+				session.engine.Quote(tableName), tempCondSQL), condArgs...))
 			condSQL, condArgs, err = builder.ToSQL(cond)
 			if err != nil {
 				return 0, err
@@ -299,7 +299,7 @@ func (session *Session) Update(bean interface{}, condiBean ...interface{}) (int6
 		} else if st.Engine.dialect.DBType() == core.POSTGRES {
 			tempCondSQL := condSQL + fmt.Sprintf(" LIMIT %d", st.LimitN)
 			cond = cond.And(builder.Expr(fmt.Sprintf("CTID IN (SELECT CTID FROM %v %v)",
-				session.engine.Quote(session.statement.TableName()), tempCondSQL), condArgs...))
+				session.engine.Quote(tableName), tempCondSQL), condArgs...))
 			condSQL, condArgs, err = builder.ToSQL(cond)
 			if err != nil {
 				return 0, err
@@ -313,7 +313,7 @@ func (session *Session) Update(bean interface{}, condiBean ...interface{}) (int6
 				table != nil && len(table.PrimaryKeys) == 1 {
 				cond = builder.Expr(fmt.Sprintf("%s IN (SELECT TOP (%d) %s FROM %v%v)",
 					table.PrimaryKeys[0], st.LimitN, table.PrimaryKeys[0],
-					session.engine.Quote(session.statement.TableName()), condSQL), condArgs...)
+					session.engine.Quote(tableName), condSQL), condArgs...)
 
 				condSQL, condArgs, err = builder.ToSQL(cond)
 				if err != nil {
@@ -334,7 +334,7 @@ func (session *Session) Update(bean interface{}, condiBean ...interface{}) (int6
 
 	sqlStr = fmt.Sprintf("UPDATE %v%v SET %v %v",
 		top,
-		session.engine.Quote(session.statement.TableName()),
+		session.engine.Quote(tableName),
 		strings.Join(colNames, ", "),
 		condSQL)
 
@@ -349,8 +349,9 @@ func (session *Session) Update(bean interface{}, condiBean ...interface{}) (int6
 
 	if table != nil {
 		if cacher := session.engine.getCacher2(table); cacher != nil && session.statement.UseCache {
-			cacher.ClearIds(session.statement.TableName())
-			cacher.ClearBeans(session.statement.TableName())
+			//session.cacheUpdate(table, tableName, sqlStr, args...)
+			cacher.ClearIds(tableName)
+			cacher.ClearBeans(tableName)
 		}
 	}
 
@@ -360,7 +361,7 @@ func (session *Session) Update(bean interface{}, condiBean ...interface{}) (int6
 			closure(bean)
 		}
 		if processor, ok := interface{}(bean).(AfterUpdateProcessor); ok {
-			session.engine.logger.Debug("[event]", session.statement.TableName(), " has after update processor")
+			session.engine.logger.Debug("[event]", tableName, " has after update processor")
 			processor.AfterUpdate()
 		}
 	} else {

+ 5 - 5
session_update_test.go

@@ -43,14 +43,14 @@ func TestUpdateMap(t *testing.T) {
 func TestUpdateLimit(t *testing.T) {
 	assert.NoError(t, prepareEngine())
 
-	type UpdateTable struct {
+	type UpdateTable2 struct {
 		Id   int64
 		Name string
 		Age  int
 	}
 
-	assert.NoError(t, testEngine.Sync2(new(UpdateTable)))
-	var tb = UpdateTable{
+	assert.NoError(t, testEngine.Sync2(new(UpdateTable2)))
+	var tb = UpdateTable2{
 		Name: "test1",
 		Age:  35,
 	}
@@ -64,13 +64,13 @@ func TestUpdateLimit(t *testing.T) {
 	assert.NoError(t, err)
 	assert.EqualValues(t, 1, cnt)
 
-	cnt, err = testEngine.OrderBy("name desc").Limit(1).Update(&UpdateTable{
+	cnt, err = testEngine.OrderBy("name desc").Limit(1).Update(&UpdateTable2{
 		Age: 30,
 	})
 	assert.NoError(t, err)
 	assert.EqualValues(t, 1, cnt)
 
-	var uts []UpdateTable
+	var uts []UpdateTable2
 	err = testEngine.Find(&uts)
 	assert.NoError(t, err)
 	assert.EqualValues(t, 2, len(uts))

+ 2 - 1
statement.go

@@ -1205,7 +1205,8 @@ func (statement *Statement) convertIDSQL(sqlStr string) string {
 			top = fmt.Sprintf("TOP %d ", statement.LimitN)
 		}
 
-		return fmt.Sprintf("SELECT %s%s FROM %v", top, colstrs, sqls[1])
+		newsql := fmt.Sprintf("SELECT %s%s FROM %v", top, colstrs, sqls[1])
+		return newsql
 	}
 	return ""
 }

+ 32 - 32
time_test.go

@@ -52,14 +52,14 @@ func TestTimeUserTimeDiffLoc(t *testing.T) {
 	assert.NoError(t, err)
 	testEngine.DatabaseTZ = dbLoc
 
-	type TimeUser struct {
+	type TimeUser2 struct {
 		Id       string
 		OperTime time.Time
 	}
 
-	assertSync(t, new(TimeUser))
+	assertSync(t, new(TimeUser2))
 
-	var user = TimeUser{
+	var user = TimeUser2{
 		Id:       "lunny",
 		OperTime: time.Now(),
 	}
@@ -70,7 +70,7 @@ func TestTimeUserTimeDiffLoc(t *testing.T) {
 	assert.NoError(t, err)
 	assert.EqualValues(t, 1, cnt)
 
-	var user2 TimeUser
+	var user2 TimeUser2
 	has, err := testEngine.Get(&user2)
 	assert.NoError(t, err)
 	assert.True(t, has)
@@ -117,14 +117,14 @@ func TestTimeUserCreatedDiffLoc(t *testing.T) {
 	assert.NoError(t, err)
 	testEngine.DatabaseTZ = dbLoc
 
-	type UserCreated struct {
+	type UserCreated2 struct {
 		Id        string
 		CreatedAt time.Time `xorm:"created"`
 	}
 
-	assertSync(t, new(UserCreated))
+	assertSync(t, new(UserCreated2))
 
-	var user = UserCreated{
+	var user = UserCreated2{
 		Id: "lunny",
 	}
 
@@ -134,7 +134,7 @@ func TestTimeUserCreatedDiffLoc(t *testing.T) {
 	assert.NoError(t, err)
 	assert.EqualValues(t, 1, cnt)
 
-	var user2 UserCreated
+	var user2 UserCreated2
 	has, err := testEngine.Get(&user2)
 	assert.NoError(t, err)
 	assert.True(t, has)
@@ -203,15 +203,15 @@ func TestTimeUserUpdatedDiffLoc(t *testing.T) {
 	assert.NoError(t, err)
 	testEngine.DatabaseTZ = dbLoc
 
-	type UserUpdated struct {
+	type UserUpdated2 struct {
 		Id        string
 		CreatedAt time.Time `xorm:"created"`
 		UpdatedAt time.Time `xorm:"updated"`
 	}
 
-	assertSync(t, new(UserUpdated))
+	assertSync(t, new(UserUpdated2))
 
-	var user = UserUpdated{
+	var user = UserUpdated2{
 		Id: "lunny",
 	}
 
@@ -221,7 +221,7 @@ func TestTimeUserUpdatedDiffLoc(t *testing.T) {
 	assert.NoError(t, err)
 	assert.EqualValues(t, 1, cnt)
 
-	var user2 UserUpdated
+	var user2 UserUpdated2
 	has, err := testEngine.Get(&user2)
 	assert.NoError(t, err)
 	assert.True(t, has)
@@ -231,7 +231,7 @@ func TestTimeUserUpdatedDiffLoc(t *testing.T) {
 	assert.EqualValues(t, formatTime(user.UpdatedAt), formatTime(user2.UpdatedAt))
 	fmt.Println("user2", user2.CreatedAt, user2.UpdatedAt)
 
-	var user3 = UserUpdated{
+	var user3 = UserUpdated2{
 		Id: "lunny2",
 	}
 
@@ -240,7 +240,7 @@ func TestTimeUserUpdatedDiffLoc(t *testing.T) {
 	assert.EqualValues(t, 1, cnt)
 	assert.True(t, user.UpdatedAt.Unix() <= user3.UpdatedAt.Unix())
 
-	var user4 UserUpdated
+	var user4 UserUpdated2
 	has, err = testEngine.Get(&user4)
 	assert.NoError(t, err)
 	assert.True(t, has)
@@ -307,16 +307,16 @@ func TestTimeUserDeletedDiffLoc(t *testing.T) {
 	assert.NoError(t, err)
 	testEngine.DatabaseTZ = dbLoc
 
-	type UserDeleted struct {
+	type UserDeleted2 struct {
 		Id        string
 		CreatedAt time.Time `xorm:"created"`
 		UpdatedAt time.Time `xorm:"updated"`
 		DeletedAt time.Time `xorm:"deleted"`
 	}
 
-	assertSync(t, new(UserDeleted))
+	assertSync(t, new(UserDeleted2))
 
-	var user = UserDeleted{
+	var user = UserDeleted2{
 		Id: "lunny",
 	}
 
@@ -325,7 +325,7 @@ func TestTimeUserDeletedDiffLoc(t *testing.T) {
 	assert.EqualValues(t, 1, cnt)
 	fmt.Println("user", user.CreatedAt, user.UpdatedAt, user.DeletedAt)
 
-	var user2 UserDeleted
+	var user2 UserDeleted2
 	has, err := testEngine.Get(&user2)
 	assert.NoError(t, err)
 	assert.True(t, has)
@@ -336,13 +336,13 @@ func TestTimeUserDeletedDiffLoc(t *testing.T) {
 	assert.True(t, isTimeZero(user2.DeletedAt))
 	fmt.Println("user2", user2.CreatedAt, user2.UpdatedAt, user2.DeletedAt)
 
-	var user3 UserDeleted
+	var user3 UserDeleted2
 	cnt, err = testEngine.Where("id = ?", "lunny").Delete(&user3)
 	assert.NoError(t, err)
 	assert.EqualValues(t, 1, cnt)
 	assert.True(t, !isTimeZero(user3.DeletedAt))
 
-	var user4 UserDeleted
+	var user4 UserDeleted2
 	has, err = testEngine.Unscoped().Get(&user4)
 	assert.NoError(t, err)
 	assert.True(t, has)
@@ -378,16 +378,16 @@ func (j *JsonDate) Unix() int64 {
 func TestCustomTimeUserDeleted(t *testing.T) {
 	assert.NoError(t, prepareEngine())
 
-	type UserDeleted struct {
+	type UserDeleted3 struct {
 		Id        string
 		CreatedAt JsonDate `xorm:"created"`
 		UpdatedAt JsonDate `xorm:"updated"`
 		DeletedAt JsonDate `xorm:"deleted"`
 	}
 
-	assertSync(t, new(UserDeleted))
+	assertSync(t, new(UserDeleted3))
 
-	var user = UserDeleted{
+	var user = UserDeleted3{
 		Id: "lunny",
 	}
 
@@ -396,7 +396,7 @@ func TestCustomTimeUserDeleted(t *testing.T) {
 	assert.EqualValues(t, 1, cnt)
 	fmt.Println("user", user.CreatedAt, user.UpdatedAt, user.DeletedAt)
 
-	var user2 UserDeleted
+	var user2 UserDeleted3
 	has, err := testEngine.Get(&user2)
 	assert.NoError(t, err)
 	assert.True(t, has)
@@ -407,13 +407,13 @@ func TestCustomTimeUserDeleted(t *testing.T) {
 	assert.True(t, isTimeZero(time.Time(user2.DeletedAt)))
 	fmt.Println("user2", user2.CreatedAt, user2.UpdatedAt, user2.DeletedAt)
 
-	var user3 UserDeleted
+	var user3 UserDeleted3
 	cnt, err = testEngine.Where("id = ?", "lunny").Delete(&user3)
 	assert.NoError(t, err)
 	assert.EqualValues(t, 1, cnt)
 	assert.True(t, !isTimeZero(time.Time(user3.DeletedAt)))
 
-	var user4 UserDeleted
+	var user4 UserDeleted3
 	has, err = testEngine.Unscoped().Get(&user4)
 	assert.NoError(t, err)
 	assert.True(t, has)
@@ -431,16 +431,16 @@ func TestCustomTimeUserDeletedDiffLoc(t *testing.T) {
 	assert.NoError(t, err)
 	testEngine.DatabaseTZ = dbLoc
 
-	type UserDeleted struct {
+	type UserDeleted4 struct {
 		Id        string
 		CreatedAt JsonDate `xorm:"created"`
 		UpdatedAt JsonDate `xorm:"updated"`
 		DeletedAt JsonDate `xorm:"deleted"`
 	}
 
-	assertSync(t, new(UserDeleted))
+	assertSync(t, new(UserDeleted4))
 
-	var user = UserDeleted{
+	var user = UserDeleted4{
 		Id: "lunny",
 	}
 
@@ -449,7 +449,7 @@ func TestCustomTimeUserDeletedDiffLoc(t *testing.T) {
 	assert.EqualValues(t, 1, cnt)
 	fmt.Println("user", user.CreatedAt, user.UpdatedAt, user.DeletedAt)
 
-	var user2 UserDeleted
+	var user2 UserDeleted4
 	has, err := testEngine.Get(&user2)
 	assert.NoError(t, err)
 	assert.True(t, has)
@@ -460,13 +460,13 @@ func TestCustomTimeUserDeletedDiffLoc(t *testing.T) {
 	assert.True(t, isTimeZero(time.Time(user2.DeletedAt)))
 	fmt.Println("user2", user2.CreatedAt, user2.UpdatedAt, user2.DeletedAt)
 
-	var user3 UserDeleted
+	var user3 UserDeleted4
 	cnt, err = testEngine.Where("id = ?", "lunny").Delete(&user3)
 	assert.NoError(t, err)
 	assert.EqualValues(t, 1, cnt)
 	assert.True(t, !isTimeZero(time.Time(user3.DeletedAt)))
 
-	var user4 UserDeleted
+	var user4 UserDeleted4
 	has, err = testEngine.Unscoped().Get(&user4)
 	assert.NoError(t, err)
 	assert.True(t, has)

+ 15 - 0
xorm_test.go

@@ -37,6 +37,21 @@ func createEngine(dbType, connStr string) error {
 
 		testEngine.ShowSQL(*showSQL)
 		testEngine.logger.SetLevel(core.LOG_DEBUG)
+		if *cache {
+			cacher := NewLRUCacher(NewMemoryStore(), 100000)
+			testEngine.SetDefaultCacher(cacher)
+		}
+
+		if len(*mapType) > 0 {
+			switch *mapType {
+			case "snake":
+				testEngine.SetMapper(core.SnakeMapper{})
+			case "same":
+				testEngine.SetMapper(core.SameMapper{})
+			case "gonic":
+				testEngine.SetMapper(core.LintGonicMapper)
+			}
+		}
 	}
 
 	tables, err := testEngine.DBMetas()