Skip to content

Commit e4f9f7a

Browse files
committed
feat: use pure-go implementation when cgo is disabled
This implements a pure-go alternative driver whenever CGO_ENABLED=0 Related: #93 Fixes: #35 Fixes: #72 Fixes: #77 Fixes: #160
1 parent 397ec6f commit e4f9f7a

8 files changed

+243
-61
lines changed

go.mod

+20-1
Original file line numberDiff line numberDiff line change
@@ -3,11 +3,30 @@ module gorm.io/driver/sqlite
33
go 1.20
44

55
require (
6-
github.com/mattn/go-sqlite3 v1.14.17
6+
github.com/mattn/go-sqlite3 v1.14.16
77
gorm.io/gorm v1.25.2-0.20230530020048-26663ab9bf55
8+
modernc.org/sqlite v1.23.1
89
)
910

1011
require (
12+
github.com/dustin/go-humanize v1.0.1 // indirect
13+
github.com/google/uuid v1.3.0 // indirect
1114
github.com/jinzhu/inflection v1.0.0 // indirect
1215
github.com/jinzhu/now v1.1.5 // indirect
16+
github.com/kballard/go-shellquote v0.0.0-20180428030007-95032a82bc51 // indirect
17+
github.com/mattn/go-isatty v0.0.16 // indirect
18+
github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec // indirect
19+
golang.org/x/mod v0.3.0 // indirect
20+
golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab // indirect
21+
golang.org/x/tools v0.0.0-20201124115921-2c860bdd6e78 // indirect
22+
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 // indirect
23+
lukechampine.com/uint128 v1.2.0 // indirect
24+
modernc.org/cc/v3 v3.40.0 // indirect
25+
modernc.org/ccgo/v3 v3.16.13 // indirect
26+
modernc.org/libc v1.22.5 // indirect
27+
modernc.org/mathutil v1.5.0 // indirect
28+
modernc.org/memory v1.5.0 // indirect
29+
modernc.org/opt v0.1.3 // indirect
30+
modernc.org/strutil v1.1.3 // indirect
31+
modernc.org/token v1.0.1 // indirect
1332
)

go.sum

