cache bug fixed

This commit is contained in:
Lunny Xiao 2013-09-25 01:31:25 +08:00
parent 22ddfa9f77
commit 9d676ebddd
4 changed files with 63 additions and 37 deletions

View File

@ -170,6 +170,14 @@ type User struct {
- 3.支持`type MyString string`等自定义的field支持Slice, Map等field成员这些成员默认存储为Text类型并且默认将使用Json格式来序列化和反序列化。也支持数据库字段类型为Blob类型如果是Blob类型则先使用Jsong格式序列化再转成[]byte格式。当然[]byte或者[]uint8默认为Blob类型并且都已二进制方式存储。 - 3.支持`type MyString string`等自定义的field支持Slice, Map等field成员这些成员默认存储为Text类型并且默认将使用Json格式来序列化和反序列化。也支持数据库字段类型为Blob类型如果是Blob类型则先使用Jsong格式序列化再转成[]byte格式。当然[]byte或者[]uint8默认为Blob类型并且都已二进制方式存储。
- 4.实现了Conversion接口的类型或者结构体将根据接口的转换方式在类型和数据库记录之间进行相互转换。
```Go
type Conversion interface {
FromDB([]byte) error
ToDB() ([]byte, error)
}
```
<a name="30" id="30"></a> <a name="30" id="30"></a>
## 3.创建表 ## 3.创建表

View File

@ -7,6 +7,7 @@ xorm是一个简单而强大的Go语言ORM库. 通过它可以使数据库操作
[![Build Status](https://drone.io/github.com/lunny/xorm/status.png)](https://drone.io/github.com/lunny/xorm/latest) [![Build Status](https://drone.io/github.com/lunny/xorm/status.png)](https://drone.io/github.com/lunny/xorm/latest)
## 讨论 ## 讨论
请加入QQ群280360085 进行讨论。 请加入QQ群280360085 进行讨论。
## 驱动支持 ## 驱动支持
@ -48,21 +49,22 @@ xorm是一个简单而强大的Go语言ORM库. 通过它可以使数据库操作
* 支持数据库连接池 * 支持数据库连接池
* 支持级联加载struct * 支持级联加载struct
## 安装 ## 安装
go get github.com/lunny/xorm go get github.com/lunny/xorm
## 快速开始
请访问 [快速开始](https://github.com/lunny/xorm/blob/master/QuickStart.md) 查看详细文档
## 文档 ## 文档
* [快速开始](https://github.com/lunny/xorm/blob/master/QuickStart.md)
请访问 [GoWalker](http://gowalker.org/github.com/lunny/xorm) 查看详细文档 * [GoWalker代码文档](http://gowalker.org/github.com/lunny/xorm)
## 案例
* [Godaily.org](http://godaily.org)
## FAQ ## FAQ
@ -75,6 +77,8 @@ type User struct {
Name string `json:"name" xorm:"name"` Name string `json:"name" xorm:"name"`
} }
``` ```
2.问xorm有几种命名映射规则
答案目前支持SnakeMapper和SameMapper两种。SnakeMapper支持结构体和成员以驼峰式命名而数据库表和字段以下划线连接命名SameMapper支持结构体和数据库的命名保持一致的映射。
## LICENSE ## LICENSE

View File

@ -18,7 +18,7 @@ type CacheStore interface {
type MemoryStore struct { type MemoryStore struct {
store map[interface{}]interface{} store map[interface{}]interface{}
mutex sync.Mutex mutex sync.RWMutex
} }
func NewMemoryStore() *MemoryStore { func NewMemoryStore() *MemoryStore {
@ -34,8 +34,8 @@ func (s *MemoryStore) Put(key, value interface{}) error {
} }
func (s *MemoryStore) Get(key interface{}) (interface{}, error) { func (s *MemoryStore) Get(key interface{}) (interface{}, error) {
s.mutex.Lock() s.mutex.Rlock()
defer s.mutex.Unlock() defer s.mutex.UnRlock()
//fmt.Println("before get store:", s.store) //fmt.Println("before get store:", s.store)
if v, ok := s.store[key]; ok { if v, ok := s.store[key]; ok {
return v, nil return v, nil

View File

@ -392,13 +392,14 @@ func (session *Session) cacheGet(bean interface{}, sql string, args ...interface
cacher := session.Statement.RefTable.Cacher cacher := session.Statement.RefTable.Cacher
tableName := session.Statement.TableName() tableName := session.Statement.TableName()
session.Engine.LogDebug("[xorm:cacheGet] find sql:", newsql, args)
ids, err := getCacheSql(cacher, tableName, newsql, args) ids, err := getCacheSql(cacher, tableName, newsql, args)
if err != nil { if err != nil {
resultsSlice, err := session.query(newsql, args...) resultsSlice, err := session.query(newsql, args...)
if err != nil { if err != nil {
return false, err return false, err
} }
session.Engine.LogDebug("[xorm:cacheGet] query ids:", resultsSlice)
ids = make([]int64, 0) ids = make([]int64, 0)
if len(resultsSlice) > 0 { if len(resultsSlice) > 0 {
data := resultsSlice[0] data := resultsSlice[0]
@ -413,19 +414,19 @@ func (session *Session) cacheGet(bean interface{}, sql string, args ...interface
} }
ids = append(ids, id) ids = append(ids, id)
} }
session.Engine.LogDebug("[xorm:cache] cache ids:", newsql, ids) session.Engine.LogDebug("[xorm:cacheGet] cache ids:", newsql, ids)
err = putCacheSql(cacher, ids, tableName, newsql, args) err = putCacheSql(cacher, ids, tableName, newsql, args)
if err != nil { if err != nil {
return false, err return false, err
} }
} else { } else {
session.Engine.LogDebug("[xorm:cache] cached sql:", newsql) session.Engine.LogDebug("[xorm:cacheGet] cached sql:", newsql)
} }
if len(ids) > 0 { if len(ids) > 0 {
structValue := reflect.Indirect(reflect.ValueOf(bean)) structValue := reflect.Indirect(reflect.ValueOf(bean))
id := ids[0] id := ids[0]
session.Engine.LogDebug("[xorm:cacheGet] get bean:", tableName, id)
cacheBean := cacher.GetBean(tableName, id) cacheBean := cacher.GetBean(tableName, id)
if cacheBean == nil { if cacheBean == nil {
newSession := session.Engine.NewSession() newSession := session.Engine.NewSession()
@ -436,10 +437,10 @@ func (session *Session) cacheGet(bean interface{}, sql string, args ...interface
return has, err return has, err
} }
session.Engine.LogDebug("[xorm:cache] cache bean:", tableName, id, cacheBean) session.Engine.LogDebug("[xorm:cacheGet] cache bean:", tableName, id, cacheBean)
cacher.PutBean(tableName, id, cacheBean) cacher.PutBean(tableName, id, cacheBean)
} else { } else {
session.Engine.LogDebug("[xorm:cache] cached bean:", tableName, id, cacheBean) session.Engine.LogDebug("[xorm:cacheGet] cached bean:", tableName, id, cacheBean)
has = true has = true
} }
structValue.Set(reflect.Indirect(reflect.ValueOf(cacheBean))) structValue.Set(reflect.Indirect(reflect.ValueOf(cacheBean)))
@ -474,7 +475,7 @@ func (session *Session) cacheFind(t reflect.Type, sql string, rowsSlicePtr inter
} }
// 查询数目太大,采用缓存将不是一个很好的方式。 // 查询数目太大,采用缓存将不是一个很好的方式。
if len(resultsSlice) > 100 { if len(resultsSlice) > 100 {
session.Engine.LogDebug("[xorm:cache] ids > 100, no cache") session.Engine.LogDebug("[xorm:cacheFind] ids > 100, no cache")
return ErrCacheFailed return ErrCacheFailed
} }
@ -495,13 +496,13 @@ func (session *Session) cacheFind(t reflect.Type, sql string, rowsSlicePtr inter
ids = append(ids, id) ids = append(ids, id)
} }
} }
session.Engine.LogDebug("[xorm:cache] cache ids:", ids, tableName, newsql, args) session.Engine.LogDebug("[xorm:cacheFind] cache ids:", ids, tableName, newsql, args)
err = putCacheSql(cacher, ids, tableName, newsql, args) err = putCacheSql(cacher, ids, tableName, newsql, args)
if err != nil { if err != nil {
return err return err
} }
} else { } else {
session.Engine.LogDebug("[xorm:cache] cached sql:", newsql, args) session.Engine.LogDebug("[xorm:cacheFind] cached sql:", newsql, args)
} }
sliceValue := reflect.Indirect(reflect.ValueOf(rowsSlicePtr)) sliceValue := reflect.Indirect(reflect.ValueOf(rowsSlicePtr))
@ -515,7 +516,7 @@ func (session *Session) cacheFind(t reflect.Type, sql string, rowsSlicePtr inter
idxes = append(idxes, idx) idxes = append(idxes, idx)
ides = append(ides, id) ides = append(ides, id)
} else { } else {
session.Engine.LogDebug("[xorm:cache] cached bean:", tableName, id, bean) session.Engine.LogDebug("[xorm:cacheFind] cached bean:", tableName, id, bean)
temps[idx] = bean temps[idx] = bean
} }
} }
@ -534,7 +535,7 @@ func (session *Session) cacheFind(t reflect.Type, sql string, rowsSlicePtr inter
for i := 0; i < vs.Len(); i++ { for i := 0; i < vs.Len(); i++ {
bean := vs.Index(i).Addr().Interface() bean := vs.Index(i).Addr().Interface()
temps[idxes[i]] = bean temps[idxes[i]] = bean
session.Engine.LogDebug("[xorm:cache] cache bean:", tableName, ides[i], bean) session.Engine.LogDebug("[xorm:cacheFind] cache bean:", tableName, ides[i], bean)
cacher.PutBean(tableName, ides[i].(int64), bean) cacher.PutBean(tableName, ides[i].(int64), bean)
} }
} }
@ -544,13 +545,11 @@ func (session *Session) cacheFind(t reflect.Type, sql string, rowsSlicePtr inter
if bean != nil { if bean != nil {
sliceValue.Set(reflect.Append(sliceValue, reflect.Indirect(reflect.ValueOf(bean)))) sliceValue.Set(reflect.Append(sliceValue, reflect.Indirect(reflect.ValueOf(bean))))
} else { } else {
session.Engine.LogDebug("[xorm:cache] cache delete:", tableName, ides[j]) session.Engine.LogDebug("[xorm:cacheFind] cache delete:", tableName, ides[j])
cacher.DelBean(tableName, ids[j]) cacher.DelBean(tableName, ids[j])
session.Engine.LogDebug("[xorm:cache] cache clear:", tableName) session.Engine.LogDebug("[xorm:cacheFind] cache clear:", tableName)
fmt.Println(cacher)
cacher.ClearIds(tableName) cacher.ClearIds(tableName)
fmt.Println(cacher)
} }
} }
@ -595,10 +594,7 @@ func (session *Session) Get(bean interface{}) (bool, error) {
return false, nil return false, nil
} }
results := resultsSlice[0] err = session.scanMapIntoStruct(bean, resultsSlice[0])
err = session.scanMapIntoStruct(bean, results)
if err != nil { if err != nil {
return true, err return true, err
} }
@ -1311,14 +1307,26 @@ func (statement *Statement) convertUpdateSql(sql string) (string, string) {
if statement.RefTable == nil || statement.RefTable.PrimaryKey == "" { if statement.RefTable == nil || statement.RefTable.PrimaryKey == "" {
return "", "" return "", ""
} }
sqls := strings.SplitN(strings.ToLower(sql), "where", 2) idx := strings.Index(strings.ToLower(sql), "where")
sqls := strings.SplitN(sql, sql[idx:idx+5], 2)
if len(sqls) != 2 { if len(sqls) != 2 {
return "", "" return "", ""
} }
var whereStr = sqls[1]
//TODO: for postgres only, if any other database?
if strings.Contains(sqls[1], "$") {
dollers := strings.Split(sqls[1], "$")
whereStr = dollers[0]
for i, c := range dollers[1:] {
ccs := strings.SplitN(c, " ", 2)
whereStr += fmt.Sprintf("$%v %v", i+1, ccs[1])
}
}
return sqls[0], fmt.Sprintf("SELECT %v FROM %v WHERE %v", return sqls[0], fmt.Sprintf("SELECT %v FROM %v WHERE %v",
statement.Engine.Quote(statement.RefTable.PrimaryKey), statement.Engine.Quote(statement.TableName()), statement.Engine.Quote(statement.RefTable.PrimaryKey), statement.Engine.Quote(statement.TableName()),
sqls[1]) whereStr)
} }
func (session *Session) cacheInsert(tables ...string) error { func (session *Session) cacheInsert(tables ...string) error {
@ -1342,14 +1350,14 @@ func (session *Session) cacheUpdate(sql string, args ...interface{}) error {
return ErrCacheFailed return ErrCacheFailed
} }
for _, filter := range session.Engine.Filters {
sql = filter.Do(sql, session)
}
oldhead, newsql := session.Statement.convertUpdateSql(sql) oldhead, newsql := session.Statement.convertUpdateSql(sql)
if newsql == "" { if newsql == "" {
return ErrCacheFailed return ErrCacheFailed
} }
for _, filter := range session.Engine.Filters {
newsql = filter.Do(newsql, session)
}
session.Engine.LogDebug("[xorm:cacheUpdate] new sql", oldhead, newsql)
var nStart int var nStart int
if len(args) > 0 { if len(args) > 0 {
@ -1363,12 +1371,15 @@ func (session *Session) cacheUpdate(sql string, args ...interface{}) error {
table := session.Statement.RefTable table := session.Statement.RefTable
cacher := table.Cacher cacher := table.Cacher
tableName := session.Statement.TableName() tableName := session.Statement.TableName()
ids, err := getCacheSql(cacher, tableName, newsql, args) session.Engine.LogDebug("[xorm:cacheUpdate] get cache sql", newsql, args[nStart:])
ids, err := getCacheSql(cacher, tableName, newsql, args[nStart:])
if err != nil { if err != nil {
resultsSlice, err := session.query(newsql, args[nStart:]...) resultsSlice, err := session.query(newsql, args[nStart:]...)
if err != nil { if err != nil {
return err return err
} }
session.Engine.LogDebug("[xorm:cacheUpdate] find updated id", resultsSlice)
ids = make([]int64, 0) ids = make([]int64, 0)
if len(resultsSlice) > 0 { if len(resultsSlice) > 0 {
for _, data := range resultsSlice { for _, data := range resultsSlice {
@ -1385,7 +1396,7 @@ func (session *Session) cacheUpdate(sql string, args ...interface{}) error {
} }
} }
} else { } else {
session.Engine.LogDebug("[xorm:cache] del cached sql:", tableName, newsql, args) session.Engine.LogDebug("[xorm:cacheUpdate] del cached sql:", tableName, newsql, args)
cacher.DelIds(tableName, genSqlKey(newsql, args)) cacher.DelIds(tableName, genSqlKey(newsql, args))
} }
@ -1410,13 +1421,16 @@ func (session *Session) cacheUpdate(sql string, args ...interface{}) error {
colName = strings.TrimSpace(strings.Replace(colName, session.Engine.QuoteStr(), "", -1)) colName = strings.TrimSpace(strings.Replace(colName, session.Engine.QuoteStr(), "", -1))
} }
//fmt.Println("find", colName) //fmt.Println("find", colName)
if col, ok := table.Columns[colName]; ok { if col, ok := table.Columns[colName]; ok {
fieldValue := col.ValueOf(bean) fieldValue := col.ValueOf(bean)
session.Engine.LogDebug("[xorm:cacheUpdate] set bean field", bean, colName, fieldValue.Interface())
//session.bytes2Value(col, fieldValue, []byte(args[idx])) //session.bytes2Value(col, fieldValue, []byte(args[idx]))
fieldValue.Set(reflect.ValueOf(args[idx])) fieldValue.Set(reflect.ValueOf(args[idx]))
} }
} }
session.Engine.LogDebug("[xorm:cacheUpdate] update cache", tableName, id, bean)
cacher.PutBean(tableName, id, bean) cacher.PutBean(tableName, id, bean)
} }
} }