From 0d1efc74a622744a03a3016bfa851bcabcc90483 Mon Sep 17 00:00:00 2001 From: Lunny Xiao Date: Wed, 4 Dec 2013 15:03:21 +0800 Subject: [PATCH] bug fixed and more benchmark tests --- base_test.go | 4 +- benchmark_base_test.go | 133 ++++++++++++++++++++++++++++- mymysql_test.go | 62 ++++++++++++-- mysql_test.go | 67 +++++++++++++-- postgres_test.go | 112 ++++++++++++++++++++++-- session.go | 8 +- sqlite3_test.go | 189 +++++++++++++++++++++++++++++++++++++---- statement.go | 11 ++- 8 files changed, 536 insertions(+), 50 deletions(-) diff --git a/base_test.go b/base_test.go index 9f7a578a..f6ac86d5 100644 --- a/base_test.go +++ b/base_test.go @@ -2563,8 +2563,8 @@ func testAll2(engine *Engine, t *testing.T) { testTime(engine, t) fmt.Println("-------------- testPrefixTableName --------------") testPrefixTableName(engine, t) - //fmt.Println("-------------- testCreatedUpdated --------------") - //testCreatedUpdated(engine, t) + fmt.Println("-------------- testCreatedUpdated --------------") + testCreatedUpdated(engine, t) fmt.Println("-------------- processors --------------") testProcessors(engine, t) fmt.Println("-------------- processors TX --------------") diff --git a/benchmark_base_test.go b/benchmark_base_test.go index 946525ea..cea7b52b 100644 --- a/benchmark_base_test.go +++ b/benchmark_base_test.go @@ -1,6 +1,7 @@ package xorm import ( + "database/sql" "testing" ) @@ -13,7 +14,102 @@ type BigStruct struct { 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() bs := &BigStruct{0, "fafdasf", "fadfa", "afadfsaf", "fadfafdsafd", "fadfafdsaf"} err := engine.CreateTables(bs) @@ -47,3 +143,38 @@ func doBenchCacheFind(engine *Engine, b *testing.B) { 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 + } +} diff --git a/mymysql_test.go b/mymysql_test.go index e13a7ab5..d27562f2 100644 --- a/mymysql_test.go +++ b/mymysql_test.go @@ -45,24 +45,74 @@ func TestMyMysqlWithCache(t *testing.T) { testAll2(engine, t) } -func BenchmarkMyMysqlNoCache(t *testing.B) { - engine, err := NewEngine("mymysql", "xorm_test2/root/") +func newMyMysqlEngine() (*Engine, error) { + 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() if err != nil { t.Error(err) return } //engine.ShowSQL = true - doBenchCacheFind(engine, t) + doBenchFind(engine, t) } -func BenchmarkMyMysqlCache(t *testing.B) { - engine, err := NewEngine("mymysql", "xorm_test2/root/") +func BenchmarkMyMysqlNoCacheFindPtr(t *testing.B) { + 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() if err != nil { t.Error(err) return } 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) } diff --git a/mysql_test.go b/mysql_test.go index 106e898e..1451c08f 100644 --- a/mysql_test.go +++ b/mysql_test.go @@ -10,8 +10,12 @@ CREATE DATABASE IF NOT EXISTS xorm_test CHARACTER SET utf8 COLLATE utf8_general_ci; */ +func newMysqlEngine() (*Engine, error) { + return NewEngine("mysql", "root:@/xorm_test?charset=utf8") +} + func TestMysql(t *testing.T) { - engine, err := NewEngine("mysql", "root:@/xorm_test?charset=utf8") + engine, err := newMysqlEngine() defer engine.Close() if err != nil { t.Error(err) @@ -27,7 +31,7 @@ func TestMysql(t *testing.T) { } func TestMysqlWithCache(t *testing.T) { - engine, err := NewEngine("mysql", "root:@/xorm_test2?charset=utf8") + engine, err := newMysqlEngine() defer engine.Close() if err != nil { t.Error(err) @@ -43,24 +47,71 @@ func TestMysqlWithCache(t *testing.T) { testAll2(engine, t) } -func BenchmarkMysqlNoCache(t *testing.B) { - engine, err := NewEngine("mysql", "root:@/xorm_test?charset=utf8") +func BenchmarkMysqlNoCacheInsert(t *testing.B) { + engine, err := newMysqlEngine() defer engine.Close() if err != nil { t.Error(err) return } //engine.ShowSQL = true - doBenchCacheFind(engine, t) + doBenchInsert(engine, t) } -func BenchmarkMysqlCache(t *testing.B) { - engine, err := NewEngine("mysql", "root:@/xorm_test?charset=utf8") +func BenchmarkMysqlNoCacheFind(t *testing.B) { + 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() if err != nil { t.Error(err) return } 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) } diff --git a/postgres_test.go b/postgres_test.go index 3cea129a..8a9b2567 100644 --- a/postgres_test.go +++ b/postgres_test.go @@ -7,8 +7,12 @@ import ( "testing" ) +func newPostgresEngine() (*Engine, error) { + return NewEngine("postgres", "dbname=xorm_test sslmode=disable") +} + func TestPostgres(t *testing.T) { - engine, err := NewEngine("postgres", "dbname=xorm_test sslmode=disable") + engine, err := newPostgresEngine() if err != nil { t.Error(err) return @@ -24,7 +28,7 @@ func TestPostgres(t *testing.T) { } func TestPostgresWithCache(t *testing.T) { - engine, err := NewEngine("postgres", "dbname=xorm_test2 sslmode=disable") + engine, err := newPostgresEngine() if err != nil { t.Error(err) return @@ -137,8 +141,49 @@ func TestPostgres2(t *testing.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() if err != nil { @@ -146,11 +191,35 @@ func BenchmarkPostgresNoCache(t *testing.B) { return } //engine.ShowSQL = true - doBenchCacheFind(engine, t) + doBenchInsert(engine, t) } -func BenchmarkPostgresCache(t *testing.B) { - engine, err := NewEngine("postgres", "dbname=xorm_test sslmode=disable") +func BenchmarkPostgresNoCacheFind(t *testing.B) { + 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() if err != nil { @@ -158,5 +227,32 @@ func BenchmarkPostgresCache(t *testing.B) { return } 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) } diff --git a/session.go b/session.go index 64e65ca4..780f95b1 100644 --- a/session.go +++ b/session.go @@ -992,7 +992,7 @@ func (session *Session) Find(rowsSlicePtr interface{}, condiBean ...interface{}) } 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.ConditionStr = strings.Join(colNames, " AND ") session.Statement.BeanArgs = args @@ -2153,7 +2153,7 @@ func (session *Session) Update(bean interface{}, condiBean ...interface{}) (int6 session.Statement.RefTable = table 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) } else { 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{} 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) } @@ -2343,7 +2343,7 @@ func (session *Session) Delete(bean interface{}) (int64, error) { table := session.Engine.autoMap(bean) 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) var condition = "" diff --git a/sqlite3_test.go b/sqlite3_test.go index 0a1c33a8..82df0508 100644 --- a/sqlite3_test.go +++ b/sqlite3_test.go @@ -1,45 +1,198 @@ package xorm import ( + //"database/sql" _ "github.com/mattn/go-sqlite3" "os" "testing" ) -func TestSqlite3(t *testing.T) { +func newSqlite3Engine() (*Engine, error) { 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() if err != nil { t.Error(err) return } engine.ShowSQL = showTestSql + engine.ShowErr = showTestSql + engine.ShowWarn = showTestSql + engine.ShowDebug = showTestSql testAll(engine, t) testAll2(engine, t) } -func BenchmarkSqlite3NoCache(t *testing.B) { - os.Remove("./test.db") - 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") +func TestSqlite3WithCache(t *testing.T) { + engine, err := newSqlite3Engine() defer engine.Close() if err != nil { t.Error(err) return } 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) } diff --git a/statement.go b/statement.go index 90837a3b..a0cdfaa9 100644 --- a/statement.go +++ b/statement.go @@ -233,13 +233,18 @@ func (statement *Statement) Table(tableNameOrBean interface{}) *Statement { }*/ // 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) var args = make([]interface{}, 0) for _, col := range table.Columns { if !includeVersion && col.IsVersion { continue } + if !includeUpdated && col.IsUpdated { + continue + } fieldValue := col.ValueOf(bean) fieldType := reflect.TypeOf(fieldValue.Interface()) var val interface{} @@ -586,7 +591,7 @@ func (statement Statement) genGetSql(bean interface{}) (string, []interface{}) { table := statement.Engine.autoMap(bean) 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.ConditionStr = strings.Join(colNames, " AND ") statement.BeanArgs = args @@ -624,7 +629,7 @@ func (statement Statement) genCountSql(bean interface{}) (string, []interface{}) table := statement.Engine.autoMap(bean) 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.BeanArgs = args var id string = "*"