+66-4
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,72 @@
1+
github.com/dustin/go-humanize v1.0.1 h1:GzkhY7T5VNhEkwH0PVJgjz+fX1rhBrR7pRT3mDkpeCY=
2+
github.com/dustin/go-humanize v1.0.1/go.mod h1:Mu1zIs6XwVuF/gI1OepvI0qD18qycQx+mFykh5fBlto=
3+
github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38=
4+
github.com/google/pprof v0.0.0-20221118152302-e6195bd50e26 h1:Xim43kblpZXfIBQsbuBVKCudVG457BR2GZFIz3uw3hQ=
5+
github.com/google/uuid v1.3.0 h1:t6JiXgmwXMjEs8VusXIJk2BXHsn+wx8BZdTaoZ5fu7I=
6+
github.com/google/uuid v1.3.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
17
github.com/jinzhu/inflection v1.0.0 h1:K317FqzuhWc8YvSVlFMCCUb36O/S9MCKRDI7QkRKD/E=
28
github.com/jinzhu/inflection v1.0.0/go.mod h1:h+uFLlag+Qp1Va5pdKtLDYj+kHp5pxUVkryuEj+Srlc=
39
github.com/jinzhu/now v1.1.5 h1:/o9tlHleP7gOFmsnYNz3RGnqzefHA47wQpKrrdTIwXQ=
410
github.com/jinzhu/now v1.1.5/go.mod h1:d3SSVoowX0Lcu0IBviAWJpolVfI5UJVZZ7cO71lE/z8=
5-
github.com/mattn/go-sqlite3 v1.14.17 h1:mCRHCLDUBXgpKAqIKsaAaAsrAlbkeomtRFKXh2L6YIM=
6-
github.com/mattn/go-sqlite3 v1.14.17/go.mod h1:2eHXhiwb8IkHr+BDWZGa96P6+rkvnG63S2DGjv9HUNg=
7-
gorm.io/gorm v1.25.0 h1:+KtYtb2roDz14EQe4bla8CbQlmb9dN3VejSai3lprfU=
8-
gorm.io/gorm v1.25.0/go.mod h1:L4uxeKpfBml98NYqVqwAdmV1a2nBtAec/cf3fpucW/k=
11+
github.com/kballard/go-shellquote v0.0.0-20180428030007-95032a82bc51 h1:Z9n2FFNUXsshfwJMBgNA0RU6/i7WVaAegv3PtuIHPMs=
12+
github.com/kballard/go-shellquote v0.0.0-20180428030007-95032a82bc51/go.mod h1:CzGEWj7cYgsdH8dAjBGEr58BoE7ScuLd+fwFZ44+/x8=
13+
github.com/mattn/go-isatty v0.0.16 h1:bq3VjFmv/sOjHtdEhmkEV4x1AJtvUvOJ2PFAZ5+peKQ=
14+
github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM=
15+
github.com/mattn/go-sqlite3 v1.14.16 h1:yOQRA0RpS5PFz/oikGwBEqvAWhWg5ufRz4ETLjwpU1Y=
16+
github.com/mattn/go-sqlite3 v1.14.16/go.mod h1:2eHXhiwb8IkHr+BDWZGa96P6+rkvnG63S2DGjv9HUNg=
17+
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
18+
github.com/remyoudompheng/bigfft v0.0.0-20200410134404-eec4a21b6bb0/go.mod h1:qqbHyh8v60DhA7CoWK5oRCqLrMHRGoxYCSS9EjAz6Eo=
19+
github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec h1:W09IVJc94icq4NjY3clb7Lk8O1qJ8BdBEF8z0ibU0rE=
20+
github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec/go.mod h1:qqbHyh8v60DhA7CoWK5oRCqLrMHRGoxYCSS9EjAz6Eo=
21+
github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
22+
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
23+
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
24+
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
25+
golang.org/x/mod v0.3.0 h1:RM4zey1++hCTbCVQfnWeKs9/IEsaBLA8vTkd0WVtmH4=
26+
golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
27+
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
28+
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
29+
golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
30+
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
31+
golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
32+
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
33+
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
34+
golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
35+
golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab h1:2QkjZIsXupsJbJIdSjjUOgWK3aEtzyuh2mPt3l/CkeU=
36+
golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
37+
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
38+
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
39+
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
40+
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
41+
golang.org/x/tools v0.0.0-20201124115921-2c860bdd6e78 h1:M8tBwCtWD/cZV9DZpFYRUgaymAYAr+aIUTWzDaM3uPs=
42+
golang.org/x/tools v0.0.0-20201124115921-2c860bdd6e78/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
43+
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
44+
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
45+
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 h1:go1bK/D/BFZV2I8cIQd1NKEZ+0owSTG1fDTci4IqFcE=
46+
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
947
gorm.io/gorm v1.25.2-0.20230530020048-26663ab9bf55 h1:sC1Xj4TYrLqg1n3AN10w871An7wJM0gzgcm8jkIkECQ=
1048
gorm.io/gorm v1.25.2-0.20230530020048-26663ab9bf55/go.mod h1:L4uxeKpfBml98NYqVqwAdmV1a2nBtAec/cf3fpucW/k=
49+
lukechampine.com/uint128 v1.2.0 h1:mBi/5l91vocEN8otkC5bDLhi2KdCticRiwbdB0O+rjI=
50+
lukechampine.com/uint128 v1.2.0/go.mod h1:c4eWIwlEGaxC/+H1VguhU4PHXNWDCDMUlWdIWl2j1gk=
51+
modernc.org/cc/v3 v3.40.0 h1:P3g79IUS/93SYhtoeaHW+kRCIrYaxJ27MFPv+7kaTOw=
52+
modernc.org/cc/v3 v3.40.0/go.mod h1:/bTg4dnWkSXowUO6ssQKnOV0yMVxDYNIsIrzqTFDGH0=
53+
modernc.org/ccgo/v3 v3.16.13 h1:Mkgdzl46i5F/CNR/Kj80Ri59hC8TKAhZrYSaqvkwzUw=
54+
modernc.org/ccgo/v3 v3.16.13/go.mod h1:2Quk+5YgpImhPjv2Qsob1DnZ/4som1lJTodubIcoUkY=
55+
modernc.org/ccorpus v1.11.6 h1:J16RXiiqiCgua6+ZvQot4yUuUy8zxgqbqEEUuGPlISk=
56+
modernc.org/httpfs v1.0.6 h1:AAgIpFZRXuYnkjftxTAZwMIiwEqAfk8aVB2/oA6nAeM=
57+
modernc.org/libc v1.22.5 h1:91BNch/e5B0uPbJFgqbxXuOnxBQjlS//icfQEGmvyjE=
58+
modernc.org/libc v1.22.5/go.mod h1:jj+Z7dTNX8fBScMVNRAYZ/jF91K8fdT2hYMThc3YjBY=
59+
modernc.org/mathutil v1.5.0 h1:rV0Ko/6SfM+8G+yKiyI830l3Wuz1zRutdslNoQ0kfiQ=
60+
modernc.org/mathutil v1.5.0/go.mod h1:mZW8CKdRPY1v87qxC/wUdX5O1qDzXMP5TH3wjfpga6E=
61+
modernc.org/memory v1.5.0 h1:N+/8c5rE6EqugZwHii4IFsaJ7MUhoWX07J5tC/iI5Ds=
62+
modernc.org/memory v1.5.0/go.mod h1:PkUhL0Mugw21sHPeskwZW4D6VscE/GQJOnIpCnW6pSU=
63+
modernc.org/opt v0.1.3 h1:3XOZf2yznlhC+ibLltsDGzABUGVx8J6pnFMS3E4dcq4=
64+
modernc.org/opt v0.1.3/go.mod h1:WdSiB5evDcignE70guQKxYUl14mgWtbClRi5wmkkTX0=
65+
modernc.org/sqlite v1.23.1 h1:nrSBg4aRQQwq59JpvGEQ15tNxoO5pX/kUjcRNwSAGQM=
66+
modernc.org/sqlite v1.23.1/go.mod h1:OrDj17Mggn6MhE+iPbBNf7RGKODDE9NFT0f3EwDzJqk=
67+
modernc.org/strutil v1.1.3 h1:fNMm+oJklMGYfU9Ylcywl0CO5O6nTfaowNsh2wpPjzY=
68+
modernc.org/strutil v1.1.3/go.mod h1:MEHNA7PdEnEwLvspRMtWTNnp2nnyvMfkimT1NKNAGbw=
69+
modernc.org/tcl v1.15.2 h1:C4ybAYCGJw968e+Me18oW55kD/FexcHbqH2xak1ROSY=
70+
modernc.org/token v1.0.1 h1:A3qvTqOwexpfZZeyI0FeGPDlSWX5pjZu9hF4lU+EKWg=
71+
modernc.org/token v1.0.1/go.mod h1:UGzOrNV1mAFSEB63lOFHIpNRUVMvYTc6yu1SMY/XTDM=
72+
modernc.org/z v1.7.3 h1:zDJf6iHjrnB+WRD88stbXokugjyc0/pB91ri1gO6LZY=

