summaryrefslogtreecommitdiff
path: root/vendor/github.com/ncruces/go-sqlite3
diff options
context:
space:
mode:
Diffstat (limited to 'vendor/github.com/ncruces/go-sqlite3')
-rw-r--r--vendor/github.com/ncruces/go-sqlite3/README.md2
-rw-r--r--vendor/github.com/ncruces/go-sqlite3/blob.go1
-rw-r--r--vendor/github.com/ncruces/go-sqlite3/config.go144
-rw-r--r--vendor/github.com/ncruces/go-sqlite3/conn.go79
-rw-r--r--vendor/github.com/ncruces/go-sqlite3/conn_iter.go11
-rw-r--r--vendor/github.com/ncruces/go-sqlite3/conn_old.go9
-rw-r--r--vendor/github.com/ncruces/go-sqlite3/const.go65
-rw-r--r--vendor/github.com/ncruces/go-sqlite3/context.go8
-rw-r--r--vendor/github.com/ncruces/go-sqlite3/driver/driver.go158
-rw-r--r--vendor/github.com/ncruces/go-sqlite3/driver/savepoint.go21
-rw-r--r--vendor/github.com/ncruces/go-sqlite3/embed/README.md18
-rw-r--r--vendor/github.com/ncruces/go-sqlite3/embed/build.sh13
-rw-r--r--vendor/github.com/ncruces/go-sqlite3/embed/exports.txt8
-rw-r--r--vendor/github.com/ncruces/go-sqlite3/embed/sqlite3.wasmbin1364101 -> 1355214 bytes
-rw-r--r--vendor/github.com/ncruces/go-sqlite3/go.work.sum2
-rw-r--r--vendor/github.com/ncruces/go-sqlite3/internal/util/mmap.go2
-rw-r--r--vendor/github.com/ncruces/go-sqlite3/sqlite.go14
-rw-r--r--vendor/github.com/ncruces/go-sqlite3/stmt.go31
-rw-r--r--vendor/github.com/ncruces/go-sqlite3/txn.go23
-rw-r--r--vendor/github.com/ncruces/go-sqlite3/value.go8
-rw-r--r--vendor/github.com/ncruces/go-sqlite3/vfs/file.go1
-rw-r--r--vendor/github.com/ncruces/go-sqlite3/vfs/filename.go8
-rw-r--r--vendor/github.com/ncruces/go-sqlite3/vfs/memdb/api.go35
-rw-r--r--vendor/github.com/ncruces/go-sqlite3/vfs/memdb/memdb.go12
-rw-r--r--vendor/github.com/ncruces/go-sqlite3/vfs/os_darwin.go4
-rw-r--r--vendor/github.com/ncruces/go-sqlite3/vfs/os_f2fs_linux.go2
-rw-r--r--vendor/github.com/ncruces/go-sqlite3/vfs/os_unix_lock.go2
-rw-r--r--vendor/github.com/ncruces/go-sqlite3/vfs/os_windows.go1
-rw-r--r--vendor/github.com/ncruces/go-sqlite3/vfs/shm_bsd.go19
-rw-r--r--vendor/github.com/ncruces/go-sqlite3/vfs/vfs.go20
-rw-r--r--vendor/github.com/ncruces/go-sqlite3/vtab.go4
31 files changed, 590 insertions, 135 deletions
diff --git a/vendor/github.com/ncruces/go-sqlite3/README.md b/vendor/github.com/ncruces/go-sqlite3/README.md
index 8cf9e7a81..f6ceed14c 100644
--- a/vendor/github.com/ncruces/go-sqlite3/README.md
+++ b/vendor/github.com/ncruces/go-sqlite3/README.md
@@ -93,7 +93,7 @@ This project aims for [high test coverage](https://github.com/ncruces/go-sqlite3
It also benefits greatly from [SQLite's](https://sqlite.org/testing.html) and
[wazero's](https://tetrate.io/blog/introducing-wazero-from-tetrate/#:~:text=Rock%2Dsolid%20test%20approach) thorough testing.
-Every commit is [tested](.github/workflows/test.yml) on
+Every commit is [tested](https://github.com/ncruces/go-sqlite3/wiki/Test-matrix) on
Linux (amd64/arm64/386/riscv64/s390x), macOS (amd64/arm64),
Windows (amd64), FreeBSD (amd64), OpenBSD (amd64), NetBSD (amd64),
illumos (amd64), and Solaris (amd64).
diff --git a/vendor/github.com/ncruces/go-sqlite3/blob.go b/vendor/github.com/ncruces/go-sqlite3/blob.go
index bb10c5fa2..6e4f7d914 100644
--- a/vendor/github.com/ncruces/go-sqlite3/blob.go
+++ b/vendor/github.com/ncruces/go-sqlite3/blob.go
@@ -143,6 +143,7 @@ func (b *Blob) WriteTo(w io.Writer) (n int64, err error) {
return n, err
}
if int64(m) != want {
+ // notest // Write misbehaving
return n, io.ErrShortWrite
}
diff --git a/vendor/github.com/ncruces/go-sqlite3/config.go b/vendor/github.com/ncruces/go-sqlite3/config.go
index 0342be7fb..3f60b8fe9 100644
--- a/vendor/github.com/ncruces/go-sqlite3/config.go
+++ b/vendor/github.com/ncruces/go-sqlite3/config.go
@@ -4,6 +4,7 @@ import (
"context"
"github.com/ncruces/go-sqlite3/internal/util"
+ "github.com/ncruces/go-sqlite3/vfs"
"github.com/tetratelabs/wazero/api"
)
@@ -56,6 +57,99 @@ func logCallback(ctx context.Context, mod api.Module, _, iCode, zMsg uint32) {
}
}
+// FileControl allows low-level control of database files.
+// Only a subset of opcodes are supported.
+//
+// https://sqlite.org/c3ref/file_control.html
+func (c *Conn) FileControl(schema string, op FcntlOpcode, arg ...any) (any, error) {
+ defer c.arena.mark()()
+
+ var schemaPtr uint32
+ if schema != "" {
+ schemaPtr = c.arena.string(schema)
+ }
+
+ switch op {
+ case FCNTL_RESET_CACHE:
+ r := c.call("sqlite3_file_control",
+ uint64(c.handle), uint64(schemaPtr),
+ uint64(op), 0)
+ return nil, c.error(r)
+
+ case FCNTL_PERSIST_WAL, FCNTL_POWERSAFE_OVERWRITE:
+ var flag int
+ switch {
+ case len(arg) == 0:
+ flag = -1
+ case arg[0]:
+ flag = 1
+ }
+ ptr := c.arena.new(4)
+ util.WriteUint32(c.mod, ptr, uint32(flag))
+ r := c.call("sqlite3_file_control",
+ uint64(c.handle), uint64(schemaPtr),
+ uint64(op), uint64(ptr))
+ return util.ReadUint32(c.mod, ptr) != 0, c.error(r)
+
+ case FCNTL_CHUNK_SIZE:
+ ptr := c.arena.new(4)
+ util.WriteUint32(c.mod, ptr, uint32(arg[0].(int)))
+ r := c.call("sqlite3_file_control",
+ uint64(c.handle), uint64(schemaPtr),
+ uint64(op), uint64(ptr))
+ return nil, c.error(r)
+
+ case FCNTL_RESERVE_BYTES:
+ bytes := -1
+ if len(arg) > 0 {
+ bytes = arg[0].(int)
+ }
+ ptr := c.arena.new(4)
+ util.WriteUint32(c.mod, ptr, uint32(bytes))
+ r := c.call("sqlite3_file_control",
+ uint64(c.handle), uint64(schemaPtr),
+ uint64(op), uint64(ptr))
+ return int(util.ReadUint32(c.mod, ptr)), c.error(r)
+
+ case FCNTL_DATA_VERSION:
+ ptr := c.arena.new(4)
+ r := c.call("sqlite3_file_control",
+ uint64(c.handle), uint64(schemaPtr),
+ uint64(op), uint64(ptr))
+ return util.ReadUint32(c.mod, ptr), c.error(r)
+
+ case FCNTL_LOCKSTATE:
+ ptr := c.arena.new(4)
+ r := c.call("sqlite3_file_control",
+ uint64(c.handle), uint64(schemaPtr),
+ uint64(op), uint64(ptr))
+ return vfs.LockLevel(util.ReadUint32(c.mod, ptr)), c.error(r)
+
+ case FCNTL_VFS_POINTER:
+ ptr := c.arena.new(4)
+ r := c.call("sqlite3_file_control",
+ uint64(c.handle), uint64(schemaPtr),
+ uint64(op), uint64(ptr))
+ const zNameOffset = 16
+ ptr = util.ReadUint32(c.mod, ptr)
+ ptr = util.ReadUint32(c.mod, ptr+zNameOffset)
+ name := util.ReadString(c.mod, ptr, _MAX_NAME)
+ return vfs.Find(name), c.error(r)
+
+ case FCNTL_FILE_POINTER, FCNTL_JOURNAL_POINTER:
+ ptr := c.arena.new(4)
+ r := c.call("sqlite3_file_control",
+ uint64(c.handle), uint64(schemaPtr),
+ uint64(op), uint64(ptr))
+ const fileHandleOffset = 4
+ ptr = util.ReadUint32(c.mod, ptr)
+ ptr = util.ReadUint32(c.mod, ptr+fileHandleOffset)
+ return util.GetHandle(c.ctx, ptr), c.error(r)
+ }
+
+ return nil, MISUSE
+}
+
// Limit allows the size of various constructs to be
// limited on a connection by connection basis.
//
@@ -68,7 +162,7 @@ func (c *Conn) Limit(id LimitCategory, value int) int {
// SetAuthorizer registers an authorizer callback with the database connection.
//
// https://sqlite.org/c3ref/set_authorizer.html
-func (c *Conn) SetAuthorizer(cb func(action AuthorizerActionCode, name3rd, name4th, schema, nameInner string) AuthorizerReturnCode) error {
+func (c *Conn) SetAuthorizer(cb func(action AuthorizerActionCode, name3rd, name4th, schema, inner string) AuthorizerReturnCode) error {
var enable uint64
if cb != nil {
enable = 1
@@ -82,9 +176,9 @@ func (c *Conn) SetAuthorizer(cb func(action AuthorizerActionCode, name3rd, name4
}
-func authorizerCallback(ctx context.Context, mod api.Module, pDB uint32, action AuthorizerActionCode, zName3rd, zName4th, zSchema, zNameInner uint32) (rc AuthorizerReturnCode) {
+func authorizerCallback(ctx context.Context, mod api.Module, pDB uint32, action AuthorizerActionCode, zName3rd, zName4th, zSchema, zInner uint32) (rc AuthorizerReturnCode) {
if c, ok := ctx.Value(connKey{}).(*Conn); ok && c.handle == pDB && c.authorizer != nil {
- var name3rd, name4th, schema, nameInner string
+ var name3rd, name4th, schema, inner string
if zName3rd != 0 {
name3rd = util.ReadString(mod, zName3rd, _MAX_NAME)
}
@@ -94,10 +188,48 @@ func authorizerCallback(ctx context.Context, mod api.Module, pDB uint32, action
if zSchema != 0 {
schema = util.ReadString(mod, zSchema, _MAX_NAME)
}
- if zNameInner != 0 {
- nameInner = util.ReadString(mod, zNameInner, _MAX_NAME)
+ if zInner != 0 {
+ inner = util.ReadString(mod, zInner, _MAX_NAME)
+ }
+ rc = c.authorizer(action, name3rd, name4th, schema, inner)
+ }
+ return rc
+}
+
+// Trace registers a trace callback function against the database connection.
+//
+// https://sqlite.org/c3ref/trace_v2.html
+func (c *Conn) Trace(mask TraceEvent, cb func(evt TraceEvent, arg1 any, arg2 any) error) error {
+ r := c.call("sqlite3_trace_go", uint64(c.handle), uint64(mask))
+ if err := c.error(r); err != nil {
+ return err
+ }
+ c.trace = cb
+ return nil
+}
+
+func traceCallback(ctx context.Context, mod api.Module, evt TraceEvent, pDB, pArg1, pArg2 uint32) (rc uint32) {
+ if c, ok := ctx.Value(connKey{}).(*Conn); ok && c.handle == pDB && c.trace != nil {
+ var arg1, arg2 any
+ if evt == TRACE_CLOSE {
+ arg1 = c
+ } else {
+ for _, s := range c.stmts {
+ if pArg1 == s.handle {
+ arg1 = s
+ switch evt {
+ case TRACE_STMT:
+ arg2 = s.SQL()
+ case TRACE_PROFILE:
+ arg2 = int64(util.ReadUint64(mod, pArg2))
+ }
+ break
+ }
+ }
+ }
+ if arg1 != nil {
+ _, rc = errorCode(c.trace(evt, arg1, arg2), ERROR)
}
- rc = c.authorizer(action, name3rd, name4th, schema, nameInner)
}
return rc
}
diff --git a/vendor/github.com/ncruces/go-sqlite3/conn.go b/vendor/github.com/ncruces/go-sqlite3/conn.go
index 39870b140..b4335f4c4 100644
--- a/vendor/github.com/ncruces/go-sqlite3/conn.go
+++ b/vendor/github.com/ncruces/go-sqlite3/conn.go
@@ -22,14 +22,16 @@ type Conn struct {
interrupt context.Context
pending *Stmt
+ stmts []*Stmt
busy func(int) bool
log func(xErrorCode, string)
collation func(*Conn, string)
+ wal func(*Conn, string, int) error
+ trace func(TraceEvent, any, any) error
authorizer func(AuthorizerActionCode, string, string, string, string) AuthorizerReturnCode
update func(AuthorizerActionCode, string, string, int64)
commit func() bool
rollback func()
- wal func(*Conn, string, int) error
arena arena
handle uint32
@@ -202,6 +204,7 @@ func (c *Conn) PrepareFlags(sql string, flags PrepareFlag) (stmt *Stmt, tail str
if stmt.handle == 0 {
return nil, "", nil
}
+ c.stmts = append(c.stmts, stmt)
return stmt, tail, nil
}
@@ -227,9 +230,8 @@ func (c *Conn) Filename(schema string) *vfs.Filename {
defer c.arena.mark()()
ptr = c.arena.string(schema)
}
-
r := c.call("sqlite3_db_filename", uint64(c.handle), uint64(ptr))
- return vfs.OpenFilename(c.ctx, c.mod, uint32(r), vfs.OPEN_MAIN_DB)
+ return vfs.GetFilename(c.ctx, c.mod, uint32(r), vfs.OPEN_MAIN_DB)
}
// ReadOnly determines if a database is read-only.
@@ -327,7 +329,12 @@ func (c *Conn) SetInterrupt(ctx context.Context) (old context.Context) {
// A busy SQL statement prevents SQLite from ignoring an interrupt
// that comes before any other statements are started.
if c.pending == nil {
- c.pending, _, _ = c.Prepare(`WITH RECURSIVE c(x) AS (VALUES(0) UNION ALL SELECT x FROM c) SELECT x FROM c`)
+ defer c.arena.mark()()
+ stmtPtr := c.arena.new(ptrlen)
+ loopPtr := c.arena.string(`WITH RECURSIVE c(x) AS (VALUES(0) UNION ALL SELECT x FROM c) SELECT x FROM c`)
+ c.call("sqlite3_prepare_v3", uint64(c.handle), uint64(loopPtr), math.MaxUint64, 0, uint64(stmtPtr), 0)
+ c.pending = &Stmt{c: c}
+ c.pending.handle = util.ReadUint32(c.mod, stmtPtr)
}
old = c.interrupt
@@ -415,10 +422,74 @@ func busyCallback(ctx context.Context, mod api.Module, pDB uint32, count int32)
return retry
}
+// Status retrieves runtime status information about a database connection.
+//
+// https://sqlite.org/c3ref/db_status.html
+func (c *Conn) Status(op DBStatus, reset bool) (current, highwater int, err error) {
+ defer c.arena.mark()()
+ hiPtr := c.arena.new(4)
+ curPtr := c.arena.new(4)
+
+ var i uint64
+ if reset {
+ i = 1
+ }
+
+ r := c.call("sqlite3_db_status", uint64(c.handle),
+ uint64(op), uint64(curPtr), uint64(hiPtr), i)
+ if err = c.error(r); err == nil {
+ current = int(util.ReadUint32(c.mod, curPtr))
+ highwater = int(util.ReadUint32(c.mod, hiPtr))
+ }
+ return
+}
+
+// TableColumnMetadata extracts metadata about a column of a table.
+//
+// https://sqlite.org/c3ref/table_column_metadata.html
+func (c *Conn) TableColumnMetadata(schema, table, column string) (declType, collSeq string, notNull, primaryKey, autoInc bool, err error) {
+ defer c.arena.mark()()
+
+ var schemaPtr, columnPtr uint32
+ declTypePtr := c.arena.new(ptrlen)
+ collSeqPtr := c.arena.new(ptrlen)
+ notNullPtr := c.arena.new(ptrlen)
+ primaryKeyPtr := c.arena.new(ptrlen)
+ autoIncPtr := c.arena.new(ptrlen)
+ if schema != "" {
+ schemaPtr = c.arena.string(schema)
+ }
+ tablePtr := c.arena.string(table)
+ if column != "" {
+ columnPtr = c.arena.string(column)
+ }
+
+ r := c.call("sqlite3_table_column_metadata", uint64(c.handle),
+ uint64(schemaPtr), uint64(tablePtr), uint64(columnPtr),
+ uint64(declTypePtr), uint64(collSeqPtr),
+ uint64(notNullPtr), uint64(primaryKeyPtr), uint64(autoIncPtr))
+ if err = c.error(r); err == nil && column != "" {
+ declType = util.ReadString(c.mod, util.ReadUint32(c.mod, declTypePtr), _MAX_NAME)
+ collSeq = util.ReadString(c.mod, util.ReadUint32(c.mod, collSeqPtr), _MAX_NAME)
+ notNull = util.ReadUint32(c.mod, notNullPtr) != 0
+ autoInc = util.ReadUint32(c.mod, autoIncPtr) != 0
+ primaryKey = util.ReadUint32(c.mod, primaryKeyPtr) != 0
+ }
+ return
+}
+
func (c *Conn) error(rc uint64, sql ...string) error {
return c.sqlite.error(rc, c.handle, sql...)
}
+func (c *Conn) stmtsIter(yield func(*Stmt) bool) {
+ for _, s := range c.stmts {
+ if !yield(s) {
+ break
+ }
+ }
+}
+
// DriverConn is implemented by the SQLite [database/sql] driver connection.
//
// It can be used to access SQLite features like [online backup].
diff --git a/vendor/github.com/ncruces/go-sqlite3/conn_iter.go b/vendor/github.com/ncruces/go-sqlite3/conn_iter.go
new file mode 100644
index 000000000..81e2a720c
--- /dev/null
+++ b/vendor/github.com/ncruces/go-sqlite3/conn_iter.go
@@ -0,0 +1,11 @@
+//go:build (go1.23 || goexperiment.rangefunc) && !vet
+
+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 }
diff --git a/vendor/github.com/ncruces/go-sqlite3/conn_old.go b/vendor/github.com/ncruces/go-sqlite3/conn_old.go
new file mode 100644
index 000000000..921011d80
--- /dev/null
+++ b/vendor/github.com/ncruces/go-sqlite3/conn_old.go
@@ -0,0 +1,9 @@
+//go:build !(go1.23 || goexperiment.rangefunc) || vet
+
+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 }
diff --git a/vendor/github.com/ncruces/go-sqlite3/const.go b/vendor/github.com/ncruces/go-sqlite3/const.go
index 2bb53656f..11eb33c88 100644
--- a/vendor/github.com/ncruces/go-sqlite3/const.go
+++ b/vendor/github.com/ncruces/go-sqlite3/const.go
@@ -109,7 +109,7 @@ const (
CANTOPEN_ISDIR ExtendedErrorCode = xErrorCode(CANTOPEN) | (2 << 8)
CANTOPEN_FULLPATH ExtendedErrorCode = xErrorCode(CANTOPEN) | (3 << 8)
CANTOPEN_CONVPATH ExtendedErrorCode = xErrorCode(CANTOPEN) | (4 << 8)
- CANTOPEN_DIRTYWAL ExtendedErrorCode = xErrorCode(CANTOPEN) | (5 << 8) /* Not Used */
+ // CANTOPEN_DIRTYWAL ExtendedErrorCode = xErrorCode(CANTOPEN) | (5 << 8) /* Not Used */
CANTOPEN_SYMLINK ExtendedErrorCode = xErrorCode(CANTOPEN) | (6 << 8)
CORRUPT_VTAB ExtendedErrorCode = xErrorCode(CORRUPT) | (1 << 8)
CORRUPT_SEQUENCE ExtendedErrorCode = xErrorCode(CORRUPT) | (2 << 8)
@@ -177,11 +177,11 @@ const (
type FunctionFlag uint32
const (
- DETERMINISTIC FunctionFlag = 0x000000800
- DIRECTONLY FunctionFlag = 0x000080000
- SUBTYPE FunctionFlag = 0x000100000
- INNOCUOUS FunctionFlag = 0x000200000
- RESULT_SUBTYPE FunctionFlag = 0x001000000
+ DETERMINISTIC FunctionFlag = 0x000000800
+ DIRECTONLY FunctionFlag = 0x000080000
+ INNOCUOUS FunctionFlag = 0x000200000
+ // SUBTYPE FunctionFlag = 0x000100000
+ // RESULT_SUBTYPE FunctionFlag = 0x001000000
)
// StmtStatus name counter values associated with the [Stmt.Status] method.
@@ -201,6 +201,27 @@ const (
STMTSTATUS_MEMUSED StmtStatus = 99
)
+// DBStatus are the available "verbs" that can be passed to the [Conn.Status] method.
+//
+// https://sqlite.org/c3ref/c_dbstatus_options.html
+type DBStatus uint32
+
+const (
+ DBSTATUS_LOOKASIDE_USED DBStatus = 0
+ DBSTATUS_CACHE_USED DBStatus = 1
+ DBSTATUS_SCHEMA_USED DBStatus = 2
+ DBSTATUS_STMT_USED DBStatus = 3
+ DBSTATUS_LOOKASIDE_HIT DBStatus = 4
+ DBSTATUS_LOOKASIDE_MISS_SIZE DBStatus = 5
+ DBSTATUS_LOOKASIDE_MISS_FULL DBStatus = 6
+ DBSTATUS_CACHE_HIT DBStatus = 7
+ DBSTATUS_CACHE_MISS DBStatus = 8
+ DBSTATUS_CACHE_WRITE DBStatus = 9
+ DBSTATUS_DEFERRED_FKS DBStatus = 10
+ DBSTATUS_CACHE_USED_SHARED DBStatus = 11
+ DBSTATUS_CACHE_SPILL DBStatus = 12
+)
+
// DBConfig are the available database connection configuration options.
//
// https://sqlite.org/c3ref/c_dbconfig_defensive.html
@@ -229,6 +250,24 @@ const (
DBCONFIG_REVERSE_SCANORDER DBConfig = 1019
)
+// FcntlOpcode are the available opcodes for [Conn.FileControl].
+//
+// https://sqlite.org/c3ref/c_fcntl_begin_atomic_write.html
+type FcntlOpcode uint32
+
+const (
+ FCNTL_LOCKSTATE FcntlOpcode = 1
+ FCNTL_CHUNK_SIZE FcntlOpcode = 6
+ FCNTL_FILE_POINTER FcntlOpcode = 7
+ FCNTL_PERSIST_WAL FcntlOpcode = 10
+ FCNTL_POWERSAFE_OVERWRITE FcntlOpcode = 13
+ FCNTL_VFS_POINTER FcntlOpcode = 27
+ FCNTL_JOURNAL_POINTER FcntlOpcode = 28
+ FCNTL_DATA_VERSION FcntlOpcode = 35
+ FCNTL_RESERVE_BYTES FcntlOpcode = 38
+ FCNTL_RESET_CACHE FcntlOpcode = 42
+)
+
// LimitCategory are the available run-time limit categories.
//
// https://sqlite.org/c3ref/c_limit_attached.html
@@ -289,8 +328,8 @@ const (
AUTH_DROP_VTABLE AuthorizerActionCode = 30 /* Table Name Module Name */
AUTH_FUNCTION AuthorizerActionCode = 31 /* NULL Function Name */
AUTH_SAVEPOINT AuthorizerActionCode = 32 /* Operation Savepoint Name */
- AUTH_COPY AuthorizerActionCode = 0 /* No longer used */
AUTH_RECURSIVE AuthorizerActionCode = 33 /* NULL NULL */
+ // AUTH_COPY AuthorizerActionCode = 0 /* No longer used */
)
// AuthorizerReturnCode are the integer codes
@@ -328,6 +367,18 @@ const (
TXN_WRITE TxnState = 2
)
+// TraceEvent identify classes of events that can be monitored with [Conn.Trace].
+//
+// https://sqlite.org/c3ref/c_trace.html
+type TraceEvent uint32
+
+const (
+ TRACE_STMT TraceEvent = 0x01
+ TRACE_PROFILE TraceEvent = 0x02
+ TRACE_ROW TraceEvent = 0x04
+ TRACE_CLOSE TraceEvent = 0x08
+)
+
// Datatype is a fundamental datatype of SQLite.
//
// https://sqlite.org/c3ref/c_blob.html
diff --git a/vendor/github.com/ncruces/go-sqlite3/context.go b/vendor/github.com/ncruces/go-sqlite3/context.go
index 8d7604c66..4fcda56d4 100644
--- a/vendor/github.com/ncruces/go-sqlite3/context.go
+++ b/vendor/github.com/ncruces/go-sqlite3/context.go
@@ -130,7 +130,8 @@ func (ctx Context) ResultNull() {
//
// https://sqlite.org/c3ref/result_blob.html
func (ctx Context) ResultTime(value time.Time, format TimeFormat) {
- if format == TimeFormatDefault {
+ switch format {
+ case TimeFormatDefault, TimeFormatAuto, time.RFC3339Nano:
ctx.resultRFC3339Nano(value)
return
}
@@ -165,7 +166,8 @@ func (ctx Context) resultRFC3339Nano(value time.Time) {
// https://sqlite.org/c3ref/result_blob.html
func (ctx Context) ResultPointer(ptr any) {
valPtr := util.AddHandle(ctx.c.ctx, ptr)
- ctx.c.call("sqlite3_result_pointer_go", uint64(valPtr))
+ ctx.c.call("sqlite3_result_pointer_go",
+ uint64(ctx.handle), uint64(valPtr))
}
// ResultJSON sets the result of the function to the JSON encoding of value.
@@ -175,7 +177,7 @@ func (ctx Context) ResultJSON(value any) {
data, err := json.Marshal(value)
if err != nil {
ctx.ResultError(err)
- return
+ return // notest
}
ctx.ResultRawText(data)
}
diff --git a/vendor/github.com/ncruces/go-sqlite3/driver/driver.go b/vendor/github.com/ncruces/go-sqlite3/driver/driver.go
index e7863b1b8..c02ba4b4f 100644
--- a/vendor/github.com/ncruces/go-sqlite3/driver/driver.go
+++ b/vendor/github.com/ncruces/go-sqlite3/driver/driver.go
@@ -8,21 +8,50 @@
//
// The data source name for "sqlite3" databases can be a filename or a "file:" [URI].
//
+// # Default transaction mode
+//
// The [TRANSACTION] mode can be specified using "_txlock":
//
// sql.Open("sqlite3", "file:demo.db?_txlock=immediate")
//
-// Possible values are: "deferred", "immediate", "exclusive".
-// A [read-only] transaction is always "deferred", regardless of "_txlock".
+// Possible values are: "deferred" (the default), "immediate", "exclusive".
+// Regardless of "_txlock":
+// - a [linearizable] transaction is always "exclusive";
+// - a [serializable] transaction is always "immediate";
+// - a [read-only] transaction is always "deferred".
+//
+// # Working with time
//
// The time encoding/decoding format can be specified using "_timefmt":
//
// sql.Open("sqlite3", "file:demo.db?_timefmt=sqlite")
//
// Possible values are: "auto" (the default), "sqlite", "rfc3339";
-// "auto" encodes as RFC 3339 and decodes any [format] supported by SQLite;
-// "sqlite" encodes as SQLite and decodes any [format] supported by SQLite;
-// "rfc3339" encodes and decodes RFC 3339 only.
+// - "auto" encodes as RFC 3339 and decodes any [format] supported by SQLite;
+// - "sqlite" encodes as SQLite and decodes any [format] supported by SQLite;
+// - "rfc3339" encodes and decodes RFC 3339 only.
+//
+// If you encode as RFC 3339 (the default),
+// consider using the TIME [collating sequence] to produce a time-ordered sequence.
+//
+// To scan values in other formats, [sqlite3.TimeFormat.Scanner] may be helpful.
+// To bind values in other formats, [sqlite3.TimeFormat.Encode] them before binding.
+//
+// When using a custom time struct, you'll have to implement
+// [database/sql/driver.Valuer] and [database/sql.Scanner].
+//
+// The Value method should ideally serialise to a time [format] supported by SQLite.
+// This ensures SQL date and time functions work as they should,
+// and that your schema works with other SQLite tools.
+// [sqlite3.TimeFormat.Encode] may help.
+//
+// The Scan method needs to take into account that the value it receives can be of differing types.
+// It can already be a [time.Time], if the driver decoded the value according to "_timefmt" rules.
+// Or it can be a: string, int64, float64, []byte, nil,
+// depending on the column type and what whoever wrote the value.
+// [sqlite3.TimeFormat.Decode] may help.
+//
+// # Setting PRAGMAs
//
// [PRAGMA] statements can be specified using "_pragma":
//
@@ -31,13 +60,17 @@
// If no PRAGMAs are specified, a busy timeout of 1 minute is set.
//
// Order matters:
-// busy timeout and locking mode should be the first PRAGMAs set, in that order.
+// encryption keys, busy timeout and locking mode should be the first PRAGMAs set,
+// in that order.
//
// [URI]: https://sqlite.org/uri.html
// [PRAGMA]: https://sqlite.org/pragma.html
-// [format]: https://sqlite.org/lang_datefunc.html#time_values
// [TRANSACTION]: https://sqlite.org/lang_transaction.html#deferred_immediate_and_exclusive_transactions
+// [linearizable]: https://pkg.go.dev/database/sql#TxOptions
+// [serializable]: https://pkg.go.dev/database/sql#TxOptions
// [read-only]: https://pkg.go.dev/database/sql#TxOptions
+// [format]: https://sqlite.org/lang_datefunc.html#time_values
+// [collating sequence]: https://sqlite.org/datatype3.html#collating_sequences
package driver
import (
@@ -69,11 +102,22 @@ func init() {
// Open opens the SQLite database specified by dataSourceName as a [database/sql.DB].
//
-// The init function is called by the driver on new connections.
+// Open accepts zero, one, or two callbacks (nil callbacks are ignored).
+// The first callback is called when the driver opens a new connection.
+// The second callback is called before the driver closes a connection.
// The [sqlite3.Conn] can be used to execute queries, register functions, etc.
-// Any error returned closes the connection and is returned to [database/sql].
-func Open(dataSourceName string, init func(*sqlite3.Conn) error) (*sql.DB, error) {
- c, err := (&SQLite{Init: init}).OpenConnector(dataSourceName)
+func Open(dataSourceName string, fn ...func(*sqlite3.Conn) error) (*sql.DB, error) {
+ var drv SQLite
+ if len(fn) > 2 {
+ return nil, sqlite3.MISUSE
+ }
+ if len(fn) > 1 {
+ drv.term = fn[1]
+ }
+ if len(fn) > 0 {
+ drv.init = fn[0]
+ }
+ c, err := drv.OpenConnector(dataSourceName)
if err != nil {
return nil, err
}
@@ -82,10 +126,8 @@ func Open(dataSourceName string, init func(*sqlite3.Conn) error) (*sql.DB, error
// SQLite implements [database/sql/driver.Driver].
type SQLite struct {
- // Init function is called by the driver on new connections.
- // The [sqlite3.Conn] can be used to execute queries, register functions, etc.
- // Any error returned closes the connection and is returned to [database/sql].
- Init func(*sqlite3.Conn) error
+ init func(*sqlite3.Conn) error
+ term func(*sqlite3.Conn) error
}
// Open implements [database/sql/driver.Driver].
@@ -119,10 +161,8 @@ func (d *SQLite) newConnector(name string) (*connector, error) {
}
switch txlock {
- case "":
- c.txBegin = "BEGIN"
- case "deferred", "immediate", "exclusive":
- c.txBegin = "BEGIN " + txlock
+ case "", "deferred", "concurrent", "immediate", "exclusive":
+ c.txLock = txlock
default:
return nil, fmt.Errorf("sqlite3: invalid _txlock: %s", txlock)
}
@@ -147,7 +187,7 @@ func (d *SQLite) newConnector(name string) (*connector, error) {
type connector struct {
driver *SQLite
name string
- txBegin string
+ txLock string
tmRead sqlite3.TimeFormat
tmWrite sqlite3.TimeFormat
pragmas bool
@@ -159,7 +199,7 @@ func (n *connector) Driver() driver.Driver {
func (n *connector) Connect(ctx context.Context) (_ driver.Conn, err error) {
c := &conn{
- txBegin: n.txBegin,
+ txLock: n.txLock,
tmRead: n.tmRead,
tmWrite: n.tmWrite,
}
@@ -178,18 +218,18 @@ func (n *connector) Connect(ctx context.Context) (_ driver.Conn, err error) {
defer c.Conn.SetInterrupt(old)
if !n.pragmas {
- err = c.Conn.BusyTimeout(60 * time.Second)
+ err = c.Conn.BusyTimeout(time.Minute)
if err != nil {
return nil, err
}
}
- if n.driver.Init != nil {
- err = n.driver.Init(c.Conn)
+ if n.driver.init != nil {
+ err = n.driver.init(c.Conn)
if err != nil {
return nil, err
}
}
- if n.pragmas || n.driver.Init != nil {
+ if n.pragmas || n.driver.init != nil {
s, _, err := c.Conn.Prepare(`PRAGMA query_only`)
if err != nil {
return nil, err
@@ -204,17 +244,24 @@ func (n *connector) Connect(ctx context.Context) (_ driver.Conn, err error) {
return nil, err
}
}
+ if n.driver.term != nil {
+ err = c.Conn.Trace(sqlite3.TRACE_CLOSE, func(sqlite3.TraceEvent, any, any) error {
+ return n.driver.term(c.Conn)
+ })
+ if err != nil {
+ return nil, err
+ }
+ }
return c, nil
}
type conn struct {
*sqlite3.Conn
- txBegin string
- txCommit string
- txRollback string
- tmRead sqlite3.TimeFormat
- tmWrite sqlite3.TimeFormat
- readOnly byte
+ txLock string
+ txReset string
+ tmRead sqlite3.TimeFormat
+ tmWrite sqlite3.TimeFormat
+ readOnly byte
}
var (
@@ -231,31 +278,30 @@ func (c *conn) Raw() *sqlite3.Conn {
// Deprecated: use BeginTx instead.
func (c *conn) Begin() (driver.Tx, error) {
+ // notest
return c.BeginTx(context.Background(), driver.TxOptions{})
}
func (c *conn) BeginTx(ctx context.Context, opts driver.TxOptions) (driver.Tx, error) {
- txBegin := c.txBegin
- c.txCommit = `COMMIT`
- c.txRollback = `ROLLBACK`
-
- if opts.ReadOnly {
- txBegin = `
- BEGIN deferred;
- PRAGMA query_only=on`
- c.txRollback = `
- ROLLBACK;
- PRAGMA query_only=` + string(c.readOnly)
- c.txCommit = c.txRollback
- }
-
+ var txLock string
switch opts.Isolation {
default:
return nil, util.IsolationErr
- case
- driver.IsolationLevel(sql.LevelDefault),
- driver.IsolationLevel(sql.LevelSerializable):
- break
+ case driver.IsolationLevel(sql.LevelLinearizable):
+ txLock = "exclusive"
+ case driver.IsolationLevel(sql.LevelSerializable):
+ txLock = "immediate"
+ case driver.IsolationLevel(sql.LevelDefault):
+ if !opts.ReadOnly {
+ txLock = c.txLock
+ }
+ }
+
+ c.txReset = ``
+ txBegin := `BEGIN ` + txLock
+ if opts.ReadOnly {
+ txBegin += ` ; PRAGMA query_only=on`
+ c.txReset = `; PRAGMA query_only=` + string(c.readOnly)
}
old := c.Conn.SetInterrupt(ctx)
@@ -269,7 +315,7 @@ func (c *conn) BeginTx(ctx context.Context, opts driver.TxOptions) (driver.Tx, e
}
func (c *conn) Commit() error {
- err := c.Conn.Exec(c.txCommit)
+ err := c.Conn.Exec(`COMMIT` + c.txReset)
if err != nil && !c.Conn.GetAutocommit() {
c.Rollback()
}
@@ -277,16 +323,17 @@ func (c *conn) Commit() error {
}
func (c *conn) Rollback() error {
- err := c.Conn.Exec(c.txRollback)
+ err := c.Conn.Exec(`ROLLBACK` + c.txReset)
if errors.Is(err, sqlite3.INTERRUPT) {
old := c.Conn.SetInterrupt(context.Background())
defer c.Conn.SetInterrupt(old)
- err = c.Conn.Exec(c.txRollback)
+ err = c.Conn.Exec(`ROLLBACK` + c.txReset)
}
return err
}
func (c *conn) Prepare(query string) (driver.Stmt, error) {
+ // notest
return c.PrepareContext(context.Background(), query)
}
@@ -329,6 +376,8 @@ func (c *conn) ExecContext(ctx context.Context, query string, args []driver.Name
}
func (c *conn) CheckNamedValue(arg *driver.NamedValue) error {
+ // Fast path: short circuit argument verification.
+ // Arguments will be rejected by conn.ExecContext.
return nil
}
@@ -363,11 +412,13 @@ func (s *stmt) NumInput() int {
// Deprecated: use ExecContext instead.
func (s *stmt) Exec(args []driver.Value) (driver.Result, error) {
+ // notest
return s.ExecContext(context.Background(), namedValues(args))
}
// Deprecated: use QueryContext instead.
func (s *stmt) Query(args []driver.Value) (driver.Rows, error) {
+ // notest
return s.QueryContext(context.Background(), namedValues(args))
}
@@ -561,7 +612,8 @@ func (r *rows) Next(dest []driver.Value) error {
}
func (r *rows) decodeTime(i int, v any) (_ time.Time, ok bool) {
- if r.tmRead == sqlite3.TimeFormatDefault {
+ switch r.tmRead {
+ case sqlite3.TimeFormatDefault, time.RFC3339Nano:
// handled by maybeTime
return
}
diff --git a/vendor/github.com/ncruces/go-sqlite3/driver/savepoint.go b/vendor/github.com/ncruces/go-sqlite3/driver/savepoint.go
index 60aa6b991..eea40dd68 100644
--- a/vendor/github.com/ncruces/go-sqlite3/driver/savepoint.go
+++ b/vendor/github.com/ncruces/go-sqlite3/driver/savepoint.go
@@ -16,12 +16,25 @@ func Savepoint(tx *sql.Tx) sqlite3.Savepoint {
return ctx.Savepoint
}
+// A saveptCtx is never canceled, has no values, and has no deadline.
type saveptCtx struct{ sqlite3.Savepoint }
-func (*saveptCtx) Deadline() (deadline time.Time, ok bool) { return }
+func (*saveptCtx) Deadline() (deadline time.Time, ok bool) {
+ // notest
+ return
+}
-func (*saveptCtx) Done() <-chan struct{} { return nil }
+func (*saveptCtx) Done() <-chan struct{} {
+ // notest
+ return nil
+}
-func (*saveptCtx) Err() error { return nil }
+func (*saveptCtx) Err() error {
+ // notest
+ return nil
+}
-func (*saveptCtx) Value(key any) any { return nil }
+func (*saveptCtx) Value(key any) any {
+ // notest
+ return nil
+}
diff --git a/vendor/github.com/ncruces/go-sqlite3/embed/README.md b/vendor/github.com/ncruces/go-sqlite3/embed/README.md
index 0156f0176..fc56933b7 100644
--- a/vendor/github.com/ncruces/go-sqlite3/embed/README.md
+++ b/vendor/github.com/ncruces/go-sqlite3/embed/README.md
@@ -1,6 +1,6 @@
# Embeddable Wasm build of SQLite
-This folder includes an embeddable Wasm build of SQLite 3.46.0 for use with
+This folder includes an embeddable Wasm build of SQLite 3.46.1 for use with
[`github.com/ncruces/go-sqlite3`](https://pkg.go.dev/github.com/ncruces/go-sqlite3).
The following optional features are compiled in:
@@ -17,14 +17,24 @@ The following optional features are compiled in:
- [regexp](https://github.com/sqlite/sqlite/blob/master/ext/misc/regexp.c)
- [series](https://github.com/sqlite/sqlite/blob/master/ext/misc/series.c)
- [uint](https://github.com/sqlite/sqlite/blob/master/ext/misc/uint.c)
-- [uuid](https://github.com/sqlite/sqlite/blob/master/ext/misc/uuid.c)
- [time](../sqlite3/time.c)
-See the [configuration options](../sqlite3/sqlite_cfg.h),
+See the [configuration options](../sqlite3/sqlite_opt.h),
and [patches](../sqlite3) applied.
Built using [`wasi-sdk`](https://github.com/WebAssembly/wasi-sdk),
and [`binaryen`](https://github.com/WebAssembly/binaryen).
The build is easily reproducible, and verifiable, using
-[Artifact Attestations](https://github.com/ncruces/go-sqlite3/attestations). \ No newline at end of file
+[Artifact Attestations](https://github.com/ncruces/go-sqlite3/attestations).
+
+### Customizing the build
+
+You can use your own custom build of SQLite.
+
+Examples of custom builds of SQLite are:
+- [`github.com/ncruces/go-sqlite3/embed/bcw2`](https://github.com/ncruces/go-sqlite3/tree/main/embed/bcw2)
+ built from a branch supporting [`BEGIN CONCURRENT`](https://sqlite.org/src/doc/begin-concurrent/doc/begin_concurrent.md)
+ and [Wal2](https://www.sqlite.org/cgi/src/doc/wal2/doc/wal2.md).
+- [`github.com/asg017/sqlite-vec-go-bindings/ncruces`](https://github.com/asg017/sqlite-vec-go-bindings)
+ which includes the [`sqlite-vec`](https://github.com/asg017/sqlite-vec) vector search extension. \ No newline at end of file
diff --git a/vendor/github.com/ncruces/go-sqlite3/embed/build.sh b/vendor/github.com/ncruces/go-sqlite3/embed/build.sh
index 8ea380e26..6141efd57 100644
--- a/vendor/github.com/ncruces/go-sqlite3/embed/build.sh
+++ b/vendor/github.com/ncruces/go-sqlite3/embed/build.sh
@@ -4,26 +4,27 @@ set -euo pipefail
cd -P -- "$(dirname -- "$0")"
ROOT=../
-BINARYEN="$ROOT/tools/binaryen-version_117/bin"
-WASI_SDK="$ROOT/tools/wasi-sdk-22.0/bin"
+BINARYEN="$ROOT/tools/binaryen/bin"
+WASI_SDK="$ROOT/tools/wasi-sdk/bin"
-"$WASI_SDK/clang" --target=wasm32-wasi -std=c23 -flto -g0 -O2 \
+trap 'rm -f sqlite3.tmp' EXIT
+
+"$WASI_SDK/clang" --target=wasm32-wasi -std=c23 -g0 -O2 \
-Wall -Wextra -Wno-unused-parameter -Wno-unused-function \
-o sqlite3.wasm "$ROOT/sqlite3/main.c" \
-I"$ROOT/sqlite3" \
-mexec-model=reactor \
- -msimd128 -mmutable-globals \
+ -matomics -msimd128 -mmutable-globals \
-mbulk-memory -mreference-types \
-mnontrapping-fptoint -msign-ext \
-fno-stack-protector -fno-stack-clash-protection \
- -Wl,--initial-memory=327680 \
-Wl,--stack-first \
-Wl,--import-undefined \
+ -Wl,--initial-memory=327680 \
-D_HAVE_SQLITE_CONFIG_H \
-DSQLITE_CUSTOM_INCLUDE=sqlite_opt.h \
$(awk '{print "-Wl,--export="$0}' exports.txt)
-trap 'rm -f sqlite3.tmp' EXIT
"$BINARYEN/wasm-ctor-eval" -g -c _initialize sqlite3.wasm -o sqlite3.tmp
"$BINARYEN/wasm-opt" -g --strip --strip-producers -c -O3 \
sqlite3.tmp -o sqlite3.wasm \
diff --git a/vendor/github.com/ncruces/go-sqlite3/embed/exports.txt b/vendor/github.com/ncruces/go-sqlite3/embed/exports.txt
index b3cb1581c..e7882cb56 100644
--- a/vendor/github.com/ncruces/go-sqlite3/embed/exports.txt
+++ b/vendor/github.com/ncruces/go-sqlite3/embed/exports.txt
@@ -55,17 +55,21 @@ sqlite3_create_function_go
sqlite3_create_module_go
sqlite3_create_window_function_go
sqlite3_database_file_object
+sqlite3_db_cacheflush
sqlite3_db_config
sqlite3_db_filename
sqlite3_db_name
sqlite3_db_readonly
sqlite3_db_release_memory
+sqlite3_db_status
sqlite3_declare_vtab
sqlite3_errcode
sqlite3_errmsg
sqlite3_error_offset
sqlite3_errstr
sqlite3_exec
+sqlite3_expanded_sql
+sqlite3_file_control
sqlite3_filename_database
sqlite3_filename_journal
sqlite3_filename_wal
@@ -100,16 +104,18 @@ sqlite3_step
sqlite3_stmt_busy
sqlite3_stmt_readonly
sqlite3_stmt_status
+sqlite3_table_column_metadata
sqlite3_total_changes64
+sqlite3_trace_go
sqlite3_txn_state
sqlite3_update_hook_go
sqlite3_uri_key
-sqlite3_uri_parameter
sqlite3_value_blob
sqlite3_value_bytes
sqlite3_value_double
sqlite3_value_dup
sqlite3_value_free
+sqlite3_value_frombind
sqlite3_value_int64
sqlite3_value_nochange
sqlite3_value_numeric_type
diff --git a/vendor/github.com/ncruces/go-sqlite3/embed/sqlite3.wasm b/vendor/github.com/ncruces/go-sqlite3/embed/sqlite3.wasm
index 43a1f99ad..5f4b64a9c 100644
--- a/vendor/github.com/ncruces/go-sqlite3/embed/sqlite3.wasm
+++ b/vendor/github.com/ncruces/go-sqlite3/embed/sqlite3.wasm
Binary files differ
diff --git a/vendor/github.com/ncruces/go-sqlite3/go.work.sum b/vendor/github.com/ncruces/go-sqlite3/go.work.sum
index 27b395cc7..76ac94b0d 100644
--- a/vendor/github.com/ncruces/go-sqlite3/go.work.sum
+++ b/vendor/github.com/ncruces/go-sqlite3/go.work.sum
@@ -3,5 +3,7 @@ golang.org/x/mod v0.17.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c=
golang.org/x/net v0.21.0/go.mod h1:bIjVDfnllIU7BJ2DNgfnXvpSvtn8VRwhlsaeUTyUS44=
golang.org/x/term v0.20.0/go.mod h1:8UkIAJTvZgivsXaD6/pH6U9ecQzZ45awqEOzuCvwpFY=
golang.org/x/term v0.21.0/go.mod h1:ooXLefLobQVslOqselCNF4SxFAaoS6KujMbsGzSDmX0=
+golang.org/x/term v0.22.0/go.mod h1:F3qCibpT5AMpCRfhfT53vVJwhLtIVHhB9XDjfFvnMI4=
+golang.org/x/term v0.23.0/go.mod h1:DgV24QBUrK6jhZXl+20l6UWznPlwAHm1Q1mGHtydmSk=
golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU=
golang.org/x/tools v0.21.1-0.20240508182429-e35e4ccd0d2d/go.mod h1:aiJjzUbINMkxbQROHiO6hDPo2LHcIPhhQsa9DLh0yGk=
diff --git a/vendor/github.com/ncruces/go-sqlite3/internal/util/mmap.go b/vendor/github.com/ncruces/go-sqlite3/internal/util/mmap.go
index 434cc12ad..b091e38b0 100644
--- a/vendor/github.com/ncruces/go-sqlite3/internal/util/mmap.go
+++ b/vendor/github.com/ncruces/go-sqlite3/internal/util/mmap.go
@@ -32,7 +32,7 @@ func (s *mmapState) new(ctx context.Context, mod api.Module, size int32) *Mapped
// Allocate page aligned memmory.
alloc := mod.ExportedFunction("aligned_alloc")
- stack := [2]uint64{
+ stack := [...]uint64{
uint64(unix.Getpagesize()),
uint64(size),
}
diff --git a/vendor/github.com/ncruces/go-sqlite3/sqlite.go b/vendor/github.com/ncruces/go-sqlite3/sqlite.go
index 61a03652f..712ad5160 100644
--- a/vendor/github.com/ncruces/go-sqlite3/sqlite.go
+++ b/vendor/github.com/ncruces/go-sqlite3/sqlite.go
@@ -13,6 +13,7 @@ import (
"github.com/ncruces/go-sqlite3/vfs"
"github.com/tetratelabs/wazero"
"github.com/tetratelabs/wazero/api"
+ "github.com/tetratelabs/wazero/experimental"
)
// Configure SQLite Wasm.
@@ -44,12 +45,14 @@ var instance struct {
}
func compileSQLite() {
- if RuntimeConfig == nil {
- RuntimeConfig = wazero.NewRuntimeConfig()
+ ctx := context.Background()
+ cfg := RuntimeConfig
+ if cfg == nil {
+ cfg = wazero.NewRuntimeConfig()
}
- ctx := context.Background()
- instance.runtime = wazero.NewRuntimeWithConfig(ctx, RuntimeConfig)
+ instance.runtime = wazero.NewRuntimeWithConfig(ctx,
+ cfg.WithCoreFeatures(api.CoreFeaturesV2|experimental.CoreFeaturesThreads))
env := instance.runtime.NewHostModuleBuilder("env")
env = vfs.ExportHostFunctions(env)
@@ -82,7 +85,7 @@ type sqlite struct {
id [32]*byte
mask uint32
}
- stack [8]uint64
+ stack [9]uint64
freer uint32
}
@@ -303,6 +306,7 @@ func exportCallbacks(env wazero.HostModuleBuilder) wazero.HostModuleBuilder {
util.ExportFuncVI(env, "go_rollback_hook", rollbackCallback)
util.ExportFuncVIIIIJ(env, "go_update_hook", updateCallback)
util.ExportFuncIIIII(env, "go_wal_hook", walCallback)
+ util.ExportFuncIIIII(env, "go_trace", traceCallback)
util.ExportFuncIIIIII(env, "go_autovacuum_pages", autoVacuumCallback)
util.ExportFuncIIIIIII(env, "go_authorizer", authorizerCallback)
util.ExportFuncVIII(env, "go_log", logCallback)
diff --git a/vendor/github.com/ncruces/go-sqlite3/stmt.go b/vendor/github.com/ncruces/go-sqlite3/stmt.go
index 381a7d06b..8e6ad2c10 100644
--- a/vendor/github.com/ncruces/go-sqlite3/stmt.go
+++ b/vendor/github.com/ncruces/go-sqlite3/stmt.go
@@ -15,6 +15,7 @@ import (
type Stmt struct {
c *Conn
err error
+ sql string
handle uint32
}
@@ -29,6 +30,15 @@ func (s *Stmt) Close() error {
}
r := s.c.call("sqlite3_finalize", uint64(s.handle))
+ for i := range s.c.stmts {
+ if s == s.c.stmts[i] {
+ l := len(s.c.stmts) - 1
+ s.c.stmts[i] = s.c.stmts[l]
+ s.c.stmts[l] = nil
+ s.c.stmts = s.c.stmts[:l]
+ break
+ }
+ }
s.handle = 0
return s.c.error(r)
@@ -41,6 +51,24 @@ func (s *Stmt) Conn() *Conn {
return s.c
}
+// SQL returns the SQL text used to create the prepared statement.
+//
+// https://sqlite.org/c3ref/expanded_sql.html
+func (s *Stmt) SQL() string {
+ return s.sql
+}
+
+// ExpandedSQL returns the SQL text of the prepared statement
+// with bound parameters expanded.
+//
+// https://sqlite.org/c3ref/expanded_sql.html
+func (s *Stmt) ExpandedSQL() string {
+ r := s.c.call("sqlite3_expanded_sql", uint64(s.handle))
+ sql := util.ReadString(s.c.mod, uint32(r), _MAX_SQL_LENGTH)
+ s.c.free(uint32(r))
+ return sql
+}
+
// ReadOnly returns true if and only if the statement
// makes no direct changes to the content of the database file.
//
@@ -283,7 +311,8 @@ func (s *Stmt) BindNull(param int) error {
//
// https://sqlite.org/c3ref/bind_blob.html
func (s *Stmt) BindTime(param int, value time.Time, format TimeFormat) error {
- if format == TimeFormatDefault {
+ switch format {
+ case TimeFormatDefault, TimeFormatAuto, time.RFC3339Nano:
return s.bindRFC3339Nano(param, value)
}
switch v := format.Encode(value).(type) {
diff --git a/vendor/github.com/ncruces/go-sqlite3/txn.go b/vendor/github.com/ncruces/go-sqlite3/txn.go
index 0efbc2d80..7121778d6 100644
--- a/vendor/github.com/ncruces/go-sqlite3/txn.go
+++ b/vendor/github.com/ncruces/go-sqlite3/txn.go
@@ -32,6 +32,19 @@ func (c *Conn) Begin() Txn {
return Txn{c}
}
+// BeginConcurrent starts a concurrent transaction.
+//
+// Experimental: requires a custom build of SQLite.
+//
+// https://sqlite.org/cgi/src/doc/begin-concurrent/doc/begin_concurrent.md
+func (c *Conn) BeginConcurrent() (Txn, error) {
+ err := c.Exec(`BEGIN CONCURRENT`)
+ if err != nil {
+ return Txn{}, err
+ }
+ return Txn{c}, nil
+}
+
// BeginImmediate starts an immediate transaction.
//
// https://sqlite.org/lang_transaction.html
@@ -217,7 +230,7 @@ func (c *Conn) txnExecInterrupted(sql string) error {
return err
}
-// TxnState starts a deferred transaction.
+// TxnState determines the transaction state of a database.
//
// https://sqlite.org/c3ref/txn_state.html
func (c *Conn) TxnState(schema string) TxnState {
@@ -292,3 +305,11 @@ func updateCallback(ctx context.Context, mod api.Module, pDB uint32, action Auth
c.update(action, schema, table, int64(rowid))
}
}
+
+// CacheFlush flushes caches to disk mid-transaction.
+//
+// https://sqlite.org/c3ref/db_cacheflush.html
+func (c *Conn) CacheFlush() error {
+ r := c.call("sqlite3_db_cacheflush", uint64(c.handle))
+ return c.error(r)
+}
diff --git a/vendor/github.com/ncruces/go-sqlite3/value.go b/vendor/github.com/ncruces/go-sqlite3/value.go
index 1894ff4f1..86f6689da 100644
--- a/vendor/github.com/ncruces/go-sqlite3/value.go
+++ b/vendor/github.com/ncruces/go-sqlite3/value.go
@@ -201,6 +201,14 @@ func (v Value) NoChange() bool {
return r != 0
}
+// FromBind returns true if value originated from a bound parameter.
+//
+// https://sqlite.org/c3ref/value_blob.html
+func (v Value) FromBind() bool {
+ r := v.c.call("sqlite3_value_frombind", v.protected())
+ return r != 0
+}
+
// InFirst returns the first element
// on the right-hand side of an IN constraint.
//
diff --git a/vendor/github.com/ncruces/go-sqlite3/vfs/file.go b/vendor/github.com/ncruces/go-sqlite3/vfs/file.go
index 93a2f7ece..176b2507b 100644
--- a/vendor/github.com/ncruces/go-sqlite3/vfs/file.go
+++ b/vendor/github.com/ncruces/go-sqlite3/vfs/file.go
@@ -69,6 +69,7 @@ func (vfsOS) Access(name string, flags AccessFlag) (bool, error) {
}
func (vfsOS) Open(name string, flags OpenFlag) (File, OpenFlag, error) {
+ // notest // OpenFilename is called instead
return nil, 0, _CANTOPEN
}
diff --git a/vendor/github.com/ncruces/go-sqlite3/vfs/filename.go b/vendor/github.com/ncruces/go-sqlite3/vfs/filename.go
index e23575bbb..51d0b8dda 100644
--- a/vendor/github.com/ncruces/go-sqlite3/vfs/filename.go
+++ b/vendor/github.com/ncruces/go-sqlite3/vfs/filename.go
@@ -20,8 +20,8 @@ type Filename struct {
stack [2]uint64
}
-// OpenFilename is an internal API users should not call directly.
-func OpenFilename(ctx context.Context, mod api.Module, id uint32, flags OpenFlag) *Filename {
+// GetFilename is an internal API users should not call directly.
+func GetFilename(ctx context.Context, mod api.Module, id uint32, flags OpenFlag) *Filename {
if id == 0 {
return nil
}
@@ -66,6 +66,10 @@ func (n *Filename) path(method string) string {
if n == nil || n.zPath == 0 {
return ""
}
+ if n.flags&(OPEN_MAIN_DB|OPEN_MAIN_JOURNAL|OPEN_WAL) == 0 {
+ return ""
+ }
+
n.stack[0] = uint64(n.zPath)
fn := n.mod.ExportedFunction(method)
if err := fn.CallWithStack(n.ctx, n.stack[:]); err != nil {
diff --git a/vendor/github.com/ncruces/go-sqlite3/vfs/memdb/api.go b/vendor/github.com/ncruces/go-sqlite3/vfs/memdb/api.go
index 5a2b84c71..843488966 100644
--- a/vendor/github.com/ncruces/go-sqlite3/vfs/memdb/api.go
+++ b/vendor/github.com/ncruces/go-sqlite3/vfs/memdb/api.go
@@ -10,7 +10,10 @@
package memdb
import (
+ "fmt"
+ "net/url"
"sync"
+ "testing"
"github.com/ncruces/go-sqlite3/vfs"
)
@@ -39,8 +42,9 @@ func Create(name string, data []byte) {
size: int64(len(data)),
}
- // Convert data from WAL to rollback journal.
- if len(data) >= 20 && data[18] == 2 && data[19] == 2 {
+ // Convert data from WAL/2 to rollback journal.
+ if len(data) >= 20 && (data[18] == 2 && data[19] == 2 ||
+ data[18] == 3 && data[19] == 3) {
data[18] = 1
data[19] = 1
}
@@ -66,3 +70,30 @@ func Delete(name string) {
defer memoryMtx.Unlock()
delete(memoryDBs, name)
}
+
+// TestDB creates an empty shared memory database for the test to use.
+// The database is automatically deleted when the test and all its subtests complete.
+// Each subsequent call to TestDB returns a unique database.
+func TestDB(tb testing.TB, params ...url.Values) string {
+ tb.Helper()
+
+ name := fmt.Sprintf("%s_%p", tb.Name(), tb)
+ tb.Cleanup(func() { Delete(name) })
+ Create(name, nil)
+
+ p := url.Values{"vfs": {"memdb"}}
+ for _, v := range params {
+ for k, v := range v {
+ for _, v := range v {
+ p.Add(k, v)
+ }
+ }
+ }
+
+ return (&url.URL{
+ Scheme: "file",
+ OmitHost: true,
+ Path: "/" + name,
+ RawQuery: p.Encode(),
+ }).String()
+}
diff --git a/vendor/github.com/ncruces/go-sqlite3/vfs/memdb/memdb.go b/vendor/github.com/ncruces/go-sqlite3/vfs/memdb/memdb.go
index f21335d8e..d313b45d1 100644
--- a/vendor/github.com/ncruces/go-sqlite3/vfs/memdb/memdb.go
+++ b/vendor/github.com/ncruces/go-sqlite3/vfs/memdb/memdb.go
@@ -30,6 +30,7 @@ func (memVFS) Open(name string, flags vfs.OpenFlag) (vfs.File, vfs.OpenFlag, err
vfs.OPEN_TEMP_DB |
vfs.OPEN_TEMP_JOURNAL
if flags&types == 0 {
+ // notest // OPEN_MEMORY
return nil, flags, sqlite3.CANTOPEN
}
@@ -82,7 +83,7 @@ type memDB struct {
size int64
// +checklocks:lockMtx
- shared int
+ shared int32
// +checklocks:lockMtx
reserved bool
// +checklocks:lockMtx
@@ -136,7 +137,7 @@ func (m *memFile) ReadAt(b []byte, off int64) (n int, err error) {
}
n = copy(b, (*m.data[base])[rest:have])
if n < len(b) {
- // Assume reads are page aligned.
+ // notest // assume reads are page aligned
return 0, io.ErrNoProgress
}
return n, nil
@@ -153,7 +154,7 @@ func (m *memFile) WriteAt(b []byte, off int64) (n int, err error) {
}
n = copy((*m.data[base])[rest:], b)
if n < len(b) {
- // Assume writes are page aligned.
+ // notest // assume writes are page aligned
return n, io.ErrShortWrite
}
if size := off + int64(len(b)); size > m.size {
@@ -226,9 +227,6 @@ func (m *memFile) Lock(lock vfs.LockLevel) error {
case vfs.LOCK_EXCLUSIVE:
if m.lock < vfs.LOCK_PENDING {
- if m.pending {
- return sqlite3.BUSY
- }
m.lock = vfs.LOCK_PENDING
m.pending = true
}
@@ -269,6 +267,7 @@ func (m *memFile) Unlock(lock vfs.LockLevel) error {
}
func (m *memFile) CheckReservedLock() (bool, error) {
+ // notest // OPEN_MEMORY
if m.lock >= vfs.LOCK_RESERVED {
return true, nil
}
@@ -278,6 +277,7 @@ func (m *memFile) CheckReservedLock() (bool, error) {
}
func (m *memFile) SectorSize() int {
+ // notest // IOCAP_POWERSAFE_OVERWRITE
return sectorSize
}
diff --git a/vendor/github.com/ncruces/go-sqlite3/vfs/os_darwin.go b/vendor/github.com/ncruces/go-sqlite3/vfs/os_darwin.go
index 8bfe96bb1..c8d84dc36 100644
--- a/vendor/github.com/ncruces/go-sqlite3/vfs/os_darwin.go
+++ b/vendor/github.com/ncruces/go-sqlite3/vfs/os_darwin.go
@@ -5,6 +5,7 @@ package vfs
import (
"io"
"os"
+ "runtime"
"time"
"golang.org/x/sys/unix"
@@ -68,7 +69,7 @@ func osUnlock(file *os.File, start, len int64) _ErrorCode {
}
func osLock(file *os.File, typ int16, start, len int64, timeout time.Duration, def _ErrorCode) _ErrorCode {
- lock := flocktimeout_t{fl: unix.Flock_t{
+ lock := &flocktimeout_t{fl: unix.Flock_t{
Type: typ,
Start: start,
Len: len,
@@ -82,6 +83,7 @@ func osLock(file *os.File, typ int16, start, len int64, timeout time.Duration, d
default:
lock.timeout = unix.NsecToTimespec(int64(timeout / time.Nanosecond))
err = unix.FcntlFlock(file.Fd(), _F_OFD_SETLKWTIMEOUT, &lock.fl)
+ runtime.KeepAlive(lock)
}
return osLockErrorCode(err, def)
}
diff --git a/vendor/github.com/ncruces/go-sqlite3/vfs/os_f2fs_linux.go b/vendor/github.com/ncruces/go-sqlite3/vfs/os_f2fs_linux.go
index a9f0e333c..487f0c7d9 100644
--- a/vendor/github.com/ncruces/go-sqlite3/vfs/os_f2fs_linux.go
+++ b/vendor/github.com/ncruces/go-sqlite3/vfs/os_f2fs_linux.go
@@ -16,6 +16,8 @@ const (
_F2FS_FEATURE_ATOMIC_WRITE = 4
)
+// notest
+
func osBatchAtomic(file *os.File) bool {
flags, err := unix.IoctlGetInt(int(file.Fd()), _F2FS_IOC_GET_FEATURES)
return err == nil && flags&_F2FS_FEATURE_ATOMIC_WRITE != 0
diff --git a/vendor/github.com/ncruces/go-sqlite3/vfs/os_unix_lock.go b/vendor/github.com/ncruces/go-sqlite3/vfs/os_unix_lock.go
index 85a7b0fc0..ffa1f5e19 100644
--- a/vendor/github.com/ncruces/go-sqlite3/vfs/os_unix_lock.go
+++ b/vendor/github.com/ncruces/go-sqlite3/vfs/os_unix_lock.go
@@ -50,6 +50,7 @@ func osDowngradeLock(file *os.File, state LockLevel) _ErrorCode {
// indicates that the other process is not following the locking
// protocol. If this happens, return IOERR_RDLOCK. Returning
// BUSY would confuse the upper layer.
+ // notest
return _IOERR_RDLOCK
}
}
@@ -98,6 +99,7 @@ func osLockErrorCode(err error, def _ErrorCode) _ErrorCode {
case unix.EPERM:
return _PERM
}
+ // notest // usually EWOULDBLOCK == EAGAIN
if errno == unix.EWOULDBLOCK && unix.EWOULDBLOCK != unix.EAGAIN {
return _BUSY
}
diff --git a/vendor/github.com/ncruces/go-sqlite3/vfs/os_windows.go b/vendor/github.com/ncruces/go-sqlite3/vfs/os_windows.go
index 83b952b16..7425b5581 100644
--- a/vendor/github.com/ncruces/go-sqlite3/vfs/os_windows.go
+++ b/vendor/github.com/ncruces/go-sqlite3/vfs/os_windows.go
@@ -66,6 +66,7 @@ func osDowngradeLock(file *os.File, state LockLevel) _ErrorCode {
if rc := osReadLock(file, _SHARED_FIRST, _SHARED_SIZE, 0); rc != _OK {
// This should never happen.
// We should always be able to reacquire the read lock.
+ // notest
return _IOERR_RDLOCK
}
}
diff --git a/vendor/github.com/ncruces/go-sqlite3/vfs/shm_bsd.go b/vendor/github.com/ncruces/go-sqlite3/vfs/shm_bsd.go
index ffeb3e0a0..65674ed2e 100644
--- a/vendor/github.com/ncruces/go-sqlite3/vfs/shm_bsd.go
+++ b/vendor/github.com/ncruces/go-sqlite3/vfs/shm_bsd.go
@@ -72,28 +72,28 @@ func (s *vfsShm) Close() error {
return nil
}
- // Unlock everything.
- s.shmLock(0, _SHM_NLOCK, _SHM_UNLOCK)
-
vfsShmFilesMtx.Lock()
defer vfsShmFilesMtx.Unlock()
+ // Unlock everything.
+ s.shmLock(0, _SHM_NLOCK, _SHM_UNLOCK)
+
// Decrease reference count.
if s.vfsShmFile.refs > 1 {
s.vfsShmFile.refs--
s.vfsShmFile = nil
return nil
}
+
+ err := s.File.Close()
for i, g := range vfsShmFiles {
if g == s.vfsShmFile {
vfsShmFiles[i] = nil
- break
+ s.vfsShmFile = nil
+ return err
}
}
-
- err := s.File.Close()
- s.vfsShmFile = nil
- return err
+ panic(util.AssertErr())
}
func (s *vfsShm) shmOpen() (rc _ErrorCode) {
@@ -234,6 +234,8 @@ func (s *vfsShm) shmLock(offset, n int32, flags _ShmFlag) _ErrorCode {
s.vfsShmFile.lock[i] = -1
s.lock[i] = true
}
+ default:
+ panic(util.AssertErr())
}
return _OK
@@ -256,5 +258,4 @@ func (s *vfsShm) shmUnmap(delete bool) {
os.Remove(s.path)
}
s.Close()
- s.vfsShmFile = nil
}
diff --git a/vendor/github.com/ncruces/go-sqlite3/vfs/vfs.go b/vendor/github.com/ncruces/go-sqlite3/vfs/vfs.go
index d624aa78c..983f28560 100644
--- a/vendor/github.com/ncruces/go-sqlite3/vfs/vfs.go
+++ b/vendor/github.com/ncruces/go-sqlite3/vfs/vfs.go
@@ -132,26 +132,20 @@ func vfsAccess(ctx context.Context, mod api.Module, pVfs, zPath uint32, flags Ac
func vfsOpen(ctx context.Context, mod api.Module, pVfs, zPath, pFile uint32, flags OpenFlag, pOutFlags, pOutVFS uint32) _ErrorCode {
vfs := vfsGet(mod, pVfs)
-
- var path string
- if zPath != 0 {
- path = util.ReadString(mod, zPath, _MAX_PATHNAME)
- }
+ name := GetFilename(ctx, mod, zPath, flags)
var file File
var err error
if ffs, ok := vfs.(VFSFilename); ok {
- name := OpenFilename(ctx, mod, zPath, flags)
file, flags, err = ffs.OpenFilename(name, flags)
} else {
- file, flags, err = vfs.Open(path, flags)
+ file, flags, err = vfs.Open(name.String(), flags)
}
if err != nil {
return vfsErrorCode(err, _CANTOPEN)
}
if file, ok := file.(FilePowersafeOverwrite); ok {
- name := OpenFilename(ctx, mod, zPath, flags)
if b, ok := util.ParseBool(name.URIParameter("psow")); ok {
file.SetPowersafeOverwrite(b)
}
@@ -169,10 +163,7 @@ func vfsOpen(ctx context.Context, mod api.Module, pVfs, zPath, pFile uint32, fla
func vfsClose(ctx context.Context, mod api.Module, pFile uint32) _ErrorCode {
err := vfsFileClose(ctx, mod, pFile)
- if err != nil {
- return vfsErrorCode(err, _IOERR_CLOSE)
- }
- return _OK
+ return vfsErrorCode(err, _IOERR_CLOSE)
}
func vfsRead(ctx context.Context, mod api.Module, pFile, zBuf uint32, iAmt int32, iOfst int64) _ErrorCode {
@@ -195,10 +186,7 @@ func vfsWrite(ctx context.Context, mod api.Module, pFile, zBuf uint32, iAmt int3
buf := util.View(mod, zBuf, uint64(iAmt))
_, err := file.WriteAt(buf, iOfst)
- if err != nil {
- return vfsErrorCode(err, _IOERR_WRITE)
- }
- return _OK
+ return vfsErrorCode(err, _IOERR_WRITE)
}
func vfsTruncate(ctx context.Context, mod api.Module, pFile uint32, nByte int64) _ErrorCode {
diff --git a/vendor/github.com/ncruces/go-sqlite3/vtab.go b/vendor/github.com/ncruces/go-sqlite3/vtab.go
index 7c19330bb..3bbff6d31 100644
--- a/vendor/github.com/ncruces/go-sqlite3/vtab.go
+++ b/vendor/github.com/ncruces/go-sqlite3/vtab.go
@@ -247,7 +247,7 @@ type VTabCursor interface {
// https://sqlite.org/vtab.html#xeof
EOF() bool
// https://sqlite.org/vtab.html#xcolumn
- Column(ctx *Context, n int) error
+ Column(ctx Context, n int) error
// https://sqlite.org/vtab.html#xrowid
RowID() (int64, error)
}
@@ -618,7 +618,7 @@ func cursorNextCallback(ctx context.Context, mod api.Module, pCur uint32) uint32
func cursorColumnCallback(ctx context.Context, mod api.Module, pCur, pCtx uint32, n int32) uint32 {
cursor := vtabGetHandle(ctx, mod, pCur).(VTabCursor)
db := ctx.Value(connKey{}).(*Conn)
- err := cursor.Column(&Context{db, pCtx}, int(n))
+ err := cursor.Column(Context{db, pCtx}, int(n))
return vtabError(ctx, mod, pCur, _CURSOR_ERROR, err)
}