Save is trying to update created_at column

Viewed 2387

We are updating our project from v1 to v2. When we try to update a row by providing only changed fields as a struct, it tries to set created_at column and returns an error. This was working back in v1. According to documentation, during update operations, fields with default values are ignored.

err := r.writeDB.Save(&Record{
    Model:   Model{
        ID:        1,
    },
    Name:    "AB",
}).Error

if err != nil {
    return err
}

Generates the following SQL statement

[3.171ms] [rows:0] UPDATE `records` SET `created_at`='0000-00-00 00:00:00',`updated_at`='2020-11-12 15:38:36.285',`name`='AB' WHERE `id` = 1

Returns following error

Error 1292: Incorrect datetime value: '0000-00-00' for column 'created_at' at row 1

With these entities

type Model struct {
    ID        int       `gorm:"primary_key,type:INT;not null;AUTO_INCREMENT"`
    CreatedAt time.Time `gorm:"type:TIMESTAMP(6)"`
    UpdatedAt time.Time `gorm:"type:TIMESTAMP(6)"`
}

type Record struct {
    Model
    Name         string
    Details      string
}

There is DB.Omit which allows ignoring a column when executing an update query. But this requires a lot of refactoring in the codebase. Does the behavior changed or is there something missing?

3 Answers

This might help you. Change the structure field (or add to replace default gorm.Model field) like this:

CreatedAt time.Time `gorm:"<-:create"` // allow read and create, but don't update

This tag helps to save created data from update.

In Gorm v2 Save(..) writes all fields to the database. As the CreatedAt field is the zero value, this is written to the database.

For you code to work, you can use a map:

err := r.writeDB.Model(&Record{Model:Model{ID:1}}).Update("name","AB").Error

Another option is to not fill in the Record struct, but just point to the table and use a Where clause:

err := r.writeDB.Model(&Record{}).Where("id = ?", 1).Update("name","AB").Error

If you have multiple updates you can use Updates(...) with a map, see here: https://gorm.io/docs/update.html

I was able to work around this problem using Omit() before save. Like this:

result := r.db.Omit("created_at").Save(item)

It omits the CreatedAt from the resulting update query, and updates everything else.

Related