github.com/ecodeclub/eorm@v0.0.2-0.20231001112437-dae71da914d0/insert_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 package eorm 15 16 import ( 17 "context" 18 "errors" 19 "fmt" 20 "testing" 21 22 "github.com/stretchr/testify/assert" 23 ) 24 25 func TestInserter_Values(t *testing.T) { 26 type User struct { 27 Id int64 `eorm:"auto_increment,primary_key"` 28 FirstName string 29 Ctime uint64 30 } 31 n := uint64(1000) 32 u := &User{ 33 Id: 12, 34 FirstName: "Tom", 35 Ctime: n, 36 } 37 u1 := &User{ 38 Id: 13, 39 FirstName: "Jerry", 40 Ctime: n, 41 } 42 db := memoryDB() 43 testCases := []CommonTestCase{ 44 { 45 name: "no examples of values", 46 builder: NewInserter[User](db).Values(), 47 wantErr: errors.New("插入0行"), 48 }, 49 { 50 name: "single example of values", 51 builder: NewInserter[User](db).Values(u), 52 wantSql: "INSERT INTO `user`(`id`,`first_name`,`ctime`) VALUES(?,?,?);", 53 wantArgs: []interface{}{int64(12), "Tom", n}, 54 }, 55 56 { 57 name: "multiple values of same type", 58 builder: NewInserter[User](db).Values(u, u1), 59 wantSql: "INSERT INTO `user`(`id`,`first_name`,`ctime`) VALUES(?,?,?),(?,?,?);", 60 wantArgs: []interface{}{int64(12), "Tom", n, int64(13), "Jerry", n}, 61 }, 62 63 { 64 name: "no example of a whole columns", 65 builder: NewInserter[User](db).Columns("Id", "FirstName").Values(u), 66 wantSql: "INSERT INTO `user`(`id`,`first_name`) VALUES(?,?);", 67 wantArgs: []interface{}{int64(12), "Tom"}, 68 }, 69 { 70 name: "an example with invalid columns", 71 builder: NewInserter[User](db).Columns("id", "FirstName").Values(u), 72 wantErr: errors.New("eorm: 未知字段 id"), 73 }, 74 { 75 name: "no whole columns and multiple values of same type", 76 builder: NewInserter[User](db).Columns("Id", "FirstName").Values(u, u1), 77 wantSql: "INSERT INTO `user`(`id`,`first_name`) VALUES(?,?),(?,?);", 78 wantArgs: []interface{}{int64(12), "Tom", int64(13), "Jerry"}, 79 }, 80 { 81 name: "ignore pk default", 82 builder: NewInserter[User](db).SkipPK().Values(u), 83 wantSql: "INSERT INTO `user`(`first_name`,`ctime`) VALUES(?,?);", 84 wantArgs: []interface{}{"Tom", uint64(1000)}, 85 }, 86 { 87 name: "ignore pk", 88 builder: NewInserter[User](db).SkipPK().Columns("Id", "FirstName").Values(u), 89 wantSql: "INSERT INTO `user`(`id`,`first_name`) VALUES(?,?);", 90 wantArgs: []interface{}{int64(12), "Tom"}, 91 }, 92 { 93 name: "ignore pk multi default", 94 builder: NewInserter[User](db).SkipPK().Values(u, u1), 95 wantSql: "INSERT INTO `user`(`first_name`,`ctime`) VALUES(?,?),(?,?);", 96 wantArgs: []interface{}{"Tom", uint64(1000), "Jerry", uint64(1000)}, 97 }, 98 { 99 name: "ignore pk multi", 100 builder: NewInserter[User](db).SkipPK().Columns("Id", "FirstName", "Ctime").Values(u, u1), 101 wantSql: "INSERT INTO `user`(`id`,`first_name`,`ctime`) VALUES(?,?,?),(?,?,?);", 102 wantArgs: []interface{}{int64(12), "Tom", uint64(1000), int64(13), "Jerry", uint64(1000)}, 103 }, 104 } 105 106 for _, tc := range testCases { 107 c := tc 108 t.Run(tc.name, func(t *testing.T) { 109 q, err := c.builder.Build() 110 assert.Equal(t, c.wantErr, err) 111 if err != nil { 112 return 113 } 114 assert.Equal(t, c.wantSql, q.SQL) 115 assert.EqualValues(t, c.wantArgs, q.Args) 116 }) 117 } 118 } 119 120 func TestInserter_ValuesForCombination(t *testing.T) { 121 type BaseEntity struct { 122 Id int64 `eorm:"auto_increment,primary_key"` 123 CreateTime uint64 124 } 125 type User struct { 126 BaseEntity 127 FirstName string 128 } 129 type Profile struct { 130 BaseEntity 131 IdCard int64 `eorm:"auto_increment,primary_key"` 132 FirstName string 133 } 134 n := uint64(1000) 135 idCard := int64(123456) 136 p := &Profile{ 137 FirstName: "Tom", 138 BaseEntity: BaseEntity{ 139 Id: 12, 140 CreateTime: n, 141 }, 142 IdCard: idCard, 143 } 144 p1 := &Profile{ 145 FirstName: "Jerry", 146 BaseEntity: BaseEntity{ 147 Id: 13, 148 CreateTime: n, 149 }, 150 IdCard: idCard, 151 } 152 u := &User{ 153 FirstName: "Tom", 154 BaseEntity: BaseEntity{ 155 Id: 12, 156 CreateTime: n, 157 }, 158 } 159 u1 := &User{ 160 FirstName: "Jerry", 161 BaseEntity: BaseEntity{ 162 Id: 13, 163 CreateTime: n, 164 }, 165 } 166 db := memoryDB() 167 testCases := []CommonTestCase{ 168 { 169 name: "no examples of values", 170 builder: NewInserter[User](db).Values(), 171 wantErr: errors.New("插入0行"), 172 }, 173 { 174 name: "single example of values", 175 builder: NewInserter[User](db).Values(u), 176 wantSql: "INSERT INTO `user`(`id`,`create_time`,`first_name`) VALUES(?,?,?);", 177 wantArgs: []interface{}{int64(12), n, "Tom"}, 178 }, 179 180 { 181 name: "multiple values of same type", 182 builder: NewInserter[User](db).Values(u, u1), 183 wantSql: "INSERT INTO `user`(`id`,`create_time`,`first_name`) VALUES(?,?,?),(?,?,?);", 184 wantArgs: []interface{}{int64(12), n, "Tom", int64(13), n, "Jerry"}, 185 }, 186 187 { 188 name: "no example of a whole columns", 189 builder: NewInserter[User](db).Columns("Id", "FirstName").Values(u), 190 wantSql: "INSERT INTO `user`(`id`,`first_name`) VALUES(?,?);", 191 wantArgs: []interface{}{int64(12), "Tom"}, 192 }, 193 194 { 195 name: "no example of a whole columns2", 196 builder: NewInserter[User](db).Columns("FirstName", "Id").Values(u), 197 wantSql: "INSERT INTO `user`(`first_name`,`id`) VALUES(?,?);", 198 wantArgs: []interface{}{"Tom", int64(12)}, 199 }, 200 { 201 name: "an example with invalid columns", 202 builder: NewInserter[User](db).Columns("id", "FirstName").Values(u), 203 wantErr: errors.New("eorm: 未知字段 id"), 204 }, 205 { 206 name: "no whole columns and multiple values of same type", 207 builder: NewInserter[User](db).Columns("Id", "FirstName").Values(u, u1), 208 wantSql: "INSERT INTO `user`(`id`,`first_name`) VALUES(?,?),(?,?);", 209 wantArgs: []interface{}{int64(12), "Tom", int64(13), "Jerry"}, 210 }, 211 { 212 name: "ignore pk default", 213 builder: NewInserter[User](db).SkipPK().Values(u), 214 wantSql: "INSERT INTO `user`(`create_time`,`first_name`) VALUES(?,?);", 215 wantArgs: []interface{}{uint64(1000), "Tom"}, 216 }, 217 { 218 name: "ignore pk", 219 builder: NewInserter[User](db).SkipPK().Columns("Id", "CreateTime", "FirstName").Values(u), 220 wantSql: "INSERT INTO `user`(`id`,`create_time`,`first_name`) VALUES(?,?,?);", 221 wantArgs: []interface{}{int64(12), uint64(1000), "Tom"}, 222 }, 223 { 224 name: "ignore pk multi default", 225 builder: NewInserter[User](db).SkipPK().Values(u, u1), 226 wantSql: "INSERT INTO `user`(`create_time`,`first_name`) VALUES(?,?),(?,?);", 227 wantArgs: []interface{}{uint64(1000), "Tom", uint64(1000), "Jerry"}, 228 }, 229 { 230 name: "ignore pk multi", 231 builder: NewInserter[User](db).SkipPK().Columns("Id", "CreateTime", "FirstName").Values(u, u1), 232 wantSql: "INSERT INTO `user`(`id`,`create_time`,`first_name`) VALUES(?,?,?),(?,?,?);", 233 wantArgs: []interface{}{int64(12), uint64(1000), "Tom", int64(13), uint64(1000), "Jerry"}, 234 }, 235 236 { 237 name: "ignore multi pk default", 238 builder: NewInserter[Profile](db).SkipPK().Values(p), 239 wantSql: "INSERT INTO `profile`(`create_time`,`first_name`) VALUES(?,?);", 240 wantArgs: []interface{}{uint64(1000), "Tom"}, 241 }, 242 { 243 name: "ignore multi pk multi data default", 244 builder: NewInserter[Profile](db).SkipPK().Values(p, p1), 245 wantSql: "INSERT INTO `profile`(`create_time`,`first_name`) VALUES(?,?),(?,?);", 246 wantArgs: []interface{}{uint64(1000), "Tom", uint64(1000), "Jerry"}, 247 }, 248 249 { 250 name: "ignore multi pk", 251 builder: NewInserter[Profile](db).SkipPK().Columns("Id", "CreateTime", "FirstName", "IdCard").Values(p), 252 wantSql: "INSERT INTO `profile`(`id`,`create_time`,`first_name`,`id_card`) VALUES(?,?,?,?);", 253 wantArgs: []interface{}{int64(12), uint64(1000), "Tom", int64(123456)}, 254 }, 255 { 256 name: "ignore multi pk multi data", 257 builder: NewInserter[Profile](db).SkipPK().Columns("Id", "CreateTime", "FirstName", "IdCard").Values(p, p1), 258 wantSql: "INSERT INTO `profile`(`id`,`create_time`,`first_name`,`id_card`) VALUES(?,?,?,?),(?,?,?,?);", 259 wantArgs: []interface{}{int64(12), uint64(1000), "Tom", int64(123456), int64(13), uint64(1000), "Jerry", int64(123456)}, 260 }, 261 } 262 263 for _, tc := range testCases { 264 c := tc 265 t.Run(tc.name, func(t *testing.T) { 266 q, err := c.builder.Build() 267 assert.Equal(t, c.wantErr, err) 268 if err != nil { 269 return 270 } 271 assert.Equal(t, c.wantSql, q.SQL) 272 assert.Equal(t, c.wantArgs, q.Args) 273 }) 274 } 275 } 276 277 func TestInserter_Exec(t *testing.T) { 278 orm := memoryDB() 279 testCases := []struct { 280 name string 281 i *Inserter[TestModel] 282 wantErr string 283 wantAffected int64 284 }{ 285 { 286 name: "invalid query", 287 i: NewInserter[TestModel](orm).Values(), 288 wantErr: "插入0行", 289 }, 290 { 291 // 表没创建 292 name: "table not exist", 293 i: NewInserter[TestModel](orm).Values(&TestModel{}), 294 wantErr: "no such table: test_model", 295 }, 296 } 297 298 for _, tc := range testCases { 299 t.Run(tc.name, func(t *testing.T) { 300 res := tc.i.Exec(context.Background()) 301 if res.Err() != nil { 302 assert.EqualError(t, res.Err(), tc.wantErr) 303 return 304 } 305 assert.Nil(t, tc.wantErr) 306 affected, err := res.RowsAffected() 307 if err != nil { 308 t.Fatal(err) 309 } 310 assert.Equal(t, tc.wantAffected, affected) 311 }) 312 } 313 } 314 315 func ExampleInserter_Build() { 316 db := memoryDB() 317 query, _ := NewInserter[TestModel](db).Values(&TestModel{ 318 Id: 1, 319 Age: 18, 320 }).Build() 321 fmt.Printf("case1\n%s", query.String()) 322 323 query, _ = NewInserter[TestModel](db).Values(&TestModel{}).Build() 324 fmt.Printf("case2\n%s", query.String()) 325 326 // Output: 327 // case1 328 // SQL: INSERT INTO `test_model`(`id`,`first_name`,`age`,`last_name`) VALUES(?,?,?,?); 329 // Args: []interface {}{1, "", 18, (*sql.NullString)(nil)} 330 // case2 331 // SQL: INSERT INTO `test_model`(`id`,`first_name`,`age`,`last_name`) VALUES(?,?,?,?); 332 // Args: []interface {}{0, "", 0, (*sql.NullString)(nil)} 333 } 334 335 func ExampleInserter_Columns() { 336 db := memoryDB() 337 query, _ := NewInserter[TestModel](db).Values(&TestModel{ 338 Id: 1, 339 Age: 18, 340 }).Columns("Id", "Age").Build() 341 fmt.Printf("case1\n%s", query.String()) 342 343 query, _ = NewInserter[TestModel](db).Values(&TestModel{ 344 Id: 1, 345 Age: 18, 346 }, &TestModel{}, &TestModel{FirstName: "Tom"}).Columns("Id", "Age").Build() 347 fmt.Printf("case2\n%s", query.String()) 348 349 // Output: 350 // case1 351 // SQL: INSERT INTO `test_model`(`id`,`age`) VALUES(?,?); 352 // Args: []interface {}{1, 18} 353 // case2 354 // SQL: INSERT INTO `test_model`(`id`,`age`) VALUES(?,?),(?,?),(?,?); 355 // Args: []interface {}{1, 18, 0, 0, 0, 0} 356 357 } 358 359 func ExampleInserter_Values() { 360 db := memoryDB() 361 query, _ := NewInserter[TestModel](db).Values(&TestModel{ 362 Id: 1, 363 Age: 18, 364 }, &TestModel{}).Build() 365 fmt.Println(query.String()) 366 // Output: 367 // SQL: INSERT INTO `test_model`(`id`,`first_name`,`age`,`last_name`) VALUES(?,?,?,?),(?,?,?,?); 368 // Args: []interface {}{1, "", 18, (*sql.NullString)(nil), 0, "", 0, (*sql.NullString)(nil)} 369 } 370 371 func ExampleNewInserter() { 372 db := memoryDB() 373 tm := &TestModel{} 374 query, _ := NewInserter[TestModel](db).Values(tm).Build() 375 fmt.Printf("SQL: %s", query.SQL) 376 // Output: 377 // SQL: INSERT INTO `test_model`(`id`,`first_name`,`age`,`last_name`) VALUES(?,?,?,?); 378 }