diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index d7222d5..cedf0a5 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -9,14 +9,17 @@ jobs: name: Test strategy: matrix: - go: ['1.20', '1.19', '1.18', '1.17'] + go: ["^1", "1.20", "1.19", "1.18"] platform: [ubuntu-latest] # can not run in windows OS + cgo: ["0", "1"] runs-on: ubuntu-latest steps: - - name: Set up Go - uses: actions/setup-go@v4 - with: - go-version: ${{ matrix.go }} - - uses: actions/checkout@v3 - - name: Test - run: go test -v -cover . + - name: Set up Go + uses: actions/setup-go@v4 + with: + go-version: ${{ matrix.go }} + - uses: actions/checkout@v3 + - name: Test + env: + CGO_ENABLED: ${{ matrix.cgo }} + run: go test -v -cover . diff --git a/go.mod b/go.mod index 0c031e7..1064a49 100644 --- a/go.mod +++ b/go.mod @@ -3,11 +3,30 @@ module gorm.io/driver/sqlite go 1.20 require ( - github.com/mattn/go-sqlite3 v1.14.17 + github.com/mattn/go-sqlite3 v1.14.16 gorm.io/gorm v1.25.2-0.20230530020048-26663ab9bf55 + modernc.org/sqlite v1.23.1 ) require ( + github.com/dustin/go-humanize v1.0.1 // indirect + github.com/google/uuid v1.3.0 // indirect github.com/jinzhu/inflection v1.0.0 // indirect github.com/jinzhu/now v1.1.5 // indirect + github.com/kballard/go-shellquote v0.0.0-20180428030007-95032a82bc51 // indirect + github.com/mattn/go-isatty v0.0.16 // indirect + github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec // indirect + golang.org/x/mod v0.3.0 // indirect + golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab // indirect + golang.org/x/tools v0.0.0-20201124115921-2c860bdd6e78 // indirect + golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 // indirect + lukechampine.com/uint128 v1.2.0 // indirect + modernc.org/cc/v3 v3.40.0 // indirect + modernc.org/ccgo/v3 v3.16.13 // indirect + modernc.org/libc v1.22.5 // indirect + modernc.org/mathutil v1.5.0 // indirect + modernc.org/memory v1.5.0 // indirect + modernc.org/opt v0.1.3 // indirect + modernc.org/strutil v1.1.3 // indirect + modernc.org/token v1.0.1 // indirect ) diff --git a/go.sum b/go.sum index 45bb183..7938d87 100644 --- a/go.sum +++ b/go.sum @@ -1,10 +1,72 @@ +github.com/dustin/go-humanize v1.0.1 h1:GzkhY7T5VNhEkwH0PVJgjz+fX1rhBrR7pRT3mDkpeCY= +github.com/dustin/go-humanize v1.0.1/go.mod h1:Mu1zIs6XwVuF/gI1OepvI0qD18qycQx+mFykh5fBlto= +github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38= +github.com/google/pprof v0.0.0-20221118152302-e6195bd50e26 h1:Xim43kblpZXfIBQsbuBVKCudVG457BR2GZFIz3uw3hQ= +github.com/google/uuid v1.3.0 h1:t6JiXgmwXMjEs8VusXIJk2BXHsn+wx8BZdTaoZ5fu7I= +github.com/google/uuid v1.3.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/jinzhu/inflection v1.0.0 h1:K317FqzuhWc8YvSVlFMCCUb36O/S9MCKRDI7QkRKD/E= github.com/jinzhu/inflection v1.0.0/go.mod h1:h+uFLlag+Qp1Va5pdKtLDYj+kHp5pxUVkryuEj+Srlc= github.com/jinzhu/now v1.1.5 h1:/o9tlHleP7gOFmsnYNz3RGnqzefHA47wQpKrrdTIwXQ= github.com/jinzhu/now v1.1.5/go.mod h1:d3SSVoowX0Lcu0IBviAWJpolVfI5UJVZZ7cO71lE/z8= -github.com/mattn/go-sqlite3 v1.14.17 h1:mCRHCLDUBXgpKAqIKsaAaAsrAlbkeomtRFKXh2L6YIM= -github.com/mattn/go-sqlite3 v1.14.17/go.mod h1:2eHXhiwb8IkHr+BDWZGa96P6+rkvnG63S2DGjv9HUNg= -gorm.io/gorm v1.25.0 h1:+KtYtb2roDz14EQe4bla8CbQlmb9dN3VejSai3lprfU= -gorm.io/gorm v1.25.0/go.mod h1:L4uxeKpfBml98NYqVqwAdmV1a2nBtAec/cf3fpucW/k= +github.com/kballard/go-shellquote v0.0.0-20180428030007-95032a82bc51 h1:Z9n2FFNUXsshfwJMBgNA0RU6/i7WVaAegv3PtuIHPMs= +github.com/kballard/go-shellquote v0.0.0-20180428030007-95032a82bc51/go.mod h1:CzGEWj7cYgsdH8dAjBGEr58BoE7ScuLd+fwFZ44+/x8= +github.com/mattn/go-isatty v0.0.16 h1:bq3VjFmv/sOjHtdEhmkEV4x1AJtvUvOJ2PFAZ5+peKQ= +github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM= +github.com/mattn/go-sqlite3 v1.14.16 h1:yOQRA0RpS5PFz/oikGwBEqvAWhWg5ufRz4ETLjwpU1Y= +github.com/mattn/go-sqlite3 v1.14.16/go.mod h1:2eHXhiwb8IkHr+BDWZGa96P6+rkvnG63S2DGjv9HUNg= +github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= +github.com/remyoudompheng/bigfft v0.0.0-20200410134404-eec4a21b6bb0/go.mod h1:qqbHyh8v60DhA7CoWK5oRCqLrMHRGoxYCSS9EjAz6Eo= +github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec h1:W09IVJc94icq4NjY3clb7Lk8O1qJ8BdBEF8z0ibU0rE= +github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec/go.mod h1:qqbHyh8v60DhA7CoWK5oRCqLrMHRGoxYCSS9EjAz6Eo= +github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= +golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= +golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= +golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= +golang.org/x/mod v0.3.0 h1:RM4zey1++hCTbCVQfnWeKs9/IEsaBLA8vTkd0WVtmH4= +golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= +golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= +golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab h1:2QkjZIsXupsJbJIdSjjUOgWK3aEtzyuh2mPt3l/CkeU= +golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= +golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= +golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20201124115921-2c860bdd6e78 h1:M8tBwCtWD/cZV9DZpFYRUgaymAYAr+aIUTWzDaM3uPs= +golang.org/x/tools v0.0.0-20201124115921-2c860bdd6e78/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= +golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 h1:go1bK/D/BFZV2I8cIQd1NKEZ+0owSTG1fDTci4IqFcE= +golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= gorm.io/gorm v1.25.2-0.20230530020048-26663ab9bf55 h1:sC1Xj4TYrLqg1n3AN10w871An7wJM0gzgcm8jkIkECQ= gorm.io/gorm v1.25.2-0.20230530020048-26663ab9bf55/go.mod h1:L4uxeKpfBml98NYqVqwAdmV1a2nBtAec/cf3fpucW/k= +lukechampine.com/uint128 v1.2.0 h1:mBi/5l91vocEN8otkC5bDLhi2KdCticRiwbdB0O+rjI= +lukechampine.com/uint128 v1.2.0/go.mod h1:c4eWIwlEGaxC/+H1VguhU4PHXNWDCDMUlWdIWl2j1gk= +modernc.org/cc/v3 v3.40.0 h1:P3g79IUS/93SYhtoeaHW+kRCIrYaxJ27MFPv+7kaTOw= +modernc.org/cc/v3 v3.40.0/go.mod h1:/bTg4dnWkSXowUO6ssQKnOV0yMVxDYNIsIrzqTFDGH0= +modernc.org/ccgo/v3 v3.16.13 h1:Mkgdzl46i5F/CNR/Kj80Ri59hC8TKAhZrYSaqvkwzUw= +modernc.org/ccgo/v3 v3.16.13/go.mod h1:2Quk+5YgpImhPjv2Qsob1DnZ/4som1lJTodubIcoUkY= +modernc.org/ccorpus v1.11.6 h1:J16RXiiqiCgua6+ZvQot4yUuUy8zxgqbqEEUuGPlISk= +modernc.org/httpfs v1.0.6 h1:AAgIpFZRXuYnkjftxTAZwMIiwEqAfk8aVB2/oA6nAeM= +modernc.org/libc v1.22.5 h1:91BNch/e5B0uPbJFgqbxXuOnxBQjlS//icfQEGmvyjE= +modernc.org/libc v1.22.5/go.mod h1:jj+Z7dTNX8fBScMVNRAYZ/jF91K8fdT2hYMThc3YjBY= +modernc.org/mathutil v1.5.0 h1:rV0Ko/6SfM+8G+yKiyI830l3Wuz1zRutdslNoQ0kfiQ= +modernc.org/mathutil v1.5.0/go.mod h1:mZW8CKdRPY1v87qxC/wUdX5O1qDzXMP5TH3wjfpga6E= +modernc.org/memory v1.5.0 h1:N+/8c5rE6EqugZwHii4IFsaJ7MUhoWX07J5tC/iI5Ds= +modernc.org/memory v1.5.0/go.mod h1:PkUhL0Mugw21sHPeskwZW4D6VscE/GQJOnIpCnW6pSU= +modernc.org/opt v0.1.3 h1:3XOZf2yznlhC+ibLltsDGzABUGVx8J6pnFMS3E4dcq4= +modernc.org/opt v0.1.3/go.mod h1:WdSiB5evDcignE70guQKxYUl14mgWtbClRi5wmkkTX0= +modernc.org/sqlite v1.23.1 h1:nrSBg4aRQQwq59JpvGEQ15tNxoO5pX/kUjcRNwSAGQM= +modernc.org/sqlite v1.23.1/go.mod h1:OrDj17Mggn6MhE+iPbBNf7RGKODDE9NFT0f3EwDzJqk= +modernc.org/strutil v1.1.3 h1:fNMm+oJklMGYfU9Ylcywl0CO5O6nTfaowNsh2wpPjzY= +modernc.org/strutil v1.1.3/go.mod h1:MEHNA7PdEnEwLvspRMtWTNnp2nnyvMfkimT1NKNAGbw= +modernc.org/tcl v1.15.2 h1:C4ybAYCGJw968e+Me18oW55kD/FexcHbqH2xak1ROSY= +modernc.org/token v1.0.1 h1:A3qvTqOwexpfZZeyI0FeGPDlSWX5pjZu9hF4lU+EKWg= +modernc.org/token v1.0.1/go.mod h1:UGzOrNV1mAFSEB63lOFHIpNRUVMvYTc6yu1SMY/XTDM= +modernc.org/z v1.7.3 h1:zDJf6iHjrnB+WRD88stbXokugjyc0/pB91ri1gO6LZY= diff --git a/sqlite.go b/sqlite.go index 8617f00..b215eb6 100644 --- a/sqlite.go +++ b/sqlite.go @@ -8,7 +8,6 @@ import ( "gorm.io/gorm/callbacks" - _ "github.com/mattn/go-sqlite3" "gorm.io/gorm" "gorm.io/gorm/clause" "gorm.io/gorm/logger" @@ -16,9 +15,6 @@ import ( "gorm.io/gorm/schema" ) -// DriverName is the default driver name for SQLite. -const DriverName = "sqlite3" - type Dialector struct { DriverName string DSN string diff --git a/sqlite_cgo.go b/sqlite_cgo.go new file mode 100644 index 0000000..520597b --- /dev/null +++ b/sqlite_cgo.go @@ -0,0 +1,11 @@ +//go:build cgo && !pure +// +build cgo,!pure + +package sqlite + +import ( + _ "github.com/mattn/go-sqlite3" //sqlite driver +) + +// DriverName is the default driver name for SQLite. +const DriverName = "sqlite3" diff --git a/sqlite_cgo_test.go b/sqlite_cgo_test.go new file mode 100644 index 0000000..8505599 --- /dev/null +++ b/sqlite_cgo_test.go @@ -0,0 +1,65 @@ +//go:build cgo && !pure +// +build cgo,!pure + +package sqlite + +import ( + "database/sql" + "os" + "testing" + + "github.com/mattn/go-sqlite3" +) + +const ( + // This is the DSN of the in-memory SQLite database for these tests. + InMemoryDSN = "file:testdatabase?mode=memory&cache=shared" + // This is the custom SQLite driver name. + CustomDriverName = "my_custom_driver" +) + +func TestMain(m *testing.M) { + // Register the custom SQlite3 driver. + // It will have one custom function called "my_custom_function". + sql.Register(CustomDriverName, + // This is the custom SQLite driver. + &sqlite3.SQLiteDriver{ + ConnectHook: func(conn *sqlite3.SQLiteConn) error { + // Define the `concat` function, since we use this elsewhere. + err := conn.RegisterFunc( + "my_custom_function", + func(arguments ...interface{}) (string, error) { + return "my-result", nil // Return a string value. + }, + true, + ) + return err + }, + }, + ) + + rows = append(rows, []testRow{ + { + description: "Explicit default driver, custom function", + dialector: &Dialector{ + DriverName: DriverName, + DSN: InMemoryDSN, + }, + openSuccess: true, + query: "SELECT my_custom_function()", + querySuccess: false, + }, + { + description: "Custom driver, custom function", + dialector: &Dialector{ + DriverName: CustomDriverName, + DSN: InMemoryDSN, + }, + openSuccess: true, + query: "SELECT my_custom_function()", + querySuccess: true, + }, + }...) + + os.Exit(m.Run()) +} diff --git a/sqlite_pure.go b/sqlite_pure.go new file mode 100644 index 0000000..bb85632 --- /dev/null +++ b/sqlite_pure.go @@ -0,0 +1,11 @@ +//go:build !cgo || (cgo && pure) +// +build !cgo cgo,pure + +package sqlite + +import ( + _ "modernc.org/sqlite" //sqlite driver +) + +// DriverName is the default driver name for SQLite. +const DriverName = "sqlite" diff --git a/sqlite_pure_test.go b/sqlite_pure_test.go new file mode 100644 index 0000000..16a2d1f --- /dev/null +++ b/sqlite_pure_test.go @@ -0,0 +1,58 @@ +//go:build !cgo || (cgo && pure) +// +build !cgo cgo,pure + +package sqlite + +import ( + "database/sql" + "database/sql/driver" + "os" + "testing" + + "modernc.org/sqlite" +) + +const ( + // This is the DSN of the in-memory SQLite database for these tests. + InMemoryDSN = "testdatabase" + // This is the custom SQLite driver name. + CustomDriverName = "my_custom_driver" +) + +func TestMain(m *testing.M) { + // Register a custom function to the default SQLite driver. + sqlite.MustRegisterDeterministicScalarFunction("my_custom_function", -1, func(ctx *sqlite.FunctionContext, args []driver.Value) (driver.Value, error) { + return "my-result", nil + }) + + // Register the custom SQlite driver. + // modernc.org/sqlite doesn't support registering functions to custom drivers. + sql.Register(CustomDriverName, + &sqlite.Driver{}, + ) + + rows = append(rows, []testRow{ + { + description: "Explicit default driver, custom function", + dialector: &Dialector{ + DriverName: DriverName, + DSN: InMemoryDSN, + }, + openSuccess: true, + query: "SELECT my_custom_function()", + querySuccess: true, + }, + { + description: "Custom driver, custom function", + dialector: &Dialector{ + DriverName: CustomDriverName, + DSN: InMemoryDSN, + }, + openSuccess: true, + query: "SELECT my_custom_function()", + querySuccess: false, + }, + }...) + + os.Exit(m.Run()) +} diff --git a/sqlite_test.go b/sqlite_test.go index d33ea02..1975c26 100644 --- a/sqlite_test.go +++ b/sqlite_test.go @@ -1,45 +1,22 @@ package sqlite import ( - "database/sql" "fmt" "testing" - "github.com/mattn/go-sqlite3" "gorm.io/gorm" ) -func TestDialector(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 custom SQLite driver name. - const CustomDriverName = "my_custom_driver" - - // Register the custom SQlite3 driver. - // It will have one custom function called "my_custom_function". - sql.Register(CustomDriverName, - &sqlite3.SQLiteDriver{ - ConnectHook: func(conn *sqlite3.SQLiteConn) error { - // Define the `concat` function, since we use this elsewhere. - err := conn.RegisterFunc( - "my_custom_function", - func(arguments ...interface{}) (string, error) { - return "my-result", nil // Return a string value. - }, - true, - ) - return err - }, - }, - ) +type testRow struct { + description string + dialector *Dialector + openSuccess bool + query string + querySuccess bool +} - rows := []struct { - description string - dialector *Dialector - openSuccess bool - query string - querySuccess bool - }{ +var ( + rows = []testRow{ { description: "Default driver", dialector: &Dialector{ @@ -67,16 +44,6 @@ func TestDialector(t *testing.T) { }, openSuccess: false, }, - { - description: "Explicit default driver, custom function", - dialector: &Dialector{ - DriverName: DriverName, - DSN: InMemoryDSN, - }, - openSuccess: true, - query: "SELECT my_custom_function()", - querySuccess: false, - }, { description: "Custom driver", dialector: &Dialector{ @@ -87,17 +54,10 @@ func TestDialector(t *testing.T) { query: "SELECT 1", querySuccess: true, }, - { - description: "Custom driver, custom function", - dialector: &Dialector{ - DriverName: CustomDriverName, - DSN: InMemoryDSN, - }, - openSuccess: true, - query: "SELECT my_custom_function()", - querySuccess: true, - }, } +) + +func TestDialector(t *testing.T) { for rowIndex, row := range rows { t.Run(fmt.Sprintf("%d/%s", rowIndex, row.description), func(t *testing.T) { db, err := gorm.Open(row.dialector, &gorm.Config{})