bug fixed and more benchmark tests

This commit is contained in:
Lunny Xiao 2013-12-04 15:03:21 +08:00
parent 4c224deeba
commit 0d1efc74a6
8 changed files with 536 additions and 50 deletions

View File

@ -2563,8 +2563,8 @@ func testAll2(engine *Engine, t *testing.T) {
testTime(engine, t) testTime(engine, t)
fmt.Println("-------------- testPrefixTableName --------------") fmt.Println("-------------- testPrefixTableName --------------")
testPrefixTableName(engine, t) testPrefixTableName(engine, t)
//fmt.Println("-------------- testCreatedUpdated --------------") fmt.Println("-------------- testCreatedUpdated --------------")
//testCreatedUpdated(engine, t) testCreatedUpdated(engine, t)
fmt.Println("-------------- processors --------------") fmt.Println("-------------- processors --------------")
testProcessors(engine, t) testProcessors(engine, t)
fmt.Println("-------------- processors TX --------------") fmt.Println("-------------- processors TX --------------")

View File

@ -1,6 +1,7 @@
package xorm package xorm
import ( import (
"database/sql"
"testing" "testing"
) )
@ -13,7 +14,102 @@ type BigStruct struct {
NickName string NickName string
} }
func doBenchCacheFind(engine *Engine, b *testing.B) { func doBenchDriverInsert(engine *Engine, db *sql.DB, b *testing.B) {
b.StopTimer()
err := engine.CreateTables(&BigStruct{})
if err != nil {
b.Error(err)
return
}
doBenchDriverInsertS(db, b)
err = engine.DropTables(&BigStruct{})
if err != nil {
b.Error(err)
return
}
}
func doBenchDriverInsertS(db *sql.DB, b *testing.B) {
b.StartTimer()
for i := 0; i < b.N; i++ {
_, err := db.Exec(`insert into big_struct (name, title, age, alias, nick_name)
values ('fafdasf', 'fadfa', 'afadfsaf', 'fadfafdsafd', 'fadfafdsaf')`)
if err != nil {
b.Error(err)
return
}
}
b.StopTimer()
}
func doBenchDriverFind(engine *Engine, db *sql.DB, b *testing.B) {
b.StopTimer()
err := engine.CreateTables(&BigStruct{})
if err != nil {
b.Error(err)
return
}
doBenchDriverFindS(db, b)
err = engine.DropTables(&BigStruct{})
if err != nil {
b.Error(err)
return
}
}
func doBenchDriverFindS(db *sql.DB, b *testing.B) {
b.StopTimer()
for i := 0; i < 100; i++ {
_, err := db.Exec(`insert into big_struct (name, title, age, alias, nick_name)
values ('fafdasf', 'fadfa', 'afadfsaf', 'fadfafdsafd', 'fadfafdsaf')`)
if err != nil {
b.Error(err)
return
}
}
b.StartTimer()
for i := 0; i < b.N; i++ {
_, err := db.Query("select * from big_struct limit 50")
if err != nil {
b.Error(err)
return
}
}
b.StopTimer()
}
func doBenchInsert(engine *Engine, b *testing.B) {
b.StopTimer()
bs := &BigStruct{0, "fafdasf", "fadfa", "afadfsaf", "fadfafdsafd", "fadfafdsaf"}
err := engine.CreateTables(bs)
if err != nil {
b.Error(err)
return
}
b.StartTimer()
for i := 0; i < b.N; i++ {
bs.Id = 0
_, err = engine.Insert(bs)
if err != nil {
b.Error(err)
return
}
}
b.StopTimer()
err = engine.DropTables(bs)
if err != nil {
b.Error(err)
return
}
}
func doBenchFind(engine *Engine, b *testing.B) {
b.StopTimer() b.StopTimer()
bs := &BigStruct{0, "fafdasf", "fadfa", "afadfsaf", "fadfafdsafd", "fadfafdsaf"} bs := &BigStruct{0, "fafdasf", "fadfa", "afadfsaf", "fadfafdsafd", "fadfafdsaf"}
err := engine.CreateTables(bs) err := engine.CreateTables(bs)
@ -47,3 +143,38 @@ func doBenchCacheFind(engine *Engine, b *testing.B) {
return return
} }
} }
func doBenchFindPtr(engine *Engine, b *testing.B) {
b.StopTimer()
bs := &BigStruct{0, "fafdasf", "fadfa", "afadfsaf", "fadfafdsafd", "fadfafdsaf"}
err := engine.CreateTables(bs)
if err != nil {
b.Error(err)
return
}
for i := 0; i < 100; i++ {
bs.Id = 0
_, err = engine.Insert(bs)
if err != nil {
b.Error(err)
return
}
}
b.StartTimer()
for i := 0; i < b.N; i++ {
bss := new([]*BigStruct)
err = engine.Limit(50).Find(bss)
if err != nil {
b.Error(err)
return
}
}
b.StopTimer()
err = engine.DropTables(bs)
if err != nil {
b.Error(err)
return
}
}