sqlite.go

-4
Original file line numberDiff line numberDiff line change
@@ -8,17 +8,13 @@ import (
88

99
"gorm.io/gorm/callbacks"
1010

11-
_ "github.com/mattn/go-sqlite3"
1211
"gorm.io/gorm"
1312
"gorm.io/gorm/clause"
1413
"gorm.io/gorm/logger"
1514
"gorm.io/gorm/migrator"
1615
"gorm.io/gorm/schema"
1716
)
1817

19-
// DriverName is the default driver name for SQLite.
20-
const DriverName = "sqlite3"
21-
2218
type Dialector struct {
2319
DriverName string
2420
DSN string

sqlite_cgo.go

+11
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
//go:build cgo
2+
// +build cgo
3+
4+
package sqlite
5+
6+
import (
7+
_ "github.com/mattn/go-sqlite3" //sqlite driver
8+
)
9+
10+
// DriverName is the default driver name for SQLite.
11+
const DriverName = "sqlite3"

sqlite_cgo_test.go

+65
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
//go:build cgo
2+
// +build cgo
3+
4+
package sqlite
5+
6+
import (
7+
"database/sql"
8+
"os"
9+
"testing"
10+
11+
"github.com/mattn/go-sqlite3"
12+
)
13+
14+
const (
15+
// This is the DSN of the in-memory SQLite database for these tests.
16+
InMemoryDSN = "file:testdatabase?mode=memory&cache=shared"
17+
// This is the custom SQLite driver name.
18+
CustomDriverName = "my_custom_driver"
19+
)
20+
21+
func TestMain(m *testing.M) {
22+
// Register the custom SQlite3 driver.
23+
// It will have one custom function called "my_custom_function".
24+
sql.Register(CustomDriverName,
25+
// This is the custom SQLite driver.
26+
&sqlite3.SQLiteDriver{
27+
ConnectHook: func(conn *sqlite3.SQLiteConn) error {
28+
// Define the `concat` function, since we use this elsewhere.
29+
err := conn.RegisterFunc(
30+
"my_custom_function",
31+
func(arguments ...interface{}) (string, error) {
32+
return "my-result", nil // Return a string value.
33+
},
34+
true,
35+
)
36+
return err
37+
},
38+
},
39+
)
40+
41+
rows = append(rows, []testRow{
42+
{
43+
description: "Explicit default driver, custom function",
44+
dialector: &Dialector{
45+
DriverName: DriverName,
46+
DSN: InMemoryDSN,
47+
},
48+
openSuccess: true,
49+
query: "SELECT my_custom_function()",
50+
querySuccess: false,
51+
},
52+
{
53+
description: "Custom driver, custom function",
54+
dialector: &Dialector{
55+
DriverName: CustomDriverName,
56+
DSN: InMemoryDSN,
57+
},
58+
openSuccess: true,
59+
query: "SELECT my_custom_function()",
60+
querySuccess: true,
61+
},
62+
}...)
63+
64+
os.Exit(m.Run())
65+
}

sqlite_pure.go

+11
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
//go:build !cgo
2+
// +build !cgo
3+
4+
package sqlite
5+
6+
import (
7+
_ "modernc.org/sqlite" //sqlite driver
8+
)
9+
10+
// DriverName is the default driver name for SQLite.
11+
const DriverName = "sqlite"

sqlite_pure_test.go

+58
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
//go:build !cgo
2+
// +build !cgo
3+
4+
package sqlite
5+
6+
import (
7+
"database/sql"
8+
"database/sql/driver"
9+
"os"
10+
"testing"
11+
12+
"modernc.org/sqlite"
13+
)
14+
15+
const (
16+
// This is the DSN of the in-memory SQLite database for these tests.
17+
InMemoryDSN = "testdatabase"
18+
// This is the custom SQLite driver name.
19+
CustomDriverName = "my_custom_driver"
20+
)
21+
22+
func TestMain(m *testing.M) {
23+
// Register a custom function to the default SQLite driver.
24+
sqlite.MustRegisterDeterministicScalarFunction("my_custom_function", -1, func(ctx *sqlite.FunctionContext, args []driver.Value) (driver.Value, error) {
25+
return "my-result", nil
26+
})
27+
28+
// Register the custom SQlite driver.
29+
// modernc.org/sqlite doesn't support registering functions to custom drivers.
30+
sql.Register(CustomDriverName,
31+
&sqlite.Driver{},
32+
)
33+
34+
rows = append(rows, []testRow{
35+
{
36+
description: "Explicit default driver, custom function",
37+
dialector: &Dialector{
38+
DriverName: DriverName,
39+
DSN: InMemoryDSN,
40+
},
41+
openSuccess: true,
42+
query: "SELECT my_custom_function()",
43+
querySuccess: true,
44+
},
45+
{
46+
description: "Custom driver, custom function",
47+
dialector: &Dialector{
48+
DriverName: CustomDriverName,
49+
DSN: InMemoryDSN,
50+
},
51+
openSuccess: true,
52+
query: "SELECT my_custom_function()",
53+
querySuccess: false,
54+
},
55+
}...)
56+
57+
os.Exit(m.Run())
58+
}

sqlite_test.go

+12-52
Original file line numberDiff line numberDiff line change
@@ -1,45 +1,22 @@
11
package sqlite
22

33
import (
4-
"database/sql"
54
"fmt"
65
"testing"
76

8-
"github.com/mattn/go-sqlite3"
97
"gorm.io/gorm"
108
)
119

12-
func TestDialector(t *testing.T) {
13-
// This is the DSN of the in-memory SQLite database for these tests.
14-
const InMemoryDSN = "file:testdatabase?mode=memory&cache=shared"
15-
// This is the custom SQLite driver name.
16-
const CustomDriverName = "my_custom_driver"
17-
18-
// Register the custom SQlite3 driver.
19-
// It will have one custom function called "my_custom_function".
20-
sql.Register(CustomDriverName,
21-
&sqlite3.SQLiteDriver{
22-
ConnectHook: func(conn *sqlite3.SQLiteConn) error {
23-
// Define the `concat` function, since we use this elsewhere.
24-
err := conn.RegisterFunc(
25-
"my_custom_function",
26-
func(arguments ...interface{}) (string, error) {
27-
return "my-result", nil // Return a string value.
28-
},
29-
true,
30-
)
31-
return err
32-
},
33-
},
34-
)
10+
type testRow struct {
11+
description string
12+
dialector *Dialector
13+
openSuccess bool
14+
query string
15+
querySuccess bool
16+
}
3517

36-
rows := []struct {
37-
description string
38-
dialector *Dialector
39-
openSuccess bool
40-
query string
41-
querySuccess bool
42-
}{
18+
var (
19+
rows = []testRow{
4320
{
4421
description: "Default driver",
4522
dialector: &Dialector{
@@ -67,16 +44,6 @@ func TestDialector(t *testing.T) {
6744
},
6845
openSuccess: false,
6946
},
70-
{
71-
description: "Explicit default driver, custom function",
72-
dialector: &Dialector{
73-
DriverName: DriverName,
74-
DSN: InMemoryDSN,
75-
},
76-
openSuccess: true,
77-
query: "SELECT my_custom_function()",
78-
querySuccess: false,
79-
},
8047
{
8148
description: "Custom driver",
8249
dialector: &Dialector{
@@ -87,17 +54,10 @@ func TestDialector(t *testing.T) {
8754
query: "SELECT 1",
8855
querySuccess: true,
8956
},
90-
{
91-
description: "Custom driver, custom function",
92-
dialector: &Dialector{
93-
DriverName: CustomDriverName,
94-
DSN: InMemoryDSN,
95-
},
96-
openSuccess: true,
97-
query: "SELECT my_custom_function()",
98-
querySuccess: true,
99-
},
10057
}
58+
)
59+
60+
func TestDialector(t *testing.T) {
10161
for rowIndex, row := range rows {
10262
t.Run(fmt.Sprintf("%d/%s", rowIndex, row.description), func(t *testing.T) {
10363
db, err := gorm.Open(row.dialector, &gorm.Config{})

0 commit comments

Comments
 (0)