diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..a725465 --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +vendor/ \ No newline at end of file diff --git a/go.mod b/go.mod index 417bdbd..d354183 100644 --- a/go.mod +++ b/go.mod @@ -1,9 +1,8 @@ module github.com/glebarez/sqlite -go 1.14 +go 1.16 require ( - github.com/davecgh/go-spew v1.1.1 // indirect github.com/stretchr/testify v1.7.0 gorm.io/gorm v1.22.3 modernc.org/sqlite v1.14.1 diff --git a/go.sum b/go.sum index 33e3e1a..eacc92b 100644 --- a/go.sum +++ b/go.sum @@ -1,6 +1,5 @@ +github.com/davecgh/go-spew v1.1.0 h1:ZDRjVQ15GmhC3fiQ8ni8+OwkZQO4DARzQgrnXU1Liz8= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= -github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= -github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/dustin/go-humanize v1.0.0 h1:VSnTsYCnlFHaM2/igO1h6X3HA71jcobQuxemgkq4zYo= github.com/dustin/go-humanize v1.0.0/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk= github.com/google/go-cmp v0.5.3 h1:x95R7cp+rSeeqAMI2knLtQ0DKlaBhv2NrtrOvafPHRo= diff --git a/sqlite.go b/sqlite.go index 0b60460..b98748f 100644 --- a/sqlite.go +++ b/sqlite.go @@ -56,7 +56,11 @@ func (dialector Dialector) Initialize(db *gorm.DB) (err error) { // https://www.sqlite.org/releaselog/3_35_0.html if compareVersion(version, "3.35.0") >= 0 { callbacks.RegisterDefaultCallbacks(db, &callbacks.Config{ - CreateClauses: []string{"INSERT", "VALUES", "ON CONFLICT", "RETURNING"}, + // CreateClauses should support RETURNING, but for now there's a bug with foreign key pragma + // RETURNING will be added as soon as bug is fixed + // in case of Primary key, the generated SQLite ID is still accessible though, + // due to LastGeneratedID support golang sql package + CreateClauses: []string{"INSERT", "VALUES", "ON CONFLICT"}, UpdateClauses: []string{"UPDATE", "SET", "WHERE", "RETURNING"}, DeleteClauses: []string{"DELETE", "FROM", "WHERE", "RETURNING"}, LastInsertIDReversed: true, diff --git a/tests/gorm_test.go b/tests/gorm_test.go new file mode 100644 index 0000000..e5648e0 --- /dev/null +++ b/tests/gorm_test.go @@ -0,0 +1,109 @@ +package tests + +import ( + "fmt" + "log" + "os" + "testing" + + "github.com/glebarez/sqlite" + "github.com/stretchr/testify/require" + "gorm.io/gorm" + "gorm.io/gorm/logger" + "gorm.io/gorm/schema" +) + +const dsn = "file::memory:?cache=shared&_pragma=foreign_keys(1)" + +var ( + // this query must produce database error due to foreign key constraint violation + violationQuery = "INSERT INTO `child` (`parent_id`) VALUES (\"non-existing\") RETURNING `id`" + + // gorm config + config = &gorm.Config{ + // for debugging you may set logging level + Logger: logger.Default.LogMode(logger.Info), + SkipDefaultTransaction: true, + + // singular table name + NamingStrategy: schema.NamingStrategy{ + SingularTable: true, + }, + } +) + +type Parent struct { + ID string `gorm:"primaryKey"` +} + +type Child struct { + ID uint64 `gorm:"primaryKey;autoIncrement;not null"` + ParentID string + Parent Parent +} + +var ( + db *gorm.DB + validChildID uint64 +) + +func TestMain(m *testing.M) { + var err error + db, err = gorm.Open(sqlite.Open(dsn), config) + if err != nil { + log.Fatalf("error connecting to DB: %v", err) + } + + //migrate + if err := db.Migrator().DropTable(&Parent{}, &Child{}); err != nil { + log.Fatal(err) + } + if err := db.AutoMigrate(&Parent{}, &Child{}); err != nil { + log.Fatal(err) + } + + // create valid records + child := &Child{ + Parent: Parent{ID: "valid-parent"}, + } + if err := db.Create(child).Error; err != nil { + log.Fatal(err) + } + validChildID = child.ID + fmt.Printf("valid child ID: %d\n", validChildID) + + // run tests + os.Exit(m.Run()) +} + +func Test_Create(t *testing.T) { + require := require.New(t) + + // create child for non-existing parent + child := &Child{ + ParentID: "non-existing", + } + + err := db.Create(child).Error + require.Error(err) + require.Equal(err.Error(), "constraint failed: FOREIGN KEY constraint failed (787)") +} + +func Test_Exec(t *testing.T) { + require := require.New(t) + err := db.Exec(violationQuery).Error + require.Error(err) + require.Equal(err.Error(), "constraint failed: FOREIGN KEY constraint failed (787)") +} + +func Test_Update(t *testing.T) { + require := require.New(t) + + // create child for non-existing parent + err := db.Updates(&Child{ + ID: validChildID, + ParentID: "non-existing", + }).Error + require.Error(err) + require.Equal(err.Error(), "constraint failed: FOREIGN KEY constraint failed (787)") +}