View File

@ -45,24 +45,74 @@ func TestMyMysqlWithCache(t *testing.T) {
testAll2(engine, t) testAll2(engine, t)
} }
func BenchmarkMyMysqlNoCache(t *testing.B) { func newMyMysqlEngine() (*Engine, error) {
engine, err := NewEngine("mymysql", "xorm_test2/root/") return NewEngine("mymysql", "xorm_test2/root/")
}
func BenchmarkMyMysqlNoCacheInsert(t *testing.B) {
engine, err := newMyMysqlEngine()
defer engine.Close()
if err != nil {
t.Error(err)
return
}
doBenchInsert(engine, t)
}
func BenchmarkMyMysqlNoCacheFind(t *testing.B) {
engine, err := newMyMysqlEngine()
defer engine.Close() defer engine.Close()
if err != nil { if err != nil {
t.Error(err) t.Error(err)
return return
} }
//engine.ShowSQL = true //engine.ShowSQL = true
doBenchCacheFind(engine, t) doBenchFind(engine, t)
} }
func BenchmarkMyMysqlCache(t *testing.B) { func BenchmarkMyMysqlNoCacheFindPtr(t *testing.B) {
engine, err := NewEngine("mymysql", "xorm_test2/root/") engine, err := newMyMysqlEngine()
defer engine.Close()
if err != nil {
t.Error(err)
return
}
//engine.ShowSQL = true
doBenchFindPtr(engine, t)
}
func BenchmarkMyMysqlCacheInsert(t *testing.B) {
engine, err := newMyMysqlEngine()
defer engine.Close() defer engine.Close()
if err != nil { if err != nil {
t.Error(err) t.Error(err)
return return
} }
engine.SetDefaultCacher(NewLRUCacher(NewMemoryStore(), 1000)) engine.SetDefaultCacher(NewLRUCacher(NewMemoryStore(), 1000))
doBenchCacheFind(engine, t)
doBenchInsert(engine, t)
}
func BenchmarkMyMysqlCacheFind(t *testing.B) {
engine, err := newMyMysqlEngine()
defer engine.Close()
if err != nil {
t.Error(err)
return
}
engine.SetDefaultCacher(NewLRUCacher(NewMemoryStore(), 1000))
doBenchFind(engine, t)
}
func BenchmarkMyMysqlCacheFindPtr(t *testing.B) {
engine, err := newMyMysqlEngine()
defer engine.Close()
if err != nil {
t.Error(err)
return
}
engine.SetDefaultCacher(NewLRUCacher(NewMemoryStore(), 1000))
doBenchFindPtr(engine, t)
} }

View File

