diff --git a/go.mod b/go.mod index 42ddcf09e..6f7053ea0 100644 --- a/go.mod +++ b/go.mod @@ -45,7 +45,7 @@ require ( github.com/miekg/dns v1.1.61 github.com/minio/minio-go/v7 v7.0.74 github.com/mitchellh/mapstructure v1.5.0 - github.com/ncruces/go-sqlite3 v0.17.1 + github.com/ncruces/go-sqlite3 v0.18.0 github.com/oklog/ulid v1.3.1 github.com/prometheus/client_golang v1.19.1 github.com/spf13/cobra v1.8.1 @@ -215,7 +215,7 @@ require ( golang.org/x/exp v0.0.0-20240222234643-814bf88cf225 // indirect golang.org/x/mod v0.18.0 // indirect golang.org/x/sync v0.8.0 // indirect - golang.org/x/sys v0.23.0 // indirect + golang.org/x/sys v0.24.0 // indirect golang.org/x/tools v0.22.0 // indirect google.golang.org/genproto/googleapis/api v0.0.0-20240311132316-a219d84964c2 // indirect google.golang.org/genproto/googleapis/rpc v0.0.0-20240401170217-c3f982113cda // indirect diff --git a/go.sum b/go.sum index 364c54a02..69a9ef2bd 100644 --- a/go.sum +++ b/go.sum @@ -438,8 +438,8 @@ github.com/modern-go/reflect2 v1.0.2 h1:xBagoLtFs94CBntxluKeaWgTMpvLxC4ur3nMaC9G github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk= 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/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/go-strftime v0.1.9 h1:bY0MQC28UADQmHmaF5dgpLmImcShSi2kHU9XLdhx/f4= github.com/ncruces/go-strftime v0.1.9/go.mod h1:Fwc5htZGVVkseilnfgOVb9mKy6w1naJmn9CehxcKcls= github.com/ncruces/julianday v1.0.0 h1:fH0OKwa7NWvniGQtxdJRxAgkBMolni2BjDHaWTxqt7M= @@ -805,8 +805,8 @@ golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBc golang.org/x/sys v0.2.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.23.0 h1:YfKFowiIMvtgl1UERQoTPPToxltDeZfbj4H7dVUCwmM= -golang.org/x/sys v0.23.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/sys v0.24.0 h1:Twjiwq9dn6R1fQcyiK+wQyHWfaz/BJB+YIpzU/Cv3Xg= +golang.org/x/sys v0.24.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= golang.org/x/term v0.2.0/go.mod h1:TVmDHMZPmdnySmBfhjOoOdhjzdE1h4u1VwSiw2l1Nuc= 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 Binary files a/vendor/github.com/ncruces/go-sqlite3/embed/sqlite3.wasm and b/vendor/github.com/ncruces/go-sqlite3/embed/sqlite3.wasm 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) } diff --git a/vendor/golang.org/x/sys/unix/ztypes_linux.go b/vendor/golang.org/x/sys/unix/ztypes_linux.go index b102b95a0..7f1961b90 100644 --- a/vendor/golang.org/x/sys/unix/ztypes_linux.go +++ b/vendor/golang.org/x/sys/unix/ztypes_linux.go @@ -3807,6 +3807,9 @@ const ( ETHTOOL_MSG_PSE_GET_REPLY = 0x25 ETHTOOL_MSG_RSS_GET_REPLY = 0x26 ETHTOOL_MSG_KERNEL_MAX = 0x2b + ETHTOOL_FLAG_COMPACT_BITSETS = 0x1 + ETHTOOL_FLAG_OMIT_REPLY = 0x2 + ETHTOOL_FLAG_STATS = 0x4 ETHTOOL_A_HEADER_UNSPEC = 0x0 ETHTOOL_A_HEADER_DEV_INDEX = 0x1 ETHTOOL_A_HEADER_DEV_NAME = 0x2 diff --git a/vendor/golang.org/x/sys/windows/types_windows.go b/vendor/golang.org/x/sys/windows/types_windows.go index 4d0c15745..3f03b3d57 100644 --- a/vendor/golang.org/x/sys/windows/types_windows.go +++ b/vendor/golang.org/x/sys/windows/types_windows.go @@ -2031,6 +2031,50 @@ const ( IF_TYPE_IEEE1394 = 144 ) +// Enum NL_PREFIX_ORIGIN for [IpAdapterUnicastAddress], see +// https://learn.microsoft.com/en-us/windows/win32/api/nldef/ne-nldef-nl_prefix_origin +const ( + IpPrefixOriginOther = 0 + IpPrefixOriginManual = 1 + IpPrefixOriginWellKnown = 2 + IpPrefixOriginDhcp = 3 + IpPrefixOriginRouterAdvertisement = 4 + IpPrefixOriginUnchanged = 1 << 4 +) + +// Enum NL_SUFFIX_ORIGIN for [IpAdapterUnicastAddress], see +// https://learn.microsoft.com/en-us/windows/win32/api/nldef/ne-nldef-nl_suffix_origin +const ( + NlsoOther = 0 + NlsoManual = 1 + NlsoWellKnown = 2 + NlsoDhcp = 3 + NlsoLinkLayerAddress = 4 + NlsoRandom = 5 + IpSuffixOriginOther = 0 + IpSuffixOriginManual = 1 + IpSuffixOriginWellKnown = 2 + IpSuffixOriginDhcp = 3 + IpSuffixOriginLinkLayerAddress = 4 + IpSuffixOriginRandom = 5 + IpSuffixOriginUnchanged = 1 << 4 +) + +// Enum NL_DAD_STATE for [IpAdapterUnicastAddress], see +// https://learn.microsoft.com/en-us/windows/win32/api/nldef/ne-nldef-nl_dad_state +const ( + NldsInvalid = 0 + NldsTentative = 1 + NldsDuplicate = 2 + NldsDeprecated = 3 + NldsPreferred = 4 + IpDadStateInvalid = 0 + IpDadStateTentative = 1 + IpDadStateDuplicate = 2 + IpDadStateDeprecated = 3 + IpDadStatePreferred = 4 +) + type SocketAddress struct { Sockaddr *syscall.RawSockaddrAny SockaddrLength int32 diff --git a/vendor/modules.txt b/vendor/modules.txt index 9d6bbcb24..7eef5fda5 100644 --- a/vendor/modules.txt +++ b/vendor/modules.txt @@ -516,7 +516,7 @@ github.com/modern-go/concurrent # github.com/modern-go/reflect2 v1.0.2 ## explicit; go 1.12 github.com/modern-go/reflect2 -# github.com/ncruces/go-sqlite3 v0.17.1 +# github.com/ncruces/go-sqlite3 v0.18.0 ## explicit; go 1.21 github.com/ncruces/go-sqlite3 github.com/ncruces/go-sqlite3/driver @@ -1124,7 +1124,7 @@ golang.org/x/oauth2/internal ## explicit; go 1.18 golang.org/x/sync/errgroup golang.org/x/sync/semaphore -# golang.org/x/sys v0.23.0 +# golang.org/x/sys v0.24.0 ## explicit; go 1.18 golang.org/x/sys/cpu golang.org/x/sys/unix