diff --git a/.gitignore b/.gitignore
index 4d7cf444..98008af1 100644
--- a/.gitignore
+++ b/.gitignore
@@ -22,3 +22,5 @@ _testmain.go
*.exe
vendor
+
+*.log
diff --git a/base_test.go b/base_test.go
index 4ef655b1..365fd240 100644
--- a/base_test.go
+++ b/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 {
diff --git a/cache.go b/cache.go
index c16fe15b..9fcbcdef 100644
--- a/cache.go
+++ b/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)
}
diff --git a/docs/QuickStart.md b/docs/QuickStart.md
index 8d13f57c..03b6a256 100644
--- a/docs/QuickStart.md
+++ b/docs/QuickStart.md
@@ -506,13 +506,14 @@ engine.ClearCache(new(User))
## 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)
-
## 15.讨论
请加入QQ群:280360085 进行讨论。
diff --git a/session.go b/session.go
index 63e87219..9784c3b1 100644
--- a/session.go
+++ b/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 {
diff --git a/statement.go b/statement.go
index 94daa433..c91dc8c6 100644
--- a/statement.go
+++ b/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 {
diff --git a/xorm.go b/xorm.go
index 9a6c30b5..80d17fe5 100644
--- a/xorm.go
+++ b/xorm.go
@@ -10,7 +10,7 @@ import (
)
const (
- version string = "0.2.0"
+ version string = "0.2.2"
)
func close(engine *Engine) {