@ -10,8 +10,12 @@ CREATE DATABASE IF NOT EXISTS xorm_test CHARACTER SET
utf8 COLLATE utf8_general_ci; utf8 COLLATE utf8_general_ci;
*/ */
func newMysqlEngine() (*Engine, error) {
return NewEngine("mysql", "root:@/xorm_test?charset=utf8")
}
func TestMysql(t *testing.T) { func TestMysql(t *testing.T) {
engine, err := NewEngine("mysql", "root:@/xorm_test?charset=utf8") engine, err := newMysqlEngine()
defer engine.Close() defer engine.Close()
if err != nil { if err != nil {
t.Error(err) t.Error(err)
@ -27,7 +31,7 @@ func TestMysql(t *testing.T) {
} }
func TestMysqlWithCache(t *testing.T) { func TestMysqlWithCache(t *testing.T) {
engine, err := NewEngine("mysql", "root:@/xorm_test2?charset=utf8") engine, err := newMysqlEngine()
defer engine.Close() defer engine.Close()
if err != nil { if err != nil {
t.Error(err) t.Error(err)
@ -43,24 +47,71 @@ func TestMysqlWithCache(t *testing.T) {
testAll2(engine, t) testAll2(engine, t)
} }
func BenchmarkMysqlNoCache(t *testing.B) { func BenchmarkMysqlNoCacheInsert(t *testing.B) {
engine, err := NewEngine("mysql", "root:@/xorm_test?charset=utf8") engine, err := newMysqlEngine()
defer engine.Close() defer engine.Close()
if err != nil { if err != nil {
t.Error(err) t.Error(err)
return return
} }
//engine.ShowSQL = true //engine.ShowSQL = true
doBenchCacheFind(engine, t) doBenchInsert(engine, t)
} }
func BenchmarkMysqlCache(t *testing.B) { func BenchmarkMysqlNoCacheFind(t *testing.B) {
engine, err := NewEngine("mysql", "root:@/xorm_test?charset=utf8") engine, err := newMysqlEngine()
defer engine.Close()
if err != nil {
t.Error(err)
return
}
//engine.ShowSQL = true
doBenchFind(engine, t)
}
func BenchmarkMysqlNoCacheFindPtr(t *testing.B) {
engine, err := newMysqlEngine()
defer engine.Close()
if err != nil {
t.Error(err)
return
}
//engine.ShowSQL = true
doBenchFindPtr(engine, t)
}
func BenchmarkMysqlCacheInsert(t *testing.B) {
engine, err := newMysqlEngine()
defer engine.Close() defer engine.Close()
if err != nil { if err != nil {
t.Error(err) t.Error(err)
return return
} }
engine.SetDefaultCacher(NewLRUCacher(NewMemoryStore(), 1000)) engine.SetDefaultCacher(NewLRUCacher(NewMemoryStore(), 1000))
doBenchCacheFind(engine, t)
doBenchInsert(engine, t)
}
func BenchmarkMysqlCacheFind(t *testing.B) {
engine, err := newMysqlEngine()
defer engine.Close()
if err != nil {
t.Error(err)
return
}
engine.SetDefaultCacher(NewLRUCacher(NewMemoryStore(), 1000))
doBenchFind(engine, t)
}
func BenchmarkMysqlCacheFindPtr(t *testing.B) {
engine, err := newMysqlEngine()
defer engine.Close()
if err != nil {
t.Error(err)
return
}
engine.SetDefaultCacher(NewLRUCacher(NewMemoryStore(), 1000))
doBenchFindPtr(engine, t)
} }

View File

@ -7,8 +7,12 @@ import (
"testing" "testing"
) )
func newPostgresEngine() (*Engine, error) {
return NewEngine("postgres", "dbname=xorm_test sslmode=disable")
}
func TestPostgres(t *testing.T) { func TestPostgres(t *testing.T) {
engine, err := NewEngine("postgres", "dbname=xorm_test sslmode=disable") engine, err := newPostgresEngine()
if err != nil { if err != nil {
t.Error(err) t.Error(err)
return return
@ -24,7 +28,7 @@ func TestPostgres(t *testing.T) {
} }
func TestPostgresWithCache(t *testing.T) { func TestPostgresWithCache(t *testing.T) {
engine, err := NewEngine("postgres", "dbname=xorm_test2 sslmode=disable") engine, err := newPostgresEngine()
if err != nil { if err != nil {
t.Error(err) t.Error(err)
return return
@ -137,8 +141,49 @@ func TestPostgres2(t *testing.T) {
transaction(engine, t) transaction(engine, t)
}*/ }*/
func BenchmarkPostgresNoCache(t *testing.B) { /*
engine, err := NewEngine("postgres", "dbname=xorm_test sslmode=disable") func BenchmarkPostgresDriverInsert(t *testing.B) {
t.StopTimer()
engine, err := newPostgresEngine()
if err != nil {
t.Error(err)
return
}
defer engine.Close()
db, err := engine.OpenDB()
if err != nil {
t.Error(err)
return
}
defer db.Close()
doBenchDriverInsert(engine, db, t)
}
func BenchmarkPostgresDriverFind(t *testing.B) {
t.StopTimer()
engine, err := newPostgresEngine()
if err != nil {
t.Error(err)
return
}
defer engine.Close()
db, err := engine.OpenDB()
if err != nil {
t.Error(err)
return
}
//defer db.Close()
doBenchDriverFind(engine, db, t)
}*/
func BenchmarkPostgresNoCacheInsert(t *testing.B) {
engine, err := newPostgresEngine()
defer engine.Close() defer engine.Close()
if err != nil { if err != nil {
@ -146,11 +191,35 @@ func BenchmarkPostgresNoCache(t *testing.B) {
return return
} }
//engine.ShowSQL = true //engine.ShowSQL = true
doBenchCacheFind(engine, t) doBenchInsert(engine, t)
} }
func BenchmarkPostgresCache(t *testing.B) { func BenchmarkPostgresNoCacheFind(t *testing.B) {
engine, err := NewEngine("postgres", "dbname=xorm_test sslmode=disable") engine, err := newPostgresEngine()
defer engine.Close()
if err != nil {
t.Error(err)
return
}
//engine.ShowSQL = true
doBenchFind(engine, t)
}
func BenchmarkPostgresNoCacheFindPtr(t *testing.B) {
engine, err := newPostgresEngine()
defer engine.Close()
if err != nil {
t.Error(err)
return
}
//engine.ShowSQL = true
doBenchFindPtr(engine, t)
}
func BenchmarkPostgresCacheInsert(t *testing.B) {
engine, err := newPostgresEngine()
defer engine.Close() defer engine.Close()
if err != nil { if err != nil {
@ -158,5 +227,32 @@ func BenchmarkPostgresCache(t *testing.B) {
return return
} }
engine.SetDefaultCacher(NewLRUCacher(NewMemoryStore(), 1000)) engine.SetDefaultCacher(NewLRUCacher(NewMemoryStore(), 1000))
doBenchCacheFind(engine, t)
doBenchInsert(engine, t)
}
func BenchmarkPostgresCacheFind(t *testing.B) {
engine, err := newPostgresEngine()
defer engine.Close()
if err != nil {
t.Error(err)
return
}
engine.SetDefaultCacher(NewLRUCacher(NewMemoryStore(), 1000))
doBenchFind(engine, t)
}
func BenchmarkPostgresCacheFindPtr(t *testing.B) {
engine, err := newPostgresEngine()
defer engine.Close()
if err != nil {
t.Error(err)
return
}
engine.SetDefaultCacher(NewLRUCacher(NewMemoryStore(), 1000))
doBenchFindPtr(engine, t)
} }

View File

@ -992,7 +992,7 @@ func (session *Session) Find(rowsSlicePtr interface{}, condiBean ...interface{})
} }
if len(condiBean) > 0 { if len(condiBean) > 0 {
colNames, args := buildConditions(session.Engine, table, condiBean[0], true, colNames, args := buildConditions(session.Engine, table, condiBean[0], true, true,
session.Statement.allUseBool, session.Statement.boolColumnMap) session.Statement.allUseBool, session.Statement.boolColumnMap)
session.Statement.ConditionStr = strings.Join(colNames, " AND ") session.Statement.ConditionStr = strings.Join(colNames, " AND ")
session.Statement.BeanArgs = args session.Statement.BeanArgs = args
@ -2153,7 +2153,7 @@ func (session *Session) Update(bean interface{}, condiBean ...interface{}) (int6
session.Statement.RefTable = table session.Statement.RefTable = table
if session.Statement.ColumnStr == "" { if session.Statement.ColumnStr == "" {
colNames, args = buildConditions(session.Engine, table, bean, false, colNames, args = buildConditions(session.Engine, table, bean, false, false,
session.Statement.allUseBool, session.Statement.boolColumnMap) session.Statement.allUseBool, session.Statement.boolColumnMap)
} else { } else {
colNames, args, err = table.genCols(session, bean, true, true) colNames, args, err = table.genCols(session, bean, true, true)
@ -2187,7 +2187,7 @@ func (session *Session) Update(bean interface{}, condiBean ...interface{}) (int6
var condiArgs []interface{} var condiArgs []interface{}
if len(condiBean) > 0 { if len(condiBean) > 0 {
condiColNames, condiArgs = buildConditions(session.Engine, session.Statement.RefTable, condiBean[0], true, condiColNames, condiArgs = buildConditions(session.Engine, session.Statement.RefTable, condiBean[0], true, true,
session.Statement.allUseBool, session.Statement.boolColumnMap) session.Statement.allUseBool, session.Statement.boolColumnMap)
} }
@ -2343,7 +2343,7 @@ func (session *Session) Delete(bean interface{}) (int64, error) {
table := session.Engine.autoMap(bean) table := session.Engine.autoMap(bean)
session.Statement.RefTable = table session.Statement.RefTable = table
colNames, args := buildConditions(session.Engine, table, bean, true, colNames, args := buildConditions(session.Engine, table, bean, true, true,
session.Statement.allUseBool, session.Statement.boolColumnMap) session.Statement.allUseBool, session.Statement.boolColumnMap)
var condition = "" var condition = ""

View File

@ -1,45 +1,198 @@
package xorm package xorm
import ( import (
//"database/sql"
_ "github.com/mattn/go-sqlite3" _ "github.com/mattn/go-sqlite3"
"os" "os"
"testing" "testing"
) )
func TestSqlite3(t *testing.T) { func newSqlite3Engine() (*Engine, error) {
os.Remove("./test.db") os.Remove("./test.db")
engine, err := NewEngine("sqlite3", "./test.db") return NewEngine("sqlite3", "./test.db")
}
func TestSqlite3(t *testing.T) {
engine, err := newSqlite3Engine()
defer engine.Close() defer engine.Close()
if err != nil { if err != nil {
t.Error(err) t.Error(err)
return return
} }
engine.ShowSQL = showTestSql engine.ShowSQL = showTestSql
engine.ShowErr = showTestSql
engine.ShowWarn = showTestSql
engine.ShowDebug = showTestSql
testAll(engine, t) testAll(engine, t)
testAll2(engine, t) testAll2(engine, t)
} }
func BenchmarkSqlite3NoCache(t *testing.B) { func TestSqlite3WithCache(t *testing.T) {
os.Remove("./test.db") engine, err := newSqlite3Engine()
engine, err := NewEngine("sqlite3", "./test.db")
defer engine.Close()
if err != nil {
t.Error(err)
return
}
//engine.ShowSQL = true
doBenchCacheFind(engine, t)
}
func BenchmarkSqlite3Cache(t *testing.B) {
os.Remove("./test.db")
engine, err := NewEngine("sqlite3", "./test.db")
defer engine.Close() defer engine.Close()
if err != nil { if err != nil {
t.Error(err) t.Error(err)
return return
} }
engine.SetDefaultCacher(NewLRUCacher(NewMemoryStore(), 1000)) engine.SetDefaultCacher(NewLRUCacher(NewMemoryStore(), 1000))
doBenchCacheFind(engine, t) engine.ShowSQL = showTestSql
engine.ShowErr = showTestSql
engine.ShowWarn = showTestSql
engine.ShowDebug = showTestSql
testAll(engine, t)
testAll2(engine, t)
}
/*func BenchmarkSqlite3DriverInsert(t *testing.B) {
t.StopTimer()
engine, err := newSqlite3Engine()
if err != nil {
t.Error(err)
return
}
err = engine.CreateTables(&BigStruct{})
if err != nil {
t.Error(err)
return
}
engine.Close()
db, err := sql.Open("sqlite3", "./test.db")
if err != nil {
t.Error(err)
return
}
doBenchDriverInsertS(db, t)
db.Close()
engine, err = newSqlite3Engine()
if err != nil {
t.Error(err)
return
}
err = engine.DropTables(&BigStruct{})
if err != nil {
t.Error(err)
return
}
defer engine.Close()
}
func BenchmarkSqlite3DriverFind(t *testing.B) {
t.StopTimer()
engine, err := newSqlite3Engine()
defer engine.Close()
if err != nil {
t.Error(err)
return
}
err = engine.CreateTables(&BigStruct{})
if err != nil {
t.Error(err)
return
}
engine.Close()
db, err := sql.Open("sqlite3", "./test.db")
if err != nil {
t.Error(err)
return
}
defer db.Close()
doBenchDriverFindS(db, t)
db.Close()
engine, err = newSqlite3Engine()
if err != nil {
t.Error(err)
return
}
err = engine.DropTables(&BigStruct{})
if err != nil {
t.Error(err)
return
}
defer engine.Close()
}*/
func BenchmarkSqlite3NoCacheInsert(t *testing.B) {
t.StopTimer()
engine, err := newSqlite3Engine()
defer engine.Close()
if err != nil {
t.Error(err)
return
}
//engine.ShowSQL = true
doBenchInsert(engine, t)
}
func BenchmarkSqlite3NoCacheFind(t *testing.B) {
t.StopTimer()
engine, err := newSqlite3Engine()
defer engine.Close()
if err != nil {
t.Error(err)
return
}
//engine.ShowSQL = true
doBenchFind(engine, t)
}
func BenchmarkSqlite3NoCacheFindPtr(t *testing.B) {
t.StopTimer()
engine, err := newSqlite3Engine()
defer engine.Close()
if err != nil {
t.Error(err)
return
}
//engine.ShowSQL = true
doBenchFindPtr(engine, t)
}
func BenchmarkSqlite3CacheInsert(t *testing.B) {
t.StopTimer()
engine, err := newSqlite3Engine()
defer engine.Close()
if err != nil {
t.Error(err)
return
}
engine.SetDefaultCacher(NewLRUCacher(NewMemoryStore(), 1000))
doBenchInsert(engine, t)
}
func BenchmarkSqlite3CacheFind(t *testing.B) {
t.StopTimer()
engine, err := newSqlite3Engine()
defer engine.Close()
if err != nil {
t.Error(err)
return
}
engine.SetDefaultCacher(NewLRUCacher(NewMemoryStore(), 1000))
doBenchFind(engine, t)
}
func BenchmarkSqlite3CacheFindPtr(t *testing.B) {
t.StopTimer()
engine, err := newSqlite3Engine()
defer engine.Close()
if err != nil {
t.Error(err)
return
}
engine.SetDefaultCacher(NewLRUCacher(NewMemoryStore(), 1000))
doBenchFindPtr(engine, t)
} }

View File

@ -233,13 +233,18 @@ func (statement *Statement) Table(tableNameOrBean interface{}) *Statement {
}*/ }*/
// Auto generating conditions according a struct // Auto generating conditions according a struct
func buildConditions(engine *Engine, table *Table, bean interface{}, includeVersion bool, allUseBool bool, boolColumnMap map[string]bool) ([]string, []interface{}) { func buildConditions(engine *Engine, table *Table, bean interface{},
includeVersion bool, includeUpdated bool, allUseBool bool,
boolColumnMap map[string]bool) ([]string, []interface{}) {
colNames := make([]string, 0) colNames := make([]string, 0)
var args = make([]interface{}, 0) var args = make([]interface{}, 0)
for _, col := range table.Columns { for _, col := range table.Columns {
if !includeVersion && col.IsVersion { if !includeVersion && col.IsVersion {
continue continue
} }
if !includeUpdated && col.IsUpdated {
continue
}
fieldValue := col.ValueOf(bean) fieldValue := col.ValueOf(bean)
fieldType := reflect.TypeOf(fieldValue.Interface()) fieldType := reflect.TypeOf(fieldValue.Interface())
var val interface{} var val interface{}
@ -586,7 +591,7 @@ func (statement Statement) genGetSql(bean interface{}) (string, []interface{}) {
table := statement.Engine.autoMap(bean) table := statement.Engine.autoMap(bean)
statement.RefTable = table statement.RefTable = table
colNames, args := buildConditions(statement.Engine, table, bean, true, colNames, args := buildConditions(statement.Engine, table, bean, true, true,
statement.allUseBool, statement.boolColumnMap) statement.allUseBool, statement.boolColumnMap)
statement.ConditionStr = strings.Join(colNames, " AND ") statement.ConditionStr = strings.Join(colNames, " AND ")
statement.BeanArgs = args statement.BeanArgs = args
@ -624,7 +629,7 @@ func (statement Statement) genCountSql(bean interface{}) (string, []interface{})
table := statement.Engine.autoMap(bean) table := statement.Engine.autoMap(bean)
statement.RefTable = table statement.RefTable = table
colNames, args := buildConditions(statement.Engine, table, bean, true, statement.allUseBool, statement.boolColumnMap) colNames, args := buildConditions(statement.Engine, table, bean, true, true, statement.allUseBool, statement.boolColumnMap)
statement.ConditionStr = strings.Join(colNames, " AND ") statement.ConditionStr = strings.Join(colNames, " AND ")
statement.BeanArgs = args statement.BeanArgs = args
var id string = "*" var id string = "*"