2020-05-23 11:08:50 +03:00
package tests_test
import (
2020-09-03 15:59:41 +03:00
"errors"
2023-11-15 16:32:56 +03:00
"fmt"
2020-12-15 10:35:11 +03:00
"regexp"
2020-05-23 11:08:50 +03:00
"testing"
2020-05-31 06:34:59 +03:00
"time"
2020-05-23 11:08:50 +03:00
2020-06-02 04:25:55 +03:00
"github.com/jinzhu/now"
2020-06-02 04:16:07 +03:00
"gorm.io/gorm"
2020-06-20 12:21:01 +03:00
"gorm.io/gorm/clause"
2020-06-02 05:34:50 +03:00
. "gorm.io/gorm/utils/tests"
2020-05-23 11:08:50 +03:00
)
func TestCreate ( t * testing . T ) {
2022-01-06 10:02:53 +03:00
user := * GetUser ( "create" , Config { } )
2020-05-23 11:08:50 +03:00
2020-05-31 06:19:45 +03:00
if results := DB . Create ( & user ) ; results . Error != nil {
t . Fatalf ( "errors happened when create: %v" , results . Error )
} else if results . RowsAffected != 1 {
t . Fatalf ( "rows affected expects: %v, got %v" , 1 , results . RowsAffected )
2020-05-23 11:08:50 +03:00
}
if user . ID == 0 {
t . Errorf ( "user's primary key should has value after create, got : %v" , user . ID )
}
if user . CreatedAt . IsZero ( ) {
t . Errorf ( "user's created at should be not zero" )
}
if user . UpdatedAt . IsZero ( ) {
t . Errorf ( "user's updated at should be not zero" )
}
var newUser User
if err := DB . Where ( "id = ?" , user . ID ) . First ( & newUser ) . Error ; err != nil {
2020-05-23 11:38:13 +03:00
t . Fatalf ( "errors happened when query: %v" , err )
2020-05-23 11:08:50 +03:00
} else {
2020-05-23 11:38:13 +03:00
CheckUser ( t , newUser , user )
2020-05-23 11:08:50 +03:00
}
}
2020-11-16 16:42:30 +03:00
func TestCreateInBatches ( t * testing . T ) {
users := [ ] User {
* GetUser ( "create_in_batches_1" , Config { Account : true , Pets : 2 , Toys : 3 , Company : true , Manager : true , Team : 0 , Languages : 1 , Friends : 1 } ) ,
* GetUser ( "create_in_batches_2" , Config { Account : false , Pets : 2 , Toys : 4 , Company : false , Manager : false , Team : 1 , Languages : 3 , Friends : 5 } ) ,
* GetUser ( "create_in_batches_3" , Config { Account : true , Pets : 0 , Toys : 3 , Company : true , Manager : false , Team : 4 , Languages : 0 , Friends : 1 } ) ,
* GetUser ( "create_in_batches_4" , Config { Account : true , Pets : 3 , Toys : 0 , Company : false , Manager : true , Team : 0 , Languages : 3 , Friends : 0 } ) ,
* GetUser ( "create_in_batches_5" , Config { Account : false , Pets : 0 , Toys : 3 , Company : true , Manager : false , Team : 1 , Languages : 3 , Friends : 1 } ) ,
* GetUser ( "create_in_batches_6" , Config { Account : true , Pets : 4 , Toys : 3 , Company : false , Manager : true , Team : 1 , Languages : 3 , Friends : 0 } ) ,
}
2020-12-02 09:59:50 +03:00
result := DB . CreateInBatches ( & users , 2 )
if result . RowsAffected != int64 ( len ( users ) ) {
t . Errorf ( "affected rows should be %v, but got %v" , len ( users ) , result . RowsAffected )
}
for _ , user := range users {
if user . ID == 0 {
t . Fatalf ( "failed to fill user's ID, got %v" , user . ID )
} else {
var newUser User
if err := DB . Where ( "id = ?" , user . ID ) . Preload ( clause . Associations ) . First ( & newUser ) . Error ; err != nil {
t . Fatalf ( "errors happened when query: %v" , err )
} else {
CheckUser ( t , newUser , user )
}
}
}
}
func TestCreateInBatchesWithDefaultSize ( t * testing . T ) {
users := [ ] User {
* GetUser ( "create_with_default_batch_size_1" , Config { Account : true , Pets : 2 , Toys : 3 , Company : true , Manager : true , Team : 0 , Languages : 1 , Friends : 1 } ) ,
* GetUser ( "create_with_default_batch_sizs_2" , Config { Account : false , Pets : 2 , Toys : 4 , Company : false , Manager : false , Team : 1 , Languages : 3 , Friends : 5 } ) ,
* GetUser ( "create_with_default_batch_sizs_3" , Config { Account : true , Pets : 0 , Toys : 3 , Company : true , Manager : false , Team : 4 , Languages : 0 , Friends : 1 } ) ,
* GetUser ( "create_with_default_batch_sizs_4" , Config { Account : true , Pets : 3 , Toys : 0 , Company : false , Manager : true , Team : 0 , Languages : 3 , Friends : 0 } ) ,
* GetUser ( "create_with_default_batch_sizs_5" , Config { Account : false , Pets : 0 , Toys : 3 , Company : true , Manager : false , Team : 1 , Languages : 3 , Friends : 1 } ) ,
* GetUser ( "create_with_default_batch_sizs_6" , Config { Account : true , Pets : 4 , Toys : 3 , Company : false , Manager : true , Team : 1 , Languages : 3 , Friends : 0 } ) ,
}
result := DB . Session ( & gorm . Session { CreateBatchSize : 2 } ) . Create ( & users )
if result . RowsAffected != int64 ( len ( users ) ) {
t . Errorf ( "affected rows should be %v, but got %v" , len ( users ) , result . RowsAffected )
}
2020-11-16 16:42:30 +03:00
for _ , user := range users {
if user . ID == 0 {
t . Fatalf ( "failed to fill user's ID, got %v" , user . ID )
} else {
var newUser User
if err := DB . Where ( "id = ?" , user . ID ) . Preload ( clause . Associations ) . First ( & newUser ) . Error ; err != nil {
t . Fatalf ( "errors happened when query: %v" , err )
} else {
CheckUser ( t , newUser , user )
}
}
}
}
2020-08-17 12:41:36 +03:00
func TestCreateFromMap ( t * testing . T ) {
if err := DB . Model ( & User { } ) . Create ( map [ string ] interface { } { "Name" : "create_from_map" , "Age" : 18 } ) . Error ; err != nil {
t . Fatalf ( "failed to create data from map, got error: %v" , err )
}
var result User
if err := DB . Where ( "name = ?" , "create_from_map" ) . First ( & result ) . Error ; err != nil || result . Age != 18 {
t . Fatalf ( "failed to create from map, got error %v" , err )
}
if err := DB . Model ( & User { } ) . Create ( map [ string ] interface { } { "name" : "create_from_map_1" , "age" : 18 } ) . Error ; err != nil {
t . Fatalf ( "failed to create data from map, got error: %v" , err )
}
var result1 User
if err := DB . Where ( "name = ?" , "create_from_map_1" ) . First ( & result1 ) . Error ; err != nil || result1 . Age != 18 {
t . Fatalf ( "failed to create from map, got error %v" , err )
}
datas := [ ] map [ string ] interface { } {
{ "Name" : "create_from_map_2" , "Age" : 19 } ,
{ "name" : "create_from_map_3" , "Age" : 20 } ,
}
2022-02-16 10:30:43 +03:00
if err := DB . Model ( & User { } ) . Create ( & datas ) . Error ; err != nil {
2020-08-17 12:41:36 +03:00
t . Fatalf ( "failed to create data from slice of map, got error: %v" , err )
}
var result2 User
if err := DB . Where ( "name = ?" , "create_from_map_2" ) . First ( & result2 ) . Error ; err != nil || result2 . Age != 19 {
t . Fatalf ( "failed to query data after create from slice of map, got error %v" , err )
}
var result3 User
if err := DB . Where ( "name = ?" , "create_from_map_3" ) . First ( & result3 ) . Error ; err != nil || result3 . Age != 20 {
t . Fatalf ( "failed to query data after create from slice of map, got error %v" , err )
}
}
2020-05-23 11:38:13 +03:00
func TestCreateWithAssociations ( t * testing . T ) {
2022-01-06 10:02:53 +03:00
user := * GetUser ( "create_with_associations" , Config {
2020-05-23 11:38:13 +03:00
Account : true ,
Pets : 2 ,
Toys : 3 ,
Company : true ,
Manager : true ,
Team : 4 ,
Languages : 3 ,
Friends : 1 ,
} )
if err := DB . Create ( & user ) . Error ; err != nil {
t . Fatalf ( "errors happened when create: %v" , err )
2020-05-23 11:08:50 +03:00
}
2020-05-23 11:38:13 +03:00
CheckUser ( t , user , user )
2020-05-23 11:08:50 +03:00
2020-05-23 11:38:13 +03:00
var user2 User
2020-05-23 16:35:12 +03:00
DB . Preload ( "Account" ) . Preload ( "Pets" ) . Preload ( "Toys" ) . Preload ( "Company" ) . Preload ( "Manager" ) . Preload ( "Team" ) . Preload ( "Languages" ) . Preload ( "Friends" ) . Find ( & user2 , "id = ?" , user . ID )
2020-05-23 11:38:13 +03:00
CheckUser ( t , user2 , user )
}
2020-05-23 11:08:50 +03:00
2020-05-23 16:03:28 +03:00
func TestBulkCreateWithAssociations ( t * testing . T ) {
users := [ ] User {
* GetUser ( "bulk_1" , Config { Account : true , Pets : 2 , Toys : 3 , Company : true , Manager : true , Team : 0 , Languages : 1 , Friends : 1 } ) ,
* GetUser ( "bulk_2" , Config { Account : false , Pets : 2 , Toys : 4 , Company : false , Manager : false , Team : 1 , Languages : 3 , Friends : 5 } ) ,
* GetUser ( "bulk_3" , Config { Account : true , Pets : 0 , Toys : 3 , Company : true , Manager : false , Team : 4 , Languages : 0 , Friends : 1 } ) ,
* GetUser ( "bulk_4" , Config { Account : true , Pets : 3 , Toys : 0 , Company : false , Manager : true , Team : 0 , Languages : 3 , Friends : 0 } ) ,
* GetUser ( "bulk_5" , Config { Account : false , Pets : 0 , Toys : 3 , Company : true , Manager : false , Team : 1 , Languages : 3 , Friends : 1 } ) ,
* GetUser ( "bulk_6" , Config { Account : true , Pets : 4 , Toys : 3 , Company : false , Manager : true , Team : 1 , Languages : 3 , Friends : 0 } ) ,
* GetUser ( "bulk_7" , Config { Account : true , Pets : 1 , Toys : 3 , Company : true , Manager : true , Team : 4 , Languages : 3 , Friends : 1 } ) ,
* GetUser ( "bulk_8" , Config { Account : false , Pets : 0 , Toys : 0 , Company : false , Manager : false , Team : 0 , Languages : 0 , Friends : 0 } ) ,
}
2020-05-31 06:19:45 +03:00
if results := DB . Create ( & users ) ; results . Error != nil {
t . Fatalf ( "errors happened when create: %v" , results . Error )
} else if results . RowsAffected != int64 ( len ( users ) ) {
t . Fatalf ( "rows affected expects: %v, got %v" , len ( users ) , results . RowsAffected )
2020-05-23 16:03:28 +03:00
}
var userIDs [ ] uint
for _ , user := range users {
userIDs = append ( userIDs , user . ID )
CheckUser ( t , user , user )
}
var users2 [ ] User
DB . Preload ( "Account" ) . Preload ( "Pets" ) . Preload ( "Toys" ) . Preload ( "Company" ) . Preload ( "Manager" ) . Preload ( "Team" ) . Preload ( "Languages" ) . Preload ( "Friends" ) . Find ( & users2 , "id IN ?" , userIDs )
for idx , user := range users2 {
CheckUser ( t , user , users [ idx ] )
}
}
2020-05-23 11:38:13 +03:00
2020-05-23 16:35:12 +03:00
func TestBulkCreatePtrDataWithAssociations ( t * testing . T ) {
users := [ ] * User {
GetUser ( "bulk_ptr_1" , Config { Account : true , Pets : 2 , Toys : 3 , Company : true , Manager : true , Team : 0 , Languages : 1 , Friends : 1 } ) ,
GetUser ( "bulk_ptr_2" , Config { Account : false , Pets : 2 , Toys : 4 , Company : false , Manager : false , Team : 1 , Languages : 3 , Friends : 5 } ) ,
GetUser ( "bulk_ptr_3" , Config { Account : true , Pets : 0 , Toys : 3 , Company : true , Manager : false , Team : 4 , Languages : 0 , Friends : 1 } ) ,
GetUser ( "bulk_ptr_4" , Config { Account : true , Pets : 3 , Toys : 0 , Company : false , Manager : true , Team : 0 , Languages : 3 , Friends : 0 } ) ,
GetUser ( "bulk_ptr_5" , Config { Account : false , Pets : 0 , Toys : 3 , Company : true , Manager : false , Team : 1 , Languages : 3 , Friends : 1 } ) ,
GetUser ( "bulk_ptr_6" , Config { Account : true , Pets : 4 , Toys : 3 , Company : false , Manager : true , Team : 1 , Languages : 3 , Friends : 0 } ) ,
GetUser ( "bulk_ptr_7" , Config { Account : true , Pets : 1 , Toys : 3 , Company : true , Manager : true , Team : 4 , Languages : 3 , Friends : 1 } ) ,
GetUser ( "bulk_ptr_8" , Config { Account : false , Pets : 0 , Toys : 0 , Company : false , Manager : false , Team : 0 , Languages : 0 , Friends : 0 } ) ,
}
2020-05-23 11:08:50 +03:00
2020-05-23 16:35:12 +03:00
if err := DB . Create ( & users ) . Error ; err != nil {
t . Fatalf ( "errors happened when create: %v" , err )
}
2020-05-23 11:08:50 +03:00
2020-05-23 16:35:12 +03:00
var userIDs [ ] uint
for _ , user := range users {
userIDs = append ( userIDs , user . ID )
CheckUser ( t , * user , * user )
}
2020-05-23 11:08:50 +03:00
2020-05-23 16:35:12 +03:00
var users2 [ ] User
DB . Preload ( "Account" ) . Preload ( "Pets" ) . Preload ( "Toys" ) . Preload ( "Company" ) . Preload ( "Manager" ) . Preload ( "Team" ) . Preload ( "Languages" ) . Preload ( "Friends" ) . Find ( & users2 , "id IN ?" , userIDs )
for idx , user := range users2 {
CheckUser ( t , user , * users [ idx ] )
}
}
2020-05-23 11:08:50 +03:00
2020-05-23 16:35:12 +03:00
func TestPolymorphicHasOne ( t * testing . T ) {
t . Run ( "Struct" , func ( t * testing . T ) {
2022-01-06 10:02:53 +03:00
pet := Pet {
2020-05-23 16:35:12 +03:00
Name : "PolymorphicHasOne" ,
Toy : Toy { Name : "Toy-PolymorphicHasOne" } ,
}
2020-05-23 11:08:50 +03:00
2020-05-23 16:35:12 +03:00
if err := DB . Create ( & pet ) . Error ; err != nil {
t . Fatalf ( "errors happened when create: %v" , err )
}
2020-05-23 11:08:50 +03:00
2020-05-23 16:35:12 +03:00
CheckPet ( t , pet , pet )
2020-05-23 11:08:50 +03:00
2020-05-23 16:35:12 +03:00
var pet2 Pet
DB . Preload ( "Toy" ) . Find ( & pet2 , "id = ?" , pet . ID )
CheckPet ( t , pet2 , pet )
} )
2020-05-23 11:08:50 +03:00
2020-05-23 16:35:12 +03:00
t . Run ( "Slice" , func ( t * testing . T ) {
2022-01-06 10:02:53 +03:00
pets := [ ] Pet { {
2020-05-23 16:35:12 +03:00
Name : "PolymorphicHasOne-Slice-1" ,
Toy : Toy { Name : "Toy-PolymorphicHasOne-Slice-1" } ,
} , {
Name : "PolymorphicHasOne-Slice-2" ,
Toy : Toy { Name : "Toy-PolymorphicHasOne-Slice-2" } ,
} , {
Name : "PolymorphicHasOne-Slice-3" ,
Toy : Toy { Name : "Toy-PolymorphicHasOne-Slice-3" } ,
} }
if err := DB . Create ( & pets ) . Error ; err != nil {
t . Fatalf ( "errors happened when create: %v" , err )
}
var petIDs [ ] uint
for _ , pet := range pets {
petIDs = append ( petIDs , pet . ID )
CheckPet ( t , pet , pet )
}
var pets2 [ ] Pet
DB . Preload ( "Toy" ) . Find ( & pets2 , "id IN ?" , petIDs )
for idx , pet := range pets2 {
CheckPet ( t , pet , pets [ idx ] )
}
} )
2020-05-23 11:08:50 +03:00
2020-05-23 16:35:12 +03:00
t . Run ( "SliceOfPtr" , func ( t * testing . T ) {
2022-01-06 10:02:53 +03:00
pets := [ ] * Pet { {
2020-05-23 16:35:12 +03:00
Name : "PolymorphicHasOne-Slice-1" ,
Toy : Toy { Name : "Toy-PolymorphicHasOne-Slice-1" } ,
} , {
Name : "PolymorphicHasOne-Slice-2" ,
Toy : Toy { Name : "Toy-PolymorphicHasOne-Slice-2" } ,
} , {
Name : "PolymorphicHasOne-Slice-3" ,
Toy : Toy { Name : "Toy-PolymorphicHasOne-Slice-3" } ,
} }
if err := DB . Create ( & pets ) . Error ; err != nil {
t . Fatalf ( "errors happened when create: %v" , err )
}
for _ , pet := range pets {
CheckPet ( t , * pet , * pet )
}
} )
2020-06-23 09:38:36 +03:00
t . Run ( "Array" , func ( t * testing . T ) {
2022-01-06 10:02:53 +03:00
pets := [ ... ] Pet { {
2020-06-23 09:38:36 +03:00
Name : "PolymorphicHasOne-Array-1" ,
Toy : Toy { Name : "Toy-PolymorphicHasOne-Array-1" } ,
} , {
Name : "PolymorphicHasOne-Array-2" ,
Toy : Toy { Name : "Toy-PolymorphicHasOne-Array-2" } ,
} , {
Name : "PolymorphicHasOne-Array-3" ,
Toy : Toy { Name : "Toy-PolymorphicHasOne-Array-3" } ,
} }
if err := DB . Create ( & pets ) . Error ; err != nil {
t . Fatalf ( "errors happened when create: %v" , err )
}
for _ , pet := range pets {
CheckPet ( t , pet , pet )
}
} )
t . Run ( "ArrayPtr" , func ( t * testing . T ) {
2022-01-06 10:02:53 +03:00
pets := [ ... ] * Pet { {
2020-06-23 09:38:36 +03:00
Name : "PolymorphicHasOne-Array-1" ,
Toy : Toy { Name : "Toy-PolymorphicHasOne-Array-1" } ,
} , {
Name : "PolymorphicHasOne-Array-2" ,
Toy : Toy { Name : "Toy-PolymorphicHasOne-Array-2" } ,
} , {
Name : "PolymorphicHasOne-Array-3" ,
Toy : Toy { Name : "Toy-PolymorphicHasOne-Array-3" } ,
} }
if err := DB . Create ( & pets ) . Error ; err != nil {
t . Fatalf ( "errors happened when create: %v" , err )
}
for _ , pet := range pets {
CheckPet ( t , * pet , * pet )
}
} )
2020-05-23 16:35:12 +03:00
}
2020-05-31 06:19:45 +03:00
2020-06-14 04:24:07 +03:00
func TestCreateEmptyStruct ( t * testing . T ) {
2020-05-31 06:19:45 +03:00
type EmptyStruct struct {
ID uint
}
DB . Migrator ( ) . DropTable ( & EmptyStruct { } )
if err := DB . AutoMigrate ( & EmptyStruct { } ) ; err != nil {
t . Errorf ( "no error should happen when auto migrate, but got %v" , err )
}
if err := DB . Create ( & EmptyStruct { } ) . Error ; err != nil {
t . Errorf ( "No error should happen when creating user, but got %v" , err )
}
}
2020-05-31 06:34:59 +03:00
2020-09-03 06:32:30 +03:00
func TestCreateEmptySlice ( t * testing . T ) {
2022-01-06 10:02:53 +03:00
data := [ ] User { }
2020-09-03 06:32:30 +03:00
if err := DB . Create ( & data ) . Error ; err != gorm . ErrEmptySlice {
t . Errorf ( "no data should be created, got %v" , err )
}
2022-01-06 10:02:53 +03:00
sliceMap := [ ] map [ string ] interface { } { }
2020-09-03 06:32:30 +03:00
if err := DB . Model ( & User { } ) . Create ( & sliceMap ) . Error ; err != gorm . ErrEmptySlice {
t . Errorf ( "no data should be created, got %v" , err )
}
}
2020-09-03 15:59:41 +03:00
func TestCreateInvalidSlice ( t * testing . T ) {
users := [ ] * User {
GetUser ( "invalid_slice_1" , Config { } ) ,
GetUser ( "invalid_slice_2" , Config { } ) ,
nil ,
}
if err := DB . Create ( & users ) . Error ; ! errors . Is ( err , gorm . ErrInvalidData ) {
t . Errorf ( "should returns error invalid data when creating from slice that contains invalid data" )
}
}
2020-05-31 06:34:59 +03:00
func TestCreateWithExistingTimestamp ( t * testing . T ) {
user := User { Name : "CreateUserExistingTimestamp" }
curTime := now . MustParse ( "2016-01-01" )
user . CreatedAt = curTime
user . UpdatedAt = curTime
DB . Save ( & user )
AssertEqual ( t , user . CreatedAt , curTime )
AssertEqual ( t , user . UpdatedAt , curTime )
var newUser User
DB . First ( & newUser , user . ID )
AssertEqual ( t , newUser . CreatedAt , curTime )
AssertEqual ( t , newUser . UpdatedAt , curTime )
}
func TestCreateWithNowFuncOverride ( t * testing . T ) {
user := User { Name : "CreateUserTimestampOverride" }
curTime := now . MustParse ( "2016-01-01" )
NEW := DB . Session ( & gorm . Session {
NowFunc : func ( ) time . Time {
return curTime
} ,
} )
NEW . Save ( & user )
AssertEqual ( t , user . CreatedAt , curTime )
AssertEqual ( t , user . UpdatedAt , curTime )
var newUser User
NEW . First ( & newUser , user . ID )
AssertEqual ( t , newUser . CreatedAt , curTime )
AssertEqual ( t , newUser . UpdatedAt , curTime )
}
2020-05-31 07:52:49 +03:00
2020-06-14 04:24:07 +03:00
func TestCreateWithNoGORMPrimaryKey ( t * testing . T ) {
2020-05-31 07:52:49 +03:00
type JoinTable struct {
UserID uint
FriendID uint
}
DB . Migrator ( ) . DropTable ( & JoinTable { } )
if err := DB . AutoMigrate ( & JoinTable { } ) ; err != nil {
t . Errorf ( "no error should happen when auto migrate, but got %v" , err )
}
jt := JoinTable { UserID : 1 , FriendID : 2 }
err := DB . Create ( & jt ) . Error
if err != nil {
t . Errorf ( "No error should happen when create a record without a GORM primary key. But in the database this primary key exists and is the union of 2 or more fields\n But got: %s" , err )
}
}
2020-05-31 08:34:53 +03:00
func TestSelectWithCreate ( t * testing . T ) {
user := * GetUser ( "select_create" , Config { Account : true , Pets : 3 , Toys : 3 , Company : true , Manager : true , Team : 3 , Languages : 3 , Friends : 4 } )
2020-07-05 06:53:10 +03:00
DB . Select ( "Account" , "Toys" , "Manager" , "ManagerID" , "Languages" , "Name" , "CreatedAt" , "Age" , "Active" ) . Create ( & user )
2020-05-31 08:34:53 +03:00
var user2 User
DB . Preload ( "Account" ) . Preload ( "Pets" ) . Preload ( "Toys" ) . Preload ( "Company" ) . Preload ( "Manager" ) . Preload ( "Team" ) . Preload ( "Languages" ) . Preload ( "Friends" ) . First ( & user2 , user . ID )
user . Birthday = nil
user . Pets = nil
user . Company = Company { }
user . Team = nil
user . Friends = nil
CheckUser ( t , user2 , user )
}
func TestOmitWithCreate ( t * testing . T ) {
user := * GetUser ( "omit_create" , Config { Account : true , Pets : 3 , Toys : 3 , Company : true , Manager : true , Team : 3 , Languages : 3 , Friends : 4 } )
DB . Omit ( "Account" , "Toys" , "Manager" , "Birthday" ) . Create ( & user )
2020-06-20 12:21:01 +03:00
var result User
DB . Preload ( "Account" ) . Preload ( "Pets" ) . Preload ( "Toys" ) . Preload ( "Company" ) . Preload ( "Manager" ) . Preload ( "Team" ) . Preload ( "Languages" ) . Preload ( "Friends" ) . First ( & result , user . ID )
2020-05-31 08:34:53 +03:00
user . Birthday = nil
user . Account = Account { }
user . Toys = nil
user . Manager = nil
2020-06-20 12:21:01 +03:00
CheckUser ( t , result , user )
user2 := * GetUser ( "omit_create" , Config { Account : true , Pets : 3 , Toys : 3 , Company : true , Manager : true , Team : 3 , Languages : 3 , Friends : 4 } )
DB . Omit ( clause . Associations ) . Create ( & user2 )
var result2 User
DB . Preload ( clause . Associations ) . First ( & result2 , user2 . ID )
user2 . Account = Account { }
user2 . Toys = nil
user2 . Manager = nil
user2 . Company = Company { }
user2 . Pets = nil
user2 . Team = nil
user2 . Languages = nil
user2 . Friends = nil
CheckUser ( t , result2 , user2 )
2020-05-31 08:34:53 +03:00
}
2020-07-23 18:41:56 +03:00
2022-05-28 17:18:43 +03:00
func TestFirstOrCreateNotExistsTable ( t * testing . T ) {
company := Company { Name : "first_or_create_if_not_exists_table" }
if err := DB . Table ( "not_exists" ) . FirstOrCreate ( & company ) . Error ; err == nil {
t . Errorf ( "not exists table, but err is nil" )
}
}
2020-07-23 18:41:56 +03:00
func TestFirstOrCreateWithPrimaryKey ( t * testing . T ) {
company := Company { ID : 100 , Name : "company100_with_primarykey" }
DB . FirstOrCreate ( & company )
if company . ID != 100 {
t . Errorf ( "invalid primary key after creating, got %v" , company . ID )
}
companies := [ ] Company {
{ ID : 101 , Name : "company101_with_primarykey" } ,
{ ID : 102 , Name : "company102_with_primarykey" } ,
}
DB . Create ( & companies )
if companies [ 0 ] . ID != 101 || companies [ 1 ] . ID != 102 {
t . Errorf ( "invalid primary key after creating, got %v, %v" , companies [ 0 ] . ID , companies [ 1 ] . ID )
}
}
2020-12-15 10:35:11 +03:00
func TestCreateFromSubQuery ( t * testing . T ) {
user := User { Name : "jinzhu" }
DB . Create ( & user )
subQuery := DB . Table ( "users" ) . Where ( "name=?" , user . Name ) . Select ( "id" )
result := DB . Session ( & gorm . Session { DryRun : true } ) . Model ( & Pet { } ) . Create ( [ ] map [ string ] interface { } {
{
"name" : "cat" ,
"user_id" : gorm . Expr ( "(?)" , DB . Table ( "(?) as tmp" , subQuery ) . Select ( "@uid:=id" ) ) ,
} ,
{
"name" : "dog" ,
"user_id" : gorm . Expr ( "@uid" ) ,
} ,
} )
if ! regexp . MustCompile ( ` INSERT INTO .pets. \(.name.,.user_id.\) .*VALUES \(.+,\(SELECT @uid:=id FROM \(SELECT id FROM .users. WHERE name=.+\) as tmp\)\),\(.+,@uid\) ` ) . MatchString ( result . Statement . SQL . String ( ) ) {
t . Errorf ( "invalid insert SQL, got %v" , result . Statement . SQL . String ( ) )
}
}
2021-10-12 16:19:08 +03:00
func TestCreateNilPointer ( t * testing . T ) {
var user * User
err := DB . Create ( user ) . Error
if err == nil || err != gorm . ErrInvalidValue {
t . Fatalf ( "it is not ErrInvalidValue" )
}
}
2022-04-13 10:52:07 +03:00
func TestFirstOrCreateRowsAffected ( t * testing . T ) {
user := User { Name : "TestFirstOrCreateRowsAffected" }
res := DB . FirstOrCreate ( & user , "name = ?" , user . Name )
if res . Error != nil || res . RowsAffected != 1 {
t . Fatalf ( "first or create rows affect err:%v rows:%d" , res . Error , res . RowsAffected )
}
res = DB . FirstOrCreate ( & user , "name = ?" , user . Name )
if res . Error != nil || res . RowsAffected != 0 {
t . Fatalf ( "first or create rows affect err:%v rows:%d" , res . Error , res . RowsAffected )
}
}
2023-03-10 11:35:26 +03:00
2023-03-10 11:50:03 +03:00
func TestCreateWithAutoIncrementCompositeKey ( t * testing . T ) {
type CompositeKeyProduct struct {
ProductID int ` gorm:"primaryKey;autoIncrement:true;" ` // primary key
LanguageCode int ` gorm:"primaryKey;" ` // primary key
Code string
Name string
}
2023-04-21 17:09:38 +03:00
if err := DB . Migrator ( ) . DropTable ( & CompositeKeyProduct { } ) ; err != nil {
t . Fatalf ( "failed to migrate, got error %v" , err )
}
2023-03-10 11:50:03 +03:00
if err := DB . AutoMigrate ( & CompositeKeyProduct { } ) ; err != nil {
t . Fatalf ( "failed to migrate, got error %v" , err )
}
prod := & CompositeKeyProduct {
LanguageCode : 56 ,
Code : "Code56" ,
Name : "ProductName56" ,
}
if err := DB . Create ( & prod ) . Error ; err != nil {
t . Fatalf ( "failed to create, got error %v" , err )
}
newProd := & CompositeKeyProduct { }
if err := DB . First ( & newProd ) . Error ; err != nil {
t . Fatalf ( "errors happened when query: %v" , err )
} else {
AssertObjEqual ( t , newProd , prod , "ProductID" , "LanguageCode" , "Code" , "Name" )
}
}
2023-11-15 16:32:56 +03:00
func TestCreateOnConflictWithDefaultNull ( t * testing . T ) {
2024-03-07 09:18:31 +03:00
type OnConflictUser struct {
2023-03-10 11:35:26 +03:00
ID string
Name string ` gorm:"default:null" `
Email string
Mobile string ` gorm:"default:'133xxxx'" `
}
2024-03-07 09:18:31 +03:00
err := DB . Migrator ( ) . DropTable ( & OnConflictUser { } )
2023-03-10 11:35:26 +03:00
AssertEqual ( t , err , nil )
2024-03-07 09:18:31 +03:00
err = DB . AutoMigrate ( & OnConflictUser { } )
2023-03-10 11:35:26 +03:00
AssertEqual ( t , err , nil )
2024-03-07 09:18:31 +03:00
u := OnConflictUser {
ID : "on-conflict-user-id" ,
Name : "on-conflict-user-name" ,
Email : "on-conflict-user-email" ,
Mobile : "on-conflict-user-mobile" ,
2023-03-10 11:35:26 +03:00
}
err = DB . Create ( & u ) . Error
AssertEqual ( t , err , nil )
2024-03-07 09:18:31 +03:00
u . Name = "on-conflict-user-name-2"
u . Email = "on-conflict-user-email-2"
2023-03-10 11:35:26 +03:00
u . Mobile = ""
err = DB . Clauses ( clause . OnConflict { UpdateAll : true } ) . Create ( & u ) . Error
AssertEqual ( t , err , nil )
2024-03-07 09:18:31 +03:00
var u2 OnConflictUser
2023-03-10 11:35:26 +03:00
err = DB . Where ( "id = ?" , u . ID ) . First ( & u2 ) . Error
AssertEqual ( t , err , nil )
2024-03-07 09:18:31 +03:00
AssertEqual ( t , u2 . Name , "on-conflict-user-name-2" )
AssertEqual ( t , u2 . Email , "on-conflict-user-email-2" )
2023-03-10 11:35:26 +03:00
AssertEqual ( t , u2 . Mobile , "133xxxx" )
}
2023-11-15 16:32:56 +03:00
func TestCreateFromMapWithoutPK ( t * testing . T ) {
if ! isMysql ( ) {
2024-03-07 09:18:31 +03:00
t . Skipf ( "This test case skipped, because of only supporting for mysql" )
2023-11-15 16:32:56 +03:00
}
// case 1: one record, create from map[string]interface{}
mapValue1 := map [ string ] interface { } { "name" : "create_from_map_with_schema1" , "age" : 1 }
if err := DB . Model ( & User { } ) . Create ( mapValue1 ) . Error ; err != nil {
t . Fatalf ( "failed to create data from map, got error: %v" , err )
}
if _ , ok := mapValue1 [ "id" ] ; ! ok {
t . Fatal ( "failed to create data from map with table, returning map has no primary key" )
}
var result1 User
if err := DB . Where ( "name = ?" , "create_from_map_with_schema1" ) . First ( & result1 ) . Error ; err != nil || result1 . Age != 1 {
t . Fatalf ( "failed to create from map, got error %v" , err )
}
var idVal int64
_ , ok := mapValue1 [ "id" ] . ( uint )
if ok {
t . Skipf ( "This test case skipped, because the db supports returning" )
}
idVal , ok = mapValue1 [ "id" ] . ( int64 )
if ! ok {
t . Fatal ( "ret result missing id" )
}
if int64 ( result1 . ID ) != idVal {
t . Fatal ( "failed to create data from map with table, @id != id" )
}
// case2: one record, create from *map[string]interface{}
mapValue2 := map [ string ] interface { } { "name" : "create_from_map_with_schema2" , "age" : 1 }
if err := DB . Model ( & User { } ) . Create ( & mapValue2 ) . Error ; err != nil {
t . Fatalf ( "failed to create data from map, got error: %v" , err )
}
if _ , ok := mapValue2 [ "id" ] ; ! ok {
t . Fatal ( "failed to create data from map with table, returning map has no primary key" )
}
var result2 User
if err := DB . Where ( "name = ?" , "create_from_map_with_schema2" ) . First ( & result2 ) . Error ; err != nil || result2 . Age != 1 {
t . Fatalf ( "failed to create from map, got error %v" , err )
}
_ , ok = mapValue2 [ "id" ] . ( uint )
if ok {
t . Skipf ( "This test case skipped, because the db supports returning" )
}
idVal , ok = mapValue2 [ "id" ] . ( int64 )
if ! ok {
t . Fatal ( "ret result missing id" )
}
if int64 ( result2 . ID ) != idVal {
t . Fatal ( "failed to create data from map with table, @id != id" )
}
// case 3: records
values := [ ] map [ string ] interface { } {
{ "name" : "create_from_map_with_schema11" , "age" : 1 } , { "name" : "create_from_map_with_schema12" , "age" : 1 } ,
}
beforeLen := len ( values )
if err := DB . Model ( & User { } ) . Create ( & values ) . Error ; err != nil {
t . Fatalf ( "failed to create data from map, got error: %v" , err )
}
// mariadb with returning, values will be appended with id map
if len ( values ) == beforeLen * 2 {
t . Skipf ( "This test case skipped, because the db supports returning" )
}
for i := range values {
v , ok := values [ i ] [ "id" ]
if ! ok {
t . Fatal ( "failed to create data from map with table, returning map has no primary key" )
}
var result User
if err := DB . Where ( "name = ?" , fmt . Sprintf ( "create_from_map_with_schema1%d" , i + 1 ) ) . First ( & result ) . Error ; err != nil || result . Age != 1 {
t . Fatalf ( "failed to create from map, got error %v" , err )
}
if int64 ( result . ID ) != v . ( int64 ) {
t . Fatal ( "failed to create data from map with table, @id != id" )
}
}
}
func TestCreateFromMapWithTable ( t * testing . T ) {
2024-03-19 06:50:28 +03:00
tableDB := DB . Table ( "users" )
supportLastInsertID := isMysql ( ) || isSqlite ( )
2023-11-15 16:32:56 +03:00
// case 1: create from map[string]interface{}
2024-03-19 06:50:28 +03:00
record := map [ string ] interface { } { "name" : "create_from_map_with_table" , "age" : 18 }
2023-11-15 16:32:56 +03:00
if err := tableDB . Create ( record ) . Error ; err != nil {
t . Fatalf ( "failed to create data from map with table, got error: %v" , err )
}
2024-03-19 06:50:28 +03:00
if _ , ok := record [ "@id" ] ; ! ok && supportLastInsertID {
2023-11-15 16:32:56 +03:00
t . Fatal ( "failed to create data from map with table, returning map has no key '@id'" )
}
var res map [ string ] interface { }
if err := tableDB . Select ( [ ] string { "id" , "name" , "age" } ) . Where ( "name = ?" , "create_from_map_with_table" ) . Find ( & res ) . Error ; err != nil || res [ "age" ] != int64 ( 18 ) {
t . Fatalf ( "failed to create from map, got error %v" , err )
}
2024-03-19 06:50:28 +03:00
if _ , ok := record [ "@id" ] ; ok && fmt . Sprint ( res [ "id" ] ) != fmt . Sprint ( record [ "@id" ] ) {
t . Fatalf ( "failed to create data from map with table, @id != id, got %v, expect %v" , res [ "id" ] , record [ "@id" ] )
2023-11-15 16:32:56 +03:00
}
// case 2: create from *map[string]interface{}
record1 := map [ string ] interface { } { "name" : "create_from_map_with_table_1" , "age" : 18 }
tableDB2 := DB . Table ( "users" )
if err := tableDB2 . Create ( & record1 ) . Error ; err != nil {
t . Fatalf ( "failed to create data from map, got error: %v" , err )
}
2024-03-19 06:50:28 +03:00
if _ , ok := record1 [ "@id" ] ; ! ok && supportLastInsertID {
2023-11-15 16:32:56 +03:00
t . Fatal ( "failed to create data from map with table, returning map has no key '@id'" )
}
var res1 map [ string ] interface { }
if err := tableDB2 . Select ( [ ] string { "id" , "name" , "age" } ) . Where ( "name = ?" , "create_from_map_with_table_1" ) . Find ( & res1 ) . Error ; err != nil || res1 [ "age" ] != int64 ( 18 ) {
t . Fatalf ( "failed to create from map, got error %v" , err )
}
2024-03-19 06:50:28 +03:00
if _ , ok := record1 [ "@id" ] ; ok && fmt . Sprint ( res1 [ "id" ] ) != fmt . Sprint ( record1 [ "@id" ] ) {
2023-11-15 16:32:56 +03:00
t . Fatal ( "failed to create data from map with table, @id != id" )
}
// case 3: create from []map[string]interface{}
records := [ ] map [ string ] interface { } {
{ "name" : "create_from_map_with_table_2" , "age" : 19 } ,
{ "name" : "create_from_map_with_table_3" , "age" : 20 } ,
}
tableDB = DB . Table ( "users" )
if err := tableDB . Create ( & records ) . Error ; err != nil {
t . Fatalf ( "failed to create data from slice of map, got error: %v" , err )
}
2024-03-19 06:50:28 +03:00
if _ , ok := records [ 0 ] [ "@id" ] ; ! ok && supportLastInsertID {
2023-11-15 16:32:56 +03:00
t . Fatal ( "failed to create data from map with table, returning map has no key '@id'" )
}
2024-03-19 06:50:28 +03:00
if _ , ok := records [ 1 ] [ "@id" ] ; ! ok && supportLastInsertID {
2023-11-15 16:32:56 +03:00
t . Fatal ( "failed to create data from map with table, returning map has no key '@id'" )
}
var res2 map [ string ] interface { }
if err := tableDB . Select ( [ ] string { "id" , "name" , "age" } ) . Where ( "name = ?" , "create_from_map_with_table_2" ) . Find ( & res2 ) . Error ; err != nil || res2 [ "age" ] != int64 ( 19 ) {
t . Fatalf ( "failed to query data after create from slice of map, got error %v" , err )
}
var res3 map [ string ] interface { }
if err := DB . Table ( "users" ) . Select ( [ ] string { "id" , "name" , "age" } ) . Where ( "name = ?" , "create_from_map_with_table_3" ) . Find ( & res3 ) . Error ; err != nil || res3 [ "age" ] != int64 ( 20 ) {
t . Fatalf ( "failed to query data after create from slice of map, got error %v" , err )
}
2024-03-19 06:50:28 +03:00
if _ , ok := records [ 0 ] [ "@id" ] ; ok && fmt . Sprint ( res2 [ "id" ] ) != fmt . Sprint ( records [ 0 ] [ "@id" ] ) {
t . Errorf ( "failed to create data from map with table, @id != id, got %v, expect %v" , res2 [ "id" ] , records [ 0 ] [ "@id" ] )
2023-11-15 16:32:56 +03:00
}
2024-03-19 06:50:28 +03:00
if _ , ok := records [ 1 ] [ "id" ] ; ok && fmt . Sprint ( res3 [ "id" ] ) != fmt . Sprint ( records [ 1 ] [ "@id" ] ) {
t . Errorf ( "failed to create data from map with table, @id != id" )
2023-11-15 16:32:56 +03:00
}
}