The following code yields a different result when used with the mysql instead of the sqlite driver.
Instead of using ON CONFLICT DO NOTHING RETURNING `id`,`id`;, this driver should do a ON CONFLICT DO UPDATE SET `id`=`id` RETURNING `id`,`id`; just as the mysql driver does.
Output when using sqlite:
2023/01/25 00:34:39 User #0: Peter1, country: New Zealand
2023/01/25 00:34:39 User #1: Peter2, country: [EMPTY]
(Correct) output when using mysql:
2023/01/25 00:34:39 User #0: Peter1, country: New Zealand
2023/01/25 00:34:39 User #1: Peter2, country: Germany
package main
import (
"fmt"
"log"
"gorm.io/driver/sqlite"
"gorm.io/gorm"
"gorm.io/gorm/clause"
)
type User struct {
gorm.Model
ID uint `gorm:"column:id; primaryKey; unique; not null"`
Name string `gorm:"column:name; unique; not null"`
Country *Country
CountryID *uint `gorm:"column:country_id"`
}
type Country struct {
gorm.Model
ID uint `gorm:"column:id; primaryKey; unique; not null"`
Name string `gorm:"column:name; unique; not null"`
}
func run() error {
const (
// dbFile = "db.sqlite"
dbFile = "file:memdb?mode=memory"
)
db, err := gorm.Open(
sqlite.Open(dbFile),
&gorm.Config{},
)
if err != nil {
return fmt.Errorf("failed to open GORM: %w", err)
}
if err := db.Debug().AutoMigrate(
&User{},
&Country{},
); err != nil {
return fmt.Errorf("failed to auto migrate: %w", err)
}
// Create countries
{
tx := db.Debug().
Create(&Country{Name: "Germany"})
if err := tx.Error; err != nil {
return fmt.Errorf("failed to create country: %w", err)
}
}
// Create users
{
tx := db.Debug().
Create(&User{Name: "Peter1", Country: &Country{Name: "New Zealand"}})
if err := tx.Error; err != nil {
return fmt.Errorf("failed to create user: %w", err)
}
}
{
tx := db.Debug().
Create(&User{Name: "Peter2", Country: &Country{Name: "Germany"}})
if err := tx.Error; err != nil {
return fmt.Errorf("failed to create user: %w", err)
}
}
// Retrieve users
{
var ms []*User
tx := db.Debug().Preload(clause.Associations).
Find(&ms)
if err := tx.Error; err != nil {
return fmt.Errorf("failed to find: %w", err)
}
for i, m := range ms {
country := "[EMPTY]"
if m.Country != nil {
country = m.Country.Name
}
log.Printf("User #%d: %s, country: %s\n", i, m.Name, country)
}
}
return nil
}
func main() {
if err := run(); err != nil {
log.Fatal(err)
}
}
The following code yields a different result when used with the mysql instead of the sqlite driver.
Instead of using
ON CONFLICT DO NOTHING RETURNING `id`,`id`;, this driver should do aON CONFLICT DO UPDATE SET `id`=`id` RETURNING `id`,`id`;just as the mysql driver does.Output when using sqlite:
(Correct) output when using mysql: