[chore]: Bump github.com/ncruces/go-sqlite3 from 0.23.0 to 0.24.0 (#3862)

Bumps [github.com/ncruces/go-sqlite3](https://github.com/ncruces/go-sqlite3) from 0.23.0 to 0.24.0.
- [Release notes](https://github.com/ncruces/go-sqlite3/releases)
- [Commits](https://github.com/ncruces/go-sqlite3/compare/v0.23.0...v0.24.0)

---
updated-dependencies:
- dependency-name: github.com/ncruces/go-sqlite3
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
This commit is contained in:
dependabot[bot] 2025-03-03 09:51:42 +00:00 committed by GitHub
parent 8488ac9286
commit 0e2e8e54ab
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
26 changed files with 215 additions and 155 deletions

4
go.mod
View file

@ -53,7 +53,7 @@ require (
github.com/miekg/dns v1.1.63 github.com/miekg/dns v1.1.63
github.com/minio/minio-go/v7 v7.0.85 github.com/minio/minio-go/v7 v7.0.85
github.com/mitchellh/mapstructure v1.5.0 github.com/mitchellh/mapstructure v1.5.0
github.com/ncruces/go-sqlite3 v0.23.0 github.com/ncruces/go-sqlite3 v0.24.0
github.com/oklog/ulid v1.3.1 github.com/oklog/ulid v1.3.1
github.com/prometheus/client_golang v1.20.5 github.com/prometheus/client_golang v1.20.5
github.com/rivo/uniseg v0.4.7 github.com/rivo/uniseg v0.4.7
@ -81,7 +81,7 @@ require (
go.opentelemetry.io/otel/sdk/metric v1.34.0 go.opentelemetry.io/otel/sdk/metric v1.34.0
go.opentelemetry.io/otel/trace v1.34.0 go.opentelemetry.io/otel/trace v1.34.0
go.uber.org/automaxprocs v1.6.0 go.uber.org/automaxprocs v1.6.0
golang.org/x/crypto v0.34.0 golang.org/x/crypto v0.35.0
golang.org/x/image v0.24.0 golang.org/x/image v0.24.0
golang.org/x/net v0.35.0 golang.org/x/net v0.35.0
golang.org/x/oauth2 v0.27.0 golang.org/x/oauth2 v0.27.0

8
go.sum generated
View file

@ -323,8 +323,8 @@ github.com/moul/http2curl v1.0.0 h1:dRMWoAtb+ePxMlLkrCbAqh4TlPHXvoGUSQ323/9Zahs=
github.com/moul/http2curl v1.0.0/go.mod h1:8UbvGypXm98wA/IqH45anm5Y2Z6ep6O31QGOAZ3H0fQ= github.com/moul/http2curl v1.0.0/go.mod h1:8UbvGypXm98wA/IqH45anm5Y2Z6ep6O31QGOAZ3H0fQ=
github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 h1:C3w9PqII01/Oq1c1nUAm88MOHcQC9l5mIlSMApZMrHA= github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 h1:C3w9PqII01/Oq1c1nUAm88MOHcQC9l5mIlSMApZMrHA=
github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ= github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ=
github.com/ncruces/go-sqlite3 v0.23.0 h1:90j/ar8Ywu2AtsfDl5WhO9sgP/rNk76BcKGIzAHO8AQ= github.com/ncruces/go-sqlite3 v0.24.0 h1:Z4jfmzu2NCd4SmyFwLT2OmF3EnTZbqwATvdiuNHNhLA=
github.com/ncruces/go-sqlite3 v0.23.0/go.mod h1:gq2nriHSczOs11SqGW5+0X+SgLdkdj4K+j4F/AhQ+8g= github.com/ncruces/go-sqlite3 v0.24.0/go.mod h1:/Vs8ACZHjJ1SA6E9RZUn3EyB1OP3nDQ4z/ar+0fplTQ=
github.com/ncruces/go-strftime v0.1.9 h1:bY0MQC28UADQmHmaF5dgpLmImcShSi2kHU9XLdhx/f4= github.com/ncruces/go-strftime v0.1.9 h1:bY0MQC28UADQmHmaF5dgpLmImcShSi2kHU9XLdhx/f4=
github.com/ncruces/go-strftime v0.1.9/go.mod h1:Fwc5htZGVVkseilnfgOVb9mKy6w1naJmn9CehxcKcls= github.com/ncruces/go-strftime v0.1.9/go.mod h1:Fwc5htZGVVkseilnfgOVb9mKy6w1naJmn9CehxcKcls=
github.com/ncruces/julianday v1.0.0 h1:fH0OKwa7NWvniGQtxdJRxAgkBMolni2BjDHaWTxqt7M= github.com/ncruces/julianday v1.0.0 h1:fH0OKwa7NWvniGQtxdJRxAgkBMolni2BjDHaWTxqt7M=
@ -529,8 +529,8 @@ golang.org/x/crypto v0.13.0/go.mod h1:y6Z2r+Rw4iayiXXAIxJIDAJ1zMW4yaTpebo8fPOliY
golang.org/x/crypto v0.19.0/go.mod h1:Iy9bg/ha4yyC70EfRS8jz+B6ybOBKMaSxLj6P6oBDfU= golang.org/x/crypto v0.19.0/go.mod h1:Iy9bg/ha4yyC70EfRS8jz+B6ybOBKMaSxLj6P6oBDfU=
golang.org/x/crypto v0.23.0/go.mod h1:CKFgDieR+mRhux2Lsu27y0fO304Db0wZe70UKqHu0v8= golang.org/x/crypto v0.23.0/go.mod h1:CKFgDieR+mRhux2Lsu27y0fO304Db0wZe70UKqHu0v8=
golang.org/x/crypto v0.31.0/go.mod h1:kDsLvtWBEx7MV9tJOj9bnXsPbxwJQ6csT/x4KIN4Ssk= golang.org/x/crypto v0.31.0/go.mod h1:kDsLvtWBEx7MV9tJOj9bnXsPbxwJQ6csT/x4KIN4Ssk=
golang.org/x/crypto v0.34.0 h1:+/C6tk6rf/+t5DhUketUbD1aNGqiSX3j15Z6xuIDlBA= golang.org/x/crypto v0.35.0 h1:b15kiHdrGCHrP6LvwaQ3c03kgNhhiMgvlhxHQhmg2Xs=
golang.org/x/crypto v0.34.0/go.mod h1:dy7dXNW32cAb/6/PRuTNsix8T+vJAqvuIy5Bli/x0YQ= golang.org/x/crypto v0.35.0/go.mod h1:dy7dXNW32cAb/6/PRuTNsix8T+vJAqvuIy5Bli/x0YQ=
golang.org/x/exp v0.0.0-20240222234643-814bf88cf225 h1:LfspQV/FYTatPTr/3HzIcmiUFH7PGP+OQ6mgDYo3yuQ= golang.org/x/exp v0.0.0-20240222234643-814bf88cf225 h1:LfspQV/FYTatPTr/3HzIcmiUFH7PGP+OQ6mgDYo3yuQ=
golang.org/x/exp v0.0.0-20240222234643-814bf88cf225/go.mod h1:CxmFvTBINI24O/j8iY7H1xHzx2i4OsyguNBmN/uPtqc= golang.org/x/exp v0.0.0-20240222234643-814bf88cf225/go.mod h1:CxmFvTBINI24O/j8iY7H1xHzx2i4OsyguNBmN/uPtqc=
golang.org/x/image v0.24.0 h1:AN7zRgVsbvmTfNyqIbbOraYL8mSwcKncEj8ofjgzcMQ= golang.org/x/image v0.24.0 h1:AN7zRgVsbvmTfNyqIbbOraYL8mSwcKncEj8ofjgzcMQ=

View file

@ -5,9 +5,6 @@
*.so *.so
*.dylib *.dylib
# Go workspace
go.work*
# Test binary, built with `go test -c` # Test binary, built with `go test -c`
*.test *.test
@ -17,3 +14,10 @@ go.work*
# Dependency directories (remove the comment below to include it) # Dependency directories (remove the comment below to include it)
# vendor/ # vendor/
tools tools
# Go workspace file
go.work
go.work.sum
# env file
.env

View file

@ -98,7 +98,7 @@ Also, post there if you used this driver for something interesting
([_"Show and tell"_](https://github.com/ncruces/go-sqlite3/discussions/categories/show-and-tell)), ([_"Show and tell"_](https://github.com/ncruces/go-sqlite3/discussions/categories/show-and-tell)),
have an [idea](https://github.com/ncruces/go-sqlite3/discussions/categories/ideas)… have an [idea](https://github.com/ncruces/go-sqlite3/discussions/categories/ideas)…
The [Issue](https://github.com/ncruces/go-sqlite3/issues) tracker is for bugs we want fixed, The [Issue](https://github.com/ncruces/go-sqlite3/issues) tracker is for bugs,
and features we're working on, planning to work on, or asking for help with. and features we're working on, planning to work on, or asking for help with.
### Alternatives ### Alternatives

View file

@ -45,7 +45,7 @@ func (c *Conn) Config(op DBConfig, arg ...bool) (bool, error) {
rc := res_t(c.call("sqlite3_db_config", stk_t(c.handle), rc := res_t(c.call("sqlite3_db_config", stk_t(c.handle),
stk_t(op), stk_t(argsPtr))) stk_t(op), stk_t(argsPtr)))
return util.Read32[uint32](c.mod, argsPtr) != 0, c.error(rc) return util.ReadBool(c.mod, argsPtr), c.error(rc)
} }
// ConfigLog sets up the error logging callback for the connection. // ConfigLog sets up the error logging callback for the connection.
@ -116,7 +116,7 @@ func (c *Conn) FileControl(schema string, op FcntlOpcode, arg ...any) (any, erro
rc = res_t(c.call("sqlite3_file_control", rc = res_t(c.call("sqlite3_file_control",
stk_t(c.handle), stk_t(schemaPtr), stk_t(c.handle), stk_t(schemaPtr),
stk_t(op), stk_t(ptr))) stk_t(op), stk_t(ptr)))
ret = util.Read32[uint32](c.mod, ptr) != 0 ret = util.ReadBool(c.mod, ptr)
case FCNTL_CHUNK_SIZE: case FCNTL_CHUNK_SIZE:
util.Write32(c.mod, ptr, int32(arg[0].(int))) util.Write32(c.mod, ptr, int32(arg[0].(int)))

View file

@ -3,6 +3,7 @@
import ( import (
"context" "context"
"fmt" "fmt"
"iter"
"math" "math"
"math/rand" "math/rand"
"net/url" "net/url"
@ -492,9 +493,9 @@ func (c *Conn) TableColumnMetadata(schema, table, column string) (declType, coll
if ptr := util.Read32[ptr_t](c.mod, collSeqPtr); ptr != 0 { if ptr := util.Read32[ptr_t](c.mod, collSeqPtr); ptr != 0 {
collSeq = util.ReadString(c.mod, ptr, _MAX_NAME) collSeq = util.ReadString(c.mod, ptr, _MAX_NAME)
} }
notNull = util.Read32[uint32](c.mod, notNullPtr) != 0 notNull = util.ReadBool(c.mod, notNullPtr)
autoInc = util.Read32[uint32](c.mod, autoIncPtr) != 0 autoInc = util.ReadBool(c.mod, autoIncPtr)
primaryKey = util.Read32[uint32](c.mod, primaryKeyPtr) != 0 primaryKey = util.ReadBool(c.mod, primaryKeyPtr)
} }
return return
} }
@ -503,10 +504,16 @@ func (c *Conn) error(rc res_t, sql ...string) error {
return c.sqlite.error(rc, c.handle, sql...) return c.sqlite.error(rc, c.handle, sql...)
} }
func (c *Conn) stmtsIter(yield func(*Stmt) bool) { // Stmts returns an iterator for the prepared statements
// associated with the database connection.
//
// https://sqlite.org/c3ref/next_stmt.html
func (c *Conn) Stmts() iter.Seq[*Stmt] {
return func(yield func(*Stmt) bool) {
for _, s := range c.stmts { for _, s := range c.stmts {
if !yield(s) { if !yield(s) {
break break
} }
} }
} }
}

View file

@ -1,11 +0,0 @@
//go:build go1.23
package sqlite3
import "iter"
// Stmts returns an iterator for the prepared statements
// associated with the database connection.
//
// https://sqlite.org/c3ref/next_stmt.html
func (c *Conn) Stmts() iter.Seq[*Stmt] { return c.stmtsIter }

View file

@ -1,9 +0,0 @@
//go:build !go1.23
package sqlite3
// Stmts returns an iterator for the prepared statements
// associated with the database connection.
//
// https://sqlite.org/c3ref/next_stmt.html
func (c *Conn) Stmts() func(func(*Stmt) bool) { return c.stmtsIter }

View file

@ -259,7 +259,10 @@
DBCONFIG_TRUSTED_SCHEMA DBConfig = 1017 DBCONFIG_TRUSTED_SCHEMA DBConfig = 1017
DBCONFIG_STMT_SCANSTATUS DBConfig = 1018 DBCONFIG_STMT_SCANSTATUS DBConfig = 1018
DBCONFIG_REVERSE_SCANORDER DBConfig = 1019 DBCONFIG_REVERSE_SCANORDER DBConfig = 1019
// DBCONFIG_MAX DBConfig = 1019 DBCONFIG_ENABLE_ATTACH_CREATE DBConfig = 1020
DBCONFIG_ENABLE_ATTACH_WRITE DBConfig = 1021
DBCONFIG_ENABLE_COMMENTS DBConfig = 1022
// DBCONFIG_MAX DBConfig = 1022
) )
// FcntlOpcode are the available opcodes for [Conn.FileControl]. // FcntlOpcode are the available opcodes for [Conn.FileControl].

View file

@ -1,6 +1,6 @@
# Embeddable Wasm build of SQLite # Embeddable Wasm build of SQLite
This folder includes an embeddable Wasm build of SQLite 3.49.0 for use with This folder includes an embeddable Wasm build of SQLite 3.49.1 for use with
[`github.com/ncruces/go-sqlite3`](https://pkg.go.dev/github.com/ncruces/go-sqlite3). [`github.com/ncruces/go-sqlite3`](https://pkg.go.dev/github.com/ncruces/go-sqlite3).
The following optional features are compiled in: The following optional features are compiled in:

View file

@ -80,6 +80,7 @@ sqlite3_interrupt
sqlite3_invoke_busy_handler_go sqlite3_invoke_busy_handler_go
sqlite3_last_insert_rowid sqlite3_last_insert_rowid
sqlite3_limit sqlite3_limit
sqlite3_log_go
sqlite3_malloc64 sqlite3_malloc64
sqlite3_open_v2 sqlite3_open_v2
sqlite3_overload_function sqlite3_overload_function

Binary file not shown.

View file

@ -2,6 +2,7 @@
import ( import (
"context" "context"
"io"
"sync" "sync"
"github.com/tetratelabs/wazero/api" "github.com/tetratelabs/wazero/api"
@ -85,13 +86,19 @@ func (c *Conn) CreateWindowFunction(name string, nArg int, flag FunctionFlag, fn
var funcPtr ptr_t var funcPtr ptr_t
defer c.arena.mark()() defer c.arena.mark()()
namePtr := c.arena.string(name) namePtr := c.arena.string(name)
if fn != nil {
funcPtr = util.AddHandle(c.ctx, fn)
}
call := "sqlite3_create_aggregate_function_go" call := "sqlite3_create_aggregate_function_go"
if _, ok := fn().(WindowFunction); ok { if fn != nil {
agg := fn()
if c, ok := agg.(io.Closer); ok {
if err := c.Close(); err != nil {
return err
}
}
if _, ok := agg.(WindowFunction); ok {
call = "sqlite3_create_window_function_go" call = "sqlite3_create_window_function_go"
} }
funcPtr = util.AddHandle(c.ctx, fn)
}
rc := res_t(c.call(call, rc := res_t(c.call(call,
stk_t(c.handle), stk_t(namePtr), stk_t(nArg), stk_t(c.handle), stk_t(namePtr), stk_t(nArg),
stk_t(flag), stk_t(funcPtr))) stk_t(flag), stk_t(funcPtr)))
@ -168,20 +175,24 @@ func stepCallback(ctx context.Context, mod api.Module, pCtx, pAgg, pApp ptr_t, n
fn.Step(Context{db, pCtx}, args[:nArg]...) fn.Step(Context{db, pCtx}, args[:nArg]...)
} }
func finalCallback(ctx context.Context, mod api.Module, pCtx, pAgg, pApp ptr_t) { func valueCallback(ctx context.Context, mod api.Module, pCtx, pAgg, pApp ptr_t, final int32) {
db := ctx.Value(connKey{}).(*Conn) db := ctx.Value(connKey{}).(*Conn)
fn, handle := callbackAggregate(db, pAgg, pApp) fn, handle := callbackAggregate(db, pAgg, pApp)
fn.Value(Context{db, pCtx}) fn.Value(Context{db, pCtx})
if err := util.DelHandle(ctx, handle); err != nil {
// Cleanup.
if final != 0 {
var err error
if handle != 0 {
err = util.DelHandle(ctx, handle)
} else if c, ok := fn.(io.Closer); ok {
err = c.Close()
}
if err != nil {
Context{db, pCtx}.ResultError(err) Context{db, pCtx}.ResultError(err)
return // notest return // notest
} }
} }
func valueCallback(ctx context.Context, mod api.Module, pCtx, pAgg ptr_t) {
db := ctx.Value(connKey{}).(*Conn)
fn := util.GetHandle(db.ctx, pAgg).(AggregateFunction)
fn.Value(Context{db, pCtx})
} }
func inverseCallback(ctx context.Context, mod api.Module, pCtx, pAgg ptr_t, nArg int32, pArg ptr_t) { func inverseCallback(ctx context.Context, mod api.Module, pCtx, pAgg ptr_t, nArg int32, pArg ptr_t) {

View file

@ -1,27 +0,0 @@
package util
import (
"runtime"
"golang.org/x/sys/cpu"
)
func CompilerSupported() bool {
switch runtime.GOOS {
case "linux", "android",
"windows", "darwin",
"freebsd", "netbsd", "dragonfly",
"solaris", "illumos":
break
default:
return false
}
switch runtime.GOARCH {
case "amd64":
return cpu.X86.HasSSE41
case "arm64":
return true
default:
return false
}
}

View file

@ -26,9 +26,6 @@ func View(mod api.Module, ptr Ptr_t, size int64) []byte {
if ptr == 0 { if ptr == 0 {
panic(NilErr) panic(NilErr)
} }
if size == 0 {
return nil
}
if uint64(size) > math.MaxUint32 { if uint64(size) > math.MaxUint32 {
panic(RangeErr) panic(RangeErr)
} }
@ -110,6 +107,18 @@ func WriteFloat64(mod api.Module, ptr Ptr_t, v float64) {
Write64(mod, ptr, math.Float64bits(v)) Write64(mod, ptr, math.Float64bits(v))
} }
func ReadBool(mod api.Module, ptr Ptr_t) bool {
return Read32[int32](mod, ptr) != 0
}
func WriteBool(mod api.Module, ptr Ptr_t, v bool) {
var i int32
if v {
i = 1
}
Write32(mod, ptr, i)
}
func ReadString(mod api.Module, ptr Ptr_t, maxlen int64) string { func ReadString(mod api.Module, ptr Ptr_t, maxlen int64) string {
if ptr == 0 { if ptr == 0 {
panic(NilErr) panic(NilErr)

View file

@ -47,11 +47,7 @@ func compileSQLite() {
ctx := context.Background() ctx := context.Background()
cfg := RuntimeConfig cfg := RuntimeConfig
if cfg == nil { if cfg == nil {
if util.CompilerSupported() { cfg = wazero.NewRuntimeConfig()
cfg = wazero.NewRuntimeConfigCompiler()
} else {
cfg = wazero.NewRuntimeConfigInterpreter()
}
if bits.UintSize < 64 { if bits.UintSize < 64 {
cfg = cfg.WithMemoryLimitPages(512) // 32MB cfg = cfg.WithMemoryLimitPages(512) // 32MB
} else { } else {
@ -321,8 +317,7 @@ func exportCallbacks(env wazero.HostModuleBuilder) wazero.HostModuleBuilder {
util.ExportFuncVI(env, "go_destroy", destroyCallback) util.ExportFuncVI(env, "go_destroy", destroyCallback)
util.ExportFuncVIIII(env, "go_func", funcCallback) util.ExportFuncVIIII(env, "go_func", funcCallback)
util.ExportFuncVIIIII(env, "go_step", stepCallback) util.ExportFuncVIIIII(env, "go_step", stepCallback)
util.ExportFuncVIII(env, "go_final", finalCallback) util.ExportFuncVIIII(env, "go_value", valueCallback)
util.ExportFuncVII(env, "go_value", valueCallback)
util.ExportFuncVIIII(env, "go_inverse", inverseCallback) util.ExportFuncVIIII(env, "go_inverse", inverseCallback)
util.ExportFuncVIIII(env, "go_collation_needed", collationCallback) util.ExportFuncVIIII(env, "go_collation_needed", collationCallback)
util.ExportFuncIIIIII(env, "go_compare", compareCallback) util.ExportFuncIIIIII(env, "go_compare", compareCallback)

View file

@ -47,11 +47,12 @@ type cksmFlags struct {
func (c cksmFile) ReadAt(p []byte, off int64) (n int, err error) { func (c cksmFile) ReadAt(p []byte, off int64) (n int, err error) {
n, err = c.File.ReadAt(p, off) n, err = c.File.ReadAt(p, off)
p = p[:n]
// SQLite is reading the header of a database file. // SQLite is reading the header of a database file.
if c.isDB && off == 0 && len(p) >= 100 && if c.isDB && off == 0 && len(p) >= 100 &&
bytes.HasPrefix(p, []byte("SQLite format 3\000")) { bytes.HasPrefix(p, []byte("SQLite format 3\000")) {
c.init(p) c.init((*[100]byte)(p))
} }
// Verify checksums. // Verify checksums.
@ -69,7 +70,7 @@ func (c cksmFile) WriteAt(p []byte, off int64) (n int, err error) {
// SQLite is writing the first page of a database file. // SQLite is writing the first page of a database file.
if c.isDB && off == 0 && len(p) >= 100 && if c.isDB && off == 0 && len(p) >= 100 &&
bytes.HasPrefix(p, []byte("SQLite format 3\000")) { bytes.HasPrefix(p, []byte("SQLite format 3\000")) {
c.init(p) c.init((*[100]byte)(p))
} }
// Compute checksums. // Compute checksums.
@ -122,12 +123,16 @@ func (c cksmFile) fileControl(ctx context.Context, mod api.Module, op _FcntlOpco
return vfsFileControlImpl(ctx, mod, c.File, op, pArg) return vfsFileControlImpl(ctx, mod, c.File, op, pArg)
} }
func (f *cksmFlags) init(header []byte) { func (f *cksmFlags) init(header *[100]byte) {
f.pageSize = 256 * int(binary.LittleEndian.Uint16(header[16:18])) f.pageSize = 256 * int(binary.LittleEndian.Uint16(header[16:18]))
if r := header[20] == 8; r != f.computeCksm { if r := header[20] == 8; r != f.computeCksm {
f.computeCksm = r f.computeCksm = r
f.verifyCksm = r f.verifyCksm = r
} }
if !sql3util.ValidPageSize(f.pageSize) {
f.computeCksm = false
f.verifyCksm = false
}
} }
func cksmCompute(a []byte) (cksm [8]byte) { func cksmCompute(a []byte) (cksm [8]byte) {

View file

@ -31,6 +31,7 @@ func (e _ErrorCode) Error() string {
_READONLY _ErrorCode = util.READONLY _READONLY _ErrorCode = util.READONLY
_IOERR _ErrorCode = util.IOERR _IOERR _ErrorCode = util.IOERR
_NOTFOUND _ErrorCode = util.NOTFOUND _NOTFOUND _ErrorCode = util.NOTFOUND
_FULL _ErrorCode = util.FULL
_CANTOPEN _ErrorCode = util.CANTOPEN _CANTOPEN _ErrorCode = util.CANTOPEN
_IOERR_READ _ErrorCode = util.IOERR_READ _IOERR_READ _ErrorCode = util.IOERR_READ
_IOERR_SHORT_READ _ErrorCode = util.IOERR_SHORT_READ _IOERR_SHORT_READ _ErrorCode = util.IOERR_SHORT_READ
@ -57,10 +58,12 @@ func (e _ErrorCode) Error() string {
_IOERR_COMMIT_ATOMIC _ErrorCode = util.IOERR_COMMIT_ATOMIC _IOERR_COMMIT_ATOMIC _ErrorCode = util.IOERR_COMMIT_ATOMIC
_IOERR_ROLLBACK_ATOMIC _ErrorCode = util.IOERR_ROLLBACK_ATOMIC _IOERR_ROLLBACK_ATOMIC _ErrorCode = util.IOERR_ROLLBACK_ATOMIC
_IOERR_DATA _ErrorCode = util.IOERR_DATA _IOERR_DATA _ErrorCode = util.IOERR_DATA
_IOERR_CORRUPTFS _ErrorCode = util.IOERR_CORRUPTFS
_BUSY_SNAPSHOT _ErrorCode = util.BUSY_SNAPSHOT _BUSY_SNAPSHOT _ErrorCode = util.BUSY_SNAPSHOT
_CANTOPEN_FULLPATH _ErrorCode = util.CANTOPEN_FULLPATH _CANTOPEN_FULLPATH _ErrorCode = util.CANTOPEN_FULLPATH
_CANTOPEN_ISDIR _ErrorCode = util.CANTOPEN_ISDIR _CANTOPEN_ISDIR _ErrorCode = util.CANTOPEN_ISDIR
_READONLY_CANTINIT _ErrorCode = util.READONLY_CANTINIT _READONLY_CANTINIT _ErrorCode = util.READONLY_CANTINIT
_READONLY_DIRECTORY _ErrorCode = util.READONLY_DIRECTORY
_OK_SYMLINK _ErrorCode = util.OK_SYMLINK _OK_SYMLINK _ErrorCode = util.OK_SYMLINK
) )

View file

@ -88,10 +88,13 @@ func (vfsOS) OpenFilename(name *Filename, flags OpenFlag) (File, OpenFlag, error
oflags |= os.O_RDWR oflags |= os.O_RDWR
} }
isCreate := flags&(OPEN_CREATE) != 0
isJournl := flags&(OPEN_MAIN_JOURNAL|OPEN_SUPER_JOURNAL|OPEN_WAL) != 0
var err error var err error
var f *os.File var f *os.File
if name == nil { if name == nil {
f, err = os.CreateTemp("", "*.db") f, err = os.CreateTemp(os.Getenv("SQLITE_TMPDIR"), "*.db")
} else { } else {
f, err = osutil.OpenFile(name.String(), oflags, 0666) f, err = osutil.OpenFile(name.String(), oflags, 0666)
} }
@ -102,6 +105,10 @@ func (vfsOS) OpenFilename(name *Filename, flags OpenFlag) (File, OpenFlag, error
if errors.Is(err, syscall.EISDIR) { if errors.Is(err, syscall.EISDIR) {
return nil, flags, _CANTOPEN_ISDIR return nil, flags, _CANTOPEN_ISDIR
} }
if isCreate && isJournl && errors.Is(err, fs.ErrPermission) &&
osAccess(name.String(), ACCESS_EXISTS) != nil {
return nil, flags, _READONLY_DIRECTORY
}
return nil, flags, err return nil, flags, err
} }
@ -119,9 +126,7 @@ func (vfsOS) OpenFilename(name *Filename, flags OpenFlag) (File, OpenFlag, error
File: f, File: f,
psow: true, psow: true,
readOnly: flags&OPEN_READONLY != 0, readOnly: flags&OPEN_READONLY != 0,
syncDir: canSyncDirs && syncDir: canSyncDirs && isCreate && isJournl,
flags&(OPEN_MAIN_JOURNAL|OPEN_SUPER_JOURNAL|OPEN_WAL) != 0 &&
flags&(OPEN_CREATE) != 0,
shm: NewSharedMemory(name.String()+"-shm", flags), shm: NewSharedMemory(name.String()+"-shm", flags),
} }
return &file, flags, nil return &file, flags, nil
@ -154,6 +159,14 @@ func (f *vfsFile) Close() error {
return f.File.Close() return f.File.Close()
} }
func (f *vfsFile) ReadAt(p []byte, off int64) (n int, err error) {
return osReadAt(f.File, p, off)
}
func (f *vfsFile) WriteAt(p []byte, off int64) (n int, err error) {
return osWriteAt(f.File, p, off)
}
func (f *vfsFile) Sync(flags SyncFlag) error { func (f *vfsFile) Sync(flags SyncFlag) error {
dataonly := (flags & SYNC_DATAONLY) != 0 dataonly := (flags & SYNC_DATAONLY) != 0
fullsync := (flags & 0x0f) == SYNC_FULL fullsync := (flags & 0x0f) == SYNC_FULL

13
vendor/github.com/ncruces/go-sqlite3/vfs/os_std_rw.go generated vendored Normal file
View file

@ -0,0 +1,13 @@
//go:build !unix && (!windows || sqlite3_dotlk)
package vfs
import "os"
func osReadAt(file *os.File, p []byte, off int64) (int, error) {
return file.ReadAt(p, off)
}
func osWriteAt(file *os.File, p []byte, off int64) (int, error) {
return file.WriteAt(p, off)
}

View file

@ -25,6 +25,28 @@ func osAccess(path string, flags AccessFlag) error {
return unix.Access(path, access) return unix.Access(path, access)
} }
func osReadAt(file *os.File, p []byte, off int64) (int, error) {
n, err := file.ReadAt(p, off)
if errno, ok := err.(unix.Errno); ok {
switch errno {
case
unix.ERANGE,
unix.EIO,
unix.ENXIO:
return n, _IOERR_CORRUPTFS
}
}
return n, err
}
func osWriteAt(file *os.File, p []byte, off int64) (int, error) {
n, err := file.WriteAt(p, off)
if errno, ok := err.(unix.Errno); ok && errno == unix.ENOSPC {
return n, _FULL
}
return n, err
}
func osSetMode(file *os.File, modeof string) error { func osSetMode(file *os.File, modeof string) error {
fi, err := os.Stat(modeof) fi, err := os.Stat(modeof)
if err != nil { if err != nil {

View file

@ -9,6 +9,23 @@
"golang.org/x/sys/windows" "golang.org/x/sys/windows"
) )
func osReadAt(file *os.File, p []byte, off int64) (int, error) {
return file.ReadAt(p, off)
}
func osWriteAt(file *os.File, p []byte, off int64) (int, error) {
n, err := file.WriteAt(p, off)
if errno, ok := err.(windows.Errno); ok {
switch errno {
case
windows.ERROR_HANDLE_DISK_FULL,
windows.ERROR_DISK_FULL:
return n, _FULL
}
}
return n, err
}
func osGetSharedLock(file *os.File) _ErrorCode { func osGetSharedLock(file *os.File) _ErrorCode {
// Acquire the PENDING lock temporarily before acquiring a new SHARED lock. // Acquire the PENDING lock temporarily before acquiring a new SHARED lock.
rc := osReadLock(file, _PENDING_BYTE, 1, 0) rc := osReadLock(file, _PENDING_BYTE, 1, 0)

View file

@ -58,13 +58,8 @@ func vfsFind(ctx context.Context, mod api.Module, zVfsName ptr_t) uint32 {
} }
func vfsLocaltime(ctx context.Context, mod api.Module, pTm ptr_t, t int64) _ErrorCode { func vfsLocaltime(ctx context.Context, mod api.Module, pTm ptr_t, t int64) _ErrorCode {
tm := time.Unix(t, 0)
var isdst int32
if tm.IsDST() {
isdst = 1
}
const size = 32 / 8 const size = 32 / 8
tm := time.Unix(t, 0)
// https://pubs.opengroup.org/onlinepubs/7908799/xsh/time.h.html // https://pubs.opengroup.org/onlinepubs/7908799/xsh/time.h.html
util.Write32(mod, pTm+0*size, int32(tm.Second())) util.Write32(mod, pTm+0*size, int32(tm.Second()))
util.Write32(mod, pTm+1*size, int32(tm.Minute())) util.Write32(mod, pTm+1*size, int32(tm.Minute()))
@ -74,7 +69,7 @@ func vfsLocaltime(ctx context.Context, mod api.Module, pTm ptr_t, t int64) _Erro
util.Write32(mod, pTm+5*size, int32(tm.Year()-1900)) util.Write32(mod, pTm+5*size, int32(tm.Year()-1900))
util.Write32(mod, pTm+6*size, int32(tm.Weekday()-time.Sunday)) util.Write32(mod, pTm+6*size, int32(tm.Weekday()-time.Sunday))
util.Write32(mod, pTm+7*size, int32(tm.YearDay()-1)) util.Write32(mod, pTm+7*size, int32(tm.YearDay()-1))
util.Write32(mod, pTm+8*size, isdst) util.WriteBool(mod, pTm+8*size, tm.IsDST())
return _OK return _OK
} }
@ -123,11 +118,7 @@ func vfsAccess(ctx context.Context, mod api.Module, pVfs, zPath ptr_t, flags Acc
path := util.ReadString(mod, zPath, _MAX_PATHNAME) path := util.ReadString(mod, zPath, _MAX_PATHNAME)
ok, err := vfs.Access(path, flags) ok, err := vfs.Access(path, flags)
var res int32 util.WriteBool(mod, pResOut, ok)
if ok {
res = 1
}
util.Write32(mod, pResOut, res)
return vfsErrorCode(err, _IOERR_ACCESS) return vfsErrorCode(err, _IOERR_ACCESS)
} }
@ -151,9 +142,8 @@ func vfsOpen(ctx context.Context, mod api.Module, pVfs, zPath, pFile ptr_t, flag
file.SetPowersafeOverwrite(b) file.SetPowersafeOverwrite(b)
} }
} }
if file, ok := file.(FileSharedMemory); ok && if file, ok := file.(FileSharedMemory); ok && pOutVFS != 0 {
pOutVFS != 0 && file.SharedMemory() != nil { util.WriteBool(mod, pOutVFS, file.SharedMemory() != nil)
util.Write32(mod, pOutVFS, int32(1))
} }
if pOutFlags != 0 { if pOutFlags != 0 {
util.Write32(mod, pOutFlags, flags) util.Write32(mod, pOutFlags, flags)
@ -225,12 +215,7 @@ func vfsUnlock(ctx context.Context, mod api.Module, pFile ptr_t, eLock LockLevel
func vfsCheckReservedLock(ctx context.Context, mod api.Module, pFile, pResOut ptr_t) _ErrorCode { func vfsCheckReservedLock(ctx context.Context, mod api.Module, pFile, pResOut ptr_t) _ErrorCode {
file := vfsFileGet(ctx, mod, pFile).(File) file := vfsFileGet(ctx, mod, pFile).(File)
locked, err := file.CheckReservedLock() locked, err := file.CheckReservedLock()
util.WriteBool(mod, pResOut, locked)
var res int32
if locked {
res = 1
}
util.Write32(mod, pResOut, res)
return vfsErrorCode(err, _IOERR_CHECKRESERVEDLOCK) return vfsErrorCode(err, _IOERR_CHECKRESERVEDLOCK)
} }
@ -254,24 +239,20 @@ func vfsFileControlImpl(ctx context.Context, mod api.Module, file File, op _Fcnt
case _FCNTL_PERSIST_WAL: case _FCNTL_PERSIST_WAL:
if file, ok := file.(FilePersistWAL); ok { if file, ok := file.(FilePersistWAL); ok {
if i := util.Read32[int32](mod, pArg); i >= 0 { if i := util.Read32[int32](mod, pArg); i < 0 {
file.SetPersistWAL(i != 0) util.WriteBool(mod, pArg, file.PersistWAL())
} else if file.PersistWAL() {
util.Write32(mod, pArg, int32(1))
} else { } else {
util.Write32(mod, pArg, int32(0)) file.SetPersistWAL(i != 0)
} }
return _OK return _OK
} }
case _FCNTL_POWERSAFE_OVERWRITE: case _FCNTL_POWERSAFE_OVERWRITE:
if file, ok := file.(FilePowersafeOverwrite); ok { if file, ok := file.(FilePowersafeOverwrite); ok {
if i := util.Read32[int32](mod, pArg); i >= 0 { if i := util.Read32[int32](mod, pArg); i < 0 {
file.SetPowersafeOverwrite(i != 0) util.WriteBool(mod, pArg, file.PowersafeOverwrite())
} else if file.PowersafeOverwrite() {
util.Write32(mod, pArg, int32(1))
} else { } else {
util.Write32(mod, pArg, int32(0)) file.SetPowersafeOverwrite(i != 0)
} }
return _OK return _OK
} }
@ -293,11 +274,7 @@ func vfsFileControlImpl(ctx context.Context, mod api.Module, file File, op _Fcnt
case _FCNTL_HAS_MOVED: case _FCNTL_HAS_MOVED:
if file, ok := file.(FileHasMoved); ok { if file, ok := file.(FileHasMoved); ok {
moved, err := file.HasMoved() moved, err := file.HasMoved()
var val uint32 util.WriteBool(mod, pArg, moved)
if moved {
val = 1
}
util.Write32(mod, pArg, val)
return vfsErrorCode(err, _IOERR_FSTAT) return vfsErrorCode(err, _IOERR_FSTAT)
} }
@ -394,7 +371,7 @@ func vfsFileControlImpl(ctx context.Context, mod api.Module, file File, op _Fcnt
case _FCNTL_LOCK_TIMEOUT: case _FCNTL_LOCK_TIMEOUT:
if file, ok := file.(FileSharedMemory); ok { if file, ok := file.(FileSharedMemory); ok {
if shm, ok := file.SharedMemory().(blockingSharedMemory); ok { if shm, ok := file.SharedMemory().(blockingSharedMemory); ok {
shm.shmEnableBlocking(util.Read32[uint32](mod, pArg) != 0) shm.shmEnableBlocking(util.ReadBool(mod, pArg))
return _OK return _OK
} }
} }

View file

@ -399,10 +399,10 @@ func (idx *IndexInfo) save() {
util.Write32(mod, ptr+20, int32(idx.IdxNum)) util.Write32(mod, ptr+20, int32(idx.IdxNum))
if idx.IdxStr != "" { if idx.IdxStr != "" {
util.Write32(mod, ptr+24, idx.c.newString(idx.IdxStr)) util.Write32(mod, ptr+24, idx.c.newString(idx.IdxStr))
util.Write32(mod, ptr+28, int32(1)) // needToFreeIdxStr util.WriteBool(mod, ptr+28, true) // needToFreeIdxStr
} }
if idx.OrderByConsumed { if idx.OrderByConsumed {
util.Write32(mod, ptr+32, int32(1)) util.WriteBool(mod, ptr+32, true)
} }
util.WriteFloat64(mod, ptr+40, idx.EstimatedCost) util.WriteFloat64(mod, ptr+40, idx.EstimatedCost)
util.Write64(mod, ptr+48, idx.EstimatedRows) util.Write64(mod, ptr+48, idx.EstimatedRows)

View file

@ -25,6 +25,11 @@
// quickly. // quickly.
const chanSize = 16 const chanSize = 16
// maxPendingPackets sets the maximum number of packets to queue while waiting
// for KEX to complete. This limits the total pending data to maxPendingPackets
// * maxPacket bytes, which is ~16.8MB.
const maxPendingPackets = 64
// keyingTransport is a packet based transport that supports key // keyingTransport is a packet based transport that supports key
// changes. It need not be thread-safe. It should pass through // changes. It need not be thread-safe. It should pass through
// msgNewKeys in both directions. // msgNewKeys in both directions.
@ -74,10 +79,18 @@ type handshakeTransport struct {
readError error readError error
mu sync.Mutex mu sync.Mutex
// Condition for the above mutex. It is used to notify a completed key
// exchange or a write failure. Writes can wait for this condition while a
// key exchange is in progress.
writeCond *sync.Cond
writeError error writeError error
sentInitPacket []byte sentInitPacket []byte
sentInitMsg *kexInitMsg sentInitMsg *kexInitMsg
pendingPackets [][]byte // Used when a key exchange is in progress. // Used to queue writes when a key exchange is in progress. The length is
// limited by pendingPacketsSize. Once full, writes will block until the key
// exchange is completed or an error occurs. If not empty, it is emptied
// all at once when the key exchange is completed in kexLoop.
pendingPackets [][]byte
writePacketsLeft uint32 writePacketsLeft uint32
writeBytesLeft int64 writeBytesLeft int64
userAuthComplete bool // whether the user authentication phase is complete userAuthComplete bool // whether the user authentication phase is complete
@ -134,6 +147,7 @@ func newHandshakeTransport(conn keyingTransport, config *Config, clientVersion,
config: config, config: config,
} }
t.writeCond = sync.NewCond(&t.mu)
t.resetReadThresholds() t.resetReadThresholds()
t.resetWriteThresholds() t.resetWriteThresholds()
@ -260,6 +274,7 @@ func (t *handshakeTransport) recordWriteError(err error) {
defer t.mu.Unlock() defer t.mu.Unlock()
if t.writeError == nil && err != nil { if t.writeError == nil && err != nil {
t.writeError = err t.writeError = err
t.writeCond.Broadcast()
} }
} }
@ -363,6 +378,8 @@ func (t *handshakeTransport) kexLoop() {
} }
} }
t.pendingPackets = t.pendingPackets[:0] t.pendingPackets = t.pendingPackets[:0]
// Unblock writePacket if waiting for KEX.
t.writeCond.Broadcast()
t.mu.Unlock() t.mu.Unlock()
} }
@ -577,12 +594,21 @@ func (t *handshakeTransport) writePacket(p []byte) error {
} }
if t.sentInitMsg != nil { if t.sentInitMsg != nil {
if len(t.pendingPackets) < maxPendingPackets {
// Copy the packet so the writer can reuse the buffer. // Copy the packet so the writer can reuse the buffer.
cp := make([]byte, len(p)) cp := make([]byte, len(p))
copy(cp, p) copy(cp, p)
t.pendingPackets = append(t.pendingPackets, cp) t.pendingPackets = append(t.pendingPackets, cp)
return nil return nil
} }
for t.sentInitMsg != nil {
// Block and wait for KEX to complete or an error.
t.writeCond.Wait()
if t.writeError != nil {
return t.writeError
}
}
}
if t.writeBytesLeft > 0 { if t.writeBytesLeft > 0 {
t.writeBytesLeft -= int64(len(p)) t.writeBytesLeft -= int64(len(p))
@ -598,6 +624,7 @@ func (t *handshakeTransport) writePacket(p []byte) error {
if err := t.pushPacket(p); err != nil { if err := t.pushPacket(p); err != nil {
t.writeError = err t.writeError = err
t.writeCond.Broadcast()
} }
return nil return nil

6
vendor/modules.txt vendored
View file

@ -698,8 +698,8 @@ github.com/modern-go/reflect2
# github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 # github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822
## explicit ## explicit
github.com/munnerz/goautoneg github.com/munnerz/goautoneg
# github.com/ncruces/go-sqlite3 v0.23.0 # github.com/ncruces/go-sqlite3 v0.24.0
## explicit; go 1.22 ## explicit; go 1.23.0
github.com/ncruces/go-sqlite3 github.com/ncruces/go-sqlite3
github.com/ncruces/go-sqlite3/driver github.com/ncruces/go-sqlite3/driver
github.com/ncruces/go-sqlite3/embed github.com/ncruces/go-sqlite3/embed
@ -1057,7 +1057,7 @@ go.uber.org/multierr
# golang.org/x/arch v0.13.0 # golang.org/x/arch v0.13.0
## explicit; go 1.18 ## explicit; go 1.18
golang.org/x/arch/x86/x86asm golang.org/x/arch/x86/x86asm
# golang.org/x/crypto v0.34.0 # golang.org/x/crypto v0.35.0
## explicit; go 1.23.0 ## explicit; go 1.23.0
golang.org/x/crypto/acme golang.org/x/crypto/acme
golang.org/x/crypto/acme/autocert golang.org/x/crypto/acme/autocert