fixed delete bug #12

This commit is contained in:
Lunny Xiao 2013-11-21 01:26:07 +08:00
parent de06e54874
commit e5c421d6ff
7 changed files with 188 additions and 33 deletions

2
.gitignore vendored
View File

@ -22,3 +22,5 @@ _testmain.go
*.exe
vendor
*.log

View File

@ -339,16 +339,25 @@ func testdelete(engine *Engine, t *testing.T) {
panic(err)
}
_, err = engine.Id(2).Get(&user)
user.Uid = 0
has, err := engine.Id(3).Get(&user)
if err != nil {
t.Error(err)
panic(err)
}
_, err = engine.Delete(&user)
if err != nil {
t.Error(err)
panic(err)
if has {
//var tt time.Time
//user.Created = tt
cnt, err := engine.UseBool().Delete(&user)
if err != nil {
t.Error(err)
panic(err)
}
if cnt != 1 {
t.Error(errors.New("delete failed"))
panic(err)
}
}
}
@ -937,8 +946,8 @@ type allCols struct {
Text string `xorm:"TEXT"`
MediumText string `xorm:"MEDIUMTEXT"`
LongText string `xorm:"LONGTEXT"`
Binary string `xorm:"BINARY"`
VarBinary string `xorm:"VARBINARY(12)"`
Binary []byte `xorm:"BINARY(23)"`
VarBinary []byte `xorm:"VARBINARY(12)"`
Date time.Time `xorm:"DATE"`
DateTime time.Time `xorm:"DATETIME"`
@ -976,6 +985,79 @@ func testColTypes(engine *Engine, t *testing.T) {
t.Error(err)
panic(err)
}
ac := &allCols{
1,
4,
8,
16,
32,
64,
128,
"123",
"fafdafa",
"fafafafdsafdsafdaf",
"fdsafafdsafdsaf",
"fafdsafdsafdsfadasfsfafd",
"fadfdsafdsafasfdasfds",
[]byte("fdafsafdasfdsafsa"),
[]byte("fdsafsdafs"),
time.Now(),
time.Now(),
time.Now(),
time.Now(),
1.34,
2.44302346,
1.3344,
2.59693523,
3.2342523543,
[]byte("fafdasf"),
[]byte("fafdfdsafdsafasf"),
[]byte("faffadsfdsdasf"),
[]byte("faffdasfdsadasf"),
[]byte("fafasdfsadffdasf"),
true,
21,
}
_, err = engine.Insert(ac)
if err != nil {
t.Error(err)
panic(err)
}
newAc := &allCols{}
has, err := engine.Get(newAc)
if err != nil {
t.Error(err)
panic(err)
}
if !has {
err = errors.New("error no ideas")
t.Error(err)
panic(err)
}
// don't use this type as query condition
newAc.Real = 0
newAc.Float = 0
newAc.Double = 0
cnt, err := engine.Delete(newAc)
if err != nil {
t.Error(err)
panic(err)
}
if cnt != 1 {
err = errors.New("delete error")
t.Error(err)
panic(err)
}
}
type MyInt int
@ -1068,6 +1150,18 @@ func testCustomType(engine *Engine, t *testing.T) {
panic(err)
}
fmt.Println(sss)
if has {
cnt, err := engine.Delete(&sss)
if err != nil {
t.Error(err)
panic(err)
}
if cnt != 1 {
t.Error(errors.New("delete error"))
panic(err)
}
}
}
type UserCU struct {

View File

@ -136,6 +136,8 @@ 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
@ -149,10 +151,12 @@ func (m *LRUCacher) GC() {
m.delBean(node.tbName, node.id)
e = next
} else {
//fmt.Printf("removing %d cache nodes ..., left %d\n", removedNum, m.idList.Len())
break
}
}
removedNum = 0
for e := m.sqlList.Front(); e != nil; {
if removedNum <= CacheGcMaxRemoved &&
time.Now().Sub(e.Value.(*sqlNode).lastVisit) > m.Expired {
@ -160,9 +164,10 @@ func (m *LRUCacher) GC() {
next := e.Next()
//fmt.Println("removing ...", e.Value)
node := e.Value.(*sqlNode)
m.DelIds(node.tbName, node.sql)
m.delIds(node.tbName, node.sql)
e = next
} else {
//fmt.Printf("removing %d cache nodes ..., left %d\n", removedNum, m.sqlList.Len())
break
}
}
@ -322,8 +327,8 @@ func (m *LRUCacher) DelIds(tableName, sql string) {
func (m *LRUCacher) delBean(tableName string, id int64) {
tid := genId(tableName, id)
if el, ok := m.idIndex[tableName][tid]; ok {
delete(m.idIndex[tableName], tid)
if el, ok := m.idIndex[tableName][id]; ok {
delete(m.idIndex[tableName], id)
m.idList.Remove(el)
m.clearIds(tableName)
}

View File

@ -506,13 +506,14 @@ engine.ClearCache(new(User))
<a name="140" id="140"></a>
## 14.案例
* [Gowalker](http://gowalker.org),源代码 [github.com/Unknwon/gowalker](http://github.com/Unknwon/gowalker)
* [GoDaily Go语言学习网站](http://godaily.org),源代码 [github.com/govc/godaily](http://github.com/govc/godaily)
* [Sudochina](http://sudochina.com) 和对应的源代码[github.com/insionng/toropress](http://github.com/insionng/toropress)
* [VeryHour](http://veryhour.com)
<a name="150" id="150"></a>
## 15.讨论
请加入QQ群280360085 进行讨论。

View File

@ -575,8 +575,8 @@ func (session *Session) cacheFind(t reflect.Type, sql string, rowsSlicePtr inter
return err
}
// 查询数目太大,采用缓存将不是一个很好的方式。
if len(resultsSlice) > 100 {
session.Engine.LogDebug("[xorm:cacheFind] ids length %v > 100, no cache", len(resultsSlice))
if len(resultsSlice) > 500 {
session.Engine.LogDebug("[xorm:cacheFind] ids length %v > 500, no cache", len(resultsSlice))
return ErrCacheFailed
}
@ -1155,29 +1155,31 @@ func row2map(rows *sql.Rows, fields []string) (resultsMap map[string][]byte, err
case reflect.Float32, reflect.Float64:
str = strconv.FormatFloat(vv.Float(), 'f', -1, 64)
result[key] = []byte(str)
case reflect.String:
str = vv.String()
result[key] = []byte(str)
case reflect.Array, reflect.Slice:
switch aa.Elem().Kind() {
case reflect.Uint8:
result[key] = rawValue.Interface().([]byte)
str = string(result[key])
default:
//session.Engine.LogError("Unsupported type")
return nil, errors.New(fmt.Sprintf("Unsupported struct type %v", vv.Type().Name()))
}
case reflect.String:
str = vv.String()
result[key] = []byte(str)
//时间类型
case reflect.Struct:
if aa.String() == "time.Time" {
str = rawValue.Interface().(time.Time).Format("2006-01-02 15:04:05.000 -0700")
str = rawValue.Interface().(time.Time).Format("2006-01-02 15:04:05.000000 -0700")
result[key] = []byte(str)
} else {
return nil, errors.New(fmt.Sprintf("Unsupported struct type %v", vv.Type().Name()))
}
case reflect.Bool:
str := strconv.FormatBool(vv.Bool())
str = strconv.FormatBool(vv.Bool())
result[key] = []byte(str)
case reflect.Complex128, reflect.Complex64:
result[key] = []byte(fmt.Sprintf("%v", vv.Complex()))
str = fmt.Sprintf("%v", vv.Complex())
result[key] = []byte(str)
/* TODO: unsupported types below
case reflect.Map:
case reflect.Ptr:
@ -1488,14 +1490,30 @@ func (session *Session) bytes2Value(col *Column, fieldValue *reflect.Value, data
fieldValue.SetString(string(data))
case reflect.Bool:
d := string(data)
//fmt.Println("------", d, "-------")
v, err := strconv.ParseBool(d)
if err != nil {
return errors.New("arg " + key + " as bool: " + err.Error())
}
fieldValue.Set(reflect.ValueOf(v))
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
x, err := strconv.ParseInt(string(data), 10, 64)
sdata := string(data)
var x int64
var err error
if col.SQLType.Name == Bit &&
strings.Contains(session.Engine.DriverName, "mysql") {
if len(data) == 1 {
x = int64(data[0])
} else {
x = 0
}
fmt.Println("######", x, data)
} else if strings.HasPrefix(sdata, "0x") {
x, err = strconv.ParseInt(sdata, 16, 64)
} else if strings.HasPrefix(sdata, "0") {
x, err = strconv.ParseInt(sdata, 8, 64)
} else {
x, err = strconv.ParseInt(sdata, 10, 64)
}
if err != nil {
return errors.New("arg " + key + " as int: " + err.Error())
}
@ -1515,13 +1533,24 @@ func (session *Session) bytes2Value(col *Column, fieldValue *reflect.Value, data
//Now only support Time type
case reflect.Struct:
if fieldValue.Type().String() == "time.Time" {
x, err := time.Parse("2006-01-02 15:04:05", string(data))
if err != nil {
x, err = time.Parse("2006-01-02 15:04:05.000 -0700", string(data))
if err != nil {
return errors.New("unsupported time format: " + string(data))
sdata := string(data)
var x time.Time
var err error
if len(sdata) > 19 {
x, err = time.Parse("2006-01-02 15:04:05.000000 -0700", sdata)
} else if len(sdata) == 19 {
x, err = time.Parse("2006-01-02 15:04:05", sdata)
} else if len(sdata) == 10 && sdata[4] == '-' && sdata[7] == '-' {
x, err = time.Parse("2006-01-02", sdata)
} else if col.SQLType.Name == Time {
if len(sdata) > 8 {
sdata = sdata[len(sdata)-8:]
}
st := "2012-03-04 " + sdata
x, err = time.Parse("2006-01-02 15:04:05", st)
}
if err != nil {
return errors.New(fmt.Sprintf("unsupported time format %v: %v", string(data), err))
}
v = x
@ -1584,8 +1613,15 @@ func (session *Session) value2Interface(col *Column, fieldValue reflect.Value) (
return fieldValue.String(), nil
case reflect.Struct:
if fieldValue.Type().String() == "time.Time" {
//return fieldValue.Interface().(time.Time).Format(time.RFC3339Nano), nil
//return fieldValue.Interface().(time.Time).Format("2006-01-02 15:04:05 -0700"), nil
if col.SQLType.Name == Time {
return fieldValue.Interface().(time.Time).Format("2006-01-02 15:04:05"), nil
} else if col.SQLType.Name == Date {
return fieldValue.Interface().(time.Time).Format("2006-01-02"), nil
}
// crying...
if session.Engine.DriverName == POSTGRES {
return fieldValue.Interface().(time.Time).Format("2006-01-02 15:04:05.000000 -0700"), nil
}
return fieldValue.Interface(), nil
}
if fieldTable, ok := session.Engine.Tables[fieldValue.Type()]; ok {

View File

@ -155,7 +155,15 @@ func buildConditions(engine *Engine, table *Table, bean interface{}, includeVers
if t.IsZero() {
continue
}
val = t
var str string
if col.SQLType.Name == Time {
str = strings.Split(t.Format("2006-01-02 15:04:05"), " ")[1]
} else if col.SQLType.Name == Date {
str = t.Format("2006-01-02")
} else {
str = t.Format("2006-01-02 15:04:05.000000 -0700")
}
val = str
} else {
engine.AutoMapType(fieldValue.Type())
if table, ok := engine.Tables[fieldValue.Type()]; ok {
@ -189,7 +197,11 @@ func buildConditions(engine *Engine, table *Table, bean interface{}, includeVers
var err error
if (fieldType.Kind() == reflect.Array || fieldType.Kind() == reflect.Slice) &&
fieldType.Elem().Kind() == reflect.Uint8 {
val = fieldValue.Bytes()
if fieldValue.Len() > 0 {
val = fieldValue.Bytes()
} else {
continue
}
} else {
bytes, err = json.Marshal(fieldValue.Interface())
if err != nil {
@ -289,6 +301,11 @@ func (statement *Statement) Omit(columns ...string) {
statement.OmitStr = statement.Engine.Quote(strings.Join(newColumns, statement.Engine.Quote(", ")))
}
func (statement *Statement) Top(limit int) *Statement {
statement.Limit(limit)
return statement
}
func (statement *Statement) Limit(limit int, start ...int) {
statement.LimitN = limit
if len(start) > 0 {

View File

@ -10,7 +10,7 @@ import (
)
const (
version string = "0.2.0"
version string = "0.2.2"
)
func close(engine *Engine) {