mirror of
https://github.com/ncruces/go-sqlite3.git
synced 2026-01-19 09:04:16 +00:00
Compare commits
9 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
b9b2ff13da | ||
|
|
78473b4b37 | ||
|
|
3806c1cc23 | ||
|
|
1660c41f8c | ||
|
|
62b67c937e | ||
|
|
9e9971c292 | ||
|
|
d13bf1afaa | ||
|
|
f7c9551d66 | ||
|
|
22beef91d2 |
14
README.md
14
README.md
@@ -12,6 +12,20 @@ It wraps a [Wasm](https://webassembly.org/) [build](embed/) of SQLite,
|
||||
and uses [wazero](https://wazero.io/) as the runtime.\
|
||||
Go, wazero and [`x/sys`](https://pkg.go.dev/golang.org/x/sys) are the _only_ runtime dependencies [^1].
|
||||
|
||||
### Getting started
|
||||
|
||||
Using the [`database/sql`](https://pkg.go.dev/database/sql) driver:
|
||||
```go
|
||||
|
||||
import "database/sql"
|
||||
import _ "github.com/ncruces/go-sqlite3/driver"
|
||||
import _ "github.com/ncruces/go-sqlite3/embed"
|
||||
|
||||
var version string
|
||||
db, _ := sql.Open("sqlite3", "file:demo.db")
|
||||
db.QueryRow(`SELECT sqlite_version()`).Scan(&version)
|
||||
```
|
||||
|
||||
### Packages
|
||||
|
||||
- [`github.com/ncruces/go-sqlite3`](https://pkg.go.dev/github.com/ncruces/go-sqlite3)
|
||||
|
||||
@@ -176,7 +176,7 @@ func Example_customTime() {
|
||||
// a time. 2009-11-17T20:34:58.650Z goes in, but parsing and formatting
|
||||
// it with [time.RFC3338Nano] results in 2009-11-17T20:34:58.65Z. Though
|
||||
// the times are identical, the trailing zero is lost in the string
|
||||
// representation so the driver considers the conversion unsuccesful.
|
||||
// representation so the driver considers the conversion unsuccessful.
|
||||
c1 := CustomTime{time.Date(
|
||||
2009, 11, 17, 20, 34, 58, 650000000, time.UTC)}
|
||||
|
||||
|
||||
@@ -58,9 +58,10 @@ func Example() {
|
||||
// Hello BLOB!
|
||||
}
|
||||
|
||||
func init() {
|
||||
func TestMain(m *testing.M) {
|
||||
sqlite3.AutoExtension(blobio.Register)
|
||||
sqlite3.AutoExtension(array.Register)
|
||||
m.Run()
|
||||
}
|
||||
|
||||
func Test_readblob(t *testing.T) {
|
||||
|
||||
@@ -12,8 +12,9 @@ import (
|
||||
_ "github.com/ncruces/go-sqlite3/internal/testcfg"
|
||||
)
|
||||
|
||||
func init() {
|
||||
func TestMain(m *testing.M) {
|
||||
sqlite3.AutoExtension(bloom.Register)
|
||||
m.Run()
|
||||
}
|
||||
|
||||
func TestRegister(t *testing.T) {
|
||||
|
||||
@@ -54,8 +54,9 @@ func Example() {
|
||||
// On Twosday, 1€ = $1.1342
|
||||
}
|
||||
|
||||
func init() {
|
||||
func TestMain(m *testing.M) {
|
||||
sqlite3.AutoExtension(csv.Register)
|
||||
m.Run()
|
||||
}
|
||||
|
||||
func TestRegister(t *testing.T) {
|
||||
|
||||
@@ -83,8 +83,9 @@ func Example() {
|
||||
// gamma 80 75 78 80
|
||||
}
|
||||
|
||||
func init() {
|
||||
func TestMain(m *testing.M) {
|
||||
sqlite3.AutoExtension(pivot.Register)
|
||||
m.Run()
|
||||
}
|
||||
|
||||
func TestRegister(t *testing.T) {
|
||||
|
||||
@@ -48,8 +48,9 @@ func Example() {
|
||||
// Twosday was 2022-2-22
|
||||
}
|
||||
|
||||
func init() {
|
||||
func TestMain(m *testing.M) {
|
||||
sqlite3.AutoExtension(statement.Register)
|
||||
m.Run()
|
||||
}
|
||||
|
||||
func TestRegister(t *testing.T) {
|
||||
|
||||
@@ -32,7 +32,7 @@ func (q *percentile) Step(ctx sqlite3.Context, arg ...sqlite3.Value) {
|
||||
q.nums = append(q.nums, a.Float())
|
||||
}
|
||||
if q.kind != median {
|
||||
q.arg1 = arg[1].Blob(q.arg1[:0])
|
||||
q.arg1 = append(q.arg1[:0], arg[1].RawText()...)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -79,7 +79,7 @@ func getPercentile(nums []float64, pos float64, disc bool) (float64, error) {
|
||||
}
|
||||
|
||||
m1 := slices.Min(nums[int(i)+1:])
|
||||
return math.FMA(f, m1, -math.FMA(f, m0, -m0)), nil
|
||||
return math.FMA(f, m1, math.FMA(-f, m0, m0)), nil
|
||||
}
|
||||
|
||||
func getPercentiles(nums []float64, pos []float64, disc bool) error {
|
||||
|
||||
@@ -10,8 +10,9 @@ import (
|
||||
_ "github.com/ncruces/go-sqlite3/internal/testcfg"
|
||||
)
|
||||
|
||||
func init() {
|
||||
func TestMain(m *testing.M) {
|
||||
sqlite3.AutoExtension(stats.Register)
|
||||
m.Run()
|
||||
}
|
||||
|
||||
func TestRegister_variance(t *testing.T) {
|
||||
|
||||
@@ -66,23 +66,23 @@ func generate(ctx sqlite3.Context, arg ...sqlite3.Value) {
|
||||
domain = uuid.Domain(arg[1].Int64())
|
||||
if domain == 0 {
|
||||
if txt := arg[1].RawText(); len(txt) > 0 {
|
||||
switch txt[0] | 0x20 {
|
||||
switch txt[0] | 0x20 { // to lower
|
||||
case 'g': // group
|
||||
domain = 1
|
||||
domain = uuid.Group
|
||||
case 'o': // org
|
||||
domain = 2
|
||||
domain = uuid.Org
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if len(arg) > 2 {
|
||||
id := uint32(arg[2].Int64())
|
||||
u, err = uuid.NewDCESecurity(domain, id)
|
||||
} else if domain == uuid.Person {
|
||||
switch {
|
||||
case len(arg) > 2:
|
||||
u, err = uuid.NewDCESecurity(domain, uint32(arg[2].Int64()))
|
||||
case domain == uuid.Person:
|
||||
u, err = uuid.NewDCEPerson()
|
||||
} else if domain == uuid.Group {
|
||||
case domain == uuid.Group:
|
||||
u, err = uuid.NewDCEGroup()
|
||||
} else {
|
||||
default:
|
||||
err = util.ErrorString("missing id")
|
||||
}
|
||||
|
||||
|
||||
@@ -78,7 +78,7 @@ func (f *countASCII) isASCII(arg sqlite3.Value) bool {
|
||||
if arg.Type() != sqlite3.TEXT {
|
||||
return false
|
||||
}
|
||||
for _, c := range arg.RawBlob() {
|
||||
for _, c := range arg.RawText() {
|
||||
if c > unicode.MaxASCII {
|
||||
return false
|
||||
}
|
||||
|
||||
@@ -5,7 +5,7 @@ go 1.21
|
||||
toolchain go1.23.0
|
||||
|
||||
require (
|
||||
github.com/ncruces/go-sqlite3 v0.17.1
|
||||
github.com/ncruces/go-sqlite3 v0.18.0
|
||||
gorm.io/gorm v1.25.11
|
||||
)
|
||||
|
||||
|
||||
@@ -2,8 +2,8 @@ github.com/jinzhu/inflection v1.0.0 h1:K317FqzuhWc8YvSVlFMCCUb36O/S9MCKRDI7QkRKD
|
||||
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/ncruces/go-sqlite3 v0.17.1 h1:VxTjDpCn87FaFlKMaAYC1jP7ND0d4UNj+6G4IQDHbgI=
|
||||
github.com/ncruces/go-sqlite3 v0.17.1/go.mod h1:FnCyui8SlDoL0mQZ5dTouNo7s7jXS0kJv9lBt1GlM9w=
|
||||
github.com/ncruces/go-sqlite3 v0.18.0 h1:aH7WGzOC0CYpUPG1LdFg7JApybiuXgYUE2itzLBwhPM=
|
||||
github.com/ncruces/go-sqlite3 v0.18.0/go.mod h1:eEOyZnW1dGTJ+zDpMuzfYamEUBtdFz5zeYhqLBtHxvM=
|
||||
github.com/ncruces/julianday v1.0.0 h1:fH0OKwa7NWvniGQtxdJRxAgkBMolni2BjDHaWTxqt7M=
|
||||
github.com/ncruces/julianday v1.0.0/go.mod h1:Dusn2KvZrrovOMJuOt0TNXL6tB7U2E8kvza5fFc9G7g=
|
||||
github.com/tetratelabs/wazero v1.8.0 h1:iEKu0d4c2Pd+QSRieYbnQC9yiFlMS9D+Jr0LsRmcF4g=
|
||||
|
||||
@@ -1,7 +1,9 @@
|
||||
package tests
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"io"
|
||||
"log"
|
||||
"net/url"
|
||||
"os"
|
||||
"os/exec"
|
||||
@@ -19,6 +21,20 @@ import (
|
||||
"github.com/ncruces/go-sqlite3/vfs/memdb"
|
||||
)
|
||||
|
||||
func TestMain(m *testing.M) {
|
||||
sqlite3.AutoExtension(func(c *sqlite3.Conn) error {
|
||||
return c.ConfigLog(func(code sqlite3.ExtendedErrorCode, msg string) {
|
||||
// Having to do journal recovery is unexpected.
|
||||
if errors.Is(code, sqlite3.NOTICE) {
|
||||
log.Panicf("%v (%d): %s", code, code, msg)
|
||||
} else {
|
||||
log.Printf("%v (%d): %s", code, code, msg)
|
||||
}
|
||||
})
|
||||
})
|
||||
m.Run()
|
||||
}
|
||||
|
||||
func Test_parallel(t *testing.T) {
|
||||
if !vfs.SupportsFileLocking {
|
||||
t.Skip("skipping without locks")
|
||||
@@ -45,12 +61,19 @@ func Test_wal(t *testing.T) {
|
||||
t.Skip("skipping without shared memory")
|
||||
}
|
||||
|
||||
var iter int
|
||||
if testing.Short() {
|
||||
iter = 1000
|
||||
} else {
|
||||
iter = 2500
|
||||
}
|
||||
|
||||
name := "file:" +
|
||||
filepath.ToSlash(filepath.Join(t.TempDir(), "test.db")) +
|
||||
"?_pragma=busy_timeout(10000)" +
|
||||
"&_pragma=journal_mode(wal)" +
|
||||
"&_pragma=synchronous(off)"
|
||||
testParallel(t, name, 1000)
|
||||
testParallel(t, name, iter)
|
||||
testIntegrity(t, name)
|
||||
}
|
||||
|
||||
|
||||
@@ -121,8 +121,8 @@ func (s *vfsShm) shmOpen() (rc _ErrorCode) {
|
||||
// Find a shared file, increase the reference count.
|
||||
for _, g := range vfsShmFiles {
|
||||
if g != nil && os.SameFile(fi, g.info) {
|
||||
g.refs++
|
||||
s.vfsShmFile = g
|
||||
g.refs++
|
||||
return _OK
|
||||
}
|
||||
}
|
||||
@@ -207,15 +207,22 @@ func (s *vfsShm) shmLock(offset, n int32, flags _ShmFlag) _ErrorCode {
|
||||
case flags&_SHM_UNLOCK != 0:
|
||||
for i := offset; i < offset+n; i++ {
|
||||
if s.lock[i] {
|
||||
if s.vfsShmFile.lock[i] == 0 {
|
||||
panic(util.AssertErr())
|
||||
}
|
||||
if s.vfsShmFile.lock[i] <= 0 {
|
||||
s.vfsShmFile.lock[i] = 0
|
||||
} else {
|
||||
s.vfsShmFile.lock[i]--
|
||||
}
|
||||
s.lock[i] = false
|
||||
}
|
||||
}
|
||||
case flags&_SHM_SHARED != 0:
|
||||
for i := offset; i < offset+n; i++ {
|
||||
if s.lock[i] {
|
||||
panic(util.AssertErr())
|
||||
}
|
||||
if s.vfsShmFile.lock[i] < 0 {
|
||||
return _BUSY
|
||||
}
|
||||
@@ -226,6 +233,9 @@ func (s *vfsShm) shmLock(offset, n int32, flags _ShmFlag) _ErrorCode {
|
||||
}
|
||||
case flags&_SHM_EXCLUSIVE != 0:
|
||||
for i := offset; i < offset+n; i++ {
|
||||
if s.lock[i] {
|
||||
panic(util.AssertErr())
|
||||
}
|
||||
if s.vfsShmFile.lock[i] != 0 {
|
||||
return _BUSY
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user