github.com/astaxie/beego@v1.12.3/orm/orm_test.go (about) 1 // Copyright 2014 beego Author. All Rights Reserved. 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 // +build go1.8 16 17 package orm 18 19 import ( 20 "bytes" 21 "context" 22 "database/sql" 23 "fmt" 24 "io/ioutil" 25 "math" 26 "os" 27 "path/filepath" 28 "reflect" 29 "runtime" 30 "strings" 31 "testing" 32 "time" 33 ) 34 35 var _ = os.PathSeparator 36 37 var ( 38 testDate = formatDate + " -0700" 39 testDateTime = formatDateTime + " -0700" 40 testTime = formatTime + " -0700" 41 ) 42 43 type argAny []interface{} 44 45 // get interface by index from interface slice 46 func (a argAny) Get(i int, args ...interface{}) (r interface{}) { 47 if i >= 0 && i < len(a) { 48 r = a[i] 49 } 50 if len(args) > 0 { 51 r = args[0] 52 } 53 return 54 } 55 56 func ValuesCompare(is bool, a interface{}, args ...interface{}) (ok bool, err error) { 57 if len(args) == 0 { 58 return false, fmt.Errorf("miss args") 59 } 60 b := args[0] 61 arg := argAny(args) 62 63 switch v := a.(type) { 64 case reflect.Kind: 65 ok = reflect.ValueOf(b).Kind() == v 66 case time.Time: 67 if v2, vo := b.(time.Time); vo { 68 if arg.Get(1) != nil { 69 format := ToStr(arg.Get(1)) 70 a = v.Format(format) 71 b = v2.Format(format) 72 ok = a == b 73 } else { 74 err = fmt.Errorf("compare datetime miss format") 75 goto wrongArg 76 } 77 } 78 default: 79 ok = ToStr(a) == ToStr(b) 80 } 81 ok = is && ok || !is && !ok 82 if !ok { 83 if is { 84 err = fmt.Errorf("expected: `%v`, get `%v`", b, a) 85 } else { 86 err = fmt.Errorf("expected: `%v`, get `%v`", b, a) 87 } 88 } 89 90 wrongArg: 91 if err != nil { 92 return false, err 93 } 94 95 return true, nil 96 } 97 98 func AssertIs(a interface{}, args ...interface{}) error { 99 if ok, err := ValuesCompare(true, a, args...); !ok { 100 return err 101 } 102 return nil 103 } 104 105 func AssertNot(a interface{}, args ...interface{}) error { 106 if ok, err := ValuesCompare(false, a, args...); !ok { 107 return err 108 } 109 return nil 110 } 111 112 func getCaller(skip int) string { 113 pc, file, line, _ := runtime.Caller(skip) 114 fun := runtime.FuncForPC(pc) 115 _, fn := filepath.Split(file) 116 data, err := ioutil.ReadFile(file) 117 var codes []string 118 if err == nil { 119 lines := bytes.Split(data, []byte{'\n'}) 120 n := 10 121 for i := 0; i < n; i++ { 122 o := line - n 123 if o < 0 { 124 continue 125 } 126 cur := o + i + 1 127 flag := " " 128 if cur == line { 129 flag = ">>" 130 } 131 code := fmt.Sprintf(" %s %5d: %s", flag, cur, strings.Replace(string(lines[o+i]), "\t", " ", -1)) 132 if code != "" { 133 codes = append(codes, code) 134 } 135 } 136 } 137 funName := fun.Name() 138 if i := strings.LastIndex(funName, "."); i > -1 { 139 funName = funName[i+1:] 140 } 141 return fmt.Sprintf("%s:%s:%d: \n%s", fn, funName, line, strings.Join(codes, "\n")) 142 } 143 144 func throwFail(t *testing.T, err error, args ...interface{}) { 145 if err != nil { 146 con := fmt.Sprintf("\t\nError: %s\n%s\n", err.Error(), getCaller(2)) 147 if len(args) > 0 { 148 parts := make([]string, 0, len(args)) 149 for _, arg := range args { 150 parts = append(parts, fmt.Sprintf("%v", arg)) 151 } 152 con += " " + strings.Join(parts, ", ") 153 } 154 t.Error(con) 155 t.Fail() 156 } 157 } 158 159 func throwFailNow(t *testing.T, err error, args ...interface{}) { 160 if err != nil { 161 con := fmt.Sprintf("\t\nError: %s\n%s\n", err.Error(), getCaller(2)) 162 if len(args) > 0 { 163 parts := make([]string, 0, len(args)) 164 for _, arg := range args { 165 parts = append(parts, fmt.Sprintf("%v", arg)) 166 } 167 con += " " + strings.Join(parts, ", ") 168 } 169 t.Error(con) 170 t.FailNow() 171 } 172 } 173 174 func TestGetDB(t *testing.T) { 175 if db, err := GetDB(); err != nil { 176 throwFailNow(t, err) 177 } else { 178 err = db.Ping() 179 throwFailNow(t, err) 180 } 181 } 182 183 func TestSyncDb(t *testing.T) { 184 RegisterModel(new(Data), new(DataNull), new(DataCustom)) 185 RegisterModel(new(User)) 186 RegisterModel(new(Profile)) 187 RegisterModel(new(Post)) 188 RegisterModel(new(Tag)) 189 RegisterModel(new(Comment)) 190 RegisterModel(new(UserBig)) 191 RegisterModel(new(PostTags)) 192 RegisterModel(new(Group)) 193 RegisterModel(new(Permission)) 194 RegisterModel(new(GroupPermissions)) 195 RegisterModel(new(InLine)) 196 RegisterModel(new(InLineOneToOne)) 197 RegisterModel(new(IntegerPk)) 198 RegisterModel(new(UintPk)) 199 RegisterModel(new(PtrPk)) 200 201 err := RunSyncdb("default", true, Debug) 202 throwFail(t, err) 203 204 modelCache.clean() 205 } 206 207 func TestRegisterModels(t *testing.T) { 208 RegisterModel(new(Data), new(DataNull), new(DataCustom)) 209 RegisterModel(new(User)) 210 RegisterModel(new(Profile)) 211 RegisterModel(new(Post)) 212 RegisterModel(new(Tag)) 213 RegisterModel(new(Comment)) 214 RegisterModel(new(UserBig)) 215 RegisterModel(new(PostTags)) 216 RegisterModel(new(Group)) 217 RegisterModel(new(Permission)) 218 RegisterModel(new(GroupPermissions)) 219 RegisterModel(new(InLine)) 220 RegisterModel(new(InLineOneToOne)) 221 RegisterModel(new(IntegerPk)) 222 RegisterModel(new(UintPk)) 223 RegisterModel(new(PtrPk)) 224 225 BootStrap() 226 227 dORM = NewOrm() 228 dDbBaser = getDbAlias("default").DbBaser 229 } 230 231 func TestModelSyntax(t *testing.T) { 232 user := &User{} 233 ind := reflect.ValueOf(user).Elem() 234 fn := getFullName(ind.Type()) 235 mi, ok := modelCache.getByFullName(fn) 236 throwFail(t, AssertIs(ok, true)) 237 238 mi, ok = modelCache.get("user") 239 throwFail(t, AssertIs(ok, true)) 240 if ok { 241 throwFail(t, AssertIs(mi.fields.GetByName("ShouldSkip") == nil, true)) 242 } 243 } 244 245 var DataValues = map[string]interface{}{ 246 "Boolean": true, 247 "Char": "char", 248 "Text": "text", 249 "JSON": `{"name":"json"}`, 250 "Jsonb": `{"name": "jsonb"}`, 251 "Time": time.Now(), 252 "Date": time.Now(), 253 "DateTime": time.Now(), 254 "Byte": byte(1<<8 - 1), 255 "Rune": rune(1<<31 - 1), 256 "Int": int(1<<31 - 1), 257 "Int8": int8(1<<7 - 1), 258 "Int16": int16(1<<15 - 1), 259 "Int32": int32(1<<31 - 1), 260 "Int64": int64(1<<63 - 1), 261 "Uint": uint(1<<32 - 1), 262 "Uint8": uint8(1<<8 - 1), 263 "Uint16": uint16(1<<16 - 1), 264 "Uint32": uint32(1<<32 - 1), 265 "Uint64": uint64(1<<63 - 1), // uint64 values with high bit set are not supported 266 "Float32": float32(100.1234), 267 "Float64": float64(100.1234), 268 "Decimal": float64(100.1234), 269 } 270 271 func TestDataTypes(t *testing.T) { 272 d := Data{} 273 ind := reflect.Indirect(reflect.ValueOf(&d)) 274 275 for name, value := range DataValues { 276 if name == "JSON" { 277 continue 278 } 279 e := ind.FieldByName(name) 280 e.Set(reflect.ValueOf(value)) 281 } 282 id, err := dORM.Insert(&d) 283 throwFail(t, err) 284 throwFail(t, AssertIs(id, 1)) 285 286 d = Data{ID: 1} 287 err = dORM.Read(&d) 288 throwFail(t, err) 289 290 ind = reflect.Indirect(reflect.ValueOf(&d)) 291 292 for name, value := range DataValues { 293 e := ind.FieldByName(name) 294 vu := e.Interface() 295 switch name { 296 case "Date": 297 vu = vu.(time.Time).In(DefaultTimeLoc).Format(testDate) 298 value = value.(time.Time).In(DefaultTimeLoc).Format(testDate) 299 case "DateTime": 300 vu = vu.(time.Time).In(DefaultTimeLoc).Format(testDateTime) 301 value = value.(time.Time).In(DefaultTimeLoc).Format(testDateTime) 302 case "Time": 303 vu = vu.(time.Time).In(DefaultTimeLoc).Format(testTime) 304 value = value.(time.Time).In(DefaultTimeLoc).Format(testTime) 305 } 306 throwFail(t, AssertIs(vu == value, true), value, vu) 307 } 308 } 309 310 func TestNullDataTypes(t *testing.T) { 311 d := DataNull{} 312 313 if IsPostgres { 314 // can removed when this fixed 315 // https://github.com/lib/pq/pull/125 316 d.DateTime = time.Now() 317 } 318 319 id, err := dORM.Insert(&d) 320 throwFail(t, err) 321 throwFail(t, AssertIs(id, 1)) 322 323 data := `{"ok":1,"data":{"arr":[1,2],"msg":"gopher"}}` 324 d = DataNull{ID: 1, JSON: data} 325 num, err := dORM.Update(&d) 326 throwFail(t, err) 327 throwFail(t, AssertIs(num, 1)) 328 329 d = DataNull{ID: 1} 330 err = dORM.Read(&d) 331 throwFail(t, err) 332 333 throwFail(t, AssertIs(d.JSON, data)) 334 335 throwFail(t, AssertIs(d.NullBool.Valid, false)) 336 throwFail(t, AssertIs(d.NullString.Valid, false)) 337 throwFail(t, AssertIs(d.NullInt64.Valid, false)) 338 throwFail(t, AssertIs(d.NullFloat64.Valid, false)) 339 340 throwFail(t, AssertIs(d.BooleanPtr, nil)) 341 throwFail(t, AssertIs(d.CharPtr, nil)) 342 throwFail(t, AssertIs(d.TextPtr, nil)) 343 throwFail(t, AssertIs(d.BytePtr, nil)) 344 throwFail(t, AssertIs(d.RunePtr, nil)) 345 throwFail(t, AssertIs(d.IntPtr, nil)) 346 throwFail(t, AssertIs(d.Int8Ptr, nil)) 347 throwFail(t, AssertIs(d.Int16Ptr, nil)) 348 throwFail(t, AssertIs(d.Int32Ptr, nil)) 349 throwFail(t, AssertIs(d.Int64Ptr, nil)) 350 throwFail(t, AssertIs(d.UintPtr, nil)) 351 throwFail(t, AssertIs(d.Uint8Ptr, nil)) 352 throwFail(t, AssertIs(d.Uint16Ptr, nil)) 353 throwFail(t, AssertIs(d.Uint32Ptr, nil)) 354 throwFail(t, AssertIs(d.Uint64Ptr, nil)) 355 throwFail(t, AssertIs(d.Float32Ptr, nil)) 356 throwFail(t, AssertIs(d.Float64Ptr, nil)) 357 throwFail(t, AssertIs(d.DecimalPtr, nil)) 358 throwFail(t, AssertIs(d.TimePtr, nil)) 359 throwFail(t, AssertIs(d.DatePtr, nil)) 360 throwFail(t, AssertIs(d.DateTimePtr, nil)) 361 362 _, err = dORM.Raw(`INSERT INTO data_null (boolean) VALUES (?)`, nil).Exec() 363 throwFail(t, err) 364 365 d = DataNull{ID: 2} 366 err = dORM.Read(&d) 367 throwFail(t, err) 368 369 booleanPtr := true 370 charPtr := string("test") 371 textPtr := string("test") 372 bytePtr := byte('t') 373 runePtr := rune('t') 374 intPtr := int(42) 375 int8Ptr := int8(42) 376 int16Ptr := int16(42) 377 int32Ptr := int32(42) 378 int64Ptr := int64(42) 379 uintPtr := uint(42) 380 uint8Ptr := uint8(42) 381 uint16Ptr := uint16(42) 382 uint32Ptr := uint32(42) 383 uint64Ptr := uint64(42) 384 float32Ptr := float32(42.0) 385 float64Ptr := float64(42.0) 386 decimalPtr := float64(42.0) 387 timePtr := time.Now() 388 datePtr := time.Now() 389 dateTimePtr := time.Now() 390 391 d = DataNull{ 392 DateTime: time.Now(), 393 NullString: sql.NullString{String: "test", Valid: true}, 394 NullBool: sql.NullBool{Bool: true, Valid: true}, 395 NullInt64: sql.NullInt64{Int64: 42, Valid: true}, 396 NullFloat64: sql.NullFloat64{Float64: 42.42, Valid: true}, 397 BooleanPtr: &booleanPtr, 398 CharPtr: &charPtr, 399 TextPtr: &textPtr, 400 BytePtr: &bytePtr, 401 RunePtr: &runePtr, 402 IntPtr: &intPtr, 403 Int8Ptr: &int8Ptr, 404 Int16Ptr: &int16Ptr, 405 Int32Ptr: &int32Ptr, 406 Int64Ptr: &int64Ptr, 407 UintPtr: &uintPtr, 408 Uint8Ptr: &uint8Ptr, 409 Uint16Ptr: &uint16Ptr, 410 Uint32Ptr: &uint32Ptr, 411 Uint64Ptr: &uint64Ptr, 412 Float32Ptr: &float32Ptr, 413 Float64Ptr: &float64Ptr, 414 DecimalPtr: &decimalPtr, 415 TimePtr: &timePtr, 416 DatePtr: &datePtr, 417 DateTimePtr: &dateTimePtr, 418 } 419 420 id, err = dORM.Insert(&d) 421 throwFail(t, err) 422 throwFail(t, AssertIs(id, 3)) 423 424 d = DataNull{ID: 3} 425 err = dORM.Read(&d) 426 throwFail(t, err) 427 428 throwFail(t, AssertIs(d.NullBool.Valid, true)) 429 throwFail(t, AssertIs(d.NullBool.Bool, true)) 430 431 throwFail(t, AssertIs(d.NullString.Valid, true)) 432 throwFail(t, AssertIs(d.NullString.String, "test")) 433 434 throwFail(t, AssertIs(d.NullInt64.Valid, true)) 435 throwFail(t, AssertIs(d.NullInt64.Int64, 42)) 436 437 throwFail(t, AssertIs(d.NullFloat64.Valid, true)) 438 throwFail(t, AssertIs(d.NullFloat64.Float64, 42.42)) 439 440 throwFail(t, AssertIs(*d.BooleanPtr, booleanPtr)) 441 throwFail(t, AssertIs(*d.CharPtr, charPtr)) 442 throwFail(t, AssertIs(*d.TextPtr, textPtr)) 443 throwFail(t, AssertIs(*d.BytePtr, bytePtr)) 444 throwFail(t, AssertIs(*d.RunePtr, runePtr)) 445 throwFail(t, AssertIs(*d.IntPtr, intPtr)) 446 throwFail(t, AssertIs(*d.Int8Ptr, int8Ptr)) 447 throwFail(t, AssertIs(*d.Int16Ptr, int16Ptr)) 448 throwFail(t, AssertIs(*d.Int32Ptr, int32Ptr)) 449 throwFail(t, AssertIs(*d.Int64Ptr, int64Ptr)) 450 throwFail(t, AssertIs(*d.UintPtr, uintPtr)) 451 throwFail(t, AssertIs(*d.Uint8Ptr, uint8Ptr)) 452 throwFail(t, AssertIs(*d.Uint16Ptr, uint16Ptr)) 453 throwFail(t, AssertIs(*d.Uint32Ptr, uint32Ptr)) 454 throwFail(t, AssertIs(*d.Uint64Ptr, uint64Ptr)) 455 throwFail(t, AssertIs(*d.Float32Ptr, float32Ptr)) 456 throwFail(t, AssertIs(*d.Float64Ptr, float64Ptr)) 457 throwFail(t, AssertIs(*d.DecimalPtr, decimalPtr)) 458 throwFail(t, AssertIs((*d.TimePtr).UTC().Format(testTime), timePtr.UTC().Format(testTime))) 459 throwFail(t, AssertIs((*d.DatePtr).UTC().Format(testDate), datePtr.UTC().Format(testDate))) 460 throwFail(t, AssertIs((*d.DateTimePtr).UTC().Format(testDateTime), dateTimePtr.UTC().Format(testDateTime))) 461 462 // test support for pointer fields using RawSeter.QueryRows() 463 var dnList []*DataNull 464 Q := dDbBaser.TableQuote() 465 num, err = dORM.Raw(fmt.Sprintf("SELECT * FROM %sdata_null%s where id=?", Q, Q), 3).QueryRows(&dnList) 466 throwFailNow(t, err) 467 throwFailNow(t, AssertIs(num, 1)) 468 equal := reflect.DeepEqual(*dnList[0], d) 469 throwFailNow(t, AssertIs(equal, true)) 470 } 471 472 func TestDataCustomTypes(t *testing.T) { 473 d := DataCustom{} 474 ind := reflect.Indirect(reflect.ValueOf(&d)) 475 476 for name, value := range DataValues { 477 e := ind.FieldByName(name) 478 if !e.IsValid() { 479 continue 480 } 481 e.Set(reflect.ValueOf(value).Convert(e.Type())) 482 } 483 484 id, err := dORM.Insert(&d) 485 throwFail(t, err) 486 throwFail(t, AssertIs(id, 1)) 487 488 d = DataCustom{ID: 1} 489 err = dORM.Read(&d) 490 throwFail(t, err) 491 492 ind = reflect.Indirect(reflect.ValueOf(&d)) 493 494 for name, value := range DataValues { 495 e := ind.FieldByName(name) 496 if !e.IsValid() { 497 continue 498 } 499 vu := e.Interface() 500 value = reflect.ValueOf(value).Convert(e.Type()).Interface() 501 throwFail(t, AssertIs(vu == value, true), value, vu) 502 } 503 } 504 505 func TestCRUD(t *testing.T) { 506 profile := NewProfile() 507 profile.Age = 30 508 profile.Money = 1234.12 509 id, err := dORM.Insert(profile) 510 throwFail(t, err) 511 throwFail(t, AssertIs(id, 1)) 512 513 user := NewUser() 514 user.UserName = "slene" 515 user.Email = "vslene@gmail.com" 516 user.Password = "pass" 517 user.Status = 3 518 user.IsStaff = true 519 user.IsActive = true 520 521 id, err = dORM.Insert(user) 522 throwFail(t, err) 523 throwFail(t, AssertIs(id, 1)) 524 525 u := &User{ID: user.ID} 526 err = dORM.Read(u) 527 throwFail(t, err) 528 529 throwFail(t, AssertIs(u.UserName, "slene")) 530 throwFail(t, AssertIs(u.Email, "vslene@gmail.com")) 531 throwFail(t, AssertIs(u.Password, "pass")) 532 throwFail(t, AssertIs(u.Status, 3)) 533 throwFail(t, AssertIs(u.IsStaff, true)) 534 throwFail(t, AssertIs(u.IsActive, true)) 535 throwFail(t, AssertIs(u.Created.In(DefaultTimeLoc), user.Created.In(DefaultTimeLoc), testDate)) 536 throwFail(t, AssertIs(u.Updated.In(DefaultTimeLoc), user.Updated.In(DefaultTimeLoc), testDateTime)) 537 538 user.UserName = "astaxie" 539 user.Profile = profile 540 num, err := dORM.Update(user) 541 throwFail(t, err) 542 throwFail(t, AssertIs(num, 1)) 543 544 u = &User{ID: user.ID} 545 err = dORM.Read(u) 546 throwFailNow(t, err) 547 throwFail(t, AssertIs(u.UserName, "astaxie")) 548 throwFail(t, AssertIs(u.Profile.ID, profile.ID)) 549 550 u = &User{UserName: "astaxie", Password: "pass"} 551 err = dORM.Read(u, "UserName") 552 throwFailNow(t, err) 553 throwFailNow(t, AssertIs(id, 1)) 554 555 u.UserName = "QQ" 556 u.Password = "111" 557 num, err = dORM.Update(u, "UserName") 558 throwFail(t, err) 559 throwFail(t, AssertIs(num, 1)) 560 561 u = &User{ID: user.ID} 562 err = dORM.Read(u) 563 throwFailNow(t, err) 564 throwFail(t, AssertIs(u.UserName, "QQ")) 565 throwFail(t, AssertIs(u.Password, "pass")) 566 567 num, err = dORM.Delete(profile) 568 throwFail(t, err) 569 throwFail(t, AssertIs(num, 1)) 570 571 u = &User{ID: user.ID} 572 err = dORM.Read(u) 573 throwFail(t, err) 574 throwFail(t, AssertIs(true, u.Profile == nil)) 575 576 num, err = dORM.Delete(user) 577 throwFail(t, err) 578 throwFail(t, AssertIs(num, 1)) 579 580 u = &User{ID: 100} 581 err = dORM.Read(u) 582 throwFail(t, AssertIs(err, ErrNoRows)) 583 584 ub := UserBig{} 585 ub.Name = "name" 586 id, err = dORM.Insert(&ub) 587 throwFail(t, err) 588 throwFail(t, AssertIs(id, 1)) 589 590 ub = UserBig{ID: 1} 591 err = dORM.Read(&ub) 592 throwFail(t, err) 593 throwFail(t, AssertIs(ub.Name, "name")) 594 595 num, err = dORM.Delete(&ub, "name") 596 throwFail(t, err) 597 throwFail(t, AssertIs(num, 1)) 598 } 599 600 func TestInsertTestData(t *testing.T) { 601 var users []*User 602 603 profile := NewProfile() 604 profile.Age = 28 605 profile.Money = 1234.12 606 607 id, err := dORM.Insert(profile) 608 throwFail(t, err) 609 throwFail(t, AssertIs(id, 2)) 610 611 user := NewUser() 612 user.UserName = "slene" 613 user.Email = "vslene@gmail.com" 614 user.Password = "pass" 615 user.Status = 1 616 user.IsStaff = false 617 user.IsActive = true 618 user.Profile = profile 619 620 users = append(users, user) 621 622 id, err = dORM.Insert(user) 623 throwFail(t, err) 624 throwFail(t, AssertIs(id, 2)) 625 626 profile = NewProfile() 627 profile.Age = 30 628 profile.Money = 4321.09 629 630 id, err = dORM.Insert(profile) 631 throwFail(t, err) 632 throwFail(t, AssertIs(id, 3)) 633 634 user = NewUser() 635 user.UserName = "astaxie" 636 user.Email = "astaxie@gmail.com" 637 user.Password = "password" 638 user.Status = 2 639 user.IsStaff = true 640 user.IsActive = false 641 user.Profile = profile 642 643 users = append(users, user) 644 645 id, err = dORM.Insert(user) 646 throwFail(t, err) 647 throwFail(t, AssertIs(id, 3)) 648 649 user = NewUser() 650 user.UserName = "nobody" 651 user.Email = "nobody@gmail.com" 652 user.Password = "nobody" 653 user.Status = 3 654 user.IsStaff = false 655 user.IsActive = false 656 657 users = append(users, user) 658 659 id, err = dORM.Insert(user) 660 throwFail(t, err) 661 throwFail(t, AssertIs(id, 4)) 662 663 tags := []*Tag{ 664 {Name: "golang", BestPost: &Post{ID: 2}}, 665 {Name: "example"}, 666 {Name: "format"}, 667 {Name: "c++"}, 668 } 669 670 posts := []*Post{ 671 {User: users[0], Tags: []*Tag{tags[0]}, Title: "Introduction", Content: `Go is a new language. Although it borrows ideas from existing languages, it has unusual properties that make effective Go programs different in character from programs written in its relatives. A straightforward translation of a C++ or Java program into Go is unlikely to produce a satisfactory result—Java programs are written in Java, not Go. On the other hand, thinking about the problem from a Go perspective could produce a successful but quite different program. In other words, to write Go well, it's important to understand its properties and idioms. It's also important to know the established conventions for programming in Go, such as naming, formatting, program construction, and so on, so that programs you write will be easy for other Go programmers to understand. 672 This document gives tips for writing clear, idiomatic Go code. It augments the language specification, the Tour of Go, and How to Write Go Code, all of which you should read first.`}, 673 {User: users[1], Tags: []*Tag{tags[0], tags[1]}, Title: "Examples", Content: `The Go package sources are intended to serve not only as the core library but also as examples of how to use the language. Moreover, many of the packages contain working, self-contained executable examples you can run directly from the golang.org web site, such as this one (click on the word "Example" to open it up). If you have a question about how to approach a problem or how something might be implemented, the documentation, code and examples in the library can provide answers, ideas and background.`}, 674 {User: users[1], Tags: []*Tag{tags[0], tags[2]}, Title: "Formatting", Content: `Formatting issues are the most contentious but the least consequential. People can adapt to different formatting styles but it's better if they don't have to, and less time is devoted to the topic if everyone adheres to the same style. The problem is how to approach this Utopia without a long prescriptive style guide. 675 With Go we take an unusual approach and let the machine take care of most formatting issues. The gofmt program (also available as go fmt, which operates at the package level rather than source file level) reads a Go program and emits the source in a standard style of indentation and vertical alignment, retaining and if necessary reformatting comments. If you want to know how to handle some new layout situation, run gofmt; if the answer doesn't seem right, rearrange your program (or file a bug about gofmt), don't work around it.`}, 676 {User: users[2], Tags: []*Tag{tags[3]}, Title: "Commentary", Content: `Go provides C-style /* */ block comments and C++-style // line comments. Line comments are the norm; block comments appear mostly as package comments, but are useful within an expression or to disable large swaths of code. 677 The program—and web server—godoc processes Go source files to extract documentation about the contents of the package. Comments that appear before top-level declarations, with no intervening newlines, are extracted along with the declaration to serve as explanatory text for the item. The nature and style of these comments determines the quality of the documentation godoc produces.`}, 678 } 679 680 comments := []*Comment{ 681 {Post: posts[0], Content: "a comment"}, 682 {Post: posts[1], Content: "yes"}, 683 {Post: posts[1]}, 684 {Post: posts[1]}, 685 {Post: posts[2]}, 686 {Post: posts[2]}, 687 } 688 689 for _, tag := range tags { 690 id, err := dORM.Insert(tag) 691 throwFail(t, err) 692 throwFail(t, AssertIs(id > 0, true)) 693 } 694 695 for _, post := range posts { 696 id, err := dORM.Insert(post) 697 throwFail(t, err) 698 throwFail(t, AssertIs(id > 0, true)) 699 700 num := len(post.Tags) 701 if num > 0 { 702 nums, err := dORM.QueryM2M(post, "tags").Add(post.Tags) 703 throwFailNow(t, err) 704 throwFailNow(t, AssertIs(nums, num)) 705 } 706 } 707 708 for _, comment := range comments { 709 id, err := dORM.Insert(comment) 710 throwFail(t, err) 711 throwFail(t, AssertIs(id > 0, true)) 712 } 713 714 permissions := []*Permission{ 715 {Name: "writePosts"}, 716 {Name: "readComments"}, 717 {Name: "readPosts"}, 718 } 719 720 groups := []*Group{ 721 { 722 Name: "admins", 723 Permissions: []*Permission{permissions[0], permissions[1], permissions[2]}, 724 }, 725 { 726 Name: "users", 727 Permissions: []*Permission{permissions[1], permissions[2]}, 728 }, 729 } 730 731 for _, permission := range permissions { 732 id, err := dORM.Insert(permission) 733 throwFail(t, err) 734 throwFail(t, AssertIs(id > 0, true)) 735 } 736 737 for _, group := range groups { 738 _, err := dORM.Insert(group) 739 throwFail(t, err) 740 throwFail(t, AssertIs(id > 0, true)) 741 742 num := len(group.Permissions) 743 if num > 0 { 744 nums, err := dORM.QueryM2M(group, "permissions").Add(group.Permissions) 745 throwFailNow(t, err) 746 throwFailNow(t, AssertIs(nums, num)) 747 } 748 } 749 750 } 751 752 func TestCustomField(t *testing.T) { 753 user := User{ID: 2} 754 err := dORM.Read(&user) 755 throwFailNow(t, err) 756 757 user.Langs = append(user.Langs, "zh-CN", "en-US") 758 user.Extra.Name = "beego" 759 user.Extra.Data = "orm" 760 _, err = dORM.Update(&user, "Langs", "Extra") 761 throwFailNow(t, err) 762 763 user = User{ID: 2} 764 err = dORM.Read(&user) 765 throwFailNow(t, err) 766 throwFailNow(t, AssertIs(len(user.Langs), 2)) 767 throwFailNow(t, AssertIs(user.Langs[0], "zh-CN")) 768 throwFailNow(t, AssertIs(user.Langs[1], "en-US")) 769 770 throwFailNow(t, AssertIs(user.Extra.Name, "beego")) 771 throwFailNow(t, AssertIs(user.Extra.Data, "orm")) 772 773 var users []User 774 Q := dDbBaser.TableQuote() 775 n, err := dORM.Raw(fmt.Sprintf("SELECT * FROM %suser%s where id=?", Q, Q), 2).QueryRows(&users) 776 throwFailNow(t, err) 777 throwFailNow(t, AssertIs(n, 1)) 778 throwFailNow(t, AssertIs(users[0].Extra.Name, "beego")) 779 throwFailNow(t, AssertIs(users[0].Extra.Data, "orm")) 780 781 user = User{} 782 err = dORM.Raw(fmt.Sprintf("SELECT * FROM %suser%s where id=?", Q, Q), 2).QueryRow(&user) 783 throwFailNow(t, err) 784 throwFailNow(t, AssertIs(user.Extra.Name, "beego")) 785 throwFailNow(t, AssertIs(user.Extra.Data, "orm")) 786 } 787 788 func TestExpr(t *testing.T) { 789 user := &User{} 790 qs := dORM.QueryTable(user) 791 qs = dORM.QueryTable((*User)(nil)) 792 qs = dORM.QueryTable("User") 793 qs = dORM.QueryTable("user") 794 num, err := qs.Filter("UserName", "slene").Filter("user_name", "slene").Filter("profile__Age", 28).Count() 795 throwFail(t, err) 796 throwFail(t, AssertIs(num, 1)) 797 798 num, err = qs.Filter("created", time.Now()).Count() 799 throwFail(t, err) 800 throwFail(t, AssertIs(num, 3)) 801 802 // num, err = qs.Filter("created", time.Now().Format(format_Date)).Count() 803 // throwFail(t, err) 804 // throwFail(t, AssertIs(num, 3)) 805 } 806 807 func TestOperators(t *testing.T) { 808 qs := dORM.QueryTable("user") 809 num, err := qs.Filter("user_name", "slene").Count() 810 throwFail(t, err) 811 throwFail(t, AssertIs(num, 1)) 812 813 num, err = qs.Filter("user_name__exact", String("slene")).Count() 814 throwFail(t, err) 815 throwFail(t, AssertIs(num, 1)) 816 817 num, err = qs.Filter("user_name__exact", "slene").Count() 818 throwFail(t, err) 819 throwFail(t, AssertIs(num, 1)) 820 821 num, err = qs.Filter("user_name__iexact", "Slene").Count() 822 throwFail(t, err) 823 throwFail(t, AssertIs(num, 1)) 824 825 if IsMysql { 826 // Now only mysql support `strictexact` 827 num, err = qs.Filter("user_name__strictexact", "Slene").Count() 828 throwFail(t, err) 829 throwFail(t, AssertIs(num, 0)) 830 831 num, err = qs.Filter("user_name__strictexact", "slene").Count() 832 throwFail(t, err) 833 throwFail(t, AssertIs(num, 1)) 834 } 835 836 num, err = qs.Filter("user_name__contains", "e").Count() 837 throwFail(t, err) 838 throwFail(t, AssertIs(num, 2)) 839 840 var shouldNum int 841 842 if IsSqlite || IsTidb { 843 shouldNum = 2 844 } else { 845 shouldNum = 0 846 } 847 848 num, err = qs.Filter("user_name__contains", "E").Count() 849 throwFail(t, err) 850 throwFail(t, AssertIs(num, shouldNum)) 851 852 num, err = qs.Filter("user_name__icontains", "E").Count() 853 throwFail(t, err) 854 throwFail(t, AssertIs(num, 2)) 855 856 num, err = qs.Filter("user_name__icontains", "E").Count() 857 throwFail(t, err) 858 throwFail(t, AssertIs(num, 2)) 859 860 num, err = qs.Filter("status__gt", 1).Count() 861 throwFail(t, err) 862 throwFail(t, AssertIs(num, 2)) 863 864 num, err = qs.Filter("status__gte", 1).Count() 865 throwFail(t, err) 866 throwFail(t, AssertIs(num, 3)) 867 868 num, err = qs.Filter("status__lt", Uint(3)).Count() 869 throwFail(t, err) 870 throwFail(t, AssertIs(num, 2)) 871 872 num, err = qs.Filter("status__lte", Int(3)).Count() 873 throwFail(t, err) 874 throwFail(t, AssertIs(num, 3)) 875 876 num, err = qs.Filter("user_name__startswith", "s").Count() 877 throwFail(t, err) 878 throwFail(t, AssertIs(num, 1)) 879 880 if IsSqlite || IsTidb { 881 shouldNum = 1 882 } else { 883 shouldNum = 0 884 } 885 886 num, err = qs.Filter("user_name__startswith", "S").Count() 887 throwFail(t, err) 888 throwFail(t, AssertIs(num, shouldNum)) 889 890 num, err = qs.Filter("user_name__istartswith", "S").Count() 891 throwFail(t, err) 892 throwFail(t, AssertIs(num, 1)) 893 894 num, err = qs.Filter("user_name__endswith", "e").Count() 895 throwFail(t, err) 896 throwFail(t, AssertIs(num, 2)) 897 898 if IsSqlite || IsTidb { 899 shouldNum = 2 900 } else { 901 shouldNum = 0 902 } 903 904 num, err = qs.Filter("user_name__endswith", "E").Count() 905 throwFail(t, err) 906 throwFail(t, AssertIs(num, shouldNum)) 907 908 num, err = qs.Filter("user_name__iendswith", "E").Count() 909 throwFail(t, err) 910 throwFail(t, AssertIs(num, 2)) 911 912 num, err = qs.Filter("profile__isnull", true).Count() 913 throwFail(t, err) 914 throwFail(t, AssertIs(num, 1)) 915 916 num, err = qs.Filter("status__in", 1, 2).Count() 917 throwFail(t, err) 918 throwFail(t, AssertIs(num, 2)) 919 920 num, err = qs.Filter("status__in", []int{1, 2}).Count() 921 throwFail(t, err) 922 throwFail(t, AssertIs(num, 2)) 923 924 n1, n2 := 1, 2 925 num, err = qs.Filter("status__in", []*int{&n1}, &n2).Count() 926 throwFail(t, err) 927 throwFail(t, AssertIs(num, 2)) 928 929 num, err = qs.Filter("id__between", 2, 3).Count() 930 throwFail(t, err) 931 throwFail(t, AssertIs(num, 2)) 932 933 num, err = qs.Filter("id__between", []int{2, 3}).Count() 934 throwFail(t, err) 935 throwFail(t, AssertIs(num, 2)) 936 937 num, err = qs.FilterRaw("user_name", "= 'slene'").Count() 938 throwFail(t, err) 939 throwFail(t, AssertIs(num, 1)) 940 941 num, err = qs.FilterRaw("status", "IN (1, 2)").Count() 942 throwFail(t, err) 943 throwFail(t, AssertIs(num, 2)) 944 945 num, err = qs.FilterRaw("profile_id", "IN (SELECT id FROM user_profile WHERE age=30)").Count() 946 throwFail(t, err) 947 throwFail(t, AssertIs(num, 1)) 948 } 949 950 func TestSetCond(t *testing.T) { 951 cond := NewCondition() 952 cond1 := cond.And("profile__isnull", false).AndNot("status__in", 1).Or("profile__age__gt", 2000) 953 954 qs := dORM.QueryTable("user") 955 num, err := qs.SetCond(cond1).Count() 956 throwFail(t, err) 957 throwFail(t, AssertIs(num, 1)) 958 959 cond2 := cond.AndCond(cond1).OrCond(cond.And("user_name", "slene")) 960 num, err = qs.SetCond(cond2).Count() 961 throwFail(t, err) 962 throwFail(t, AssertIs(num, 2)) 963 964 cond3 := cond.AndNotCond(cond.And("status__in", 1)) 965 num, err = qs.SetCond(cond3).Count() 966 throwFail(t, err) 967 throwFail(t, AssertIs(num, 2)) 968 969 cond4 := cond.And("user_name", "slene").OrNotCond(cond.And("user_name", "slene")) 970 num, err = qs.SetCond(cond4).Count() 971 throwFail(t, err) 972 throwFail(t, AssertIs(num, 3)) 973 974 cond5 := cond.Raw("user_name", "= 'slene'").OrNotCond(cond.And("user_name", "slene")) 975 num, err = qs.SetCond(cond5).Count() 976 throwFail(t, err) 977 throwFail(t, AssertIs(num, 3)) 978 } 979 980 func TestLimit(t *testing.T) { 981 var posts []*Post 982 qs := dORM.QueryTable("post") 983 num, err := qs.Limit(1).All(&posts) 984 throwFail(t, err) 985 throwFail(t, AssertIs(num, 1)) 986 987 num, err = qs.Limit(-1).All(&posts) 988 throwFail(t, err) 989 throwFail(t, AssertIs(num, 4)) 990 991 num, err = qs.Limit(-1, 2).All(&posts) 992 throwFail(t, err) 993 throwFail(t, AssertIs(num, 2)) 994 995 num, err = qs.Limit(0, 2).All(&posts) 996 throwFail(t, err) 997 throwFail(t, AssertIs(num, 2)) 998 } 999 1000 func TestOffset(t *testing.T) { 1001 var posts []*Post 1002 qs := dORM.QueryTable("post") 1003 num, err := qs.Limit(1).Offset(2).All(&posts) 1004 throwFail(t, err) 1005 throwFail(t, AssertIs(num, 1)) 1006 1007 num, err = qs.Offset(2).All(&posts) 1008 throwFail(t, err) 1009 throwFail(t, AssertIs(num, 2)) 1010 } 1011 1012 func TestOrderBy(t *testing.T) { 1013 qs := dORM.QueryTable("user") 1014 num, err := qs.OrderBy("-status").Filter("user_name", "nobody").Count() 1015 throwFail(t, err) 1016 throwFail(t, AssertIs(num, 1)) 1017 1018 num, err = qs.OrderBy("status").Filter("user_name", "slene").Count() 1019 throwFail(t, err) 1020 throwFail(t, AssertIs(num, 1)) 1021 1022 num, err = qs.OrderBy("-profile__age").Filter("user_name", "astaxie").Count() 1023 throwFail(t, err) 1024 throwFail(t, AssertIs(num, 1)) 1025 } 1026 1027 func TestAll(t *testing.T) { 1028 var users []*User 1029 qs := dORM.QueryTable("user") 1030 num, err := qs.OrderBy("Id").All(&users) 1031 throwFail(t, err) 1032 throwFailNow(t, AssertIs(num, 3)) 1033 1034 throwFail(t, AssertIs(users[0].UserName, "slene")) 1035 throwFail(t, AssertIs(users[1].UserName, "astaxie")) 1036 throwFail(t, AssertIs(users[2].UserName, "nobody")) 1037 1038 var users2 []User 1039 qs = dORM.QueryTable("user") 1040 num, err = qs.OrderBy("Id").All(&users2) 1041 throwFail(t, err) 1042 throwFailNow(t, AssertIs(num, 3)) 1043 1044 throwFailNow(t, AssertIs(users2[0].UserName, "slene")) 1045 throwFailNow(t, AssertIs(users2[1].UserName, "astaxie")) 1046 throwFailNow(t, AssertIs(users2[2].UserName, "nobody")) 1047 1048 qs = dORM.QueryTable("user") 1049 num, err = qs.OrderBy("Id").RelatedSel().All(&users2, "UserName") 1050 throwFail(t, err) 1051 throwFailNow(t, AssertIs(num, 3)) 1052 throwFailNow(t, AssertIs(len(users2), 3)) 1053 throwFailNow(t, AssertIs(users2[0].UserName, "slene")) 1054 throwFailNow(t, AssertIs(users2[1].UserName, "astaxie")) 1055 throwFailNow(t, AssertIs(users2[2].UserName, "nobody")) 1056 throwFailNow(t, AssertIs(users2[0].ID, 0)) 1057 throwFailNow(t, AssertIs(users2[1].ID, 0)) 1058 throwFailNow(t, AssertIs(users2[2].ID, 0)) 1059 throwFailNow(t, AssertIs(users2[0].Profile == nil, false)) 1060 throwFailNow(t, AssertIs(users2[1].Profile == nil, false)) 1061 throwFailNow(t, AssertIs(users2[2].Profile == nil, true)) 1062 1063 qs = dORM.QueryTable("user") 1064 num, err = qs.Filter("user_name", "nothing").All(&users) 1065 throwFailNow(t, err) 1066 throwFailNow(t, AssertIs(num, 0)) 1067 1068 var users3 []*User 1069 qs = dORM.QueryTable("user") 1070 num, err = qs.Filter("user_name", "nothing").All(&users3) 1071 throwFailNow(t, err) 1072 throwFailNow(t, AssertIs(num, 0)) 1073 throwFailNow(t, AssertIs(users3 == nil, false)) 1074 } 1075 1076 func TestOne(t *testing.T) { 1077 var user User 1078 qs := dORM.QueryTable("user") 1079 err := qs.One(&user) 1080 throwFail(t, err) 1081 1082 user = User{} 1083 err = qs.OrderBy("Id").Limit(1).One(&user) 1084 throwFailNow(t, err) 1085 throwFail(t, AssertIs(user.UserName, "slene")) 1086 throwFail(t, AssertNot(err, ErrMultiRows)) 1087 1088 user = User{} 1089 err = qs.OrderBy("-Id").Limit(100).One(&user) 1090 throwFailNow(t, err) 1091 throwFail(t, AssertIs(user.UserName, "nobody")) 1092 throwFail(t, AssertNot(err, ErrMultiRows)) 1093 1094 err = qs.Filter("user_name", "nothing").One(&user) 1095 throwFail(t, AssertIs(err, ErrNoRows)) 1096 1097 } 1098 1099 func TestValues(t *testing.T) { 1100 var maps []Params 1101 qs := dORM.QueryTable("user") 1102 1103 num, err := qs.OrderBy("Id").Values(&maps) 1104 throwFail(t, err) 1105 throwFail(t, AssertIs(num, 3)) 1106 if num == 3 { 1107 throwFail(t, AssertIs(maps[0]["UserName"], "slene")) 1108 throwFail(t, AssertIs(maps[2]["Profile"], nil)) 1109 } 1110 1111 num, err = qs.OrderBy("Id").Values(&maps, "UserName", "Profile__Age") 1112 throwFail(t, err) 1113 throwFail(t, AssertIs(num, 3)) 1114 if num == 3 { 1115 throwFail(t, AssertIs(maps[0]["UserName"], "slene")) 1116 throwFail(t, AssertIs(maps[0]["Profile__Age"], 28)) 1117 throwFail(t, AssertIs(maps[2]["Profile__Age"], nil)) 1118 } 1119 1120 num, err = qs.Filter("UserName", "slene").Values(&maps) 1121 throwFail(t, err) 1122 throwFail(t, AssertIs(num, 1)) 1123 } 1124 1125 func TestValuesList(t *testing.T) { 1126 var list []ParamsList 1127 qs := dORM.QueryTable("user") 1128 1129 num, err := qs.OrderBy("Id").ValuesList(&list) 1130 throwFail(t, err) 1131 throwFail(t, AssertIs(num, 3)) 1132 if num == 3 { 1133 throwFail(t, AssertIs(list[0][1], "slene")) 1134 throwFail(t, AssertIs(list[2][9], nil)) 1135 } 1136 1137 num, err = qs.OrderBy("Id").ValuesList(&list, "UserName", "Profile__Age") 1138 throwFail(t, err) 1139 throwFail(t, AssertIs(num, 3)) 1140 if num == 3 { 1141 throwFail(t, AssertIs(list[0][0], "slene")) 1142 throwFail(t, AssertIs(list[0][1], 28)) 1143 throwFail(t, AssertIs(list[2][1], nil)) 1144 } 1145 } 1146 1147 func TestValuesFlat(t *testing.T) { 1148 var list ParamsList 1149 qs := dORM.QueryTable("user") 1150 1151 num, err := qs.OrderBy("id").ValuesFlat(&list, "UserName") 1152 throwFail(t, err) 1153 throwFail(t, AssertIs(num, 3)) 1154 if num == 3 { 1155 throwFail(t, AssertIs(list[0], "slene")) 1156 throwFail(t, AssertIs(list[1], "astaxie")) 1157 throwFail(t, AssertIs(list[2], "nobody")) 1158 } 1159 } 1160 1161 func TestRelatedSel(t *testing.T) { 1162 if IsTidb { 1163 // Skip it. TiDB does not support relation now. 1164 return 1165 } 1166 qs := dORM.QueryTable("user") 1167 num, err := qs.Filter("profile__age", 28).Count() 1168 throwFail(t, err) 1169 throwFail(t, AssertIs(num, 1)) 1170 1171 num, err = qs.Filter("profile__age__gt", 28).Count() 1172 throwFail(t, err) 1173 throwFail(t, AssertIs(num, 1)) 1174 1175 num, err = qs.Filter("profile__user__profile__age__gt", 28).Count() 1176 throwFail(t, err) 1177 throwFail(t, AssertIs(num, 1)) 1178 1179 var user User 1180 err = qs.Filter("user_name", "slene").RelatedSel("profile").One(&user) 1181 throwFail(t, err) 1182 throwFail(t, AssertIs(num, 1)) 1183 throwFail(t, AssertNot(user.Profile, nil)) 1184 if user.Profile != nil { 1185 throwFail(t, AssertIs(user.Profile.Age, 28)) 1186 } 1187 1188 err = qs.Filter("user_name", "slene").RelatedSel().One(&user) 1189 throwFail(t, err) 1190 throwFail(t, AssertIs(num, 1)) 1191 throwFail(t, AssertNot(user.Profile, nil)) 1192 if user.Profile != nil { 1193 throwFail(t, AssertIs(user.Profile.Age, 28)) 1194 } 1195 1196 err = qs.Filter("user_name", "nobody").RelatedSel("profile").One(&user) 1197 throwFail(t, err) 1198 throwFail(t, AssertIs(num, 1)) 1199 throwFail(t, AssertIs(user.Profile, nil)) 1200 1201 qs = dORM.QueryTable("user_profile") 1202 num, err = qs.Filter("user__username", "slene").Count() 1203 throwFail(t, err) 1204 throwFail(t, AssertIs(num, 1)) 1205 1206 var posts []*Post 1207 qs = dORM.QueryTable("post") 1208 num, err = qs.RelatedSel().All(&posts) 1209 throwFail(t, err) 1210 throwFailNow(t, AssertIs(num, 4)) 1211 1212 throwFailNow(t, AssertIs(posts[0].User.UserName, "slene")) 1213 throwFailNow(t, AssertIs(posts[1].User.UserName, "astaxie")) 1214 throwFailNow(t, AssertIs(posts[2].User.UserName, "astaxie")) 1215 throwFailNow(t, AssertIs(posts[3].User.UserName, "nobody")) 1216 } 1217 1218 func TestReverseQuery(t *testing.T) { 1219 var profile Profile 1220 err := dORM.QueryTable("user_profile").Filter("User", 3).One(&profile) 1221 throwFailNow(t, err) 1222 throwFailNow(t, AssertIs(profile.Age, 30)) 1223 1224 profile = Profile{} 1225 err = dORM.QueryTable("user_profile").Filter("User__UserName", "astaxie").One(&profile) 1226 throwFailNow(t, err) 1227 throwFailNow(t, AssertIs(profile.Age, 30)) 1228 1229 var user User 1230 err = dORM.QueryTable("user").Filter("Posts__Title", "Examples").One(&user) 1231 throwFailNow(t, err) 1232 throwFailNow(t, AssertIs(user.UserName, "astaxie")) 1233 1234 user = User{} 1235 err = dORM.QueryTable("user").Filter("Posts__User__UserName", "astaxie").Limit(1).One(&user) 1236 throwFailNow(t, err) 1237 throwFailNow(t, AssertIs(user.UserName, "astaxie")) 1238 1239 user = User{} 1240 err = dORM.QueryTable("user").Filter("Posts__User__UserName", "astaxie").RelatedSel().Limit(1).One(&user) 1241 throwFailNow(t, err) 1242 throwFailNow(t, AssertIs(user.UserName, "astaxie")) 1243 throwFailNow(t, AssertIs(user.Profile == nil, false)) 1244 throwFailNow(t, AssertIs(user.Profile.Age, 30)) 1245 1246 var posts []*Post 1247 num, err := dORM.QueryTable("post").Filter("Tags__Tag__Name", "golang").All(&posts) 1248 throwFailNow(t, err) 1249 throwFailNow(t, AssertIs(num, 3)) 1250 throwFailNow(t, AssertIs(posts[0].Title, "Introduction")) 1251 1252 posts = []*Post{} 1253 num, err = dORM.QueryTable("post").Filter("Tags__Tag__Name", "golang").Filter("User__UserName", "slene").All(&posts) 1254 throwFailNow(t, err) 1255 throwFailNow(t, AssertIs(num, 1)) 1256 throwFailNow(t, AssertIs(posts[0].Title, "Introduction")) 1257 1258 posts = []*Post{} 1259 num, err = dORM.QueryTable("post").Filter("Tags__Tag__Name", "golang"). 1260 Filter("User__UserName", "slene").RelatedSel().All(&posts) 1261 throwFailNow(t, err) 1262 throwFailNow(t, AssertIs(num, 1)) 1263 throwFailNow(t, AssertIs(posts[0].User == nil, false)) 1264 throwFailNow(t, AssertIs(posts[0].User.UserName, "slene")) 1265 1266 var tags []*Tag 1267 num, err = dORM.QueryTable("tag").Filter("Posts__Post__Title", "Introduction").All(&tags) 1268 throwFailNow(t, err) 1269 throwFailNow(t, AssertIs(num, 1)) 1270 throwFailNow(t, AssertIs(tags[0].Name, "golang")) 1271 1272 tags = []*Tag{} 1273 num, err = dORM.QueryTable("tag").Filter("Posts__Post__Title", "Introduction"). 1274 Filter("BestPost__User__UserName", "astaxie").All(&tags) 1275 throwFailNow(t, err) 1276 throwFailNow(t, AssertIs(num, 1)) 1277 throwFailNow(t, AssertIs(tags[0].Name, "golang")) 1278 1279 tags = []*Tag{} 1280 num, err = dORM.QueryTable("tag").Filter("Posts__Post__Title", "Introduction"). 1281 Filter("BestPost__User__UserName", "astaxie").RelatedSel().All(&tags) 1282 throwFailNow(t, err) 1283 throwFailNow(t, AssertIs(num, 1)) 1284 throwFailNow(t, AssertIs(tags[0].Name, "golang")) 1285 throwFailNow(t, AssertIs(tags[0].BestPost == nil, false)) 1286 throwFailNow(t, AssertIs(tags[0].BestPost.Title, "Examples")) 1287 throwFailNow(t, AssertIs(tags[0].BestPost.User == nil, false)) 1288 throwFailNow(t, AssertIs(tags[0].BestPost.User.UserName, "astaxie")) 1289 } 1290 1291 func TestLoadRelated(t *testing.T) { 1292 // load reverse foreign key 1293 user := User{ID: 3} 1294 1295 err := dORM.Read(&user) 1296 throwFailNow(t, err) 1297 1298 num, err := dORM.LoadRelated(&user, "Posts") 1299 throwFailNow(t, err) 1300 throwFailNow(t, AssertIs(num, 2)) 1301 throwFailNow(t, AssertIs(len(user.Posts), 2)) 1302 throwFailNow(t, AssertIs(user.Posts[0].User.ID, 3)) 1303 1304 num, err = dORM.LoadRelated(&user, "Posts", true) 1305 throwFailNow(t, err) 1306 throwFailNow(t, AssertIs(num, 2)) 1307 throwFailNow(t, AssertIs(len(user.Posts), 2)) 1308 throwFailNow(t, AssertIs(user.Posts[0].User.UserName, "astaxie")) 1309 1310 num, err = dORM.LoadRelated(&user, "Posts", true, 1) 1311 throwFailNow(t, err) 1312 throwFailNow(t, AssertIs(num, 1)) 1313 throwFailNow(t, AssertIs(len(user.Posts), 1)) 1314 1315 num, err = dORM.LoadRelated(&user, "Posts", true, 0, 0, "-Id") 1316 throwFailNow(t, err) 1317 throwFailNow(t, AssertIs(num, 2)) 1318 throwFailNow(t, AssertIs(len(user.Posts), 2)) 1319 throwFailNow(t, AssertIs(user.Posts[0].Title, "Formatting")) 1320 1321 num, err = dORM.LoadRelated(&user, "Posts", true, 1, 1, "Id") 1322 throwFailNow(t, err) 1323 throwFailNow(t, AssertIs(num, 1)) 1324 throwFailNow(t, AssertIs(len(user.Posts), 1)) 1325 throwFailNow(t, AssertIs(user.Posts[0].Title, "Formatting")) 1326 1327 // load reverse one to one 1328 profile := Profile{ID: 3} 1329 profile.BestPost = &Post{ID: 2} 1330 num, err = dORM.Update(&profile, "BestPost") 1331 throwFailNow(t, err) 1332 throwFailNow(t, AssertIs(num, 1)) 1333 1334 err = dORM.Read(&profile) 1335 throwFailNow(t, err) 1336 1337 num, err = dORM.LoadRelated(&profile, "User") 1338 throwFailNow(t, err) 1339 throwFailNow(t, AssertIs(num, 1)) 1340 throwFailNow(t, AssertIs(profile.User == nil, false)) 1341 throwFailNow(t, AssertIs(profile.User.UserName, "astaxie")) 1342 1343 num, err = dORM.LoadRelated(&profile, "User", true) 1344 throwFailNow(t, err) 1345 throwFailNow(t, AssertIs(num, 1)) 1346 throwFailNow(t, AssertIs(profile.User == nil, false)) 1347 throwFailNow(t, AssertIs(profile.User.UserName, "astaxie")) 1348 throwFailNow(t, AssertIs(profile.User.Profile.Age, profile.Age)) 1349 1350 // load rel one to one 1351 err = dORM.Read(&user) 1352 throwFailNow(t, err) 1353 1354 num, err = dORM.LoadRelated(&user, "Profile") 1355 throwFailNow(t, err) 1356 throwFailNow(t, AssertIs(num, 1)) 1357 throwFailNow(t, AssertIs(user.Profile == nil, false)) 1358 throwFailNow(t, AssertIs(user.Profile.Age, 30)) 1359 1360 num, err = dORM.LoadRelated(&user, "Profile", true) 1361 throwFailNow(t, err) 1362 throwFailNow(t, AssertIs(num, 1)) 1363 throwFailNow(t, AssertIs(user.Profile == nil, false)) 1364 throwFailNow(t, AssertIs(user.Profile.Age, 30)) 1365 throwFailNow(t, AssertIs(user.Profile.BestPost == nil, false)) 1366 throwFailNow(t, AssertIs(user.Profile.BestPost.Title, "Examples")) 1367 1368 post := Post{ID: 2} 1369 1370 // load rel foreign key 1371 err = dORM.Read(&post) 1372 throwFailNow(t, err) 1373 1374 num, err = dORM.LoadRelated(&post, "User") 1375 throwFailNow(t, err) 1376 throwFailNow(t, AssertIs(num, 1)) 1377 throwFailNow(t, AssertIs(post.User == nil, false)) 1378 throwFailNow(t, AssertIs(post.User.UserName, "astaxie")) 1379 1380 num, err = dORM.LoadRelated(&post, "User", true) 1381 throwFailNow(t, err) 1382 throwFailNow(t, AssertIs(num, 1)) 1383 throwFailNow(t, AssertIs(post.User == nil, false)) 1384 throwFailNow(t, AssertIs(post.User.UserName, "astaxie")) 1385 throwFailNow(t, AssertIs(post.User.Profile == nil, false)) 1386 throwFailNow(t, AssertIs(post.User.Profile.Age, 30)) 1387 1388 // load rel m2m 1389 post = Post{ID: 2} 1390 1391 err = dORM.Read(&post) 1392 throwFailNow(t, err) 1393 1394 num, err = dORM.LoadRelated(&post, "Tags") 1395 throwFailNow(t, err) 1396 throwFailNow(t, AssertIs(num, 2)) 1397 throwFailNow(t, AssertIs(len(post.Tags), 2)) 1398 throwFailNow(t, AssertIs(post.Tags[0].Name, "golang")) 1399 1400 num, err = dORM.LoadRelated(&post, "Tags", true) 1401 throwFailNow(t, err) 1402 throwFailNow(t, AssertIs(num, 2)) 1403 throwFailNow(t, AssertIs(len(post.Tags), 2)) 1404 throwFailNow(t, AssertIs(post.Tags[0].Name, "golang")) 1405 throwFailNow(t, AssertIs(post.Tags[0].BestPost == nil, false)) 1406 throwFailNow(t, AssertIs(post.Tags[0].BestPost.User.UserName, "astaxie")) 1407 1408 // load reverse m2m 1409 tag := Tag{ID: 1} 1410 1411 err = dORM.Read(&tag) 1412 throwFailNow(t, err) 1413 1414 num, err = dORM.LoadRelated(&tag, "Posts") 1415 throwFailNow(t, err) 1416 throwFailNow(t, AssertIs(num, 3)) 1417 throwFailNow(t, AssertIs(tag.Posts[0].Title, "Introduction")) 1418 throwFailNow(t, AssertIs(tag.Posts[0].User.ID, 2)) 1419 throwFailNow(t, AssertIs(tag.Posts[0].User.Profile == nil, true)) 1420 1421 num, err = dORM.LoadRelated(&tag, "Posts", true) 1422 throwFailNow(t, err) 1423 throwFailNow(t, AssertIs(num, 3)) 1424 throwFailNow(t, AssertIs(tag.Posts[0].Title, "Introduction")) 1425 throwFailNow(t, AssertIs(tag.Posts[0].User.ID, 2)) 1426 throwFailNow(t, AssertIs(tag.Posts[0].User.UserName, "slene")) 1427 } 1428 1429 func TestQueryM2M(t *testing.T) { 1430 post := Post{ID: 4} 1431 m2m := dORM.QueryM2M(&post, "Tags") 1432 1433 tag1 := []*Tag{{Name: "TestTag1"}, {Name: "TestTag2"}} 1434 tag2 := &Tag{Name: "TestTag3"} 1435 tag3 := []interface{}{&Tag{Name: "TestTag4"}} 1436 1437 tags := []interface{}{tag1[0], tag1[1], tag2, tag3[0]} 1438 1439 for _, tag := range tags { 1440 _, err := dORM.Insert(tag) 1441 throwFailNow(t, err) 1442 } 1443 1444 num, err := m2m.Add(tag1) 1445 throwFailNow(t, err) 1446 throwFailNow(t, AssertIs(num, 2)) 1447 1448 num, err = m2m.Add(tag2) 1449 throwFailNow(t, err) 1450 throwFailNow(t, AssertIs(num, 1)) 1451 1452 num, err = m2m.Add(tag3) 1453 throwFailNow(t, err) 1454 throwFailNow(t, AssertIs(num, 1)) 1455 1456 num, err = m2m.Count() 1457 throwFailNow(t, err) 1458 throwFailNow(t, AssertIs(num, 5)) 1459 1460 num, err = m2m.Remove(tag3) 1461 throwFailNow(t, err) 1462 throwFailNow(t, AssertIs(num, 1)) 1463 1464 num, err = m2m.Count() 1465 throwFailNow(t, err) 1466 throwFailNow(t, AssertIs(num, 4)) 1467 1468 exist := m2m.Exist(tag2) 1469 throwFailNow(t, AssertIs(exist, true)) 1470 1471 num, err = m2m.Remove(tag2) 1472 throwFailNow(t, err) 1473 throwFailNow(t, AssertIs(num, 1)) 1474 1475 exist = m2m.Exist(tag2) 1476 throwFailNow(t, AssertIs(exist, false)) 1477 1478 num, err = m2m.Count() 1479 throwFailNow(t, err) 1480 throwFailNow(t, AssertIs(num, 3)) 1481 1482 num, err = m2m.Clear() 1483 throwFailNow(t, err) 1484 throwFailNow(t, AssertIs(num, 3)) 1485 1486 num, err = m2m.Count() 1487 throwFailNow(t, err) 1488 throwFailNow(t, AssertIs(num, 0)) 1489 1490 tag := Tag{Name: "test"} 1491 _, err = dORM.Insert(&tag) 1492 throwFailNow(t, err) 1493 1494 m2m = dORM.QueryM2M(&tag, "Posts") 1495 1496 post1 := []*Post{{Title: "TestPost1"}, {Title: "TestPost2"}} 1497 post2 := &Post{Title: "TestPost3"} 1498 post3 := []interface{}{&Post{Title: "TestPost4"}} 1499 1500 posts := []interface{}{post1[0], post1[1], post2, post3[0]} 1501 1502 for _, post := range posts { 1503 p := post.(*Post) 1504 p.User = &User{ID: 1} 1505 _, err := dORM.Insert(post) 1506 throwFailNow(t, err) 1507 } 1508 1509 num, err = m2m.Add(post1) 1510 throwFailNow(t, err) 1511 throwFailNow(t, AssertIs(num, 2)) 1512 1513 num, err = m2m.Add(post2) 1514 throwFailNow(t, err) 1515 throwFailNow(t, AssertIs(num, 1)) 1516 1517 num, err = m2m.Add(post3) 1518 throwFailNow(t, err) 1519 throwFailNow(t, AssertIs(num, 1)) 1520 1521 num, err = m2m.Count() 1522 throwFailNow(t, err) 1523 throwFailNow(t, AssertIs(num, 4)) 1524 1525 num, err = m2m.Remove(post3) 1526 throwFailNow(t, err) 1527 throwFailNow(t, AssertIs(num, 1)) 1528 1529 num, err = m2m.Count() 1530 throwFailNow(t, err) 1531 throwFailNow(t, AssertIs(num, 3)) 1532 1533 exist = m2m.Exist(post2) 1534 throwFailNow(t, AssertIs(exist, true)) 1535 1536 num, err = m2m.Remove(post2) 1537 throwFailNow(t, err) 1538 throwFailNow(t, AssertIs(num, 1)) 1539 1540 exist = m2m.Exist(post2) 1541 throwFailNow(t, AssertIs(exist, false)) 1542 1543 num, err = m2m.Count() 1544 throwFailNow(t, err) 1545 throwFailNow(t, AssertIs(num, 2)) 1546 1547 num, err = m2m.Clear() 1548 throwFailNow(t, err) 1549 throwFailNow(t, AssertIs(num, 2)) 1550 1551 num, err = m2m.Count() 1552 throwFailNow(t, err) 1553 throwFailNow(t, AssertIs(num, 0)) 1554 1555 num, err = dORM.Delete(&tag) 1556 throwFailNow(t, err) 1557 throwFailNow(t, AssertIs(num, 1)) 1558 } 1559 1560 func TestQueryRelate(t *testing.T) { 1561 // post := &Post{Id: 2} 1562 1563 // qs := dORM.QueryRelate(post, "Tags") 1564 // num, err := qs.Count() 1565 // throwFailNow(t, err) 1566 // throwFailNow(t, AssertIs(num, 2)) 1567 1568 // var tags []*Tag 1569 // num, err = qs.All(&tags) 1570 // throwFailNow(t, err) 1571 // throwFailNow(t, AssertIs(num, 2)) 1572 // throwFailNow(t, AssertIs(tags[0].Name, "golang")) 1573 1574 // num, err = dORM.QueryTable("Tag").Filter("Posts__Post", 2).Count() 1575 // throwFailNow(t, err) 1576 // throwFailNow(t, AssertIs(num, 2)) 1577 } 1578 1579 func TestPkManyRelated(t *testing.T) { 1580 permission := &Permission{Name: "readPosts"} 1581 err := dORM.Read(permission, "Name") 1582 throwFailNow(t, err) 1583 1584 var groups []*Group 1585 qs := dORM.QueryTable("Group") 1586 num, err := qs.Filter("Permissions__Permission", permission.ID).All(&groups) 1587 throwFailNow(t, err) 1588 throwFailNow(t, AssertIs(num, 2)) 1589 } 1590 1591 func TestPrepareInsert(t *testing.T) { 1592 qs := dORM.QueryTable("user") 1593 i, err := qs.PrepareInsert() 1594 throwFailNow(t, err) 1595 1596 var user User 1597 user.UserName = "testing1" 1598 num, err := i.Insert(&user) 1599 throwFail(t, err) 1600 throwFail(t, AssertIs(num > 0, true)) 1601 1602 user.UserName = "testing2" 1603 num, err = i.Insert(&user) 1604 throwFail(t, err) 1605 throwFail(t, AssertIs(num > 0, true)) 1606 1607 num, err = qs.Filter("user_name__in", "testing1", "testing2").Delete() 1608 throwFail(t, err) 1609 throwFail(t, AssertIs(num, 2)) 1610 1611 err = i.Close() 1612 throwFail(t, err) 1613 err = i.Close() 1614 throwFail(t, AssertIs(err, ErrStmtClosed)) 1615 } 1616 1617 func TestRawExec(t *testing.T) { 1618 Q := dDbBaser.TableQuote() 1619 1620 query := fmt.Sprintf("UPDATE %suser%s SET %suser_name%s = ? WHERE %suser_name%s = ?", Q, Q, Q, Q, Q, Q) 1621 res, err := dORM.Raw(query, "testing", "slene").Exec() 1622 throwFail(t, err) 1623 num, err := res.RowsAffected() 1624 throwFail(t, AssertIs(num, 1), err) 1625 1626 res, err = dORM.Raw(query, "slene", "testing").Exec() 1627 throwFail(t, err) 1628 num, err = res.RowsAffected() 1629 throwFail(t, AssertIs(num, 1), err) 1630 } 1631 1632 func TestRawQueryRow(t *testing.T) { 1633 var ( 1634 Boolean bool 1635 Char string 1636 Text string 1637 Time time.Time 1638 Date time.Time 1639 DateTime time.Time 1640 Byte byte 1641 Rune rune 1642 Int int 1643 Int8 int 1644 Int16 int16 1645 Int32 int32 1646 Int64 int64 1647 Uint uint 1648 Uint8 uint8 1649 Uint16 uint16 1650 Uint32 uint32 1651 Uint64 uint64 1652 Float32 float32 1653 Float64 float64 1654 Decimal float64 1655 ) 1656 1657 dataValues := make(map[string]interface{}, len(DataValues)) 1658 1659 for k, v := range DataValues { 1660 dataValues[strings.ToLower(k)] = v 1661 } 1662 1663 Q := dDbBaser.TableQuote() 1664 1665 cols := []string{ 1666 "id", "boolean", "char", "text", "time", "date", "datetime", "byte", "rune", "int", "int8", "int16", "int32", 1667 "int64", "uint", "uint8", "uint16", "uint32", "uint64", "float32", "float64", "decimal", 1668 } 1669 sep := fmt.Sprintf("%s, %s", Q, Q) 1670 query := fmt.Sprintf("SELECT %s%s%s FROM data WHERE id = ?", Q, strings.Join(cols, sep), Q) 1671 var id int 1672 values := []interface{}{ 1673 &id, &Boolean, &Char, &Text, &Time, &Date, &DateTime, &Byte, &Rune, &Int, &Int8, &Int16, &Int32, 1674 &Int64, &Uint, &Uint8, &Uint16, &Uint32, &Uint64, &Float32, &Float64, &Decimal, 1675 } 1676 err := dORM.Raw(query, 1).QueryRow(values...) 1677 throwFailNow(t, err) 1678 for i, col := range cols { 1679 vu := values[i] 1680 v := reflect.ValueOf(vu).Elem().Interface() 1681 switch col { 1682 case "id": 1683 throwFail(t, AssertIs(id, 1)) 1684 case "time": 1685 v = v.(time.Time).In(DefaultTimeLoc) 1686 value := dataValues[col].(time.Time).In(DefaultTimeLoc) 1687 throwFail(t, AssertIs(v, value, testTime)) 1688 case "date": 1689 v = v.(time.Time).In(DefaultTimeLoc) 1690 value := dataValues[col].(time.Time).In(DefaultTimeLoc) 1691 throwFail(t, AssertIs(v, value, testDate)) 1692 case "datetime": 1693 v = v.(time.Time).In(DefaultTimeLoc) 1694 value := dataValues[col].(time.Time).In(DefaultTimeLoc) 1695 throwFail(t, AssertIs(v, value, testDateTime)) 1696 default: 1697 throwFail(t, AssertIs(v, dataValues[col])) 1698 } 1699 } 1700 1701 var ( 1702 uid int 1703 status *int 1704 pid *int 1705 ) 1706 1707 cols = []string{ 1708 "id", "Status", "profile_id", 1709 } 1710 query = fmt.Sprintf("SELECT %s%s%s FROM %suser%s WHERE id = ?", Q, strings.Join(cols, sep), Q, Q, Q) 1711 err = dORM.Raw(query, 4).QueryRow(&uid, &status, &pid) 1712 throwFail(t, err) 1713 throwFail(t, AssertIs(uid, 4)) 1714 throwFail(t, AssertIs(*status, 3)) 1715 throwFail(t, AssertIs(pid, nil)) 1716 1717 // test for sql.Null* fields 1718 nData := &DataNull{ 1719 NullString: sql.NullString{String: "test sql.null", Valid: true}, 1720 NullBool: sql.NullBool{Bool: true, Valid: true}, 1721 NullInt64: sql.NullInt64{Int64: 42, Valid: true}, 1722 NullFloat64: sql.NullFloat64{Float64: 42.42, Valid: true}, 1723 } 1724 newId, err := dORM.Insert(nData) 1725 throwFailNow(t, err) 1726 1727 var nd *DataNull 1728 query = fmt.Sprintf("SELECT * FROM %sdata_null%s where id=?", Q, Q) 1729 err = dORM.Raw(query, newId).QueryRow(&nd) 1730 throwFailNow(t, err) 1731 1732 throwFailNow(t, AssertNot(nd, nil)) 1733 throwFail(t, AssertIs(nd.NullBool.Valid, true)) 1734 throwFail(t, AssertIs(nd.NullBool.Bool, true)) 1735 throwFail(t, AssertIs(nd.NullString.Valid, true)) 1736 throwFail(t, AssertIs(nd.NullString.String, "test sql.null")) 1737 throwFail(t, AssertIs(nd.NullInt64.Valid, true)) 1738 throwFail(t, AssertIs(nd.NullInt64.Int64, 42)) 1739 throwFail(t, AssertIs(nd.NullFloat64.Valid, true)) 1740 throwFail(t, AssertIs(nd.NullFloat64.Float64, 42.42)) 1741 } 1742 1743 // user_profile table 1744 type userProfile struct { 1745 User 1746 Age int 1747 Money float64 1748 } 1749 1750 func TestQueryRows(t *testing.T) { 1751 Q := dDbBaser.TableQuote() 1752 1753 var datas []*Data 1754 1755 query := fmt.Sprintf("SELECT * FROM %sdata%s", Q, Q) 1756 num, err := dORM.Raw(query).QueryRows(&datas) 1757 throwFailNow(t, err) 1758 throwFailNow(t, AssertIs(num, 1)) 1759 throwFailNow(t, AssertIs(len(datas), 1)) 1760 1761 ind := reflect.Indirect(reflect.ValueOf(datas[0])) 1762 1763 for name, value := range DataValues { 1764 e := ind.FieldByName(name) 1765 vu := e.Interface() 1766 switch name { 1767 case "Time": 1768 vu = vu.(time.Time).In(DefaultTimeLoc).Format(testTime) 1769 value = value.(time.Time).In(DefaultTimeLoc).Format(testTime) 1770 case "Date": 1771 vu = vu.(time.Time).In(DefaultTimeLoc).Format(testDate) 1772 value = value.(time.Time).In(DefaultTimeLoc).Format(testDate) 1773 case "DateTime": 1774 vu = vu.(time.Time).In(DefaultTimeLoc).Format(testDateTime) 1775 value = value.(time.Time).In(DefaultTimeLoc).Format(testDateTime) 1776 } 1777 throwFail(t, AssertIs(vu == value, true), value, vu) 1778 } 1779 1780 var datas2 []Data 1781 1782 query = fmt.Sprintf("SELECT * FROM %sdata%s", Q, Q) 1783 num, err = dORM.Raw(query).QueryRows(&datas2) 1784 throwFailNow(t, err) 1785 throwFailNow(t, AssertIs(num, 1)) 1786 throwFailNow(t, AssertIs(len(datas2), 1)) 1787 1788 ind = reflect.Indirect(reflect.ValueOf(datas2[0])) 1789 1790 for name, value := range DataValues { 1791 e := ind.FieldByName(name) 1792 vu := e.Interface() 1793 switch name { 1794 case "Time": 1795 vu = vu.(time.Time).In(DefaultTimeLoc).Format(testTime) 1796 value = value.(time.Time).In(DefaultTimeLoc).Format(testTime) 1797 case "Date": 1798 vu = vu.(time.Time).In(DefaultTimeLoc).Format(testDate) 1799 value = value.(time.Time).In(DefaultTimeLoc).Format(testDate) 1800 case "DateTime": 1801 vu = vu.(time.Time).In(DefaultTimeLoc).Format(testDateTime) 1802 value = value.(time.Time).In(DefaultTimeLoc).Format(testDateTime) 1803 } 1804 throwFail(t, AssertIs(vu == value, true), value, vu) 1805 } 1806 1807 var ids []int 1808 var usernames []string 1809 query = fmt.Sprintf("SELECT %sid%s, %suser_name%s FROM %suser%s ORDER BY %sid%s ASC", Q, Q, Q, Q, Q, Q, Q, Q) 1810 num, err = dORM.Raw(query).QueryRows(&ids, &usernames) 1811 throwFailNow(t, err) 1812 throwFailNow(t, AssertIs(num, 3)) 1813 throwFailNow(t, AssertIs(len(ids), 3)) 1814 throwFailNow(t, AssertIs(ids[0], 2)) 1815 throwFailNow(t, AssertIs(usernames[0], "slene")) 1816 throwFailNow(t, AssertIs(ids[1], 3)) 1817 throwFailNow(t, AssertIs(usernames[1], "astaxie")) 1818 throwFailNow(t, AssertIs(ids[2], 4)) 1819 throwFailNow(t, AssertIs(usernames[2], "nobody")) 1820 1821 //test query rows by nested struct 1822 var l []userProfile 1823 query = fmt.Sprintf("SELECT * FROM %suser_profile%s LEFT JOIN %suser%s ON %suser_profile%s.%sid%s = %suser%s.%sid%s", Q, Q, Q, Q, Q, Q, Q, Q, Q, Q, Q, Q) 1824 num, err = dORM.Raw(query).QueryRows(&l) 1825 throwFailNow(t, err) 1826 throwFailNow(t, AssertIs(num, 2)) 1827 throwFailNow(t, AssertIs(len(l), 2)) 1828 throwFailNow(t, AssertIs(l[0].UserName, "slene")) 1829 throwFailNow(t, AssertIs(l[0].Age, 28)) 1830 throwFailNow(t, AssertIs(l[1].UserName, "astaxie")) 1831 throwFailNow(t, AssertIs(l[1].Age, 30)) 1832 1833 // test for sql.Null* fields 1834 nData := &DataNull{ 1835 NullString: sql.NullString{String: "test sql.null", Valid: true}, 1836 NullBool: sql.NullBool{Bool: true, Valid: true}, 1837 NullInt64: sql.NullInt64{Int64: 42, Valid: true}, 1838 NullFloat64: sql.NullFloat64{Float64: 42.42, Valid: true}, 1839 } 1840 newId, err := dORM.Insert(nData) 1841 throwFailNow(t, err) 1842 1843 var nDataList []*DataNull 1844 query = fmt.Sprintf("SELECT * FROM %sdata_null%s where id=?", Q, Q) 1845 num, err = dORM.Raw(query, newId).QueryRows(&nDataList) 1846 throwFailNow(t, err) 1847 throwFailNow(t, AssertIs(num, 1)) 1848 1849 nd := nDataList[0] 1850 throwFailNow(t, AssertNot(nd, nil)) 1851 throwFail(t, AssertIs(nd.NullBool.Valid, true)) 1852 throwFail(t, AssertIs(nd.NullBool.Bool, true)) 1853 throwFail(t, AssertIs(nd.NullString.Valid, true)) 1854 throwFail(t, AssertIs(nd.NullString.String, "test sql.null")) 1855 throwFail(t, AssertIs(nd.NullInt64.Valid, true)) 1856 throwFail(t, AssertIs(nd.NullInt64.Int64, 42)) 1857 throwFail(t, AssertIs(nd.NullFloat64.Valid, true)) 1858 throwFail(t, AssertIs(nd.NullFloat64.Float64, 42.42)) 1859 } 1860 1861 func TestRawValues(t *testing.T) { 1862 Q := dDbBaser.TableQuote() 1863 1864 var maps []Params 1865 query := fmt.Sprintf("SELECT %suser_name%s FROM %suser%s WHERE %sStatus%s = ?", Q, Q, Q, Q, Q, Q) 1866 num, err := dORM.Raw(query, 1).Values(&maps) 1867 throwFail(t, err) 1868 throwFail(t, AssertIs(num, 1)) 1869 if num == 1 { 1870 throwFail(t, AssertIs(maps[0]["user_name"], "slene")) 1871 } 1872 1873 var lists []ParamsList 1874 num, err = dORM.Raw(query, 1).ValuesList(&lists) 1875 throwFail(t, err) 1876 throwFail(t, AssertIs(num, 1)) 1877 if num == 1 { 1878 throwFail(t, AssertIs(lists[0][0], "slene")) 1879 } 1880 1881 query = fmt.Sprintf("SELECT %sprofile_id%s FROM %suser%s ORDER BY %sid%s ASC", Q, Q, Q, Q, Q, Q) 1882 var list ParamsList 1883 num, err = dORM.Raw(query).ValuesFlat(&list) 1884 throwFail(t, err) 1885 throwFail(t, AssertIs(num, 3)) 1886 if num == 3 { 1887 throwFail(t, AssertIs(list[0], "2")) 1888 throwFail(t, AssertIs(list[1], "3")) 1889 throwFail(t, AssertIs(list[2], nil)) 1890 } 1891 } 1892 1893 func TestRawPrepare(t *testing.T) { 1894 switch { 1895 case IsMysql || IsSqlite: 1896 1897 pre, err := dORM.Raw("INSERT INTO tag (name) VALUES (?)").Prepare() 1898 throwFail(t, err) 1899 if pre != nil { 1900 r, err := pre.Exec("name1") 1901 throwFail(t, err) 1902 1903 tid, err := r.LastInsertId() 1904 throwFail(t, err) 1905 throwFail(t, AssertIs(tid > 0, true)) 1906 1907 r, err = pre.Exec("name2") 1908 throwFail(t, err) 1909 1910 id, err := r.LastInsertId() 1911 throwFail(t, err) 1912 throwFail(t, AssertIs(id, tid+1)) 1913 1914 r, err = pre.Exec("name3") 1915 throwFail(t, err) 1916 1917 id, err = r.LastInsertId() 1918 throwFail(t, err) 1919 throwFail(t, AssertIs(id, tid+2)) 1920 1921 err = pre.Close() 1922 throwFail(t, err) 1923 1924 res, err := dORM.Raw("DELETE FROM tag WHERE name IN (?, ?, ?)", []string{"name1", "name2", "name3"}).Exec() 1925 throwFail(t, err) 1926 1927 num, err := res.RowsAffected() 1928 throwFail(t, err) 1929 throwFail(t, AssertIs(num, 3)) 1930 } 1931 1932 case IsPostgres: 1933 1934 pre, err := dORM.Raw(`INSERT INTO "tag" ("name") VALUES (?) RETURNING "id"`).Prepare() 1935 throwFail(t, err) 1936 if pre != nil { 1937 _, err := pre.Exec("name1") 1938 throwFail(t, err) 1939 1940 _, err = pre.Exec("name2") 1941 throwFail(t, err) 1942 1943 _, err = pre.Exec("name3") 1944 throwFail(t, err) 1945 1946 err = pre.Close() 1947 throwFail(t, err) 1948 1949 res, err := dORM.Raw(`DELETE FROM "tag" WHERE "name" IN (?, ?, ?)`, []string{"name1", "name2", "name3"}).Exec() 1950 throwFail(t, err) 1951 1952 if err == nil { 1953 num, err := res.RowsAffected() 1954 throwFail(t, err) 1955 throwFail(t, AssertIs(num, 3)) 1956 } 1957 } 1958 } 1959 } 1960 1961 func TestUpdate(t *testing.T) { 1962 qs := dORM.QueryTable("user") 1963 num, err := qs.Filter("user_name", "slene").Filter("is_staff", false).Update(Params{ 1964 "is_staff": true, 1965 "is_active": true, 1966 }) 1967 throwFail(t, err) 1968 throwFail(t, AssertIs(num, 1)) 1969 1970 // with join 1971 num, err = qs.Filter("user_name", "slene").Filter("profile__age", 28).Filter("is_staff", true).Update(Params{ 1972 "is_staff": false, 1973 }) 1974 throwFail(t, err) 1975 throwFail(t, AssertIs(num, 1)) 1976 1977 num, err = qs.Filter("user_name", "slene").Update(Params{ 1978 "Nums": ColValue(ColAdd, 100), 1979 }) 1980 throwFail(t, err) 1981 throwFail(t, AssertIs(num, 1)) 1982 1983 num, err = qs.Filter("user_name", "slene").Update(Params{ 1984 "Nums": ColValue(ColMinus, 50), 1985 }) 1986 throwFail(t, err) 1987 throwFail(t, AssertIs(num, 1)) 1988 1989 num, err = qs.Filter("user_name", "slene").Update(Params{ 1990 "Nums": ColValue(ColMultiply, 3), 1991 }) 1992 throwFail(t, err) 1993 throwFail(t, AssertIs(num, 1)) 1994 1995 num, err = qs.Filter("user_name", "slene").Update(Params{ 1996 "Nums": ColValue(ColExcept, 5), 1997 }) 1998 throwFail(t, err) 1999 throwFail(t, AssertIs(num, 1)) 2000 2001 user := User{UserName: "slene"} 2002 err = dORM.Read(&user, "UserName") 2003 throwFail(t, err) 2004 throwFail(t, AssertIs(user.Nums, 30)) 2005 } 2006 2007 func TestDelete(t *testing.T) { 2008 qs := dORM.QueryTable("user_profile") 2009 num, err := qs.Filter("user__user_name", "slene").Delete() 2010 throwFail(t, err) 2011 throwFail(t, AssertIs(num, 1)) 2012 2013 qs = dORM.QueryTable("user") 2014 num, err = qs.Filter("user_name", "slene").Filter("profile__isnull", true).Count() 2015 throwFail(t, err) 2016 throwFail(t, AssertIs(num, 1)) 2017 2018 qs = dORM.QueryTable("comment") 2019 num, err = qs.Count() 2020 throwFail(t, err) 2021 throwFail(t, AssertIs(num, 6)) 2022 2023 qs = dORM.QueryTable("post") 2024 num, err = qs.Filter("Id", 3).Delete() 2025 throwFail(t, err) 2026 throwFail(t, AssertIs(num, 1)) 2027 2028 qs = dORM.QueryTable("comment") 2029 num, err = qs.Count() 2030 throwFail(t, err) 2031 throwFail(t, AssertIs(num, 4)) 2032 2033 qs = dORM.QueryTable("comment") 2034 num, err = qs.Filter("Post__User", 3).Delete() 2035 throwFail(t, err) 2036 throwFail(t, AssertIs(num, 3)) 2037 2038 qs = dORM.QueryTable("comment") 2039 num, err = qs.Count() 2040 throwFail(t, err) 2041 throwFail(t, AssertIs(num, 1)) 2042 } 2043 2044 func TestTransaction(t *testing.T) { 2045 // this test worked when database support transaction 2046 2047 o := NewOrm() 2048 err := o.Begin() 2049 throwFail(t, err) 2050 2051 var names = []string{"1", "2", "3"} 2052 2053 var tag Tag 2054 tag.Name = names[0] 2055 id, err := o.Insert(&tag) 2056 throwFail(t, err) 2057 throwFail(t, AssertIs(id > 0, true)) 2058 2059 num, err := o.QueryTable("tag").Filter("name", "golang").Update(Params{"name": names[1]}) 2060 throwFail(t, err) 2061 throwFail(t, AssertIs(num, 1)) 2062 2063 switch { 2064 case IsMysql || IsSqlite: 2065 res, err := o.Raw("INSERT INTO tag (name) VALUES (?)", names[2]).Exec() 2066 throwFail(t, err) 2067 if err == nil { 2068 id, err = res.LastInsertId() 2069 throwFail(t, err) 2070 throwFail(t, AssertIs(id > 0, true)) 2071 } 2072 } 2073 2074 err = o.Rollback() 2075 throwFail(t, err) 2076 2077 num, err = o.QueryTable("tag").Filter("name__in", names).Count() 2078 throwFail(t, err) 2079 throwFail(t, AssertIs(num, 0)) 2080 2081 err = o.Begin() 2082 throwFail(t, err) 2083 2084 tag.Name = "commit" 2085 id, err = o.Insert(&tag) 2086 throwFail(t, err) 2087 throwFail(t, AssertIs(id > 0, true)) 2088 2089 o.Commit() 2090 throwFail(t, err) 2091 2092 num, err = o.QueryTable("tag").Filter("name", "commit").Delete() 2093 throwFail(t, err) 2094 throwFail(t, AssertIs(num, 1)) 2095 2096 } 2097 2098 func TestTransactionIsolationLevel(t *testing.T) { 2099 // this test worked when database support transaction isolation level 2100 if IsSqlite { 2101 return 2102 } 2103 2104 o1 := NewOrm() 2105 o2 := NewOrm() 2106 2107 // start two transaction with isolation level repeatable read 2108 err := o1.BeginTx(context.Background(), &sql.TxOptions{Isolation: sql.LevelRepeatableRead}) 2109 throwFail(t, err) 2110 err = o2.BeginTx(context.Background(), &sql.TxOptions{Isolation: sql.LevelRepeatableRead}) 2111 throwFail(t, err) 2112 2113 // o1 insert tag 2114 var tag Tag 2115 tag.Name = "test-transaction" 2116 id, err := o1.Insert(&tag) 2117 throwFail(t, err) 2118 throwFail(t, AssertIs(id > 0, true)) 2119 2120 // o2 query tag table, no result 2121 num, err := o2.QueryTable("tag").Filter("name", "test-transaction").Count() 2122 throwFail(t, err) 2123 throwFail(t, AssertIs(num, 0)) 2124 2125 // o1 commit 2126 o1.Commit() 2127 2128 // o2 query tag table, still no result 2129 num, err = o2.QueryTable("tag").Filter("name", "test-transaction").Count() 2130 throwFail(t, err) 2131 throwFail(t, AssertIs(num, 0)) 2132 2133 // o2 commit and query tag table, get the result 2134 o2.Commit() 2135 num, err = o2.QueryTable("tag").Filter("name", "test-transaction").Count() 2136 throwFail(t, err) 2137 throwFail(t, AssertIs(num, 1)) 2138 2139 num, err = o1.QueryTable("tag").Filter("name", "test-transaction").Delete() 2140 throwFail(t, err) 2141 throwFail(t, AssertIs(num, 1)) 2142 } 2143 2144 func TestBeginTxWithContextCanceled(t *testing.T) { 2145 o := NewOrm() 2146 ctx, cancel := context.WithCancel(context.Background()) 2147 o.BeginTx(ctx, nil) 2148 id, err := o.Insert(&Tag{Name: "test-context"}) 2149 throwFail(t, err) 2150 throwFail(t, AssertIs(id > 0, true)) 2151 2152 // cancel the context before commit to make it error 2153 cancel() 2154 err = o.Commit() 2155 throwFail(t, AssertIs(err, context.Canceled)) 2156 } 2157 2158 func TestReadOrCreate(t *testing.T) { 2159 u := &User{ 2160 UserName: "Kyle", 2161 Email: "kylemcc@gmail.com", 2162 Password: "other_pass", 2163 Status: 7, 2164 IsStaff: false, 2165 IsActive: true, 2166 } 2167 2168 created, pk, err := dORM.ReadOrCreate(u, "UserName") 2169 throwFail(t, err) 2170 throwFail(t, AssertIs(created, true)) 2171 throwFail(t, AssertIs(u.ID, pk)) 2172 throwFail(t, AssertIs(u.UserName, "Kyle")) 2173 throwFail(t, AssertIs(u.Email, "kylemcc@gmail.com")) 2174 throwFail(t, AssertIs(u.Password, "other_pass")) 2175 throwFail(t, AssertIs(u.Status, 7)) 2176 throwFail(t, AssertIs(u.IsStaff, false)) 2177 throwFail(t, AssertIs(u.IsActive, true)) 2178 throwFail(t, AssertIs(u.Created.In(DefaultTimeLoc), u.Created.In(DefaultTimeLoc), testDate)) 2179 throwFail(t, AssertIs(u.Updated.In(DefaultTimeLoc), u.Updated.In(DefaultTimeLoc), testDateTime)) 2180 2181 nu := &User{UserName: u.UserName, Email: "someotheremail@gmail.com"} 2182 created, pk, err = dORM.ReadOrCreate(nu, "UserName") 2183 throwFail(t, err) 2184 throwFail(t, AssertIs(created, false)) 2185 throwFail(t, AssertIs(nu.ID, u.ID)) 2186 throwFail(t, AssertIs(pk, u.ID)) 2187 throwFail(t, AssertIs(nu.UserName, u.UserName)) 2188 throwFail(t, AssertIs(nu.Email, u.Email)) // should contain the value in the table, not the one specified above 2189 throwFail(t, AssertIs(nu.Password, u.Password)) 2190 throwFail(t, AssertIs(nu.Status, u.Status)) 2191 throwFail(t, AssertIs(nu.IsStaff, u.IsStaff)) 2192 throwFail(t, AssertIs(nu.IsActive, u.IsActive)) 2193 2194 dORM.Delete(u) 2195 } 2196 2197 func TestInLine(t *testing.T) { 2198 name := "inline" 2199 email := "hello@go.com" 2200 inline := NewInLine() 2201 inline.Name = name 2202 inline.Email = email 2203 2204 id, err := dORM.Insert(inline) 2205 throwFail(t, err) 2206 throwFail(t, AssertIs(id, 1)) 2207 2208 il := NewInLine() 2209 il.ID = 1 2210 err = dORM.Read(il) 2211 throwFail(t, err) 2212 2213 throwFail(t, AssertIs(il.Name, name)) 2214 throwFail(t, AssertIs(il.Email, email)) 2215 throwFail(t, AssertIs(il.Created.In(DefaultTimeLoc), inline.Created.In(DefaultTimeLoc), testDate)) 2216 throwFail(t, AssertIs(il.Updated.In(DefaultTimeLoc), inline.Updated.In(DefaultTimeLoc), testDateTime)) 2217 } 2218 2219 func TestInLineOneToOne(t *testing.T) { 2220 name := "121" 2221 email := "121@go.com" 2222 inline := NewInLine() 2223 inline.Name = name 2224 inline.Email = email 2225 2226 id, err := dORM.Insert(inline) 2227 throwFail(t, err) 2228 throwFail(t, AssertIs(id, 2)) 2229 2230 note := "one2one" 2231 il121 := NewInLineOneToOne() 2232 il121.Note = note 2233 il121.InLine = inline 2234 _, err = dORM.Insert(il121) 2235 throwFail(t, err) 2236 throwFail(t, AssertIs(il121.ID, 1)) 2237 2238 il := NewInLineOneToOne() 2239 err = dORM.QueryTable(il).Filter("Id", 1).RelatedSel().One(il) 2240 2241 throwFail(t, err) 2242 throwFail(t, AssertIs(il.Note, note)) 2243 throwFail(t, AssertIs(il.InLine.ID, id)) 2244 throwFail(t, AssertIs(il.InLine.Name, name)) 2245 throwFail(t, AssertIs(il.InLine.Email, email)) 2246 2247 rinline := NewInLine() 2248 err = dORM.QueryTable(rinline).Filter("InLineOneToOne__Id", 1).One(rinline) 2249 2250 throwFail(t, err) 2251 throwFail(t, AssertIs(rinline.ID, id)) 2252 throwFail(t, AssertIs(rinline.Name, name)) 2253 throwFail(t, AssertIs(rinline.Email, email)) 2254 } 2255 2256 func TestIntegerPk(t *testing.T) { 2257 its := []IntegerPk{ 2258 {ID: math.MinInt64, Value: "-"}, 2259 {ID: 0, Value: "0"}, 2260 {ID: math.MaxInt64, Value: "+"}, 2261 } 2262 2263 num, err := dORM.InsertMulti(len(its), its) 2264 throwFail(t, err) 2265 throwFail(t, AssertIs(num, len(its))) 2266 2267 for _, intPk := range its { 2268 out := IntegerPk{ID: intPk.ID} 2269 err = dORM.Read(&out) 2270 throwFail(t, err) 2271 throwFail(t, AssertIs(out.Value, intPk.Value)) 2272 } 2273 2274 num, err = dORM.InsertMulti(1, []*IntegerPk{{ 2275 ID: 1, Value: "ok", 2276 }}) 2277 throwFail(t, err) 2278 throwFail(t, AssertIs(num, 1)) 2279 } 2280 2281 func TestInsertAuto(t *testing.T) { 2282 u := &User{ 2283 UserName: "autoPre", 2284 Email: "autoPre@gmail.com", 2285 } 2286 2287 id, err := dORM.Insert(u) 2288 throwFail(t, err) 2289 2290 id += 100 2291 su := &User{ 2292 ID: int(id), 2293 UserName: "auto", 2294 Email: "auto@gmail.com", 2295 } 2296 2297 nid, err := dORM.Insert(su) 2298 throwFail(t, err) 2299 throwFail(t, AssertIs(nid, id)) 2300 2301 users := []User{ 2302 {ID: int(id + 100), UserName: "auto_100"}, 2303 {ID: int(id + 110), UserName: "auto_110"}, 2304 {ID: int(id + 120), UserName: "auto_120"}, 2305 } 2306 num, err := dORM.InsertMulti(100, users) 2307 throwFail(t, err) 2308 throwFail(t, AssertIs(num, 3)) 2309 2310 u = &User{ 2311 UserName: "auto_121", 2312 } 2313 2314 nid, err = dORM.Insert(u) 2315 throwFail(t, err) 2316 throwFail(t, AssertIs(nid, id+120+1)) 2317 } 2318 2319 func TestUintPk(t *testing.T) { 2320 name := "go" 2321 u := &UintPk{ 2322 ID: 8, 2323 Name: name, 2324 } 2325 2326 created, _, err := dORM.ReadOrCreate(u, "ID") 2327 throwFail(t, err) 2328 throwFail(t, AssertIs(created, true)) 2329 throwFail(t, AssertIs(u.Name, name)) 2330 2331 nu := &UintPk{ID: 8} 2332 created, pk, err := dORM.ReadOrCreate(nu, "ID") 2333 throwFail(t, err) 2334 throwFail(t, AssertIs(created, false)) 2335 throwFail(t, AssertIs(nu.ID, u.ID)) 2336 throwFail(t, AssertIs(pk, u.ID)) 2337 throwFail(t, AssertIs(nu.Name, name)) 2338 2339 dORM.Delete(u) 2340 } 2341 2342 func TestPtrPk(t *testing.T) { 2343 parent := &IntegerPk{ID: 10, Value: "10"} 2344 2345 id, _ := dORM.Insert(parent) 2346 if !IsMysql { 2347 // MySql does not support last_insert_id in this case: see #2382 2348 throwFail(t, AssertIs(id, 10)) 2349 } 2350 2351 ptr := PtrPk{ID: parent, Positive: true} 2352 num, err := dORM.InsertMulti(2, []PtrPk{ptr}) 2353 throwFail(t, err) 2354 throwFail(t, AssertIs(num, 1)) 2355 throwFail(t, AssertIs(ptr.ID, parent)) 2356 2357 nptr := &PtrPk{ID: parent} 2358 created, pk, err := dORM.ReadOrCreate(nptr, "ID") 2359 throwFail(t, err) 2360 throwFail(t, AssertIs(created, false)) 2361 throwFail(t, AssertIs(pk, 10)) 2362 throwFail(t, AssertIs(nptr.ID, parent)) 2363 throwFail(t, AssertIs(nptr.Positive, true)) 2364 2365 nptr = &PtrPk{Positive: true} 2366 created, pk, err = dORM.ReadOrCreate(nptr, "Positive") 2367 throwFail(t, err) 2368 throwFail(t, AssertIs(created, false)) 2369 throwFail(t, AssertIs(pk, 10)) 2370 throwFail(t, AssertIs(nptr.ID, parent)) 2371 2372 nptr.Positive = false 2373 num, err = dORM.Update(nptr) 2374 throwFail(t, err) 2375 throwFail(t, AssertIs(num, 1)) 2376 throwFail(t, AssertIs(nptr.ID, parent)) 2377 throwFail(t, AssertIs(nptr.Positive, false)) 2378 2379 num, err = dORM.Delete(nptr) 2380 throwFail(t, err) 2381 throwFail(t, AssertIs(num, 1)) 2382 } 2383 2384 func TestSnake(t *testing.T) { 2385 cases := map[string]string{ 2386 "i": "i", 2387 "I": "i", 2388 "iD": "i_d", 2389 "ID": "i_d", 2390 "NO": "n_o", 2391 "NOO": "n_o_o", 2392 "NOOooOOoo": "n_o_ooo_o_ooo", 2393 "OrderNO": "order_n_o", 2394 "tagName": "tag_name", 2395 "tag_Name": "tag__name", 2396 "tag_name": "tag_name", 2397 "_tag_name": "_tag_name", 2398 "tag_666name": "tag_666name", 2399 "tag_666Name": "tag_666_name", 2400 } 2401 for name, want := range cases { 2402 got := snakeString(name) 2403 throwFail(t, AssertIs(got, want)) 2404 } 2405 } 2406 2407 func TestIgnoreCaseTag(t *testing.T) { 2408 type testTagModel struct { 2409 ID int `orm:"pk"` 2410 NOO string `orm:"column(n)"` 2411 Name01 string `orm:"NULL"` 2412 Name02 string `orm:"COLUMN(Name)"` 2413 Name03 string `orm:"Column(name)"` 2414 } 2415 modelCache.clean() 2416 RegisterModel(&testTagModel{}) 2417 info, ok := modelCache.get("test_tag_model") 2418 throwFail(t, AssertIs(ok, true)) 2419 throwFail(t, AssertNot(info, nil)) 2420 if t == nil { 2421 return 2422 } 2423 throwFail(t, AssertIs(info.fields.GetByName("NOO").column, "n")) 2424 throwFail(t, AssertIs(info.fields.GetByName("Name01").null, true)) 2425 throwFail(t, AssertIs(info.fields.GetByName("Name02").column, "Name")) 2426 throwFail(t, AssertIs(info.fields.GetByName("Name03").column, "name")) 2427 } 2428 2429 func TestInsertOrUpdate(t *testing.T) { 2430 RegisterModel(new(User)) 2431 user := User{UserName: "unique_username133", Status: 1, Password: "o"} 2432 user1 := User{UserName: "unique_username133", Status: 2, Password: "o"} 2433 user2 := User{UserName: "unique_username133", Status: 3, Password: "oo"} 2434 dORM.Insert(&user) 2435 test := User{UserName: "unique_username133"} 2436 fmt.Println(dORM.Driver().Name()) 2437 if dORM.Driver().Name() == "sqlite3" { 2438 fmt.Println("sqlite3 is nonsupport") 2439 return 2440 } 2441 //test1 2442 _, err := dORM.InsertOrUpdate(&user1, "user_name") 2443 if err != nil { 2444 fmt.Println(err) 2445 if err.Error() == "postgres version must 9.5 or higher" || err.Error() == "`sqlite3` nonsupport InsertOrUpdate in beego" { 2446 } else { 2447 throwFailNow(t, err) 2448 } 2449 } else { 2450 dORM.Read(&test, "user_name") 2451 throwFailNow(t, AssertIs(user1.Status, test.Status)) 2452 } 2453 //test2 2454 _, err = dORM.InsertOrUpdate(&user2, "user_name") 2455 if err != nil { 2456 fmt.Println(err) 2457 if err.Error() == "postgres version must 9.5 or higher" || err.Error() == "`sqlite3` nonsupport InsertOrUpdate in beego" { 2458 } else { 2459 throwFailNow(t, err) 2460 } 2461 } else { 2462 dORM.Read(&test, "user_name") 2463 throwFailNow(t, AssertIs(user2.Status, test.Status)) 2464 throwFailNow(t, AssertIs(user2.Password, strings.TrimSpace(test.Password))) 2465 } 2466 2467 //postgres ON CONFLICT DO UPDATE SET can`t use colu=colu+values 2468 if IsPostgres { 2469 return 2470 } 2471 //test3 + 2472 _, err = dORM.InsertOrUpdate(&user2, "user_name", "status=status+1") 2473 if err != nil { 2474 fmt.Println(err) 2475 if err.Error() == "postgres version must 9.5 or higher" || err.Error() == "`sqlite3` nonsupport InsertOrUpdate in beego" { 2476 } else { 2477 throwFailNow(t, err) 2478 } 2479 } else { 2480 dORM.Read(&test, "user_name") 2481 throwFailNow(t, AssertIs(user2.Status+1, test.Status)) 2482 } 2483 //test4 - 2484 _, err = dORM.InsertOrUpdate(&user2, "user_name", "status=status-1") 2485 if err != nil { 2486 fmt.Println(err) 2487 if err.Error() == "postgres version must 9.5 or higher" || err.Error() == "`sqlite3` nonsupport InsertOrUpdate in beego" { 2488 } else { 2489 throwFailNow(t, err) 2490 } 2491 } else { 2492 dORM.Read(&test, "user_name") 2493 throwFailNow(t, AssertIs((user2.Status+1)-1, test.Status)) 2494 } 2495 //test5 * 2496 _, err = dORM.InsertOrUpdate(&user2, "user_name", "status=status*3") 2497 if err != nil { 2498 fmt.Println(err) 2499 if err.Error() == "postgres version must 9.5 or higher" || err.Error() == "`sqlite3` nonsupport InsertOrUpdate in beego" { 2500 } else { 2501 throwFailNow(t, err) 2502 } 2503 } else { 2504 dORM.Read(&test, "user_name") 2505 throwFailNow(t, AssertIs(((user2.Status+1)-1)*3, test.Status)) 2506 } 2507 //test6 / 2508 _, err = dORM.InsertOrUpdate(&user2, "user_name", "Status=Status/3") 2509 if err != nil { 2510 fmt.Println(err) 2511 if err.Error() == "postgres version must 9.5 or higher" || err.Error() == "`sqlite3` nonsupport InsertOrUpdate in beego" { 2512 } else { 2513 throwFailNow(t, err) 2514 } 2515 } else { 2516 dORM.Read(&test, "user_name") 2517 throwFailNow(t, AssertIs((((user2.Status+1)-1)*3)/3, test.Status)) 2518 } 2519 }