fixed delete bug #12
This commit is contained in:
parent
de06e54874
commit
e5c421d6ff
|
@ -22,3 +22,5 @@ _testmain.go
|
|||
|
||||
*.exe
|
||||
vendor
|
||||
|
||||
*.log
|
||||
|
|
108
base_test.go
108
base_test.go
|
@ -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 {
|
||||
|
|
11
cache.go
11
cache.go
|
@ -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)
|
||||
}
|
||||
|
|
|
@ -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 进行讨论。
|
||||
|
|
74
session.go
74
session.go
|
@ -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 {
|
||||
|
|
21
statement.go
21
statement.go
|
@ -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 {
|
||||
|
|
Loading…
Reference in New Issue