Skip to content

Commit debc5f1

Browse files
committed
fix: Assigning nil value to *uuid.UUID field in Updates
This PR adds handling for the assignment of a nil value to a *uuid.UUID field (resolved as a reflect.Ptr to a reflect.Array), to ensure that the model object reflects the correct value after Updates() has completed. This PR also adds few supporting test cases for Updates() with a map and uuid.UUID column.
1 parent a9d2729 commit debc5f1

File tree

7 files changed

+47
-7
lines changed

7 files changed

+47
-7
lines changed

schema/field.go

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -896,7 +896,9 @@ func (field *Field) setupValuerAndSetter() {
896896
if !reflectV.IsValid() {
897897
field.ReflectValueOf(ctx, value).Set(reflect.New(field.FieldType).Elem())
898898
} else if reflectV.Kind() == reflect.Ptr && reflectV.IsNil() {
899-
return
899+
if field.FieldType.Elem().Kind() == reflect.Array && field.OwnerSchema == nil {
900+
field.ReflectValueOf(ctx, value).Set(reflectV)
901+
}
900902
} else if reflectV.Type().AssignableTo(field.FieldType) {
901903
field.ReflectValueOf(ctx, value).Set(reflectV)
902904
} else if reflectV.Kind() == reflect.Ptr {

tests/connpool_test.go

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -101,12 +101,12 @@ func TestConnPoolWrapper(t *testing.T) {
101101
db: nativeDB,
102102
expect: []string{
103103
"SELECT VERSION()",
104-
"INSERT INTO `users` (`created_at`,`updated_at`,`deleted_at`,`name`,`age`,`birthday`,`company_id`,`manager_id`,`active`) VALUES (?,?,?,?,?,?,?,?,?)",
104+
"INSERT INTO `users` (`created_at`,`updated_at`,`deleted_at`,`name`,`age`,`birthday`,`company_id`,`manager_id`,`active`,`user_uuid`) VALUES (?,?,?,?,?,?,?,?,?,?)",
105105
"SELECT * FROM `users` WHERE name = ? AND `users`.`deleted_at` IS NULL ORDER BY `users`.`id` LIMIT ?",
106-
"INSERT INTO `users` (`created_at`,`updated_at`,`deleted_at`,`name`,`age`,`birthday`,`company_id`,`manager_id`,`active`) VALUES (?,?,?,?,?,?,?,?,?)",
106+
"INSERT INTO `users` (`created_at`,`updated_at`,`deleted_at`,`name`,`age`,`birthday`,`company_id`,`manager_id`,`active`,`user_uuid`) VALUES (?,?,?,?,?,?,?,?,?,?)",
107107
"SELECT * FROM `users` WHERE name = ? AND `users`.`deleted_at` IS NULL ORDER BY `users`.`id` LIMIT ?",
108108
"SELECT * FROM `users` WHERE name = ? AND `users`.`deleted_at` IS NULL ORDER BY `users`.`id` LIMIT ?",
109-
"INSERT INTO `users` (`created_at`,`updated_at`,`deleted_at`,`name`,`age`,`birthday`,`company_id`,`manager_id`,`active`) VALUES (?,?,?,?,?,?,?,?,?)",
109+
"INSERT INTO `users` (`created_at`,`updated_at`,`deleted_at`,`name`,`age`,`birthday`,`company_id`,`manager_id`,`active`,`user_uuid`) VALUES (?,?,?,?,?,?,?,?,?,?)",
110110
"SELECT * FROM `users` WHERE name = ? AND `users`.`deleted_at` IS NULL ORDER BY `users`.`id` LIMIT ?",
111111
"SELECT * FROM `users` WHERE name = ? AND `users`.`deleted_at` IS NULL ORDER BY `users`.`id` LIMIT ?",
112112
},

tests/embedded_struct_test.go

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ import (
88
"testing"
99
"time"
1010

11+
"github.com/google/uuid"
1112
"gorm.io/gorm"
1213
. "gorm.io/gorm/utils/tests"
1314
)
@@ -114,6 +115,7 @@ func TestEmbeddedPointerTypeStruct(t *testing.T) {
114115
ContentPtr *Content
115116
Birthday time.Time
116117
BirthdayPtr *time.Time
118+
AuthorUUID *uuid.UUID
117119
}
118120

119121
type HNPost struct {

tests/go.mod

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ require (
77
github.com/jinzhu/now v1.1.5
88
github.com/lib/pq v1.10.9
99
github.com/stretchr/testify v1.9.0
10+
gorm.io/datatypes v1.2.2
1011
gorm.io/driver/mysql v1.5.7
1112
gorm.io/driver/postgres v1.5.10
1213
gorm.io/driver/sqlite v1.5.6

tests/sql_builder_test.go

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -158,7 +158,7 @@ func TestDryRun(t *testing.T) {
158158
dryRunDB := DB.Session(&gorm.Session{DryRun: true})
159159

160160
stmt := dryRunDB.Create(&user).Statement
161-
if stmt.SQL.String() == "" || len(stmt.Vars) != 9 {
161+
if stmt.SQL.String() == "" || len(stmt.Vars) != 10 {
162162
t.Errorf("Failed to generate sql, got %v", stmt.SQL.String())
163163
}
164164

@@ -403,7 +403,7 @@ func TestToSQL(t *testing.T) {
403403
sql = DB.ToSQL(func(tx *gorm.DB) *gorm.DB {
404404
return tx.Model(&User{}).Create(user)
405405
})
406-
assertEqualSQL(t, `INSERT INTO "users" ("created_at","updated_at","deleted_at","name","age","birthday","company_id","manager_id","active") VALUES ('2021-10-18 00:00:00','2021-10-18 00:00:00',NULL,'foo',20,NULL,NULL,NULL,false) RETURNING "id"`, sql)
406+
assertEqualSQL(t, `INSERT INTO "users" ("created_at","updated_at","deleted_at","name","age","birthday","company_id","manager_id","active","user_uuid") VALUES ('2021-10-18 00:00:00','2021-10-18 00:00:00',NULL,'foo',20,NULL,NULL,NULL,false,NULL) RETURNING "id"`, sql)
407407

408408
// save
409409
user = &User{Name: "foo", Age: 20}
@@ -412,7 +412,7 @@ func TestToSQL(t *testing.T) {
412412
sql = DB.ToSQL(func(tx *gorm.DB) *gorm.DB {
413413
return tx.Model(&User{}).Save(user)
414414
})
415-
assertEqualSQL(t, `INSERT INTO "users" ("created_at","updated_at","deleted_at","name","age","birthday","company_id","manager_id","active") VALUES ('2021-10-18 00:00:00','2021-10-18 00:00:00',NULL,'foo',20,NULL,NULL,NULL,false) RETURNING "id"`, sql)
415+
assertEqualSQL(t, `INSERT INTO "users" ("created_at","updated_at","deleted_at","name","age","birthday","company_id","manager_id","active","user_uuid") VALUES ('2021-10-18 00:00:00','2021-10-18 00:00:00',NULL,'foo',20,NULL,NULL,NULL,false,NULL) RETURNING "id"`, sql)
416416

417417
// updates
418418
user = &User{Name: "bar", Age: 22}

tests/update_test.go

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ import (
88
"testing"
99
"time"
1010

11+
"gorm.io/datatypes"
1112
"gorm.io/gorm"
1213
"gorm.io/gorm/clause"
1314
"gorm.io/gorm/utils"
@@ -183,6 +184,38 @@ func TestUpdates(t *testing.T) {
183184

184185
user3.Age += 100
185186
AssertObjEqual(t, user4, user3, "UpdatedAt", "Age")
187+
188+
// Updates() with map and datatypes.UUID - Case 1 - Update with UUID value
189+
uuidVal := datatypes.NewUUIDv4()
190+
tx := DB.Model(&user4)
191+
uuidErr := tx.Updates(map[string]interface{}{"user_uuid": uuidVal}).Error
192+
if uuidErr != nil {
193+
t.Errorf("No error should occur while updating with UUID value, but got %v", uuidErr)
194+
}
195+
// Expecting the model object (user4) to reflect the UUID value assignment.
196+
AssertEqual(t, user4.UserUUID, uuidVal)
197+
198+
// Updates() with map and datatypes.UUID - Case 2 - Update with UUID nil pointer
199+
var nilUUIDPtr *datatypes.UUID = nil
200+
uuidErr = tx.Updates(map[string]interface{}{"user_uuid": nilUUIDPtr}).Error
201+
if uuidErr != nil {
202+
t.Errorf("No error should occur while updating with nil UUID pointer, but got %v", uuidErr)
203+
}
204+
// Expecting the model object (user4) to reflect the UUID nil pointer assignment.
205+
AssertEqual(t, user4.UserUUID, nilUUIDPtr)
206+
207+
// Updates() with map and datatypes.UUID - Case 3 - Update with a non-nil UUID pointer
208+
uuidVal2 := datatypes.NewUUIDv1()
209+
if uuidErr != nil {
210+
t.Errorf("No error should occur while generating UUID, but got %v", uuidErr)
211+
}
212+
var nonNilUUIDPtr *datatypes.UUID = &uuidVal2
213+
uuidErr = tx.Updates(map[string]interface{}{"user_uuid": nonNilUUIDPtr}).Error
214+
if uuidErr != nil {
215+
t.Errorf("No error should occur while updating with non-nil UUID pointer, but got %v", uuidErr)
216+
}
217+
// Expecting the model object (user4) to reflect the non-nil UUID pointer assignment.
218+
AssertEqual(t, user4.UserUUID, nonNilUUIDPtr)
186219
}
187220

188221
func TestUpdateColumn(t *testing.T) {

utils/tests/models.go

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import (
44
"database/sql"
55
"time"
66

7+
"gorm.io/datatypes"
78
"gorm.io/gorm"
89
)
910

@@ -30,6 +31,7 @@ type User struct {
3031
Languages []Language `gorm:"many2many:UserSpeak;"`
3132
Friends []*User `gorm:"many2many:user_friends;"`
3233
Active bool
34+
UserUUID *datatypes.UUID
3335
}
3436

3537
type Account struct {

0 commit comments

Comments
 (0)