Skip to content

Inconsistent behavior between this and the "mysql" driver (probably a bug) #129

Description

@leonklingele

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)
	}
}

Metadata

Metadata

Assignees

Labels

No labels
No labels

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions