GORM Playground Link

https://github.com/go-gorm/playground/pull/663

Description

When using the OnConflict handler, if you run two Creates on the same *gorm.DB, the second create will reuse some of the state from the first Create.

If the struct in the first create is larger than that in the second, this will cause a panic. If the struct in the second create is larger than the first, this will cause some other error which I have not investigated.

In addition to the GORM playground above, this can be seen in an even more minimal test case:

package example

import (
    "testing"

    "gorm.io/driver/sqlite"
    "gorm.io/gorm"
    "gorm.io/gorm/clause"
)

type FieldRich struct {
    First  string `gorm:"primaryKey"`
    Second string
    Third  string
}

type FieldPoor struct {
    NumberOne int64 `gorm:"primaryKey"`
    NumberTwo int64
}

func TestExample(t *testing.T) {
    db, _ := gorm.Open(sqlite.Open("file::memory:?cache=shared"))
    db.AutoMigrate(&FieldRich{})
    db.AutoMigrate(&FieldPoor{})

    db.Create(&FieldRich{"one", "two", "three"})
    db.Create(&FieldPoor{5, 4})

    dbUpsert := db.Clauses(clause.OnConflict{UpdateAll: true})
    dbUpsert.Create(&FieldRich{"one", "two", "three"})
    dbUpsert.Create(&FieldPoor{5, 4})
}

Comment From: shedyfreak

it seems that the missing annotations of gorm on the other fields makes it fail, IMO this is a misuse of the library rather than a bug. it seems that the struct is finaly parsed as array of " fields" and at some level it fails to understand that those fields are not part of the gorm struct. I m not sure if there is any action requiered here.

Comment From: a631807682

https://gorm.io/docs/method_chaining.html#New-Session-Methods