diff --git a/go.mod b/go.mod index 7777c86..503a5b6 100644 --- a/go.mod +++ b/go.mod @@ -5,6 +5,7 @@ go 1.18 require ( github.com/glebarez/go-sqlite v1.21.1 gorm.io/gorm v1.25.0 + modernc.org/sqlite v1.21.1 ) require ( @@ -18,5 +19,4 @@ require ( modernc.org/libc v1.22.3 // indirect modernc.org/mathutil v1.5.0 // indirect modernc.org/memory v1.5.0 // indirect - modernc.org/sqlite v1.21.1 // indirect ) diff --git a/sqlite.go b/sqlite.go index 5f015b0..f4207fa 100644 --- a/sqlite.go +++ b/sqlite.go @@ -8,7 +8,8 @@ import ( "gorm.io/gorm/callbacks" - _ "github.com/glebarez/go-sqlite" + gosqlite "github.com/glebarez/go-sqlite" + sqlite3 "modernc.org/sqlite/lib" "gorm.io/gorm" "gorm.io/gorm/clause" @@ -197,6 +198,19 @@ func (dialectopr Dialector) RollbackTo(tx *gorm.DB, name string) error { return nil } +func (dialector Dialector) Translate(err error) error { + switch terr := err.(type) { + case *gosqlite.Error: + switch terr.Code() { + case sqlite3.SQLITE_CONSTRAINT_UNIQUE: + return gorm.ErrDuplicatedKey + case sqlite3.SQLITE_CONSTRAINT_PRIMARYKEY: + return gorm.ErrDuplicatedKey + } + } + return err +} + func compareVersion(version1, version2 string) int { n, m := len(version1), len(version2) i, j := 0, 0 diff --git a/sqlite_error_translator_test.go b/sqlite_error_translator_test.go new file mode 100644 index 0000000..b2e3584 --- /dev/null +++ b/sqlite_error_translator_test.go @@ -0,0 +1,48 @@ +package sqlite + +import ( + "testing" + + "gorm.io/gorm" + "gorm.io/gorm/logger" +) + +func TestErrorTranslator(t *testing.T) { + // This is the DSN of the in-memory SQLite database for these tests. + const InMemoryDSN = "file:testdatabase?mode=memory&cache=shared" + + // This is the example object for testing the unique constraint error + type Article struct { + ArticleNumber string `gorm:"unique"` + } + + db, err := gorm.Open(&Dialector{DSN: InMemoryDSN}, &gorm.Config{ + Logger: logger.Default.LogMode(logger.Silent), + TranslateError: true}) + + if err != nil { + t.Errorf("Expected Open to succeed; got error: %v", err) + } + if db == nil { + t.Errorf("Expected db to be non-nil.") + } + + err = db.AutoMigrate(&Article{}) + if err != nil { + t.Errorf("Expected to migrate database models to succeed: %v", err) + } + + err = db.Create(&Article{ArticleNumber: "A00000XX"}).Error + if err != nil { + t.Errorf("Expected first create to succeed: %v", err) + } + + err = db.Create(&Article{ArticleNumber: "A00000XX"}).Error + if err == nil { + t.Errorf("Expected second create to fail.") + } + + if err != gorm.ErrDuplicatedKey { + t.Errorf("Expected error from second create to be gorm.ErrDuplicatedKey: %v", err) + } +}