Skip to content

Use Clauses(clause.OnConflict{UpdateAll: true}) If the field type is struct and there is a default value which is not null, it will be ignored. #7527

@mohuishou

Description

@mohuishou

GORM Playground Link

go-gorm/playground#819

Description

Use Clauses(clause.OnConflict{UpdateAll: true}) If the field type is struct and there is a default value which is not null, it will be ignored.

type User struct {
	gorm.Model
	Company   Company `gorm:"default:'{}';serializer:json"`
}

func TestGORM(t *testing.T) {
	user := User{Name: "jinzhu"}

	DB.Create(&user)

	var result User
	if err := DB.First(&result, user.ID).Error; err != nil {
		t.Errorf("Failed, got error: %v", err)
	}

	user.Company.Name = "test"
	err := DB.Clauses(clause.OnConflict{UpdateAll: true}).Create(&user).Error
	if err != nil {
		t.Errorf("Failed upsert user: %+v", err)
		return
	}

	err = DB.First(&result, user.ID).Error
	if err != nil {
		t.Errorf("Failed, got error: %v", err)
		return
	}

	if result.Company.Name != "test" {
		t.Errorf("want test, but got %s", result.Company.Name)
		return
	}

}

The generated SQL is as follows. It can be found that the fields related to company are missing after ON CONFLICT (id) DO UPDATE SET.

INSERT INTO `users` (
  `created_at`, `updated_at`, `deleted_at`, 
  `name`, `age`, `birthday`, `company_id`, 
  `manager_id`, `active`, `id`, `company`
) 
VALUES 
  (
    "2025-07-22 06:43:59.827", "2025-07-22 06:43:59.827", 
    NULL, "jinzhu", 0, NULL, NULL, NULL, 
    false, 1, "{""ID"":0,""Name"":""test""}"
  ) ON CONFLICT (`id`) DO UPDATE SET 
  `updated_at` = "2025-07-22 06:43:59.829", 
  `deleted_at` = `excluded`.`deleted_at`, 
  `name` = `excluded`.`name`, 
  `age` = `excluded`.`age`, 
  `birthday` = `excluded`.`birthday`, 
  `company_id` = `excluded`.`company_id`, 
  `manager_id` = `excluded`.`manager_id`, 
  `active` = `excluded`.`active` RETURNING `id`, 
  `company`

The problem lies in the following part: when the field is a struct and not a time field, DefaultValueInterface == nil, but here only NULL is specially judged.
https://github.com/go-gorm/gorm/blob/master/callbacks/create.go#L374

if !field.PrimaryKey && (!field.HasDefaultValue || field.DefaultValueInterface != nil || strings.EqualFold(field.DefaultValue, "NULL")) && field.AutoCreateTime == 0 {

The special judgment for NULL was added in #6129 to fix the bug #5944 that I submitted earlier.

similar issue

#7397

Metadata

Metadata

Assignees

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions