Open
Description
GORM Playground Link
Description
type ValueDep struct {
gorm.Model
ID int `gorm:"primarykey,autoIncrement"`
ValueID int
Name string `gorm:"column:name; default:'default'"`
Params Params `gorm:"column:params; type:jsonb; default:'{}'"`
}
type Value struct {
gorm.Model
ID int `gorm:"primarykey,autoIncrement"`
Deps []*ValueDep `gorm:"foreignKey:ValueID"`
}
type Params map[string]string
func (p *Params) Scan(val interface{}) error {
switch v := val.(type) {
case []byte:
return json.Unmarshal(v, p)
case string:
return json.Unmarshal([]byte(v), p)
default:
return fmt.Errorf("unsupported type: %T", v)
}
}
func (p Params) Value() (driver.Value, error) {
return json.Marshal(p)
}
Steps to reproduce:
var value Value
// read value from the db
// assign new values to the map
value.Deps[0].Params["foo"] = "new-bar"
// save the struct to the db
DB.Session(&gorm.Session{FullSaveAssociations: true}).Save(value)
SQL which is supposed to update association will look like this
INSERT INTO "value_deps" ("created_at","updated_at","deleted_at","value_id","name","params","id") VALUES ('2023-06-16 20:10:28.427','2023-06-16 20:10:28.444',NULL,11,'new-name','{"foo":"new-bar"}',11) ON CONFLICT ("id") DO UPDATE SET "updated_at"='2023-06-16 20:10:28.444',"deleted_at"="excluded"."deleted_at","value_id"="excluded"."value_id","name"="excluded"."name" RETURNING "id","params","id"
Notice, that the params field isn't listed in the SET clause. Which means that this sql will work correctly only if we're inserting a new association. If we're trying to update an existing one the new-bar
value will be lost.
This happens only if we specify default:'{}'
option. Without it the save will work ok