github.com/ecodeclub/eorm@v0.0.2-0.20231001112437-dae71da914d0/db_test.go (about) 1 // Copyright 2021 ecodeclub 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 15 package eorm 16 17 import ( 18 "context" 19 "database/sql" 20 "errors" 21 "fmt" 22 "testing" 23 24 "github.com/DATA-DOG/go-sqlmock" 25 "github.com/ecodeclub/eorm/internal/datasource/single" 26 "github.com/stretchr/testify/assert" 27 28 "github.com/ecodeclub/eorm/internal/datasource/masterslave" 29 30 "github.com/ecodeclub/eorm/internal/valuer" 31 _ "github.com/mattn/go-sqlite3" 32 ) 33 34 func TestDB_BeginTx(t *testing.T) { 35 mockDB, mock, err := sqlmock.New() 36 if err != nil { 37 t.Fatal(err) 38 } 39 defer func() { _ = mockDB.Close() }() 40 41 db, err := OpenDS("mysql", single.NewDB(mockDB)) 42 if err != nil { 43 t.Fatal(err) 44 } 45 // Begin 失败 46 mock.ExpectBegin().WillReturnError(errors.New("begin failed")) 47 tx, err := db.BeginTx(context.Background(), &sql.TxOptions{}) 48 assert.Equal(t, errors.New("begin failed"), err) 49 assert.Nil(t, tx) 50 51 mock.ExpectBegin() 52 tx, err = db.BeginTx(context.Background(), &sql.TxOptions{}) 53 assert.Nil(t, err) 54 assert.NotNil(t, tx) 55 } 56 57 func ExampleMiddleware() { 58 db, _ := Open("sqlite3", "file:test.db?cache=shared&mode=memory", 59 DBWithMiddlewares(func(next HandleFunc) HandleFunc { 60 return func(ctx context.Context, queryContext *QueryContext) *QueryResult { 61 return &QueryResult{Result: "mdl1"} 62 } 63 }, func(next HandleFunc) HandleFunc { 64 return func(ctx context.Context, queryContext *QueryContext) *QueryResult { 65 return &QueryResult{Result: "mdl2"} 66 } 67 })) 68 defer func() { 69 _ = db.Close() 70 }() 71 fmt.Println(len(db.ms)) 72 // Output: 73 // 2 74 } 75 76 func ExampleDB_BeginTx() { 77 db, _ := Open("sqlite3", "file:test.db?cache=shared&mode=memory") 78 defer func() { 79 _ = db.Close() 80 }() 81 tx, err := db.BeginTx(context.Background(), &sql.TxOptions{}) 82 if err == nil { 83 fmt.Println("Begin") 84 } 85 // 或者 tx.Rollback() 86 err = tx.Commit() 87 if err == nil { 88 fmt.Println("Commit") 89 } 90 // Output: 91 // Begin 92 // Commit 93 } 94 95 func ExampleOpen() { 96 // case1 without DBOption 97 db, _ := Open("sqlite3", "file:test.db?cache=shared&mode=memory") 98 fmt.Printf("case1 dialect: %s\n", db.dialect.Name) 99 100 // Output: 101 // case1 dialect: SQLite 102 } 103 104 func ExampleNewDeleter() { 105 tm := &TestModel{} 106 db := memoryDB() 107 query, _ := NewDeleter[TestModel](db).From(tm).Build() 108 fmt.Printf("SQL: %s", query.SQL) 109 // Output: 110 // SQL: DELETE FROM `test_model`; 111 } 112 113 func ExampleNewUpdater() { 114 tm := &TestModel{ 115 Age: 18, 116 } 117 db := memoryDB() 118 query, _ := NewUpdater[TestModel](db).Update(tm).Build() 119 fmt.Printf("SQL: %s", query.SQL) 120 // Output: 121 // SQL: UPDATE `test_model` SET `id`=?,`first_name`=?,`age`=?,`last_name`=?; 122 } 123 124 // memoryDB 返回一个基于内存的 ORM,它使用的是 sqlite3 内存模式。 125 func memoryDB() *DB { 126 db, err := Open("sqlite3", "file:test.db?cache=shared&mode=memory") 127 if err != nil { 128 panic(err) 129 } 130 return db 131 } 132 133 func memoryDBWithDB(dbName string) *DB { 134 db, err := Open("sqlite3", fmt.Sprintf("file:%s.db?cache=shared&mode=memory", dbName)) 135 if err != nil { 136 panic(err) 137 } 138 return db 139 } 140 141 // go test -bench=BenchmarkQuerier_Get -benchmem -benchtime=10000x 142 // goos: linux 143 // goarch: amd64 144 // pkg: github.com/ecodeclub/eorm 145 // cpu: Intel(R) Core(TM) i5-10400F CPU @ 2.90GHz 146 // BenchmarkQuerier_Get/unsafe-12 10000 446263 ns/op 3849 B/op 116 allocs/op 147 // BenchmarkQuerier_Get/reflect-12 10000 854557 ns/op 4062 B/op 128 allocs/op 148 // PASS 149 // ok github.com/ecodeclub/eorm 13.072s 150 func BenchmarkQuerier_Get(b *testing.B) { 151 b.ReportAllocs() 152 db := memoryDBWithDB("benchmarkQuerierGet") 153 defer func() { 154 _ = db.Close() 155 }() 156 _ = RawQuery[any](db, TestModel{}.CreateSQL()).Exec(context.Background()) 157 res := NewInserter[TestModel](db).Values(&TestModel{ 158 Id: 12, 159 FirstName: "Deng", 160 Age: 18, 161 LastName: &sql.NullString{String: "Ming", Valid: true}, 162 }).Exec(context.Background()) 163 if res.Err() != nil { 164 b.Fatal(res.Err()) 165 } 166 affected, err := res.RowsAffected() 167 if err != nil { 168 b.Fatal(err) 169 } 170 if affected == 0 { 171 b.Fatal() 172 } 173 174 b.Run("unsafe", func(b *testing.B) { 175 db.valCreator = valuer.PrimitiveCreator{ 176 Creator: valuer.NewUnsafeValue, 177 } 178 for i := 0; i < b.N; i++ { 179 _, err = NewSelector[TestModel](db).From(TableOf(&TestModel{}, "t1")).Get(context.Background()) 180 if err != nil { 181 b.Fatal(err) 182 } 183 } 184 }) 185 186 b.Run("reflect", func(b *testing.B) { 187 db.valCreator = valuer.PrimitiveCreator{ 188 Creator: valuer.NewReflectValue, 189 } 190 for i := 0; i < b.N; i++ { 191 _, err = NewSelector[TestModel](db).From(TableOf(&TestModel{}, "t1")).Get(context.Background()) 192 if err != nil { 193 b.Fatal(err) 194 } 195 } 196 }) 197 } 198 199 // MasterSlavesMemoryDB 返回一个基于内存的 MasterSlaveDB,它使用的是 sqlite3 内存模式。 200 func MasterSlavesMemoryDB() *masterslave.MasterSlavesDB { 201 db, err := sql.Open("sqlite3", "file:test.db?cache=shared&mode=memory") 202 if err != nil { 203 panic(err) 204 } 205 masterSlaveDB := masterslave.NewMasterSlavesDB(db) 206 return masterSlaveDB 207 }