diff options
Diffstat (limited to 'vendor/github.com/ncruces/go-sqlite3')
96 files changed, 0 insertions, 12295 deletions
diff --git a/vendor/github.com/ncruces/go-sqlite3/.gitignore b/vendor/github.com/ncruces/go-sqlite3/.gitignore deleted file mode 100644 index 9a50edc5c..000000000 --- a/vendor/github.com/ncruces/go-sqlite3/.gitignore +++ /dev/null @@ -1,19 +0,0 @@ -# Binaries for programs and plugins -*.exe -*.exe~ -*.dll -*.so -*.dylib - -# Go workspace -go.work* - -# Test binary, built with `go test -c` -*.test - -# Output of the go coverage tool, specifically when used with LiteIDE -*.out - -# Dependency directories (remove the comment below to include it) -# vendor/ -tools
\ No newline at end of file diff --git a/vendor/github.com/ncruces/go-sqlite3/LICENSE b/vendor/github.com/ncruces/go-sqlite3/LICENSE deleted file mode 100644 index 9bdc1df48..000000000 --- a/vendor/github.com/ncruces/go-sqlite3/LICENSE +++ /dev/null @@ -1,21 +0,0 @@ -MIT License - -Copyright (c) 2023 Nuno Cruces - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. diff --git a/vendor/github.com/ncruces/go-sqlite3/README.md b/vendor/github.com/ncruces/go-sqlite3/README.md deleted file mode 100644 index 7591f3cb3..000000000 --- a/vendor/github.com/ncruces/go-sqlite3/README.md +++ /dev/null @@ -1,109 +0,0 @@ -# Go bindings to SQLite using wazero - -[](https://pkg.go.dev/github.com/ncruces/go-sqlite3) -[](https://goreportcard.com/report/github.com/ncruces/go-sqlite3) -[](https://github.com/ncruces/go-sqlite3/wiki/Test-coverage-report) - -Go module `github.com/ncruces/go-sqlite3` is a `cgo`-free [SQLite](https://sqlite.org/) wrapper.\ -It provides a [`database/sql`](https://pkg.go.dev/database/sql) compatible driver, -as well as direct access to most of the [C SQLite API](https://sqlite.org/cintro.html). - -It wraps a [Wasm](https://webassembly.org/) [build](embed/) of SQLite, -and uses [wazero](https://wazero.io/) as the runtime.\ -Go, wazero and [`x/sys`](https://pkg.go.dev/golang.org/x/sys) are the _only_ direct dependencies. - -### Getting started - -Using the [`database/sql`](https://pkg.go.dev/database/sql) driver: -```go - -import "database/sql" -import _ "github.com/ncruces/go-sqlite3/driver" -import _ "github.com/ncruces/go-sqlite3/embed" - -var version string -db, _ := sql.Open("sqlite3", "file:demo.db") -db.QueryRow(`SELECT sqlite_version()`).Scan(&version) -``` - -### Packages - -- [`github.com/ncruces/go-sqlite3`](https://pkg.go.dev/github.com/ncruces/go-sqlite3) - wraps the [C SQLite API](https://sqlite.org/cintro.html) - ([example usage](https://pkg.go.dev/github.com/ncruces/go-sqlite3#example-package)). -- [`github.com/ncruces/go-sqlite3/driver`](https://pkg.go.dev/github.com/ncruces/go-sqlite3/driver) - provides a [`database/sql`](https://pkg.go.dev/database/sql) driver - ([example usage](https://pkg.go.dev/github.com/ncruces/go-sqlite3/driver#example-package)). -- [`github.com/ncruces/go-sqlite3/embed`](https://pkg.go.dev/github.com/ncruces/go-sqlite3/embed) - embeds a build of SQLite into your application. -- [`github.com/ncruces/go-sqlite3/vfs`](https://pkg.go.dev/github.com/ncruces/go-sqlite3/vfs) - wraps the [C SQLite VFS API](https://sqlite.org/vfs.html) and provides a pure Go implementation. -- [`github.com/ncruces/go-sqlite3/gormlite`](https://pkg.go.dev/github.com/ncruces/go-sqlite3/gormlite) - provides a [GORM](https://gorm.io) driver. - -### Advanced features - -- [incremental BLOB I/O](https://sqlite.org/c3ref/blob_open.html) -- [nested transactions](https://sqlite.org/lang_savepoint.html) -- [custom functions](https://sqlite.org/c3ref/create_function.html) -- [virtual tables](https://sqlite.org/vtab.html) -- [custom VFSes](https://sqlite.org/vfs.html) -- [online backup](https://sqlite.org/backup.html) -- [JSON support](https://sqlite.org/json1.html) -- [math functions](https://sqlite.org/lang_mathfunc.html) -- [full-text search](https://sqlite.org/fts5.html) -- [geospatial search](https://sqlite.org/geopoly.html) -- [Unicode support](https://pkg.go.dev/github.com/ncruces/go-sqlite3/ext/unicode) -- [statistics functions](https://pkg.go.dev/github.com/ncruces/go-sqlite3/ext/stats) -- [encryption at rest](vfs/adiantum/README.md) -- [many extensions](ext/README.md) -- [custom VFSes](vfs/README.md#custom-vfses) -- [and more…](embed/README.md) - -### Caveats - -This module replaces the SQLite [OS Interface](https://sqlite.org/vfs.html) -(aka VFS) with a [pure Go](vfs/) implementation, -which has advantages and disadvantages. - -Read more about the Go VFS design [here](vfs/README.md). - -### Testing - -This project aims for [high test coverage](https://github.com/ncruces/go-sqlite3/wiki/Test-coverage-report). -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](https://github.com/ncruces/go-sqlite3/wiki/Support-matrix) on -Linux (amd64/arm64/386/riscv64/ppc64le/s390x), macOS (amd64/arm64), -Windows (amd64), FreeBSD (amd64/arm64), OpenBSD (amd64), NetBSD (amd64/arm64), -DragonFly BSD (amd64), illumos (amd64), and Solaris (amd64). - -The Go VFS is tested by running SQLite's -[mptest](https://github.com/sqlite/sqlite/blob/master/mptest/mptest.c). - -### Performance - -Perfomance of the [`database/sql`](https://pkg.go.dev/database/sql) driver is -[competitive](https://github.com/cvilsmeier/go-sqlite-bench) with alternatives. - -The Wasm and VFS layers are also tested by running SQLite's -[speedtest1](https://github.com/sqlite/sqlite/blob/master/test/speedtest1.c). - -### FAQ, issues, new features - -For questions, please see [Discussions](https://github.com/ncruces/go-sqlite3/discussions/categories/q-a). - -Also, post there if you used this driver for something interesting -([_"Show and tell"_](https://github.com/ncruces/go-sqlite3/discussions/categories/show-and-tell)), -have an [idea](https://github.com/ncruces/go-sqlite3/discussions/categories/ideas)… - -The [Issue](https://github.com/ncruces/go-sqlite3/issues) tracker is for bugs we want fixed, -and features we're working on, planning to work on, or asking for help with. - -### Alternatives - -- [`modernc.org/sqlite`](https://pkg.go.dev/modernc.org/sqlite) -- [`crawshaw.io/sqlite`](https://pkg.go.dev/crawshaw.io/sqlite) -- [`github.com/mattn/go-sqlite3`](https://pkg.go.dev/github.com/mattn/go-sqlite3) -- [`github.com/zombiezen/go-sqlite`](https://pkg.go.dev/github.com/zombiezen/go-sqlite) diff --git a/vendor/github.com/ncruces/go-sqlite3/backup.go b/vendor/github.com/ncruces/go-sqlite3/backup.go deleted file mode 100644 index 58b6229a7..000000000 --- a/vendor/github.com/ncruces/go-sqlite3/backup.go +++ /dev/null @@ -1,134 +0,0 @@ -package sqlite3 - -// Backup is an handle to an ongoing online backup operation. -// -// https://sqlite.org/c3ref/backup.html -type Backup struct { - c *Conn - handle ptr_t - otherc ptr_t -} - -// Backup backs up srcDB on the src connection to the "main" database in dstURI. -// -// Backup opens the SQLite database file dstURI, -// and blocks until the entire backup is complete. -// Use [Conn.BackupInit] for incremental backup. -// -// https://sqlite.org/backup.html -func (src *Conn) Backup(srcDB, dstURI string) error { - b, err := src.BackupInit(srcDB, dstURI) - if err != nil { - return err - } - defer b.Close() - _, err = b.Step(-1) - return err -} - -// Restore restores dstDB on the dst connection from the "main" database in srcURI. -// -// Restore opens the SQLite database file srcURI, -// and blocks until the entire restore is complete. -// -// https://sqlite.org/backup.html -func (dst *Conn) Restore(dstDB, srcURI string) error { - src, err := dst.openDB(srcURI, OPEN_READONLY|OPEN_URI) - if err != nil { - return err - } - b, err := dst.backupInit(dst.handle, dstDB, src, "main") - if err != nil { - return err - } - defer b.Close() - _, err = b.Step(-1) - return err -} - -// BackupInit initializes a backup operation to copy the content of one database into another. -// -// BackupInit opens the SQLite database file dstURI, -// then initializes a backup that copies the contents of srcDB on the src connection -// to the "main" database in dstURI. -// -// https://sqlite.org/c3ref/backup_finish.html#sqlite3backupinit -func (src *Conn) BackupInit(srcDB, dstURI string) (*Backup, error) { - dst, err := src.openDB(dstURI, OPEN_READWRITE|OPEN_CREATE|OPEN_URI) - if err != nil { - return nil, err - } - return src.backupInit(dst, "main", src.handle, srcDB) -} - -func (c *Conn) backupInit(dst ptr_t, dstName string, src ptr_t, srcName string) (*Backup, error) { - defer c.arena.mark()() - dstPtr := c.arena.string(dstName) - srcPtr := c.arena.string(srcName) - - other := dst - if c.handle == dst { - other = src - } - - ptr := ptr_t(c.call("sqlite3_backup_init", - stk_t(dst), stk_t(dstPtr), - stk_t(src), stk_t(srcPtr))) - if ptr == 0 { - defer c.closeDB(other) - rc := res_t(c.call("sqlite3_errcode", stk_t(dst))) - return nil, c.sqlite.error(rc, dst) - } - - return &Backup{ - c: c, - otherc: other, - handle: ptr, - }, nil -} - -// Close finishes a backup operation. -// -// It is safe to close a nil, zero or closed Backup. -// -// https://sqlite.org/c3ref/backup_finish.html#sqlite3backupfinish -func (b *Backup) Close() error { - if b == nil || b.handle == 0 { - return nil - } - - rc := res_t(b.c.call("sqlite3_backup_finish", stk_t(b.handle))) - b.c.closeDB(b.otherc) - b.handle = 0 - return b.c.error(rc) -} - -// Step copies up to nPage pages between the source and destination databases. -// If nPage is negative, all remaining source pages are copied. -// -// https://sqlite.org/c3ref/backup_finish.html#sqlite3backupstep -func (b *Backup) Step(nPage int) (done bool, err error) { - rc := res_t(b.c.call("sqlite3_backup_step", stk_t(b.handle), stk_t(nPage))) - if rc == _DONE { - return true, nil - } - return false, b.c.error(rc) -} - -// Remaining returns the number of pages still to be backed up -// at the conclusion of the most recent [Backup.Step]. -// -// https://sqlite.org/c3ref/backup_finish.html#sqlite3backupremaining -func (b *Backup) Remaining() int { - n := int32(b.c.call("sqlite3_backup_remaining", stk_t(b.handle))) - return int(n) -} - -// PageCount returns the total number of pages in the source database -// at the conclusion of the most recent [Backup.Step]. -// -// https://sqlite.org/c3ref/backup_finish.html#sqlite3backuppagecount -func (b *Backup) PageCount() int { - n := int32(b.c.call("sqlite3_backup_pagecount", stk_t(b.handle))) - return int(n) -} diff --git a/vendor/github.com/ncruces/go-sqlite3/blob.go b/vendor/github.com/ncruces/go-sqlite3/blob.go deleted file mode 100644 index 2fac72045..000000000 --- a/vendor/github.com/ncruces/go-sqlite3/blob.go +++ /dev/null @@ -1,261 +0,0 @@ -package sqlite3 - -import ( - "io" - - "github.com/ncruces/go-sqlite3/internal/util" -) - -// ZeroBlob represents a zero-filled, length n BLOB -// that can be used as an argument to -// [database/sql.DB.Exec] and similar methods. -type ZeroBlob int64 - -// Blob is an handle to an open BLOB. -// -// It implements [io.ReadWriteSeeker] for incremental BLOB I/O. -// -// https://sqlite.org/c3ref/blob.html -type Blob struct { - c *Conn - bytes int64 - offset int64 - handle ptr_t - bufptr ptr_t - buflen int64 -} - -var _ io.ReadWriteSeeker = &Blob{} - -// OpenBlob opens a BLOB for incremental I/O. -// -// https://sqlite.org/c3ref/blob_open.html -func (c *Conn) OpenBlob(db, table, column string, row int64, write bool) (*Blob, error) { - defer c.arena.mark()() - blobPtr := c.arena.new(ptrlen) - dbPtr := c.arena.string(db) - tablePtr := c.arena.string(table) - columnPtr := c.arena.string(column) - - var flags int32 - if write { - flags = 1 - } - - c.checkInterrupt(c.handle) - rc := res_t(c.call("sqlite3_blob_open", stk_t(c.handle), - stk_t(dbPtr), stk_t(tablePtr), stk_t(columnPtr), - stk_t(row), stk_t(flags), stk_t(blobPtr))) - - if err := c.error(rc); err != nil { - return nil, err - } - - blob := Blob{c: c} - blob.handle = util.Read32[ptr_t](c.mod, blobPtr) - blob.bytes = int64(int32(c.call("sqlite3_blob_bytes", stk_t(blob.handle)))) - return &blob, nil -} - -// Close closes a BLOB handle. -// -// It is safe to close a nil, zero or closed Blob. -// -// https://sqlite.org/c3ref/blob_close.html -func (b *Blob) Close() error { - if b == nil || b.handle == 0 { - return nil - } - - rc := res_t(b.c.call("sqlite3_blob_close", stk_t(b.handle))) - b.c.free(b.bufptr) - b.handle = 0 - return b.c.error(rc) -} - -// Size returns the size of the BLOB in bytes. -// -// https://sqlite.org/c3ref/blob_bytes.html -func (b *Blob) Size() int64 { - return b.bytes -} - -// Read implements the [io.Reader] interface. -// -// https://sqlite.org/c3ref/blob_read.html -func (b *Blob) Read(p []byte) (n int, err error) { - if b.offset >= b.bytes { - return 0, io.EOF - } - - want := int64(len(p)) - avail := b.bytes - b.offset - if want > avail { - want = avail - } - if want > b.buflen { - b.bufptr = b.c.realloc(b.bufptr, want) - b.buflen = want - } - - rc := res_t(b.c.call("sqlite3_blob_read", stk_t(b.handle), - stk_t(b.bufptr), stk_t(want), stk_t(b.offset))) - err = b.c.error(rc) - if err != nil { - return 0, err - } - b.offset += want - if b.offset >= b.bytes { - err = io.EOF - } - - copy(p, util.View(b.c.mod, b.bufptr, want)) - return int(want), err -} - -// WriteTo implements the [io.WriterTo] interface. -// -// https://sqlite.org/c3ref/blob_read.html -func (b *Blob) WriteTo(w io.Writer) (n int64, err error) { - if b.offset >= b.bytes { - return 0, nil - } - - want := int64(1024 * 1024) - avail := b.bytes - b.offset - if want > avail { - want = avail - } - if want > b.buflen { - b.bufptr = b.c.realloc(b.bufptr, want) - b.buflen = want - } - - for want > 0 { - rc := res_t(b.c.call("sqlite3_blob_read", stk_t(b.handle), - stk_t(b.bufptr), stk_t(want), stk_t(b.offset))) - err = b.c.error(rc) - if err != nil { - return n, err - } - - mem := util.View(b.c.mod, b.bufptr, want) - m, err := w.Write(mem[:want]) - b.offset += int64(m) - n += int64(m) - if err != nil { - return n, err - } - if int64(m) != want { - // notest // Write misbehaving - return n, io.ErrShortWrite - } - - avail = b.bytes - b.offset - if want > avail { - want = avail - } - } - return n, nil -} - -// Write implements the [io.Writer] interface. -// -// https://sqlite.org/c3ref/blob_write.html -func (b *Blob) Write(p []byte) (n int, err error) { - want := int64(len(p)) - if want > b.buflen { - b.bufptr = b.c.realloc(b.bufptr, want) - b.buflen = want - } - util.WriteBytes(b.c.mod, b.bufptr, p) - - rc := res_t(b.c.call("sqlite3_blob_write", stk_t(b.handle), - stk_t(b.bufptr), stk_t(want), stk_t(b.offset))) - err = b.c.error(rc) - if err != nil { - return 0, err - } - b.offset += int64(len(p)) - return len(p), nil -} - -// ReadFrom implements the [io.ReaderFrom] interface. -// -// https://sqlite.org/c3ref/blob_write.html -func (b *Blob) ReadFrom(r io.Reader) (n int64, err error) { - want := int64(1024 * 1024) - avail := b.bytes - b.offset - if l, ok := r.(*io.LimitedReader); ok && want > l.N { - want = l.N - } - if want > avail { - want = avail - } - if want < 1 { - want = 1 - } - if want > b.buflen { - b.bufptr = b.c.realloc(b.bufptr, want) - b.buflen = want - } - - for { - mem := util.View(b.c.mod, b.bufptr, want) - m, err := r.Read(mem[:want]) - if m > 0 { - rc := res_t(b.c.call("sqlite3_blob_write", stk_t(b.handle), - stk_t(b.bufptr), stk_t(m), stk_t(b.offset))) - err := b.c.error(rc) - if err != nil { - return n, err - } - b.offset += int64(m) - n += int64(m) - } - if err == io.EOF { - return n, nil - } - if err != nil { - return n, err - } - - avail = b.bytes - b.offset - if want > avail { - want = avail - } - if want < 1 { - want = 1 - } - } -} - -// Seek implements the [io.Seeker] interface. -func (b *Blob) Seek(offset int64, whence int) (int64, error) { - switch whence { - default: - return 0, util.WhenceErr - case io.SeekStart: - break - case io.SeekCurrent: - offset += b.offset - case io.SeekEnd: - offset += b.bytes - } - if offset < 0 { - return 0, util.OffsetErr - } - b.offset = offset - return offset, nil -} - -// Reopen moves a BLOB handle to a new row of the same database table. -// -// https://sqlite.org/c3ref/blob_reopen.html -func (b *Blob) Reopen(row int64) error { - b.c.checkInterrupt(b.c.handle) - err := b.c.error(res_t(b.c.call("sqlite3_blob_reopen", stk_t(b.handle), stk_t(row)))) - b.bytes = int64(int32(b.c.call("sqlite3_blob_bytes", stk_t(b.handle)))) - b.offset = 0 - return err -} diff --git a/vendor/github.com/ncruces/go-sqlite3/config.go b/vendor/github.com/ncruces/go-sqlite3/config.go deleted file mode 100644 index 7fff6ead3..000000000 --- a/vendor/github.com/ncruces/go-sqlite3/config.go +++ /dev/null @@ -1,383 +0,0 @@ -package sqlite3 - -import ( - "context" - "fmt" - "strconv" - - "github.com/tetratelabs/wazero/api" - - "github.com/ncruces/go-sqlite3/internal/util" - "github.com/ncruces/go-sqlite3/vfs" -) - -// Config makes configuration changes to a database connection. -// Only boolean configuration options are supported. -// Called with no arg reads the current configuration value, -// called with one arg sets and returns the new value. -// -// https://sqlite.org/c3ref/db_config.html -func (c *Conn) Config(op DBConfig, arg ...bool) (bool, error) { - if op < DBCONFIG_ENABLE_FKEY || op > DBCONFIG_REVERSE_SCANORDER { - return false, MISUSE - } - - // We need to call sqlite3_db_config, a variadic function. - // We only support the `int int*` variants. - // The int is a three-valued bool: -1 queries, 0/1 sets false/true. - // The int* points to where new state will be written to. - // The vararg is a pointer to an array containing these arguments: - // an int and an int* pointing to that int. - - defer c.arena.mark()() - argsPtr := c.arena.new(intlen + ptrlen) - - var flag int32 - switch { - case len(arg) == 0: - flag = -1 - case arg[0]: - flag = 1 - } - - util.Write32(c.mod, argsPtr+0*ptrlen, flag) - util.Write32(c.mod, argsPtr+1*ptrlen, argsPtr) - - rc := res_t(c.call("sqlite3_db_config", stk_t(c.handle), - stk_t(op), stk_t(argsPtr))) - return util.Read32[uint32](c.mod, argsPtr) != 0, c.error(rc) -} - -// ConfigLog sets up the error logging callback for the connection. -// -// https://sqlite.org/errlog.html -func (c *Conn) ConfigLog(cb func(code ExtendedErrorCode, msg string)) error { - var enable int32 - if cb != nil { - enable = 1 - } - rc := res_t(c.call("sqlite3_config_log_go", stk_t(enable))) - if err := c.error(rc); err != nil { - return err - } - c.log = cb - return nil -} - -func logCallback(ctx context.Context, mod api.Module, _ ptr_t, iCode res_t, zMsg ptr_t) { - if c, ok := ctx.Value(connKey{}).(*Conn); ok && c.log != nil { - msg := util.ReadString(mod, zMsg, _MAX_LENGTH) - c.log(xErrorCode(iCode), msg) - } -} - -// Log writes a message into the error log established by [Conn.ConfigLog]. -// -// https://sqlite.org/c3ref/log.html -func (c *Conn) Log(code ExtendedErrorCode, format string, a ...any) { - if c.log != nil { - c.log(code, fmt.Sprintf(format, a...)) - } -} - -// 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()() - ptr := c.arena.new(max(ptrlen, intlen)) - - var schemaPtr ptr_t - if schema != "" { - schemaPtr = c.arena.string(schema) - } - - var rc res_t - var ret any - switch op { - default: - return nil, MISUSE - - case FCNTL_RESET_CACHE: - rc = res_t(c.call("sqlite3_file_control", - stk_t(c.handle), stk_t(schemaPtr), - stk_t(op), 0)) - - case FCNTL_PERSIST_WAL, FCNTL_POWERSAFE_OVERWRITE: - var flag int32 - switch { - case len(arg) == 0: - flag = -1 - case arg[0]: - flag = 1 - } - util.Write32(c.mod, ptr, flag) - rc = res_t(c.call("sqlite3_file_control", - stk_t(c.handle), stk_t(schemaPtr), - stk_t(op), stk_t(ptr))) - ret = util.Read32[uint32](c.mod, ptr) != 0 - - case FCNTL_CHUNK_SIZE: - util.Write32(c.mod, ptr, int32(arg[0].(int))) - rc = res_t(c.call("sqlite3_file_control", - stk_t(c.handle), stk_t(schemaPtr), - stk_t(op), stk_t(ptr))) - - case FCNTL_RESERVE_BYTES: - bytes := -1 - if len(arg) > 0 { - bytes = arg[0].(int) - } - util.Write32(c.mod, ptr, int32(bytes)) - rc = res_t(c.call("sqlite3_file_control", - stk_t(c.handle), stk_t(schemaPtr), - stk_t(op), stk_t(ptr))) - ret = int(util.Read32[int32](c.mod, ptr)) - - case FCNTL_DATA_VERSION: - rc = res_t(c.call("sqlite3_file_control", - stk_t(c.handle), stk_t(schemaPtr), - stk_t(op), stk_t(ptr))) - ret = util.Read32[uint32](c.mod, ptr) - - case FCNTL_LOCKSTATE: - rc = res_t(c.call("sqlite3_file_control", - stk_t(c.handle), stk_t(schemaPtr), - stk_t(op), stk_t(ptr))) - ret = util.Read32[vfs.LockLevel](c.mod, ptr) - - case FCNTL_VFS_POINTER: - rc = res_t(c.call("sqlite3_file_control", - stk_t(c.handle), stk_t(schemaPtr), - stk_t(op), stk_t(ptr))) - if rc == _OK { - const zNameOffset = 16 - ptr = util.Read32[ptr_t](c.mod, ptr) - ptr = util.Read32[ptr_t](c.mod, ptr+zNameOffset) - name := util.ReadString(c.mod, ptr, _MAX_NAME) - ret = vfs.Find(name) - } - - case FCNTL_FILE_POINTER, FCNTL_JOURNAL_POINTER: - rc = res_t(c.call("sqlite3_file_control", - stk_t(c.handle), stk_t(schemaPtr), - stk_t(op), stk_t(ptr))) - if rc == _OK { - const fileHandleOffset = 4 - ptr = util.Read32[ptr_t](c.mod, ptr) - ptr = util.Read32[ptr_t](c.mod, ptr+fileHandleOffset) - ret = util.GetHandle(c.ctx, ptr) - } - } - - if err := c.error(rc); err != nil { - return nil, err - } - return ret, nil -} - -// Limit allows the size of various constructs to be -// limited on a connection by connection basis. -// -// https://sqlite.org/c3ref/limit.html -func (c *Conn) Limit(id LimitCategory, value int) int { - v := int32(c.call("sqlite3_limit", stk_t(c.handle), stk_t(id), stk_t(value))) - return int(v) -} - -// 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, inner string) AuthorizerReturnCode) error { - var enable int32 - if cb != nil { - enable = 1 - } - rc := res_t(c.call("sqlite3_set_authorizer_go", stk_t(c.handle), stk_t(enable))) - if err := c.error(rc); err != nil { - return err - } - c.authorizer = cb - return nil - -} - -func authorizerCallback(ctx context.Context, mod api.Module, pDB ptr_t, action AuthorizerActionCode, zName3rd, zName4th, zSchema, zInner ptr_t) (rc AuthorizerReturnCode) { - if c, ok := ctx.Value(connKey{}).(*Conn); ok && c.handle == pDB && c.authorizer != nil { - var name3rd, name4th, schema, inner string - if zName3rd != 0 { - name3rd = util.ReadString(mod, zName3rd, _MAX_NAME) - } - if zName4th != 0 { - name4th = util.ReadString(mod, zName4th, _MAX_NAME) - } - if zSchema != 0 { - schema = util.ReadString(mod, zSchema, _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 { - rc := res_t(c.call("sqlite3_trace_go", stk_t(c.handle), stk_t(mask))) - if err := c.error(rc); err != nil { - return err - } - c.trace = cb - return nil -} - -func traceCallback(ctx context.Context, mod api.Module, evt TraceEvent, pDB, pArg1, pArg2 ptr_t) (rc res_t) { - 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 = util.Read64[int64](mod, pArg2) - } - break - } - } - } - if arg1 != nil { - _, rc = errorCode(c.trace(evt, arg1, arg2), ERROR) - } - } - return rc -} - -// WALCheckpoint checkpoints a WAL database. -// -// https://sqlite.org/c3ref/wal_checkpoint_v2.html -func (c *Conn) WALCheckpoint(schema string, mode CheckpointMode) (nLog, nCkpt int, err error) { - defer c.arena.mark()() - nLogPtr := c.arena.new(ptrlen) - nCkptPtr := c.arena.new(ptrlen) - schemaPtr := c.arena.string(schema) - rc := res_t(c.call("sqlite3_wal_checkpoint_v2", - stk_t(c.handle), stk_t(schemaPtr), stk_t(mode), - stk_t(nLogPtr), stk_t(nCkptPtr))) - nLog = int(util.Read32[int32](c.mod, nLogPtr)) - nCkpt = int(util.Read32[int32](c.mod, nCkptPtr)) - return nLog, nCkpt, c.error(rc) -} - -// WALAutoCheckpoint configures WAL auto-checkpoints. -// -// https://sqlite.org/c3ref/wal_autocheckpoint.html -func (c *Conn) WALAutoCheckpoint(pages int) error { - rc := res_t(c.call("sqlite3_wal_autocheckpoint", stk_t(c.handle), stk_t(pages))) - return c.error(rc) -} - -// WALHook registers a callback function to be invoked -// each time data is committed to a database in WAL mode. -// -// https://sqlite.org/c3ref/wal_hook.html -func (c *Conn) WALHook(cb func(db *Conn, schema string, pages int) error) { - var enable int32 - if cb != nil { - enable = 1 - } - c.call("sqlite3_wal_hook_go", stk_t(c.handle), stk_t(enable)) - c.wal = cb -} - -func walCallback(ctx context.Context, mod api.Module, _, pDB, zSchema ptr_t, pages int32) (rc res_t) { - if c, ok := ctx.Value(connKey{}).(*Conn); ok && c.handle == pDB && c.wal != nil { - schema := util.ReadString(mod, zSchema, _MAX_NAME) - err := c.wal(c, schema, int(pages)) - _, rc = errorCode(err, ERROR) - } - return rc -} - -// AutoVacuumPages registers a autovacuum compaction amount callback. -// -// https://sqlite.org/c3ref/autovacuum_pages.html -func (c *Conn) AutoVacuumPages(cb func(schema string, dbPages, freePages, bytesPerPage uint) uint) error { - var funcPtr ptr_t - if cb != nil { - funcPtr = util.AddHandle(c.ctx, cb) - } - rc := res_t(c.call("sqlite3_autovacuum_pages_go", stk_t(c.handle), stk_t(funcPtr))) - return c.error(rc) -} - -func autoVacuumCallback(ctx context.Context, mod api.Module, pApp, zSchema ptr_t, nDbPage, nFreePage, nBytePerPage uint32) uint32 { - fn := util.GetHandle(ctx, pApp).(func(schema string, dbPages, freePages, bytesPerPage uint) uint) - schema := util.ReadString(mod, zSchema, _MAX_NAME) - return uint32(fn(schema, uint(nDbPage), uint(nFreePage), uint(nBytePerPage))) -} - -// SoftHeapLimit imposes a soft limit on heap size. -// -// https://sqlite.org/c3ref/hard_heap_limit64.html -func (c *Conn) SoftHeapLimit(n int64) int64 { - return int64(c.call("sqlite3_soft_heap_limit64", stk_t(n))) -} - -// HardHeapLimit imposes a hard limit on heap size. -// -// https://sqlite.org/c3ref/hard_heap_limit64.html -func (c *Conn) HardHeapLimit(n int64) int64 { - return int64(c.call("sqlite3_hard_heap_limit64", stk_t(n))) -} - -// EnableChecksums enables checksums on a database. -// -// https://sqlite.org/cksumvfs.html -func (c *Conn) EnableChecksums(schema string) error { - r, err := c.FileControl(schema, FCNTL_RESERVE_BYTES) - if err != nil { - return err - } - if r == 8 { - // Correct value, enabled. - return nil - } - if r == 0 { - // Default value, enable. - _, err = c.FileControl(schema, FCNTL_RESERVE_BYTES, 8) - if err != nil { - return err - } - r, err = c.FileControl(schema, FCNTL_RESERVE_BYTES) - if err != nil { - return err - } - } - if r != 8 { - // Invalid value. - return util.ErrorString("sqlite3: reserve bytes must be 8, is: " + strconv.Itoa(r.(int))) - } - - // VACUUM the database. - if schema != "" { - err = c.Exec(`VACUUM ` + QuoteIdentifier(schema)) - } else { - err = c.Exec(`VACUUM`) - } - if err != nil { - return err - } - - // Checkpoint the WAL. - _, _, err = c.WALCheckpoint(schema, CHECKPOINT_RESTART) - return err -} diff --git a/vendor/github.com/ncruces/go-sqlite3/conn.go b/vendor/github.com/ncruces/go-sqlite3/conn.go deleted file mode 100644 index fffc7416a..000000000 --- a/vendor/github.com/ncruces/go-sqlite3/conn.go +++ /dev/null @@ -1,512 +0,0 @@ -package sqlite3 - -import ( - "context" - "fmt" - "math" - "math/rand" - "net/url" - "runtime" - "strings" - "time" - - "github.com/tetratelabs/wazero/api" - - "github.com/ncruces/go-sqlite3/internal/util" - "github.com/ncruces/go-sqlite3/vfs" -) - -// Conn is a database connection handle. -// A Conn is not safe for concurrent use by multiple goroutines. -// -// https://sqlite.org/c3ref/sqlite3.html -type Conn struct { - *sqlite - - interrupt context.Context - pending *Stmt - stmts []*Stmt - busy func(context.Context, 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() - - busy1st time.Time - busylst time.Time - arena arena - handle ptr_t -} - -// Open calls [OpenFlags] with [OPEN_READWRITE], [OPEN_CREATE] and [OPEN_URI]. -func Open(filename string) (*Conn, error) { - return newConn(context.Background(), filename, OPEN_READWRITE|OPEN_CREATE|OPEN_URI) -} - -// OpenContext is like [Open] but includes a context, -// which is used to interrupt the process of opening the connectiton. -func OpenContext(ctx context.Context, filename string) (*Conn, error) { - return newConn(ctx, filename, OPEN_READWRITE|OPEN_CREATE|OPEN_URI) -} - -// OpenFlags opens an SQLite database file as specified by the filename argument. -// -// If none of the required flags are used, a combination of [OPEN_READWRITE] and [OPEN_CREATE] is used. -// If a URI filename is used, PRAGMA statements to execute can be specified using "_pragma": -// -// sqlite3.Open("file:demo.db?_pragma=busy_timeout(10000)") -// -// https://sqlite.org/c3ref/open.html -func OpenFlags(filename string, flags OpenFlag) (*Conn, error) { - if flags&(OPEN_READONLY|OPEN_READWRITE|OPEN_CREATE) == 0 { - flags |= OPEN_READWRITE | OPEN_CREATE - } - return newConn(context.Background(), filename, flags) -} - -type connKey = util.ConnKey - -func newConn(ctx context.Context, filename string, flags OpenFlag) (ret *Conn, _ error) { - err := ctx.Err() - if err != nil { - return nil, err - } - - c := &Conn{interrupt: ctx} - c.sqlite, err = instantiateSQLite() - if err != nil { - return nil, err - } - defer func() { - if ret == nil { - c.Close() - c.sqlite.close() - } else { - c.interrupt = context.Background() - } - }() - - c.ctx = context.WithValue(c.ctx, connKey{}, c) - c.arena = c.newArena() - c.handle, err = c.openDB(filename, flags) - if err == nil { - err = initExtensions(c) - } - if err != nil { - return nil, err - } - return c, nil -} - -func (c *Conn) openDB(filename string, flags OpenFlag) (ptr_t, error) { - defer c.arena.mark()() - connPtr := c.arena.new(ptrlen) - namePtr := c.arena.string(filename) - - flags |= OPEN_EXRESCODE - rc := res_t(c.call("sqlite3_open_v2", stk_t(namePtr), stk_t(connPtr), stk_t(flags), 0)) - - handle := util.Read32[ptr_t](c.mod, connPtr) - if err := c.sqlite.error(rc, handle); err != nil { - c.closeDB(handle) - return 0, err - } - - c.call("sqlite3_progress_handler_go", stk_t(handle), 100) - if flags|OPEN_URI != 0 && strings.HasPrefix(filename, "file:") { - var pragmas strings.Builder - if _, after, ok := strings.Cut(filename, "?"); ok { - query, _ := url.ParseQuery(after) - for _, p := range query["_pragma"] { - pragmas.WriteString(`PRAGMA `) - pragmas.WriteString(p) - pragmas.WriteString(`;`) - } - } - if pragmas.Len() != 0 { - c.checkInterrupt(handle) - pragmaPtr := c.arena.string(pragmas.String()) - rc := res_t(c.call("sqlite3_exec", stk_t(handle), stk_t(pragmaPtr), 0, 0, 0)) - if err := c.sqlite.error(rc, handle, pragmas.String()); err != nil { - err = fmt.Errorf("sqlite3: invalid _pragma: %w", err) - c.closeDB(handle) - return 0, err - } - } - } - return handle, nil -} - -func (c *Conn) closeDB(handle ptr_t) { - rc := res_t(c.call("sqlite3_close_v2", stk_t(handle))) - if err := c.sqlite.error(rc, handle); err != nil { - panic(err) - } -} - -// Close closes the database connection. -// -// If the database connection is associated with unfinalized prepared statements, -// open blob handles, and/or unfinished backup objects, -// Close will leave the database connection open and return [BUSY]. -// -// It is safe to close a nil, zero or closed Conn. -// -// https://sqlite.org/c3ref/close.html -func (c *Conn) Close() error { - if c == nil || c.handle == 0 { - return nil - } - - c.pending.Close() - c.pending = nil - - rc := res_t(c.call("sqlite3_close", stk_t(c.handle))) - if err := c.error(rc); err != nil { - return err - } - - c.handle = 0 - return c.close() -} - -// Exec is a convenience function that allows an application to run -// multiple statements of SQL without having to use a lot of code. -// -// https://sqlite.org/c3ref/exec.html -func (c *Conn) Exec(sql string) error { - defer c.arena.mark()() - sqlPtr := c.arena.string(sql) - - c.checkInterrupt(c.handle) - rc := res_t(c.call("sqlite3_exec", stk_t(c.handle), stk_t(sqlPtr), 0, 0, 0)) - return c.error(rc, sql) -} - -// Prepare calls [Conn.PrepareFlags] with no flags. -func (c *Conn) Prepare(sql string) (stmt *Stmt, tail string, err error) { - return c.PrepareFlags(sql, 0) -} - -// PrepareFlags compiles the first SQL statement in sql; -// tail is left pointing to what remains uncompiled. -// If the input text contains no SQL (if the input is an empty string or a comment), -// both stmt and err will be nil. -// -// https://sqlite.org/c3ref/prepare.html -func (c *Conn) PrepareFlags(sql string, flags PrepareFlag) (stmt *Stmt, tail string, err error) { - if len(sql) > _MAX_SQL_LENGTH { - return nil, "", TOOBIG - } - - defer c.arena.mark()() - stmtPtr := c.arena.new(ptrlen) - tailPtr := c.arena.new(ptrlen) - sqlPtr := c.arena.string(sql) - - c.checkInterrupt(c.handle) - rc := res_t(c.call("sqlite3_prepare_v3", stk_t(c.handle), - stk_t(sqlPtr), stk_t(len(sql)+1), stk_t(flags), - stk_t(stmtPtr), stk_t(tailPtr))) - - stmt = &Stmt{c: c} - stmt.handle = util.Read32[ptr_t](c.mod, stmtPtr) - if sql := sql[util.Read32[ptr_t](c.mod, tailPtr)-sqlPtr:]; sql != "" { - tail = sql - } - - if err := c.error(rc, sql); err != nil { - return nil, "", err - } - if stmt.handle == 0 { - return nil, "", nil - } - c.stmts = append(c.stmts, stmt) - return stmt, tail, nil -} - -// DBName returns the schema name for n-th database on the database connection. -// -// https://sqlite.org/c3ref/db_name.html -func (c *Conn) DBName(n int) string { - ptr := ptr_t(c.call("sqlite3_db_name", stk_t(c.handle), stk_t(n))) - if ptr == 0 { - return "" - } - return util.ReadString(c.mod, ptr, _MAX_NAME) -} - -// Filename returns the filename for a database. -// -// https://sqlite.org/c3ref/db_filename.html -func (c *Conn) Filename(schema string) *vfs.Filename { - var ptr ptr_t - if schema != "" { - defer c.arena.mark()() - ptr = c.arena.string(schema) - } - ptr = ptr_t(c.call("sqlite3_db_filename", stk_t(c.handle), stk_t(ptr))) - return vfs.GetFilename(c.ctx, c.mod, ptr, vfs.OPEN_MAIN_DB) -} - -// ReadOnly determines if a database is read-only. -// -// https://sqlite.org/c3ref/db_readonly.html -func (c *Conn) ReadOnly(schema string) (ro bool, ok bool) { - var ptr ptr_t - if schema != "" { - defer c.arena.mark()() - ptr = c.arena.string(schema) - } - b := int32(c.call("sqlite3_db_readonly", stk_t(c.handle), stk_t(ptr))) - return b > 0, b < 0 -} - -// GetAutocommit tests the connection for auto-commit mode. -// -// https://sqlite.org/c3ref/get_autocommit.html -func (c *Conn) GetAutocommit() bool { - b := int32(c.call("sqlite3_get_autocommit", stk_t(c.handle))) - return b != 0 -} - -// LastInsertRowID returns the rowid of the most recent successful INSERT -// on the database connection. -// -// https://sqlite.org/c3ref/last_insert_rowid.html -func (c *Conn) LastInsertRowID() int64 { - return int64(c.call("sqlite3_last_insert_rowid", stk_t(c.handle))) -} - -// SetLastInsertRowID allows the application to set the value returned by -// [Conn.LastInsertRowID]. -// -// https://sqlite.org/c3ref/set_last_insert_rowid.html -func (c *Conn) SetLastInsertRowID(id int64) { - c.call("sqlite3_set_last_insert_rowid", stk_t(c.handle), stk_t(id)) -} - -// Changes returns the number of rows modified, inserted or deleted -// by the most recently completed INSERT, UPDATE or DELETE statement -// on the database connection. -// -// https://sqlite.org/c3ref/changes.html -func (c *Conn) Changes() int64 { - return int64(c.call("sqlite3_changes64", stk_t(c.handle))) -} - -// TotalChanges returns the number of rows modified, inserted or deleted -// by all INSERT, UPDATE or DELETE statements completed -// since the database connection was opened. -// -// https://sqlite.org/c3ref/total_changes.html -func (c *Conn) TotalChanges() int64 { - return int64(c.call("sqlite3_total_changes64", stk_t(c.handle))) -} - -// ReleaseMemory frees memory used by a database connection. -// -// https://sqlite.org/c3ref/db_release_memory.html -func (c *Conn) ReleaseMemory() error { - rc := res_t(c.call("sqlite3_db_release_memory", stk_t(c.handle))) - return c.error(rc) -} - -// GetInterrupt gets the context set with [Conn.SetInterrupt]. -func (c *Conn) GetInterrupt() context.Context { - return c.interrupt -} - -// SetInterrupt interrupts a long-running query when a context is done. -// -// Subsequent uses of the connection will return [INTERRUPT] -// until the context is reset by another call to SetInterrupt. -// -// To associate a timeout with a connection: -// -// ctx, cancel := context.WithTimeout(context.TODO(), 100*time.Millisecond) -// conn.SetInterrupt(ctx) -// defer cancel() -// -// SetInterrupt returns the old context assigned to the connection. -// -// https://sqlite.org/c3ref/interrupt.html -func (c *Conn) SetInterrupt(ctx context.Context) (old context.Context) { - old = c.interrupt - c.interrupt = ctx - - if ctx == old || ctx.Done() == old.Done() { - return old - } - - // A busy SQL statement prevents SQLite from ignoring an interrupt - // that comes before any other statements are started. - if c.pending == nil { - 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", stk_t(c.handle), stk_t(loopPtr), math.MaxUint64, - stk_t(PREPARE_PERSISTENT), stk_t(stmtPtr), 0) - c.pending = &Stmt{c: c} - c.pending.handle = util.Read32[ptr_t](c.mod, stmtPtr) - } - - if old.Done() != nil && ctx.Err() == nil { - c.pending.Reset() - } - if ctx.Done() != nil { - c.pending.Step() - } - return old -} - -func (c *Conn) checkInterrupt(handle ptr_t) { - if c.interrupt.Err() != nil { - c.call("sqlite3_interrupt", stk_t(handle)) - } -} - -func progressCallback(ctx context.Context, mod api.Module, _ ptr_t) (interrupt int32) { - if c, ok := ctx.Value(connKey{}).(*Conn); ok { - if c.interrupt.Done() != nil { - runtime.Gosched() - } - if c.interrupt.Err() != nil { - interrupt = 1 - } - } - return interrupt -} - -// BusyTimeout sets a busy timeout. -// -// https://sqlite.org/c3ref/busy_timeout.html -func (c *Conn) BusyTimeout(timeout time.Duration) error { - ms := min((timeout+time.Millisecond-1)/time.Millisecond, math.MaxInt32) - rc := res_t(c.call("sqlite3_busy_timeout", stk_t(c.handle), stk_t(ms))) - return c.error(rc) -} - -func timeoutCallback(ctx context.Context, mod api.Module, count, tmout int32) (retry int32) { - // https://fractaledmind.github.io/2024/04/15/sqlite-on-rails-the-how-and-why-of-optimal-performance/ - if c, ok := ctx.Value(connKey{}).(*Conn); ok && c.interrupt.Err() == nil { - switch { - case count == 0: - c.busy1st = time.Now() - case time.Since(c.busy1st) >= time.Duration(tmout)*time.Millisecond: - return 0 - } - if time.Since(c.busylst) < time.Millisecond { - const sleepIncrement = 2*1024*1024 - 1 // power of two, ~2ms - time.Sleep(time.Duration(rand.Int63() & sleepIncrement)) - } - c.busylst = time.Now() - return 1 - } - return 0 -} - -// BusyHandler registers a callback to handle [BUSY] errors. -// -// https://sqlite.org/c3ref/busy_handler.html -func (c *Conn) BusyHandler(cb func(ctx context.Context, count int) (retry bool)) error { - var enable int32 - if cb != nil { - enable = 1 - } - rc := res_t(c.call("sqlite3_busy_handler_go", stk_t(c.handle), stk_t(enable))) - if err := c.error(rc); err != nil { - return err - } - c.busy = cb - return nil -} - -func busyCallback(ctx context.Context, mod api.Module, pDB ptr_t, count int32) (retry int32) { - if c, ok := ctx.Value(connKey{}).(*Conn); ok && c.handle == pDB && c.busy != nil { - interrupt := c.interrupt - if interrupt == nil { - interrupt = context.Background() - } - if interrupt.Err() == nil && c.busy(interrupt, int(count)) { - retry = 1 - } - } - 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(intlen) - curPtr := c.arena.new(intlen) - - var i int32 - if reset { - i = 1 - } - - rc := res_t(c.call("sqlite3_db_status", stk_t(c.handle), - stk_t(op), stk_t(curPtr), stk_t(hiPtr), stk_t(i))) - if err = c.error(rc); err == nil { - current = int(util.Read32[int32](c.mod, curPtr)) - highwater = int(util.Read32[int32](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 ptr_t - declTypePtr := c.arena.new(ptrlen) - collSeqPtr := c.arena.new(ptrlen) - notNullPtr := c.arena.new(ptrlen) - autoIncPtr := c.arena.new(ptrlen) - primaryKeyPtr := c.arena.new(ptrlen) - if schema != "" { - schemaPtr = c.arena.string(schema) - } - tablePtr := c.arena.string(table) - if column != "" { - columnPtr = c.arena.string(column) - } - - rc := res_t(c.call("sqlite3_table_column_metadata", stk_t(c.handle), - stk_t(schemaPtr), stk_t(tablePtr), stk_t(columnPtr), - stk_t(declTypePtr), stk_t(collSeqPtr), - stk_t(notNullPtr), stk_t(primaryKeyPtr), stk_t(autoIncPtr))) - if err = c.error(rc); err == nil && column != "" { - if ptr := util.Read32[ptr_t](c.mod, declTypePtr); ptr != 0 { - declType = util.ReadString(c.mod, ptr, _MAX_NAME) - } - if ptr := util.Read32[ptr_t](c.mod, collSeqPtr); ptr != 0 { - collSeq = util.ReadString(c.mod, ptr, _MAX_NAME) - } - notNull = util.Read32[uint32](c.mod, notNullPtr) != 0 - autoInc = util.Read32[uint32](c.mod, autoIncPtr) != 0 - primaryKey = util.Read32[uint32](c.mod, primaryKeyPtr) != 0 - } - return -} - -func (c *Conn) error(rc res_t, 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 - } - } -} diff --git a/vendor/github.com/ncruces/go-sqlite3/conn_iter.go b/vendor/github.com/ncruces/go-sqlite3/conn_iter.go deleted file mode 100644 index 470f0ade2..000000000 --- a/vendor/github.com/ncruces/go-sqlite3/conn_iter.go +++ /dev/null @@ -1,11 +0,0 @@ -//go:build go1.23 - -package sqlite3 - -import "iter" - -// Stmts returns an iterator for the prepared statements -// associated with the database connection. -// -// https://sqlite.org/c3ref/next_stmt.html -func (c *Conn) Stmts() iter.Seq[*Stmt] { return c.stmtsIter } diff --git a/vendor/github.com/ncruces/go-sqlite3/conn_old.go b/vendor/github.com/ncruces/go-sqlite3/conn_old.go deleted file mode 100644 index 4663fa04d..000000000 --- a/vendor/github.com/ncruces/go-sqlite3/conn_old.go +++ /dev/null @@ -1,9 +0,0 @@ -//go:build !go1.23 - -package sqlite3 - -// Stmts returns an iterator for the prepared statements -// associated with the database connection. -// -// https://sqlite.org/c3ref/next_stmt.html -func (c *Conn) Stmts() func(func(*Stmt) bool) { return c.stmtsIter } diff --git a/vendor/github.com/ncruces/go-sqlite3/const.go b/vendor/github.com/ncruces/go-sqlite3/const.go deleted file mode 100644 index 086902a6c..000000000 --- a/vendor/github.com/ncruces/go-sqlite3/const.go +++ /dev/null @@ -1,423 +0,0 @@ -package sqlite3 - -import ( - "strconv" - - "github.com/ncruces/go-sqlite3/internal/util" -) - -const ( - _OK = 0 /* Successful result */ - _ROW = 100 /* sqlite3_step() has another row ready */ - _DONE = 101 /* sqlite3_step() has finished executing */ - - _MAX_NAME = 1e6 // Self-imposed limit for most NUL terminated strings. - _MAX_LENGTH = 1e9 - _MAX_SQL_LENGTH = 1e9 - _MAX_FUNCTION_ARG = 100 - - ptrlen = util.PtrLen - intlen = util.IntLen -) - -type ( - stk_t = util.Stk_t - ptr_t = util.Ptr_t - res_t = util.Res_t -) - -// ErrorCode is a result code that [Error.Code] might return. -// -// https://sqlite.org/rescode.html -type ErrorCode uint8 - -const ( - ERROR ErrorCode = 1 /* Generic error */ - INTERNAL ErrorCode = 2 /* Internal logic error in SQLite */ - PERM ErrorCode = 3 /* Access permission denied */ - ABORT ErrorCode = 4 /* Callback routine requested an abort */ - BUSY ErrorCode = 5 /* The database file is locked */ - LOCKED ErrorCode = 6 /* A table in the database is locked */ - NOMEM ErrorCode = 7 /* A malloc() failed */ - READONLY ErrorCode = 8 /* Attempt to write a readonly database */ - INTERRUPT ErrorCode = 9 /* Operation terminated by sqlite3_interrupt() */ - IOERR ErrorCode = 10 /* Some kind of disk I/O error occurred */ - CORRUPT ErrorCode = 11 /* The database disk image is malformed */ - NOTFOUND ErrorCode = 12 /* Unknown opcode in sqlite3_file_control() */ - FULL ErrorCode = 13 /* Insertion failed because database is full */ - CANTOPEN ErrorCode = 14 /* Unable to open the database file */ - PROTOCOL ErrorCode = 15 /* Database lock protocol error */ - EMPTY ErrorCode = 16 /* Internal use only */ - SCHEMA ErrorCode = 17 /* The database schema changed */ - TOOBIG ErrorCode = 18 /* String or BLOB exceeds size limit */ - CONSTRAINT ErrorCode = 19 /* Abort due to constraint violation */ - MISMATCH ErrorCode = 20 /* Data type mismatch */ - MISUSE ErrorCode = 21 /* Library used incorrectly */ - NOLFS ErrorCode = 22 /* Uses OS features not supported on host */ - AUTH ErrorCode = 23 /* Authorization denied */ - FORMAT ErrorCode = 24 /* Not used */ - RANGE ErrorCode = 25 /* 2nd parameter to sqlite3_bind out of range */ - NOTADB ErrorCode = 26 /* File opened that is not a database file */ - NOTICE ErrorCode = 27 /* Notifications from sqlite3_log() */ - WARNING ErrorCode = 28 /* Warnings from sqlite3_log() */ -) - -// ExtendedErrorCode is a result code that [Error.ExtendedCode] might return. -// -// https://sqlite.org/rescode.html -type ( - ExtendedErrorCode uint16 - xErrorCode = ExtendedErrorCode -) - -const ( - ERROR_MISSING_COLLSEQ ExtendedErrorCode = xErrorCode(ERROR) | (1 << 8) - ERROR_RETRY ExtendedErrorCode = xErrorCode(ERROR) | (2 << 8) - ERROR_SNAPSHOT ExtendedErrorCode = xErrorCode(ERROR) | (3 << 8) - IOERR_READ ExtendedErrorCode = xErrorCode(IOERR) | (1 << 8) - IOERR_SHORT_READ ExtendedErrorCode = xErrorCode(IOERR) | (2 << 8) - IOERR_WRITE ExtendedErrorCode = xErrorCode(IOERR) | (3 << 8) - IOERR_FSYNC ExtendedErrorCode = xErrorCode(IOERR) | (4 << 8) - IOERR_DIR_FSYNC ExtendedErrorCode = xErrorCode(IOERR) | (5 << 8) - IOERR_TRUNCATE ExtendedErrorCode = xErrorCode(IOERR) | (6 << 8) - IOERR_FSTAT ExtendedErrorCode = xErrorCode(IOERR) | (7 << 8) - IOERR_UNLOCK ExtendedErrorCode = xErrorCode(IOERR) | (8 << 8) - IOERR_RDLOCK ExtendedErrorCode = xErrorCode(IOERR) | (9 << 8) - IOERR_DELETE ExtendedErrorCode = xErrorCode(IOERR) | (10 << 8) - IOERR_BLOCKED ExtendedErrorCode = xErrorCode(IOERR) | (11 << 8) - IOERR_NOMEM ExtendedErrorCode = xErrorCode(IOERR) | (12 << 8) - IOERR_ACCESS ExtendedErrorCode = xErrorCode(IOERR) | (13 << 8) - IOERR_CHECKRESERVEDLOCK ExtendedErrorCode = xErrorCode(IOERR) | (14 << 8) - IOERR_LOCK ExtendedErrorCode = xErrorCode(IOERR) | (15 << 8) - IOERR_CLOSE ExtendedErrorCode = xErrorCode(IOERR) | (16 << 8) - IOERR_DIR_CLOSE ExtendedErrorCode = xErrorCode(IOERR) | (17 << 8) - IOERR_SHMOPEN ExtendedErrorCode = xErrorCode(IOERR) | (18 << 8) - IOERR_SHMSIZE ExtendedErrorCode = xErrorCode(IOERR) | (19 << 8) - IOERR_SHMLOCK ExtendedErrorCode = xErrorCode(IOERR) | (20 << 8) - IOERR_SHMMAP ExtendedErrorCode = xErrorCode(IOERR) | (21 << 8) - IOERR_SEEK ExtendedErrorCode = xErrorCode(IOERR) | (22 << 8) - IOERR_DELETE_NOENT ExtendedErrorCode = xErrorCode(IOERR) | (23 << 8) - IOERR_MMAP ExtendedErrorCode = xErrorCode(IOERR) | (24 << 8) - IOERR_GETTEMPPATH ExtendedErrorCode = xErrorCode(IOERR) | (25 << 8) - IOERR_CONVPATH ExtendedErrorCode = xErrorCode(IOERR) | (26 << 8) - IOERR_VNODE ExtendedErrorCode = xErrorCode(IOERR) | (27 << 8) - IOERR_AUTH ExtendedErrorCode = xErrorCode(IOERR) | (28 << 8) - IOERR_BEGIN_ATOMIC ExtendedErrorCode = xErrorCode(IOERR) | (29 << 8) - IOERR_COMMIT_ATOMIC ExtendedErrorCode = xErrorCode(IOERR) | (30 << 8) - IOERR_ROLLBACK_ATOMIC ExtendedErrorCode = xErrorCode(IOERR) | (31 << 8) - IOERR_DATA ExtendedErrorCode = xErrorCode(IOERR) | (32 << 8) - IOERR_CORRUPTFS ExtendedErrorCode = xErrorCode(IOERR) | (33 << 8) - IOERR_IN_PAGE ExtendedErrorCode = xErrorCode(IOERR) | (34 << 8) - LOCKED_SHAREDCACHE ExtendedErrorCode = xErrorCode(LOCKED) | (1 << 8) - LOCKED_VTAB ExtendedErrorCode = xErrorCode(LOCKED) | (2 << 8) - BUSY_RECOVERY ExtendedErrorCode = xErrorCode(BUSY) | (1 << 8) - BUSY_SNAPSHOT ExtendedErrorCode = xErrorCode(BUSY) | (2 << 8) - BUSY_TIMEOUT ExtendedErrorCode = xErrorCode(BUSY) | (3 << 8) - CANTOPEN_NOTEMPDIR ExtendedErrorCode = xErrorCode(CANTOPEN) | (1 << 8) - 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_SYMLINK ExtendedErrorCode = xErrorCode(CANTOPEN) | (6 << 8) - CORRUPT_VTAB ExtendedErrorCode = xErrorCode(CORRUPT) | (1 << 8) - CORRUPT_SEQUENCE ExtendedErrorCode = xErrorCode(CORRUPT) | (2 << 8) - CORRUPT_INDEX ExtendedErrorCode = xErrorCode(CORRUPT) | (3 << 8) - READONLY_RECOVERY ExtendedErrorCode = xErrorCode(READONLY) | (1 << 8) - READONLY_CANTLOCK ExtendedErrorCode = xErrorCode(READONLY) | (2 << 8) - READONLY_ROLLBACK ExtendedErrorCode = xErrorCode(READONLY) | (3 << 8) - READONLY_DBMOVED ExtendedErrorCode = xErrorCode(READONLY) | (4 << 8) - READONLY_CANTINIT ExtendedErrorCode = xErrorCode(READONLY) | (5 << 8) - READONLY_DIRECTORY ExtendedErrorCode = xErrorCode(READONLY) | (6 << 8) - ABORT_ROLLBACK ExtendedErrorCode = xErrorCode(ABORT) | (2 << 8) - CONSTRAINT_CHECK ExtendedErrorCode = xErrorCode(CONSTRAINT) | (1 << 8) - CONSTRAINT_COMMITHOOK ExtendedErrorCode = xErrorCode(CONSTRAINT) | (2 << 8) - CONSTRAINT_FOREIGNKEY ExtendedErrorCode = xErrorCode(CONSTRAINT) | (3 << 8) - CONSTRAINT_FUNCTION ExtendedErrorCode = xErrorCode(CONSTRAINT) | (4 << 8) - CONSTRAINT_NOTNULL ExtendedErrorCode = xErrorCode(CONSTRAINT) | (5 << 8) - CONSTRAINT_PRIMARYKEY ExtendedErrorCode = xErrorCode(CONSTRAINT) | (6 << 8) - CONSTRAINT_TRIGGER ExtendedErrorCode = xErrorCode(CONSTRAINT) | (7 << 8) - CONSTRAINT_UNIQUE ExtendedErrorCode = xErrorCode(CONSTRAINT) | (8 << 8) - CONSTRAINT_VTAB ExtendedErrorCode = xErrorCode(CONSTRAINT) | (9 << 8) - CONSTRAINT_ROWID ExtendedErrorCode = xErrorCode(CONSTRAINT) | (10 << 8) - CONSTRAINT_PINNED ExtendedErrorCode = xErrorCode(CONSTRAINT) | (11 << 8) - CONSTRAINT_DATATYPE ExtendedErrorCode = xErrorCode(CONSTRAINT) | (12 << 8) - NOTICE_RECOVER_WAL ExtendedErrorCode = xErrorCode(NOTICE) | (1 << 8) - NOTICE_RECOVER_ROLLBACK ExtendedErrorCode = xErrorCode(NOTICE) | (2 << 8) - NOTICE_RBU ExtendedErrorCode = xErrorCode(NOTICE) | (3 << 8) - WARNING_AUTOINDEX ExtendedErrorCode = xErrorCode(WARNING) | (1 << 8) - AUTH_USER ExtendedErrorCode = xErrorCode(AUTH) | (1 << 8) -) - -// OpenFlag is a flag for the [OpenFlags] function. -// -// https://sqlite.org/c3ref/c_open_autoproxy.html -type OpenFlag uint32 - -const ( - OPEN_READONLY OpenFlag = 0x00000001 /* Ok for sqlite3_open_v2() */ - OPEN_READWRITE OpenFlag = 0x00000002 /* Ok for sqlite3_open_v2() */ - OPEN_CREATE OpenFlag = 0x00000004 /* Ok for sqlite3_open_v2() */ - OPEN_URI OpenFlag = 0x00000040 /* Ok for sqlite3_open_v2() */ - OPEN_MEMORY OpenFlag = 0x00000080 /* Ok for sqlite3_open_v2() */ - OPEN_NOMUTEX OpenFlag = 0x00008000 /* Ok for sqlite3_open_v2() */ - OPEN_FULLMUTEX OpenFlag = 0x00010000 /* Ok for sqlite3_open_v2() */ - OPEN_SHAREDCACHE OpenFlag = 0x00020000 /* Ok for sqlite3_open_v2() */ - OPEN_PRIVATECACHE OpenFlag = 0x00040000 /* Ok for sqlite3_open_v2() */ - OPEN_NOFOLLOW OpenFlag = 0x01000000 /* Ok for sqlite3_open_v2() */ - OPEN_EXRESCODE OpenFlag = 0x02000000 /* Extended result codes */ -) - -// PrepareFlag is a flag that can be passed to [Conn.PrepareFlags]. -// -// https://sqlite.org/c3ref/c_prepare_normalize.html -type PrepareFlag uint32 - -const ( - PREPARE_PERSISTENT PrepareFlag = 0x01 - PREPARE_NORMALIZE PrepareFlag = 0x02 - PREPARE_NO_VTAB PrepareFlag = 0x04 - PREPARE_DONT_LOG PrepareFlag = 0x10 -) - -// FunctionFlag is a flag that can be passed to -// [Conn.CreateFunction] and [Conn.CreateWindowFunction]. -// -// https://sqlite.org/c3ref/c_deterministic.html -type FunctionFlag uint32 - -const ( - DETERMINISTIC FunctionFlag = 0x000000800 - DIRECTONLY FunctionFlag = 0x000080000 - INNOCUOUS FunctionFlag = 0x000200000 - SELFORDER1 FunctionFlag = 0x002000000 - // SUBTYPE FunctionFlag = 0x000100000 - // RESULT_SUBTYPE FunctionFlag = 0x001000000 -) - -// StmtStatus name counter values associated with the [Stmt.Status] method. -// -// https://sqlite.org/c3ref/c_stmtstatus_counter.html -type StmtStatus uint32 - -const ( - STMTSTATUS_FULLSCAN_STEP StmtStatus = 1 - STMTSTATUS_SORT StmtStatus = 2 - STMTSTATUS_AUTOINDEX StmtStatus = 3 - STMTSTATUS_VM_STEP StmtStatus = 4 - STMTSTATUS_REPREPARE StmtStatus = 5 - STMTSTATUS_RUN StmtStatus = 6 - STMTSTATUS_FILTER_MISS StmtStatus = 7 - STMTSTATUS_FILTER_HIT StmtStatus = 8 - 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 - // DBSTATUS_MAX DBStatus = 12 -) - -// DBConfig are the available database connection configuration options. -// -// https://sqlite.org/c3ref/c_dbconfig_defensive.html -type DBConfig uint32 - -const ( - // DBCONFIG_MAINDBNAME DBConfig = 1000 - // DBCONFIG_LOOKASIDE DBConfig = 1001 - DBCONFIG_ENABLE_FKEY DBConfig = 1002 - DBCONFIG_ENABLE_TRIGGER DBConfig = 1003 - DBCONFIG_ENABLE_FTS3_TOKENIZER DBConfig = 1004 - DBCONFIG_ENABLE_LOAD_EXTENSION DBConfig = 1005 - DBCONFIG_NO_CKPT_ON_CLOSE DBConfig = 1006 - DBCONFIG_ENABLE_QPSG DBConfig = 1007 - DBCONFIG_TRIGGER_EQP DBConfig = 1008 - DBCONFIG_RESET_DATABASE DBConfig = 1009 - DBCONFIG_DEFENSIVE DBConfig = 1010 - DBCONFIG_WRITABLE_SCHEMA DBConfig = 1011 - DBCONFIG_LEGACY_ALTER_TABLE DBConfig = 1012 - DBCONFIG_DQS_DML DBConfig = 1013 - DBCONFIG_DQS_DDL DBConfig = 1014 - DBCONFIG_ENABLE_VIEW DBConfig = 1015 - DBCONFIG_LEGACY_FILE_FORMAT DBConfig = 1016 - DBCONFIG_TRUSTED_SCHEMA DBConfig = 1017 - DBCONFIG_STMT_SCANSTATUS DBConfig = 1018 - DBCONFIG_REVERSE_SCANORDER DBConfig = 1019 - // DBCONFIG_MAX 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 -type LimitCategory uint32 - -const ( - LIMIT_LENGTH LimitCategory = 0 - LIMIT_SQL_LENGTH LimitCategory = 1 - LIMIT_COLUMN LimitCategory = 2 - LIMIT_EXPR_DEPTH LimitCategory = 3 - LIMIT_COMPOUND_SELECT LimitCategory = 4 - LIMIT_VDBE_OP LimitCategory = 5 - LIMIT_FUNCTION_ARG LimitCategory = 6 - LIMIT_ATTACHED LimitCategory = 7 - LIMIT_LIKE_PATTERN_LENGTH LimitCategory = 8 - LIMIT_VARIABLE_NUMBER LimitCategory = 9 - LIMIT_TRIGGER_DEPTH LimitCategory = 10 - LIMIT_WORKER_THREADS LimitCategory = 11 -) - -// AuthorizerActionCode are the integer action codes -// that the authorizer callback may be passed. -// -// https://sqlite.org/c3ref/c_alter_table.html -type AuthorizerActionCode uint32 - -const ( - /***************************************************** 3rd ************ 4th ***********/ - AUTH_CREATE_INDEX AuthorizerActionCode = 1 /* Index Name Table Name */ - AUTH_CREATE_TABLE AuthorizerActionCode = 2 /* Table Name NULL */ - AUTH_CREATE_TEMP_INDEX AuthorizerActionCode = 3 /* Index Name Table Name */ - AUTH_CREATE_TEMP_TABLE AuthorizerActionCode = 4 /* Table Name NULL */ - AUTH_CREATE_TEMP_TRIGGER AuthorizerActionCode = 5 /* Trigger Name Table Name */ - AUTH_CREATE_TEMP_VIEW AuthorizerActionCode = 6 /* View Name NULL */ - AUTH_CREATE_TRIGGER AuthorizerActionCode = 7 /* Trigger Name Table Name */ - AUTH_CREATE_VIEW AuthorizerActionCode = 8 /* View Name NULL */ - AUTH_DELETE AuthorizerActionCode = 9 /* Table Name NULL */ - AUTH_DROP_INDEX AuthorizerActionCode = 10 /* Index Name Table Name */ - AUTH_DROP_TABLE AuthorizerActionCode = 11 /* Table Name NULL */ - AUTH_DROP_TEMP_INDEX AuthorizerActionCode = 12 /* Index Name Table Name */ - AUTH_DROP_TEMP_TABLE AuthorizerActionCode = 13 /* Table Name NULL */ - AUTH_DROP_TEMP_TRIGGER AuthorizerActionCode = 14 /* Trigger Name Table Name */ - AUTH_DROP_TEMP_VIEW AuthorizerActionCode = 15 /* View Name NULL */ - AUTH_DROP_TRIGGER AuthorizerActionCode = 16 /* Trigger Name Table Name */ - AUTH_DROP_VIEW AuthorizerActionCode = 17 /* View Name NULL */ - AUTH_INSERT AuthorizerActionCode = 18 /* Table Name NULL */ - AUTH_PRAGMA AuthorizerActionCode = 19 /* Pragma Name 1st arg or NULL */ - AUTH_READ AuthorizerActionCode = 20 /* Table Name Column Name */ - AUTH_SELECT AuthorizerActionCode = 21 /* NULL NULL */ - AUTH_TRANSACTION AuthorizerActionCode = 22 /* Operation NULL */ - AUTH_UPDATE AuthorizerActionCode = 23 /* Table Name Column Name */ - AUTH_ATTACH AuthorizerActionCode = 24 /* Filename NULL */ - AUTH_DETACH AuthorizerActionCode = 25 /* Database Name NULL */ - AUTH_ALTER_TABLE AuthorizerActionCode = 26 /* Database Name Table Name */ - AUTH_REINDEX AuthorizerActionCode = 27 /* Index Name NULL */ - AUTH_ANALYZE AuthorizerActionCode = 28 /* Table Name NULL */ - AUTH_CREATE_VTABLE AuthorizerActionCode = 29 /* Table Name Module Name */ - AUTH_DROP_VTABLE AuthorizerActionCode = 30 /* Table Name Module Name */ - AUTH_FUNCTION AuthorizerActionCode = 31 /* NULL Function Name */ - AUTH_SAVEPOINT AuthorizerActionCode = 32 /* Operation Savepoint Name */ - AUTH_RECURSIVE AuthorizerActionCode = 33 /* NULL NULL */ - // AUTH_COPY AuthorizerActionCode = 0 /* No longer used */ -) - -// AuthorizerReturnCode are the integer codes -// that the authorizer callback may return. -// -// https://sqlite.org/c3ref/c_deny.html -type AuthorizerReturnCode uint32 - -const ( - AUTH_OK AuthorizerReturnCode = 0 - AUTH_DENY AuthorizerReturnCode = 1 /* Abort the SQL statement with an error */ - AUTH_IGNORE AuthorizerReturnCode = 2 /* Don't allow access, but don't generate an error */ -) - -// CheckpointMode are all the checkpoint mode values. -// -// https://sqlite.org/c3ref/c_checkpoint_full.html -type CheckpointMode uint32 - -const ( - CHECKPOINT_PASSIVE CheckpointMode = 0 /* Do as much as possible w/o blocking */ - CHECKPOINT_FULL CheckpointMode = 1 /* Wait for writers, then checkpoint */ - CHECKPOINT_RESTART CheckpointMode = 2 /* Like FULL but wait for readers */ - CHECKPOINT_TRUNCATE CheckpointMode = 3 /* Like RESTART but also truncate WAL */ -) - -// TxnState are the allowed return values from [Conn.TxnState]. -// -// https://sqlite.org/c3ref/c_txn_none.html -type TxnState uint32 - -const ( - TXN_NONE TxnState = 0 - TXN_READ TxnState = 1 - 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 -type Datatype uint32 - -const ( - INTEGER Datatype = 1 - FLOAT Datatype = 2 - TEXT Datatype = 3 - BLOB Datatype = 4 - NULL Datatype = 5 -) - -// String implements the [fmt.Stringer] interface. -func (t Datatype) String() string { - const name = "INTEGERFLOATEXTBLOBNULL" - switch t { - case INTEGER: - return name[0:7] - case FLOAT: - return name[7:12] - case TEXT: - return name[11:15] - case BLOB: - return name[15:19] - case NULL: - return name[19:23] - } - return strconv.FormatUint(uint64(t), 10) -} diff --git a/vendor/github.com/ncruces/go-sqlite3/context.go b/vendor/github.com/ncruces/go-sqlite3/context.go deleted file mode 100644 index 637ddc282..000000000 --- a/vendor/github.com/ncruces/go-sqlite3/context.go +++ /dev/null @@ -1,228 +0,0 @@ -package sqlite3 - -import ( - "encoding/json" - "errors" - "math" - "time" - - "github.com/ncruces/go-sqlite3/internal/util" -) - -// Context is the context in which an SQL function executes. -// An SQLite [Context] is in no way related to a Go [context.Context]. -// -// https://sqlite.org/c3ref/context.html -type Context struct { - c *Conn - handle ptr_t -} - -// Conn returns the database connection of the -// [Conn.CreateFunction] or [Conn.CreateWindowFunction] -// routines that originally registered the application defined function. -// -// https://sqlite.org/c3ref/context_db_handle.html -func (ctx Context) Conn() *Conn { - return ctx.c -} - -// SetAuxData saves metadata for argument n of the function. -// -// https://sqlite.org/c3ref/get_auxdata.html -func (ctx Context) SetAuxData(n int, data any) { - ptr := util.AddHandle(ctx.c.ctx, data) - ctx.c.call("sqlite3_set_auxdata_go", stk_t(ctx.handle), stk_t(n), stk_t(ptr)) -} - -// GetAuxData returns metadata for argument n of the function. -// -// https://sqlite.org/c3ref/get_auxdata.html -func (ctx Context) GetAuxData(n int) any { - ptr := ptr_t(ctx.c.call("sqlite3_get_auxdata", stk_t(ctx.handle), stk_t(n))) - return util.GetHandle(ctx.c.ctx, ptr) -} - -// ResultBool sets the result of the function to a bool. -// SQLite does not have a separate boolean storage class. -// Instead, boolean values are stored as integers 0 (false) and 1 (true). -// -// https://sqlite.org/c3ref/result_blob.html -func (ctx Context) ResultBool(value bool) { - var i int64 - if value { - i = 1 - } - ctx.ResultInt64(i) -} - -// ResultInt sets the result of the function to an int. -// -// https://sqlite.org/c3ref/result_blob.html -func (ctx Context) ResultInt(value int) { - ctx.ResultInt64(int64(value)) -} - -// ResultInt64 sets the result of the function to an int64. -// -// https://sqlite.org/c3ref/result_blob.html -func (ctx Context) ResultInt64(value int64) { - ctx.c.call("sqlite3_result_int64", - stk_t(ctx.handle), stk_t(value)) -} - -// ResultFloat sets the result of the function to a float64. -// -// https://sqlite.org/c3ref/result_blob.html -func (ctx Context) ResultFloat(value float64) { - ctx.c.call("sqlite3_result_double", - stk_t(ctx.handle), stk_t(math.Float64bits(value))) -} - -// ResultText sets the result of the function to a string. -// -// https://sqlite.org/c3ref/result_blob.html -func (ctx Context) ResultText(value string) { - ptr := ctx.c.newString(value) - ctx.c.call("sqlite3_result_text_go", - stk_t(ctx.handle), stk_t(ptr), stk_t(len(value))) -} - -// ResultRawText sets the text result of the function to a []byte. -// Returning a nil slice is the same as calling [Context.ResultNull]. -// -// https://sqlite.org/c3ref/result_blob.html -func (ctx Context) ResultRawText(value []byte) { - ptr := ctx.c.newBytes(value) - ctx.c.call("sqlite3_result_text_go", - stk_t(ctx.handle), stk_t(ptr), stk_t(len(value))) -} - -// ResultBlob sets the result of the function to a []byte. -// Returning a nil slice is the same as calling [Context.ResultNull]. -// -// https://sqlite.org/c3ref/result_blob.html -func (ctx Context) ResultBlob(value []byte) { - ptr := ctx.c.newBytes(value) - ctx.c.call("sqlite3_result_blob_go", - stk_t(ctx.handle), stk_t(ptr), stk_t(len(value))) -} - -// ResultZeroBlob sets the result of the function to a zero-filled, length n BLOB. -// -// https://sqlite.org/c3ref/result_blob.html -func (ctx Context) ResultZeroBlob(n int64) { - ctx.c.call("sqlite3_result_zeroblob64", - stk_t(ctx.handle), stk_t(n)) -} - -// ResultNull sets the result of the function to NULL. -// -// https://sqlite.org/c3ref/result_blob.html -func (ctx Context) ResultNull() { - ctx.c.call("sqlite3_result_null", - stk_t(ctx.handle)) -} - -// ResultTime sets the result of the function to a [time.Time]. -// -// https://sqlite.org/c3ref/result_blob.html -func (ctx Context) ResultTime(value time.Time, format TimeFormat) { - switch format { - case TimeFormatDefault, TimeFormatAuto, time.RFC3339Nano: - ctx.resultRFC3339Nano(value) - return - } - switch v := format.Encode(value).(type) { - case string: - ctx.ResultText(v) - case int64: - ctx.ResultInt64(v) - case float64: - ctx.ResultFloat(v) - default: - panic(util.AssertErr()) - } -} - -func (ctx Context) resultRFC3339Nano(value time.Time) { - const maxlen = int64(len(time.RFC3339Nano)) + 5 - - ptr := ctx.c.new(maxlen) - buf := util.View(ctx.c.mod, ptr, maxlen) - buf = value.AppendFormat(buf[:0], time.RFC3339Nano) - - ctx.c.call("sqlite3_result_text_go", - stk_t(ctx.handle), stk_t(ptr), stk_t(len(buf))) -} - -// ResultPointer sets the result of the function to NULL, just like [Context.ResultNull], -// except that it also associates ptr with that NULL value such that it can be retrieved -// within an application-defined SQL function using [Value.Pointer]. -// -// 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", - stk_t(ctx.handle), stk_t(valPtr)) -} - -// ResultJSON sets the result of the function to the JSON encoding of value. -// -// https://sqlite.org/c3ref/result_blob.html -func (ctx Context) ResultJSON(value any) { - data, err := json.Marshal(value) - if err != nil { - ctx.ResultError(err) - return // notest - } - ctx.ResultRawText(data) -} - -// ResultValue sets the result of the function to a copy of [Value]. -// -// https://sqlite.org/c3ref/result_blob.html -func (ctx Context) ResultValue(value Value) { - if value.c != ctx.c { - ctx.ResultError(MISUSE) - return - } - ctx.c.call("sqlite3_result_value", - stk_t(ctx.handle), stk_t(value.handle)) -} - -// ResultError sets the result of the function an error. -// -// https://sqlite.org/c3ref/result_blob.html -func (ctx Context) ResultError(err error) { - if errors.Is(err, NOMEM) { - ctx.c.call("sqlite3_result_error_nomem", stk_t(ctx.handle)) - return - } - - if errors.Is(err, TOOBIG) { - ctx.c.call("sqlite3_result_error_toobig", stk_t(ctx.handle)) - return - } - - msg, code := errorCode(err, _OK) - if msg != "" { - defer ctx.c.arena.mark()() - ptr := ctx.c.arena.string(msg) - ctx.c.call("sqlite3_result_error", - stk_t(ctx.handle), stk_t(ptr), stk_t(len(msg))) - } - if code != _OK { - ctx.c.call("sqlite3_result_error_code", - stk_t(ctx.handle), stk_t(code)) - } -} - -// VTabNoChange may return true if a column is being fetched as part -// of an update during which the column value will not change. -// -// https://sqlite.org/c3ref/vtab_nochange.html -func (ctx Context) VTabNoChange() bool { - b := int32(ctx.c.call("sqlite3_vtab_nochange", stk_t(ctx.handle))) - return b != 0 -} diff --git a/vendor/github.com/ncruces/go-sqlite3/driver/driver.go b/vendor/github.com/ncruces/go-sqlite3/driver/driver.go deleted file mode 100644 index 21799aeb2..000000000 --- a/vendor/github.com/ncruces/go-sqlite3/driver/driver.go +++ /dev/null @@ -1,783 +0,0 @@ -// Package driver provides a database/sql driver for SQLite. -// -// Importing package driver registers a [database/sql] driver named "sqlite3". -// You may also need to import package embed. -// -// import _ "github.com/ncruces/go-sqlite3/driver" -// import _ "github.com/ncruces/go-sqlite3/embed" -// -// 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" (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. -// -// 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 encode 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, or 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": -// -// sql.Open("sqlite3", "file:demo.db?_pragma=busy_timeout(10000)") -// -// If no PRAGMAs are specified, a busy timeout of 1 minute is set. -// -// Order matters: -// 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 -// [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 ( - "context" - "database/sql" - "database/sql/driver" - "errors" - "fmt" - "io" - "net/url" - "reflect" - "strings" - "time" - "unsafe" - - "github.com/ncruces/go-sqlite3" - "github.com/ncruces/go-sqlite3/internal/util" -) - -// This variable can be replaced with -ldflags: -// -// go build -ldflags="-X github.com/ncruces/go-sqlite3/driver.driverName=sqlite" -var driverName = "sqlite3" - -func init() { - if driverName != "" { - sql.Register(driverName, &SQLite{}) - } -} - -// Open opens the SQLite database specified by dataSourceName as a [database/sql.DB]. -// -// 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. -func Open(dataSourceName string, fn ...func(*sqlite3.Conn) error) (*sql.DB, error) { - if len(fn) > 2 { - return nil, sqlite3.MISUSE - } - var init, term func(*sqlite3.Conn) error - if len(fn) > 1 { - term = fn[1] - } - if len(fn) > 0 { - init = fn[0] - } - c, err := newConnector(dataSourceName, init, term) - if err != nil { - return nil, err - } - return sql.OpenDB(c), nil -} - -// SQLite implements [database/sql/driver.Driver]. -type SQLite struct{} - -var ( - // Ensure these interfaces are implemented: - _ driver.DriverContext = &SQLite{} -) - -// Open implements [database/sql/driver.Driver]. -func (d *SQLite) Open(name string) (driver.Conn, error) { - c, err := newConnector(name, nil, nil) - if err != nil { - return nil, err - } - return c.Connect(context.Background()) -} - -// OpenConnector implements [database/sql/driver.DriverContext]. -func (d *SQLite) OpenConnector(name string) (driver.Connector, error) { - return newConnector(name, nil, nil) -} - -func newConnector(name string, init, term func(*sqlite3.Conn) error) (*connector, error) { - c := connector{name: name, init: init, term: term} - - var txlock, timefmt string - if strings.HasPrefix(name, "file:") { - if _, after, ok := strings.Cut(name, "?"); ok { - query, err := url.ParseQuery(after) - if err != nil { - return nil, err - } - txlock = query.Get("_txlock") - timefmt = query.Get("_timefmt") - c.pragmas = query.Has("_pragma") - } - } - - switch txlock { - case "", "deferred", "concurrent", "immediate", "exclusive": - c.txLock = txlock - default: - return nil, fmt.Errorf("sqlite3: invalid _txlock: %s", txlock) - } - - switch timefmt { - case "": - c.tmRead = sqlite3.TimeFormatAuto - c.tmWrite = sqlite3.TimeFormatDefault - case "sqlite": - c.tmRead = sqlite3.TimeFormatAuto - c.tmWrite = sqlite3.TimeFormat3 - case "rfc3339": - c.tmRead = sqlite3.TimeFormatDefault - c.tmWrite = sqlite3.TimeFormatDefault - default: - c.tmRead = sqlite3.TimeFormat(timefmt) - c.tmWrite = sqlite3.TimeFormat(timefmt) - } - return &c, nil -} - -type connector struct { - init func(*sqlite3.Conn) error - term func(*sqlite3.Conn) error - name string - txLock string - tmRead sqlite3.TimeFormat - tmWrite sqlite3.TimeFormat - pragmas bool -} - -func (n *connector) Driver() driver.Driver { - return &SQLite{} -} - -func (n *connector) Connect(ctx context.Context) (ret driver.Conn, err error) { - c := &conn{ - txLock: n.txLock, - tmRead: n.tmRead, - tmWrite: n.tmWrite, - } - - c.Conn, err = sqlite3.OpenContext(ctx, n.name) - if err != nil { - return nil, err - } - defer func() { - if ret == nil { - c.Close() - } - }() - - old := c.Conn.SetInterrupt(ctx) - defer c.Conn.SetInterrupt(old) - - if !n.pragmas { - err = c.Conn.BusyTimeout(time.Minute) - if err != nil { - return nil, err - } - } - if n.init != nil { - err = n.init(c.Conn) - if err != nil { - return nil, err - } - } - if n.pragmas || n.init != nil { - s, _, err := c.Conn.Prepare(`PRAGMA query_only`) - if err != nil { - return nil, err - } - defer s.Close() - if s.Step() && s.ColumnBool(0) { - c.readOnly = '1' - } else { - c.readOnly = '0' - } - err = s.Close() - if err != nil { - return nil, err - } - } - if n.term != nil { - err = c.Conn.Trace(sqlite3.TRACE_CLOSE, func(sqlite3.TraceEvent, any, any) error { - return n.term(c.Conn) - }) - if err != nil { - return nil, err - } - } - return c, nil -} - -// Conn is implemented by the SQLite [database/sql] driver connections. -// -// It can be used to access SQLite features like [online backup]: -// -// db, err := driver.Open("temp.db") -// if err != nil { -// log.Fatal(err) -// } -// defer db.Close() -// -// conn, err := db.Conn(context.TODO()) -// if err != nil { -// log.Fatal(err) -// } -// defer conn.Close() -// -// err = conn.Raw(func(driverConn any) error { -// conn := driverConn.(driver.Conn) -// return conn.Raw().Backup("main", "backup.db") -// }) -// if err != nil { -// log.Fatal(err) -// } -// -// [online backup]: https://sqlite.org/backup.html -type Conn interface { - Raw() *sqlite3.Conn - driver.Conn - driver.ConnBeginTx - driver.ConnPrepareContext -} - -type conn struct { - *sqlite3.Conn - txLock string - txReset string - tmRead sqlite3.TimeFormat - tmWrite sqlite3.TimeFormat - readOnly byte -} - -var ( - // Ensure these interfaces are implemented: - _ Conn = &conn{} - _ driver.ExecerContext = &conn{} -) - -func (c *conn) Raw() *sqlite3.Conn { - return c.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) { - var txLock string - switch opts.Isolation { - default: - return nil, util.IsolationErr - 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) - defer c.Conn.SetInterrupt(old) - - err := c.Conn.Exec(txBegin) - if err != nil { - return nil, err - } - return c, nil -} - -func (c *conn) Commit() error { - err := c.Conn.Exec(`COMMIT` + c.txReset) - if err != nil && !c.Conn.GetAutocommit() { - c.Rollback() - } - return err -} - -func (c *conn) Rollback() error { - 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(`ROLLBACK` + c.txReset) - } - return err -} - -func (c *conn) Prepare(query string) (driver.Stmt, error) { - // notest - return c.PrepareContext(context.Background(), query) -} - -func (c *conn) PrepareContext(ctx context.Context, query string) (driver.Stmt, error) { - old := c.Conn.SetInterrupt(ctx) - defer c.Conn.SetInterrupt(old) - - s, tail, err := c.Conn.Prepare(query) - if err != nil { - return nil, err - } - if notWhitespace(tail) { - s.Close() - return nil, util.TailErr - } - return &stmt{Stmt: s, tmRead: c.tmRead, tmWrite: c.tmWrite, inputs: -2}, nil -} - -func (c *conn) ExecContext(ctx context.Context, query string, args []driver.NamedValue) (driver.Result, error) { - if len(args) != 0 { - // Slow path. - return nil, driver.ErrSkip - } - - if savept, ok := ctx.(*saveptCtx); ok { - // Called from driver.Savepoint. - savept.Savepoint = c.Conn.Savepoint() - return resultRowsAffected(0), nil - } - - old := c.Conn.SetInterrupt(ctx) - defer c.Conn.SetInterrupt(old) - - err := c.Conn.Exec(query) - if err != nil { - return nil, err - } - - return newResult(c.Conn), nil -} - -func (c *conn) CheckNamedValue(arg *driver.NamedValue) error { - // Fast path: short circuit argument verification. - // Arguments will be rejected by conn.ExecContext. - return nil -} - -type stmt struct { - *sqlite3.Stmt - tmWrite sqlite3.TimeFormat - tmRead sqlite3.TimeFormat - inputs int -} - -var ( - // Ensure these interfaces are implemented: - _ driver.StmtExecContext = &stmt{} - _ driver.StmtQueryContext = &stmt{} - _ driver.NamedValueChecker = &stmt{} -) - -func (s *stmt) NumInput() int { - if s.inputs >= -1 { - return s.inputs - } - n := s.Stmt.BindCount() - for i := 1; i <= n; i++ { - if s.Stmt.BindName(i) != "" { - s.inputs = -1 - return -1 - } - } - s.inputs = n - return n -} - -// 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)) -} - -func (s *stmt) ExecContext(ctx context.Context, args []driver.NamedValue) (driver.Result, error) { - err := s.setupBindings(args) - if err != nil { - return nil, err - } - - old := s.Stmt.Conn().SetInterrupt(ctx) - defer s.Stmt.Conn().SetInterrupt(old) - - err = errors.Join( - s.Stmt.Exec(), - s.Stmt.ClearBindings()) - if err != nil { - return nil, err - } - - return newResult(s.Stmt.Conn()), nil -} - -func (s *stmt) QueryContext(ctx context.Context, args []driver.NamedValue) (driver.Rows, error) { - err := s.setupBindings(args) - if err != nil { - return nil, err - } - return &rows{ctx: ctx, stmt: s}, nil -} - -func (s *stmt) setupBindings(args []driver.NamedValue) (err error) { - var ids [3]int - for _, arg := range args { - ids := ids[:0] - if arg.Name == "" { - ids = append(ids, arg.Ordinal) - } else { - for _, prefix := range [...]string{":", "@", "$"} { - if id := s.Stmt.BindIndex(prefix + arg.Name); id != 0 { - ids = append(ids, id) - } - } - } - - for _, id := range ids { - switch a := arg.Value.(type) { - case bool: - err = s.Stmt.BindBool(id, a) - case int: - err = s.Stmt.BindInt(id, a) - case int64: - err = s.Stmt.BindInt64(id, a) - case float64: - err = s.Stmt.BindFloat(id, a) - case string: - err = s.Stmt.BindText(id, a) - case []byte: - err = s.Stmt.BindBlob(id, a) - case sqlite3.ZeroBlob: - err = s.Stmt.BindZeroBlob(id, int64(a)) - case time.Time: - err = s.Stmt.BindTime(id, a, s.tmWrite) - case util.JSON: - err = s.Stmt.BindJSON(id, a.Value) - case util.PointerUnwrap: - err = s.Stmt.BindPointer(id, util.UnwrapPointer(a)) - case nil: - err = s.Stmt.BindNull(id) - default: - panic(util.AssertErr()) - } - if err != nil { - return err - } - } - } - return nil -} - -func (s *stmt) CheckNamedValue(arg *driver.NamedValue) error { - switch arg.Value.(type) { - case bool, int, int64, float64, string, []byte, - time.Time, sqlite3.ZeroBlob, - util.JSON, util.PointerUnwrap, - nil: - return nil - default: - return driver.ErrSkip - } -} - -func newResult(c *sqlite3.Conn) driver.Result { - rows := c.Changes() - if rows != 0 { - id := c.LastInsertRowID() - if id != 0 { - return result{id, rows} - } - } - return resultRowsAffected(rows) -} - -type result struct{ lastInsertId, rowsAffected int64 } - -func (r result) LastInsertId() (int64, error) { - return r.lastInsertId, nil -} - -func (r result) RowsAffected() (int64, error) { - return r.rowsAffected, nil -} - -type resultRowsAffected int64 - -func (r resultRowsAffected) LastInsertId() (int64, error) { - return 0, nil -} - -func (r resultRowsAffected) RowsAffected() (int64, error) { - return int64(r), nil -} - -type rows struct { - ctx context.Context - *stmt - names []string - types []string - nulls []bool - scans []scantype -} - -type scantype byte - -const ( - _ANY scantype = iota - _INT scantype = scantype(sqlite3.INTEGER) - _REAL scantype = scantype(sqlite3.FLOAT) - _TEXT scantype = scantype(sqlite3.TEXT) - _BLOB scantype = scantype(sqlite3.BLOB) - _NULL scantype = scantype(sqlite3.NULL) - _BOOL scantype = iota - _TIME -) - -var ( - // Ensure these interfaces are implemented: - _ driver.RowsColumnTypeDatabaseTypeName = &rows{} - _ driver.RowsColumnTypeNullable = &rows{} -) - -func (r *rows) Close() error { - return errors.Join( - r.Stmt.Reset(), - r.Stmt.ClearBindings()) -} - -func (r *rows) Columns() []string { - if r.names == nil { - count := r.Stmt.ColumnCount() - names := make([]string, count) - for i := range names { - names[i] = r.Stmt.ColumnName(i) - } - r.names = names - } - return r.names -} - -func (r *rows) loadColumnMetadata() { - if r.nulls == nil { - count := r.Stmt.ColumnCount() - nulls := make([]bool, count) - types := make([]string, count) - scans := make([]scantype, count) - for i := range nulls { - if col := r.Stmt.ColumnOriginName(i); col != "" { - types[i], _, nulls[i], _, _, _ = r.Stmt.Conn().TableColumnMetadata( - r.Stmt.ColumnDatabaseName(i), - r.Stmt.ColumnTableName(i), - col) - types[i] = strings.ToUpper(types[i]) - // These types are only used before we have rows, - // and otherwise as type hints. - // The first few ensure STRICT tables are strictly typed. - // The other two are type hints for booleans and time. - switch types[i] { - case "INT", "INTEGER": - scans[i] = _INT - case "REAL": - scans[i] = _REAL - case "TEXT": - scans[i] = _TEXT - case "BLOB": - scans[i] = _BLOB - case "BOOLEAN": - scans[i] = _BOOL - case "DATE", "TIME", "DATETIME", "TIMESTAMP": - scans[i] = _TIME - } - } - } - r.nulls = nulls - r.types = types - r.scans = scans - } -} - -func (r *rows) declType(index int) string { - if r.types == nil { - count := r.Stmt.ColumnCount() - types := make([]string, count) - for i := range types { - types[i] = strings.ToUpper(r.Stmt.ColumnDeclType(i)) - } - r.types = types - } - return r.types[index] -} - -func (r *rows) ColumnTypeDatabaseTypeName(index int) string { - r.loadColumnMetadata() - decltype := r.types[index] - if len := len(decltype); len > 0 && decltype[len-1] == ')' { - if i := strings.LastIndexByte(decltype, '('); i >= 0 { - decltype = decltype[:i] - } - } - return strings.TrimSpace(decltype) -} - -func (r *rows) ColumnTypeNullable(index int) (nullable, ok bool) { - r.loadColumnMetadata() - if r.nulls[index] { - return false, true - } - return true, false -} - -func (r *rows) ColumnTypeScanType(index int) (typ reflect.Type) { - r.loadColumnMetadata() - scan := r.scans[index] - - if r.Stmt.Busy() { - // SQLite is dynamically typed and we now have a row. - // Always use the type of the value itself, - // unless the scan type is more specific - // and can scan the actual value. - val := scantype(r.Stmt.ColumnType(index)) - useValType := true - switch { - case scan == _TIME && val != _BLOB && val != _NULL: - t := r.Stmt.ColumnTime(index, r.tmRead) - useValType = t == time.Time{} - case scan == _BOOL && val == _INT: - i := r.Stmt.ColumnInt64(index) - useValType = i != 0 && i != 1 - case scan == _BLOB && val == _NULL: - useValType = false - } - if useValType { - scan = val - } - } - - switch scan { - case _INT: - return reflect.TypeFor[int64]() - case _REAL: - return reflect.TypeFor[float64]() - case _TEXT: - return reflect.TypeFor[string]() - case _BLOB: - return reflect.TypeFor[[]byte]() - case _BOOL: - return reflect.TypeFor[bool]() - case _TIME: - return reflect.TypeFor[time.Time]() - default: - return reflect.TypeFor[any]() - } -} - -func (r *rows) Next(dest []driver.Value) error { - old := r.Stmt.Conn().SetInterrupt(r.ctx) - defer r.Stmt.Conn().SetInterrupt(old) - - if !r.Stmt.Step() { - if err := r.Stmt.Err(); err != nil { - return err - } - return io.EOF - } - - data := unsafe.Slice((*any)(unsafe.SliceData(dest)), len(dest)) - err := r.Stmt.Columns(data...) - for i := range dest { - if t, ok := r.decodeTime(i, dest[i]); ok { - dest[i] = t - } - } - return err -} - -func (r *rows) decodeTime(i int, v any) (_ time.Time, ok bool) { - switch v := v.(type) { - case int64, float64: - // could be a time value - case string: - if r.tmWrite != "" && r.tmWrite != time.RFC3339 && r.tmWrite != time.RFC3339Nano { - break - } - t, ok := maybeTime(v) - if ok { - return t, true - } - default: - return - } - switch r.declType(i) { - case "DATE", "TIME", "DATETIME", "TIMESTAMP": - // could be a time value - default: - return - } - t, err := r.tmRead.Decode(v) - return t, err == nil -} diff --git a/vendor/github.com/ncruces/go-sqlite3/driver/savepoint.go b/vendor/github.com/ncruces/go-sqlite3/driver/savepoint.go deleted file mode 100644 index eea40dd68..000000000 --- a/vendor/github.com/ncruces/go-sqlite3/driver/savepoint.go +++ /dev/null @@ -1,40 +0,0 @@ -package driver - -import ( - "database/sql" - "time" - - "github.com/ncruces/go-sqlite3" -) - -// Savepoint establishes a new transaction savepoint. -// -// https://sqlite.org/lang_savepoint.html -func Savepoint(tx *sql.Tx) sqlite3.Savepoint { - var ctx saveptCtx - tx.ExecContext(&ctx, "") - 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) { - // notest - return -} - -func (*saveptCtx) Done() <-chan struct{} { - // notest - return nil -} - -func (*saveptCtx) Err() error { - // notest - return nil -} - -func (*saveptCtx) Value(key any) any { - // notest - return nil -} diff --git a/vendor/github.com/ncruces/go-sqlite3/driver/time.go b/vendor/github.com/ncruces/go-sqlite3/driver/time.go deleted file mode 100644 index b3ebdd263..000000000 --- a/vendor/github.com/ncruces/go-sqlite3/driver/time.go +++ /dev/null @@ -1,29 +0,0 @@ -package driver - -import "time" - -// Convert a string in [time.RFC3339Nano] format into a [time.Time] -// if it roundtrips back to the same string. -// This way times can be persisted to, and recovered from, the database, -// but if a string is needed, [database/sql] will recover the same string. -func maybeTime(text string) (_ time.Time, _ bool) { - // Weed out (some) values that can't possibly be - // [time.RFC3339Nano] timestamps. - if len(text) < len("2006-01-02T15:04:05Z") { - return - } - if len(text) > len(time.RFC3339Nano) { - return - } - if text[4] != '-' || text[10] != 'T' || text[16] != ':' { - return - } - - // Slow path. - var buf [len(time.RFC3339Nano)]byte - date, err := time.Parse(time.RFC3339Nano, text) - if err == nil && text == string(date.AppendFormat(buf[:0], time.RFC3339Nano)) { - return date, true - } - return -} diff --git a/vendor/github.com/ncruces/go-sqlite3/driver/util.go b/vendor/github.com/ncruces/go-sqlite3/driver/util.go deleted file mode 100644 index 987585576..000000000 --- a/vendor/github.com/ncruces/go-sqlite3/driver/util.go +++ /dev/null @@ -1,74 +0,0 @@ -package driver - -import "database/sql/driver" - -func namedValues(args []driver.Value) []driver.NamedValue { - named := make([]driver.NamedValue, len(args)) - for i, v := range args { - named[i] = driver.NamedValue{ - Ordinal: i + 1, - Value: v, - } - } - return named -} - -func notWhitespace(sql string) bool { - const ( - code = iota - slash - minus - ccomment - sqlcomment - endcomment - ) - - state := code - for _, b := range ([]byte)(sql) { - if b == 0 { - break - } - - switch state { - case code: - switch b { - case '/': - state = slash - case '-': - state = minus - case ' ', ';', '\t', '\n', '\v', '\f', '\r': - continue - default: - return true - } - case slash: - if b != '*' { - return true - } - state = ccomment - case minus: - if b != '-' { - return true - } - state = sqlcomment - case ccomment: - if b == '*' { - state = endcomment - } - case sqlcomment: - if b == '\n' { - state = code - } - case endcomment: - switch b { - case '/': - state = code - case '*': - state = endcomment - default: - state = ccomment - } - } - } - return state == slash || state == minus -} diff --git a/vendor/github.com/ncruces/go-sqlite3/embed/README.md b/vendor/github.com/ncruces/go-sqlite3/embed/README.md deleted file mode 100644 index 59329a917..000000000 --- a/vendor/github.com/ncruces/go-sqlite3/embed/README.md +++ /dev/null @@ -1,41 +0,0 @@ -# Embeddable Wasm build of SQLite - -This folder includes an embeddable Wasm build of SQLite 3.49.0 for use with -[`github.com/ncruces/go-sqlite3`](https://pkg.go.dev/github.com/ncruces/go-sqlite3). - -The following optional features are compiled in: -- [math functions](https://sqlite.org/lang_mathfunc.html) -- [FTS5](https://sqlite.org/fts5.html) -- [JSON](https://sqlite.org/json1.html) -- [R*Tree](https://sqlite.org/rtree.html) -- [GeoPoly](https://sqlite.org/geopoly.html) -- [Spellfix1](https://sqlite.org/spellfix1.html) -- [soundex](https://sqlite.org/lang_corefunc.html#soundex) -- [stat4](https://sqlite.org/compile.html#enable_stat4) -- [base64](https://github.com/sqlite/sqlite/blob/master/ext/misc/base64.c) -- [decimal](https://github.com/sqlite/sqlite/blob/master/ext/misc/decimal.c) -- [ieee754](https://github.com/sqlite/sqlite/blob/master/ext/misc/ieee754.c) -- [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) -- [time](../sqlite3/time.c) - -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). - -### 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://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 deleted file mode 100644 index a6b21d366..000000000 --- a/vendor/github.com/ncruces/go-sqlite3/embed/build.sh +++ /dev/null @@ -1,33 +0,0 @@ -#!/usr/bin/env bash -set -euo pipefail - -cd -P -- "$(dirname -- "$0")" - -ROOT=../ -BINARYEN="$ROOT/tools/binaryen/bin" -WASI_SDK="$ROOT/tools/wasi-sdk/bin" - -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 -mmultivalue \ - -mbulk-memory -mreference-types \ - -mnontrapping-fptoint -msign-ext \ - -fno-stack-protector -fno-stack-clash-protection \ - -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) - -"$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 \ - --enable-simd --enable-mutable-globals --enable-multivalue \ - --enable-bulk-memory --enable-reference-types \ - --enable-nontrapping-float-to-int --enable-sign-ext
\ No newline at end of file diff --git a/vendor/github.com/ncruces/go-sqlite3/embed/exports.txt b/vendor/github.com/ncruces/go-sqlite3/embed/exports.txt deleted file mode 100644 index 597c79547..000000000 --- a/vendor/github.com/ncruces/go-sqlite3/embed/exports.txt +++ /dev/null @@ -1,140 +0,0 @@ -aligned_alloc -sqlite3_anycollseq_init -sqlite3_autovacuum_pages_go -sqlite3_backup_finish -sqlite3_backup_init -sqlite3_backup_pagecount -sqlite3_backup_remaining -sqlite3_backup_step -sqlite3_bind_blob_go -sqlite3_bind_double -sqlite3_bind_int64 -sqlite3_bind_null -sqlite3_bind_parameter_count -sqlite3_bind_parameter_index -sqlite3_bind_parameter_name -sqlite3_bind_pointer_go -sqlite3_bind_text_go -sqlite3_bind_value -sqlite3_bind_zeroblob64 -sqlite3_blob_bytes -sqlite3_blob_close -sqlite3_blob_open -sqlite3_blob_read -sqlite3_blob_reopen -sqlite3_blob_write -sqlite3_busy_handler_go -sqlite3_busy_timeout -sqlite3_changes64 -sqlite3_clear_bindings -sqlite3_close -sqlite3_close_v2 -sqlite3_collation_needed_go -sqlite3_column_blob -sqlite3_column_bytes -sqlite3_column_count -sqlite3_column_database_name -sqlite3_column_decltype -sqlite3_column_double -sqlite3_column_int64 -sqlite3_column_name -sqlite3_column_origin_name -sqlite3_column_table_name -sqlite3_column_text -sqlite3_column_type -sqlite3_column_value -sqlite3_columns_go -sqlite3_commit_hook_go -sqlite3_config_log_go -sqlite3_create_aggregate_function_go -sqlite3_create_collation_go -sqlite3_create_function_go -sqlite3_create_module_go -sqlite3_create_window_function_go -sqlite3_data_count -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 -sqlite3_finalize -sqlite3_free -sqlite3_get_autocommit -sqlite3_get_auxdata -sqlite3_hard_heap_limit64 -sqlite3_interrupt -sqlite3_invoke_busy_handler_go -sqlite3_last_insert_rowid -sqlite3_limit -sqlite3_malloc64 -sqlite3_open_v2 -sqlite3_overload_function -sqlite3_prepare_v3 -sqlite3_progress_handler_go -sqlite3_realloc64 -sqlite3_reset -sqlite3_result_blob_go -sqlite3_result_double -sqlite3_result_error -sqlite3_result_error_code -sqlite3_result_error_nomem -sqlite3_result_error_toobig -sqlite3_result_int64 -sqlite3_result_null -sqlite3_result_pointer_go -sqlite3_result_text_go -sqlite3_result_value -sqlite3_result_zeroblob64 -sqlite3_rollback_hook_go -sqlite3_set_authorizer_go -sqlite3_set_auxdata_go -sqlite3_set_last_insert_rowid -sqlite3_soft_heap_limit64 -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_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 -sqlite3_value_pointer_go -sqlite3_value_text -sqlite3_value_type -sqlite3_vtab_collation -sqlite3_vtab_config_go -sqlite3_vtab_distinct -sqlite3_vtab_in -sqlite3_vtab_in_first -sqlite3_vtab_in_next -sqlite3_vtab_nochange -sqlite3_vtab_on_conflict -sqlite3_vtab_rhs_value -sqlite3_wal_autocheckpoint -sqlite3_wal_checkpoint_v2 -sqlite3_wal_hook_go
\ No newline at end of file diff --git a/vendor/github.com/ncruces/go-sqlite3/embed/init.go b/vendor/github.com/ncruces/go-sqlite3/embed/init.go deleted file mode 100644 index 5ffd69516..000000000 --- a/vendor/github.com/ncruces/go-sqlite3/embed/init.go +++ /dev/null @@ -1,21 +0,0 @@ -// Package embed embeds SQLite into your application. -// -// Importing package embed initializes the [sqlite3.Binary] variable -// with an appropriate build of SQLite: -// -// import _ "github.com/ncruces/go-sqlite3/embed" -package embed - -import ( - _ "embed" - "unsafe" - - "github.com/ncruces/go-sqlite3" -) - -//go:embed sqlite3.wasm -var binary string - -func init() { - sqlite3.Binary = unsafe.Slice(unsafe.StringData(binary), len(binary)) -} diff --git a/vendor/github.com/ncruces/go-sqlite3/embed/sqlite3.wasm b/vendor/github.com/ncruces/go-sqlite3/embed/sqlite3.wasm Binary files differdeleted file mode 100644 index e61dc9356..000000000 --- a/vendor/github.com/ncruces/go-sqlite3/embed/sqlite3.wasm +++ /dev/null diff --git a/vendor/github.com/ncruces/go-sqlite3/error.go b/vendor/github.com/ncruces/go-sqlite3/error.go deleted file mode 100644 index 6d4bd63f8..000000000 --- a/vendor/github.com/ncruces/go-sqlite3/error.go +++ /dev/null @@ -1,172 +0,0 @@ -package sqlite3 - -import ( - "errors" - "strconv" - "strings" - - "github.com/ncruces/go-sqlite3/internal/util" -) - -// Error wraps an SQLite Error Code. -// -// https://sqlite.org/c3ref/errcode.html -type Error struct { - str string - msg string - sql string - code res_t -} - -// Code returns the primary error code for this error. -// -// https://sqlite.org/rescode.html -func (e *Error) Code() ErrorCode { - return ErrorCode(e.code) -} - -// ExtendedCode returns the extended error code for this error. -// -// https://sqlite.org/rescode.html -func (e *Error) ExtendedCode() ExtendedErrorCode { - return ExtendedErrorCode(e.code) -} - -// Error implements the error interface. -func (e *Error) Error() string { - var b strings.Builder - b.WriteString("sqlite3: ") - - if e.str != "" { - b.WriteString(e.str) - } else { - b.WriteString(strconv.Itoa(int(e.code))) - } - - if e.msg != "" { - b.WriteString(": ") - b.WriteString(e.msg) - } - - return b.String() -} - -// Is tests whether this error matches a given [ErrorCode] or [ExtendedErrorCode]. -// -// It makes it possible to do: -// -// if errors.Is(err, sqlite3.BUSY) { -// // ... handle BUSY -// } -func (e *Error) Is(err error) bool { - switch c := err.(type) { - case ErrorCode: - return c == e.Code() - case ExtendedErrorCode: - return c == e.ExtendedCode() - } - return false -} - -// As converts this error to an [ErrorCode] or [ExtendedErrorCode]. -func (e *Error) As(err any) bool { - switch c := err.(type) { - case *ErrorCode: - *c = e.Code() - return true - case *ExtendedErrorCode: - *c = e.ExtendedCode() - return true - } - return false -} - -// Temporary returns true for [BUSY] errors. -func (e *Error) Temporary() bool { - return e.Code() == BUSY -} - -// Timeout returns true for [BUSY_TIMEOUT] errors. -func (e *Error) Timeout() bool { - return e.ExtendedCode() == BUSY_TIMEOUT -} - -// SQL returns the SQL starting at the token that triggered a syntax error. -func (e *Error) SQL() string { - return e.sql -} - -// Error implements the error interface. -func (e ErrorCode) Error() string { - return util.ErrorCodeString(uint32(e)) -} - -// Temporary returns true for [BUSY] errors. -func (e ErrorCode) Temporary() bool { - return e == BUSY -} - -// ExtendedCode returns the extended error code for this error. -func (e ErrorCode) ExtendedCode() ExtendedErrorCode { - return ExtendedErrorCode(e) -} - -// Error implements the error interface. -func (e ExtendedErrorCode) Error() string { - return util.ErrorCodeString(uint32(e)) -} - -// Is tests whether this error matches a given [ErrorCode]. -func (e ExtendedErrorCode) Is(err error) bool { - c, ok := err.(ErrorCode) - return ok && c == ErrorCode(e) -} - -// As converts this error to an [ErrorCode]. -func (e ExtendedErrorCode) As(err any) bool { - c, ok := err.(*ErrorCode) - if ok { - *c = ErrorCode(e) - } - return ok -} - -// Temporary returns true for [BUSY] errors. -func (e ExtendedErrorCode) Temporary() bool { - return ErrorCode(e) == BUSY -} - -// Timeout returns true for [BUSY_TIMEOUT] errors. -func (e ExtendedErrorCode) Timeout() bool { - return e == BUSY_TIMEOUT -} - -// Code returns the primary error code for this error. -func (e ExtendedErrorCode) Code() ErrorCode { - return ErrorCode(e) -} - -func errorCode(err error, def ErrorCode) (msg string, code res_t) { - switch code := err.(type) { - case nil: - return "", _OK - case ErrorCode: - return "", res_t(code) - case xErrorCode: - return "", res_t(code) - case *Error: - return code.msg, res_t(code.code) - } - - var ecode ErrorCode - var xcode xErrorCode - switch { - case errors.As(err, &xcode): - code = res_t(xcode) - case errors.As(err, &ecode): - code = res_t(ecode) - default: - code = res_t(def) - } - return err.Error(), code -} diff --git a/vendor/github.com/ncruces/go-sqlite3/func.go b/vendor/github.com/ncruces/go-sqlite3/func.go deleted file mode 100644 index 6b69368b4..000000000 --- a/vendor/github.com/ncruces/go-sqlite3/func.go +++ /dev/null @@ -1,233 +0,0 @@ -package sqlite3 - -import ( - "context" - "sync" - - "github.com/tetratelabs/wazero/api" - - "github.com/ncruces/go-sqlite3/internal/util" -) - -// CollationNeeded registers a callback to be invoked -// whenever an unknown collation sequence is required. -// -// https://sqlite.org/c3ref/collation_needed.html -func (c *Conn) CollationNeeded(cb func(db *Conn, name string)) error { - var enable int32 - if cb != nil { - enable = 1 - } - rc := res_t(c.call("sqlite3_collation_needed_go", stk_t(c.handle), stk_t(enable))) - if err := c.error(rc); err != nil { - return err - } - c.collation = cb - return nil -} - -// AnyCollationNeeded uses [Conn.CollationNeeded] to register -// a fake collating function for any unknown collating sequence. -// The fake collating function works like BINARY. -// -// This can be used to load schemas that contain -// one or more unknown collating sequences. -func (c Conn) AnyCollationNeeded() error { - rc := res_t(c.call("sqlite3_anycollseq_init", stk_t(c.handle), 0, 0)) - if err := c.error(rc); err != nil { - return err - } - c.collation = nil - return nil -} - -// CreateCollation defines a new collating sequence. -// -// https://sqlite.org/c3ref/create_collation.html -func (c *Conn) CreateCollation(name string, fn func(a, b []byte) int) error { - var funcPtr ptr_t - defer c.arena.mark()() - namePtr := c.arena.string(name) - if fn != nil { - funcPtr = util.AddHandle(c.ctx, fn) - } - rc := res_t(c.call("sqlite3_create_collation_go", - stk_t(c.handle), stk_t(namePtr), stk_t(funcPtr))) - return c.error(rc) -} - -// CreateFunction defines a new scalar SQL function. -// -// https://sqlite.org/c3ref/create_function.html -func (c *Conn) CreateFunction(name string, nArg int, flag FunctionFlag, fn ScalarFunction) error { - var funcPtr ptr_t - defer c.arena.mark()() - namePtr := c.arena.string(name) - if fn != nil { - funcPtr = util.AddHandle(c.ctx, fn) - } - rc := res_t(c.call("sqlite3_create_function_go", - stk_t(c.handle), stk_t(namePtr), stk_t(nArg), - stk_t(flag), stk_t(funcPtr))) - return c.error(rc) -} - -// ScalarFunction is the type of a scalar SQL function. -// Implementations must not retain arg. -type ScalarFunction func(ctx Context, arg ...Value) - -// CreateWindowFunction defines a new aggregate or aggregate window SQL function. -// If fn returns a [WindowFunction], then an aggregate window function is created. -// If fn returns an [io.Closer], it will be called to free resources. -// -// https://sqlite.org/c3ref/create_function.html -func (c *Conn) CreateWindowFunction(name string, nArg int, flag FunctionFlag, fn func() AggregateFunction) error { - var funcPtr ptr_t - defer c.arena.mark()() - namePtr := c.arena.string(name) - if fn != nil { - funcPtr = util.AddHandle(c.ctx, fn) - } - call := "sqlite3_create_aggregate_function_go" - if _, ok := fn().(WindowFunction); ok { - call = "sqlite3_create_window_function_go" - } - rc := res_t(c.call(call, - stk_t(c.handle), stk_t(namePtr), stk_t(nArg), - stk_t(flag), stk_t(funcPtr))) - return c.error(rc) -} - -// AggregateFunction is the interface an aggregate function should implement. -// -// https://sqlite.org/appfunc.html -type AggregateFunction interface { - // Step is invoked to add a row to the current window. - // The function arguments, if any, corresponding to the row being added, are passed to Step. - // Implementations must not retain arg. - Step(ctx Context, arg ...Value) - - // Value is invoked to return the current (or final) value of the aggregate. - Value(ctx Context) -} - -// WindowFunction is the interface an aggregate window function should implement. -// -// https://sqlite.org/windowfunctions.html -type WindowFunction interface { - AggregateFunction - - // Inverse is invoked to remove the oldest presently aggregated result of Step from the current window. - // The function arguments, if any, are those passed to Step for the row being removed. - // Implementations must not retain arg. - Inverse(ctx Context, arg ...Value) -} - -// OverloadFunction overloads a function for a virtual table. -// -// https://sqlite.org/c3ref/overload_function.html -func (c *Conn) OverloadFunction(name string, nArg int) error { - defer c.arena.mark()() - namePtr := c.arena.string(name) - rc := res_t(c.call("sqlite3_overload_function", - stk_t(c.handle), stk_t(namePtr), stk_t(nArg))) - return c.error(rc) -} - -func destroyCallback(ctx context.Context, mod api.Module, pApp ptr_t) { - util.DelHandle(ctx, pApp) -} - -func collationCallback(ctx context.Context, mod api.Module, pArg, pDB ptr_t, eTextRep uint32, zName ptr_t) { - if c, ok := ctx.Value(connKey{}).(*Conn); ok && c.handle == pDB && c.collation != nil { - name := util.ReadString(mod, zName, _MAX_NAME) - c.collation(c, name) - } -} - -func compareCallback(ctx context.Context, mod api.Module, pApp ptr_t, nKey1 int32, pKey1 ptr_t, nKey2 int32, pKey2 ptr_t) uint32 { - fn := util.GetHandle(ctx, pApp).(func(a, b []byte) int) - return uint32(fn(util.View(mod, pKey1, int64(nKey1)), util.View(mod, pKey2, int64(nKey2)))) -} - -func funcCallback(ctx context.Context, mod api.Module, pCtx, pApp ptr_t, nArg int32, pArg ptr_t) { - args := getFuncArgs() - defer putFuncArgs(args) - db := ctx.Value(connKey{}).(*Conn) - fn := util.GetHandle(db.ctx, pApp).(ScalarFunction) - callbackArgs(db, args[:nArg], pArg) - fn(Context{db, pCtx}, args[:nArg]...) -} - -func stepCallback(ctx context.Context, mod api.Module, pCtx, pAgg, pApp ptr_t, nArg int32, pArg ptr_t) { - args := getFuncArgs() - defer putFuncArgs(args) - db := ctx.Value(connKey{}).(*Conn) - callbackArgs(db, args[:nArg], pArg) - fn, _ := callbackAggregate(db, pAgg, pApp) - fn.Step(Context{db, pCtx}, args[:nArg]...) -} - -func finalCallback(ctx context.Context, mod api.Module, pCtx, pAgg, pApp ptr_t) { - db := ctx.Value(connKey{}).(*Conn) - fn, handle := callbackAggregate(db, pAgg, pApp) - fn.Value(Context{db, pCtx}) - if err := util.DelHandle(ctx, handle); err != nil { - Context{db, pCtx}.ResultError(err) - return // notest - } -} - -func valueCallback(ctx context.Context, mod api.Module, pCtx, pAgg ptr_t) { - db := ctx.Value(connKey{}).(*Conn) - fn := util.GetHandle(db.ctx, pAgg).(AggregateFunction) - fn.Value(Context{db, pCtx}) -} - -func inverseCallback(ctx context.Context, mod api.Module, pCtx, pAgg ptr_t, nArg int32, pArg ptr_t) { - args := getFuncArgs() - defer putFuncArgs(args) - db := ctx.Value(connKey{}).(*Conn) - callbackArgs(db, args[:nArg], pArg) - fn := util.GetHandle(db.ctx, pAgg).(WindowFunction) - fn.Inverse(Context{db, pCtx}, args[:nArg]...) -} - -func callbackAggregate(db *Conn, pAgg, pApp ptr_t) (AggregateFunction, ptr_t) { - if pApp == 0 { - handle := util.Read32[ptr_t](db.mod, pAgg) - return util.GetHandle(db.ctx, handle).(AggregateFunction), handle - } - - // We need to create the aggregate. - fn := util.GetHandle(db.ctx, pApp).(func() AggregateFunction)() - if pAgg != 0 { - handle := util.AddHandle(db.ctx, fn) - util.Write32(db.mod, pAgg, handle) - return fn, handle - } - return fn, 0 -} - -func callbackArgs(db *Conn, arg []Value, pArg ptr_t) { - for i := range arg { - arg[i] = Value{ - c: db, - handle: util.Read32[ptr_t](db.mod, pArg+ptr_t(i)*ptrlen), - } - } -} - -var funcArgsPool sync.Pool - -func putFuncArgs(p *[_MAX_FUNCTION_ARG]Value) { - funcArgsPool.Put(p) -} - -func getFuncArgs() *[_MAX_FUNCTION_ARG]Value { - if p := funcArgsPool.Get(); p == nil { - return new([_MAX_FUNCTION_ARG]Value) - } else { - return p.(*[_MAX_FUNCTION_ARG]Value) - } -} diff --git a/vendor/github.com/ncruces/go-sqlite3/internal/alloc/alloc_other.go b/vendor/github.com/ncruces/go-sqlite3/internal/alloc/alloc_other.go deleted file mode 100644 index b420acc45..000000000 --- a/vendor/github.com/ncruces/go-sqlite3/internal/alloc/alloc_other.go +++ /dev/null @@ -1,24 +0,0 @@ -//go:build !unix && !windows - -package alloc - -import "github.com/tetratelabs/wazero/experimental" - -func NewMemory(cap, max uint64) experimental.LinearMemory { - return &sliceMemory{make([]byte, 0, cap)} -} - -type sliceMemory struct { - buf []byte -} - -func (b *sliceMemory) Free() {} - -func (b *sliceMemory) Reallocate(size uint64) []byte { - if cap := uint64(cap(b.buf)); size > cap { - b.buf = append(b.buf[:cap], make([]byte, size-cap)...) - } else { - b.buf = b.buf[:size] - } - return b.buf -} diff --git a/vendor/github.com/ncruces/go-sqlite3/internal/alloc/alloc_unix.go b/vendor/github.com/ncruces/go-sqlite3/internal/alloc/alloc_unix.go deleted file mode 100644 index a00dbbf24..000000000 --- a/vendor/github.com/ncruces/go-sqlite3/internal/alloc/alloc_unix.go +++ /dev/null @@ -1,67 +0,0 @@ -//go:build unix - -package alloc - -import ( - "math" - - "github.com/tetratelabs/wazero/experimental" - "golang.org/x/sys/unix" -) - -func NewMemory(_, max uint64) experimental.LinearMemory { - // Round up to the page size. - rnd := uint64(unix.Getpagesize() - 1) - max = (max + rnd) &^ rnd - - if max > math.MaxInt { - // This ensures int(max) overflows to a negative value, - // and unix.Mmap returns EINVAL. - max = math.MaxUint64 - } - - // Reserve max bytes of address space, to ensure we won't need to move it. - // A protected, private, anonymous mapping should not commit memory. - b, err := unix.Mmap(-1, 0, int(max), unix.PROT_NONE, unix.MAP_PRIVATE|unix.MAP_ANON) - if err != nil { - panic(err) - } - return &mmappedMemory{buf: b[:0]} -} - -// The slice covers the entire mmapped memory: -// - len(buf) is the already committed memory, -// - cap(buf) is the reserved address space. -type mmappedMemory struct { - buf []byte -} - -func (m *mmappedMemory) Reallocate(size uint64) []byte { - com := uint64(len(m.buf)) - res := uint64(cap(m.buf)) - if com < size && size <= res { - // Round up to the page size. - rnd := uint64(unix.Getpagesize() - 1) - new := (size + rnd) &^ rnd - - // Commit additional memory up to new bytes. - err := unix.Mprotect(m.buf[com:new], unix.PROT_READ|unix.PROT_WRITE) - if err != nil { - return nil - } - - // Update committed memory. - m.buf = m.buf[:new] - } - // Limit returned capacity because bytes beyond - // len(m.buf) have not yet been committed. - return m.buf[:size:len(m.buf)] -} - -func (m *mmappedMemory) Free() { - err := unix.Munmap(m.buf[:cap(m.buf)]) - if err != nil { - panic(err) - } - m.buf = nil -} diff --git a/vendor/github.com/ncruces/go-sqlite3/internal/alloc/alloc_windows.go b/vendor/github.com/ncruces/go-sqlite3/internal/alloc/alloc_windows.go deleted file mode 100644 index 6bfc73a0c..000000000 --- a/vendor/github.com/ncruces/go-sqlite3/internal/alloc/alloc_windows.go +++ /dev/null @@ -1,74 +0,0 @@ -package alloc - -import ( - "math" - "reflect" - "unsafe" - - "github.com/tetratelabs/wazero/experimental" - "golang.org/x/sys/windows" -) - -func NewMemory(_, max uint64) experimental.LinearMemory { - // Round up to the page size. - rnd := uint64(windows.Getpagesize() - 1) - max = (max + rnd) &^ rnd - - if max > math.MaxInt { - // This ensures uintptr(max) overflows to a large value, - // and windows.VirtualAlloc returns an error. - max = math.MaxUint64 - } - - // Reserve max bytes of address space, to ensure we won't need to move it. - // This does not commit memory. - r, err := windows.VirtualAlloc(0, uintptr(max), windows.MEM_RESERVE, windows.PAGE_READWRITE) - if err != nil { - panic(err) - } - - mem := virtualMemory{addr: r} - // SliceHeader, although deprecated, avoids a go vet warning. - sh := (*reflect.SliceHeader)(unsafe.Pointer(&mem.buf)) - sh.Cap = int(max) - sh.Data = r - return &mem -} - -// The slice covers the entire mmapped memory: -// - len(buf) is the already committed memory, -// - cap(buf) is the reserved address space. -type virtualMemory struct { - buf []byte - addr uintptr -} - -func (m *virtualMemory) Reallocate(size uint64) []byte { - com := uint64(len(m.buf)) - res := uint64(cap(m.buf)) - if com < size && size <= res { - // Round up to the page size. - rnd := uint64(windows.Getpagesize() - 1) - new := (size + rnd) &^ rnd - - // Commit additional memory up to new bytes. - _, err := windows.VirtualAlloc(m.addr, uintptr(new), windows.MEM_COMMIT, windows.PAGE_READWRITE) - if err != nil { - return nil - } - - // Update committed memory. - m.buf = m.buf[:new] - } - // Limit returned capacity because bytes beyond - // len(m.buf) have not yet been committed. - return m.buf[:size:len(m.buf)] -} - -func (m *virtualMemory) Free() { - err := windows.VirtualFree(m.addr, 0, windows.MEM_RELEASE) - if err != nil { - panic(err) - } - m.addr = 0 -} diff --git a/vendor/github.com/ncruces/go-sqlite3/internal/dotlk/dotlk.go b/vendor/github.com/ncruces/go-sqlite3/internal/dotlk/dotlk.go deleted file mode 100644 index 3c8d782d7..000000000 --- a/vendor/github.com/ncruces/go-sqlite3/internal/dotlk/dotlk.go +++ /dev/null @@ -1,29 +0,0 @@ -package dotlk - -import ( - "errors" - "io/fs" - "os" -) - -// LockShm creates a directory on disk to prevent SQLite -// from using this path for a shared memory file. -func LockShm(name string) error { - err := os.Mkdir(name, 0777) - if errors.Is(err, fs.ErrExist) { - s, err := os.Lstat(name) - if err == nil && s.IsDir() { - return nil - } - } - return err -} - -// Unlock removes the lock or shared memory file. -func Unlock(name string) error { - err := os.Remove(name) - if errors.Is(err, fs.ErrNotExist) { - return nil - } - return err -} diff --git a/vendor/github.com/ncruces/go-sqlite3/internal/dotlk/dotlk_other.go b/vendor/github.com/ncruces/go-sqlite3/internal/dotlk/dotlk_other.go deleted file mode 100644 index 5399a5f8a..000000000 --- a/vendor/github.com/ncruces/go-sqlite3/internal/dotlk/dotlk_other.go +++ /dev/null @@ -1,13 +0,0 @@ -//go:build !unix - -package dotlk - -import "os" - -// TryLock returns nil if it acquired the lock, -// fs.ErrExist if another process has the lock. -func TryLock(name string) error { - f, err := os.OpenFile(name, os.O_RDWR|os.O_CREATE|os.O_EXCL, 0666) - f.Close() - return err -} diff --git a/vendor/github.com/ncruces/go-sqlite3/internal/dotlk/dotlk_unix.go b/vendor/github.com/ncruces/go-sqlite3/internal/dotlk/dotlk_unix.go deleted file mode 100644 index 177ab30bb..000000000 --- a/vendor/github.com/ncruces/go-sqlite3/internal/dotlk/dotlk_unix.go +++ /dev/null @@ -1,50 +0,0 @@ -//go:build unix - -package dotlk - -import ( - "errors" - "io/fs" - "os" - "strconv" - - "golang.org/x/sys/unix" -) - -// TryLock returns nil if it acquired the lock, -// fs.ErrExist if another process has the lock. -func TryLock(name string) error { - for retry := true; retry; retry = false { - f, err := os.OpenFile(name, os.O_RDWR|os.O_CREATE|os.O_EXCL, 0666) - if err == nil { - f.WriteString(strconv.Itoa(os.Getpid())) - f.Close() - return nil - } - if !errors.Is(err, fs.ErrExist) { - return err - } - if !removeStale(name) { - break - } - } - return fs.ErrExist -} - -func removeStale(name string) bool { - buf, err := os.ReadFile(name) - if err != nil { - return errors.Is(err, fs.ErrNotExist) - } - - pid, err := strconv.Atoi(string(buf)) - if err != nil { - return false - } - if unix.Kill(pid, 0) == nil { - return false - } - - err = os.Remove(name) - return err == nil || errors.Is(err, fs.ErrNotExist) -} diff --git a/vendor/github.com/ncruces/go-sqlite3/internal/util/compiler.go b/vendor/github.com/ncruces/go-sqlite3/internal/util/compiler.go deleted file mode 100644 index aeefcced9..000000000 --- a/vendor/github.com/ncruces/go-sqlite3/internal/util/compiler.go +++ /dev/null @@ -1,27 +0,0 @@ -package util - -import ( - "runtime" - - "golang.org/x/sys/cpu" -) - -func CompilerSupported() bool { - switch runtime.GOOS { - case "linux", "android", - "windows", "darwin", - "freebsd", "netbsd", "dragonfly", - "solaris", "illumos": - break - default: - return false - } - switch runtime.GOARCH { - case "amd64": - return cpu.X86.HasSSE41 - case "arm64": - return true - default: - return false - } -} diff --git a/vendor/github.com/ncruces/go-sqlite3/internal/util/const.go b/vendor/github.com/ncruces/go-sqlite3/internal/util/const.go deleted file mode 100644 index 5e89018dd..000000000 --- a/vendor/github.com/ncruces/go-sqlite3/internal/util/const.go +++ /dev/null @@ -1,117 +0,0 @@ -package util - -// https://sqlite.com/rescode.html -const ( - OK = 0 /* Successful result */ - - ERROR = 1 /* Generic error */ - INTERNAL = 2 /* Internal logic error in SQLite */ - PERM = 3 /* Access permission denied */ - ABORT = 4 /* Callback routine requested an abort */ - BUSY = 5 /* The database file is locked */ - LOCKED = 6 /* A table in the database is locked */ - NOMEM = 7 /* A malloc() failed */ - READONLY = 8 /* Attempt to write a readonly database */ - INTERRUPT = 9 /* Operation terminated by sqlite3_interrupt() */ - IOERR = 10 /* Some kind of disk I/O error occurred */ - CORRUPT = 11 /* The database disk image is malformed */ - NOTFOUND = 12 /* Unknown opcode in sqlite3_file_control() */ - FULL = 13 /* Insertion failed because database is full */ - CANTOPEN = 14 /* Unable to open the database file */ - PROTOCOL = 15 /* Database lock protocol error */ - EMPTY = 16 /* Internal use only */ - SCHEMA = 17 /* The database schema changed */ - TOOBIG = 18 /* String or BLOB exceeds size limit */ - CONSTRAINT = 19 /* Abort due to constraint violation */ - MISMATCH = 20 /* Data type mismatch */ - MISUSE = 21 /* Library used incorrectly */ - NOLFS = 22 /* Uses OS features not supported on host */ - AUTH = 23 /* Authorization denied */ - FORMAT = 24 /* Not used */ - RANGE = 25 /* 2nd parameter to sqlite3_bind out of range */ - NOTADB = 26 /* File opened that is not a database file */ - NOTICE = 27 /* Notifications from sqlite3_log() */ - WARNING = 28 /* Warnings from sqlite3_log() */ - - ROW = 100 /* sqlite3_step() has another row ready */ - DONE = 101 /* sqlite3_step() has finished executing */ - - ERROR_MISSING_COLLSEQ = ERROR | (1 << 8) - ERROR_RETRY = ERROR | (2 << 8) - ERROR_SNAPSHOT = ERROR | (3 << 8) - IOERR_READ = IOERR | (1 << 8) - IOERR_SHORT_READ = IOERR | (2 << 8) - IOERR_WRITE = IOERR | (3 << 8) - IOERR_FSYNC = IOERR | (4 << 8) - IOERR_DIR_FSYNC = IOERR | (5 << 8) - IOERR_TRUNCATE = IOERR | (6 << 8) - IOERR_FSTAT = IOERR | (7 << 8) - IOERR_UNLOCK = IOERR | (8 << 8) - IOERR_RDLOCK = IOERR | (9 << 8) - IOERR_DELETE = IOERR | (10 << 8) - IOERR_BLOCKED = IOERR | (11 << 8) - IOERR_NOMEM = IOERR | (12 << 8) - IOERR_ACCESS = IOERR | (13 << 8) - IOERR_CHECKRESERVEDLOCK = IOERR | (14 << 8) - IOERR_LOCK = IOERR | (15 << 8) - IOERR_CLOSE = IOERR | (16 << 8) - IOERR_DIR_CLOSE = IOERR | (17 << 8) - IOERR_SHMOPEN = IOERR | (18 << 8) - IOERR_SHMSIZE = IOERR | (19 << 8) - IOERR_SHMLOCK = IOERR | (20 << 8) - IOERR_SHMMAP = IOERR | (21 << 8) - IOERR_SEEK = IOERR | (22 << 8) - IOERR_DELETE_NOENT = IOERR | (23 << 8) - IOERR_MMAP = IOERR | (24 << 8) - IOERR_GETTEMPPATH = IOERR | (25 << 8) - IOERR_CONVPATH = IOERR | (26 << 8) - IOERR_VNODE = IOERR | (27 << 8) - IOERR_AUTH = IOERR | (28 << 8) - IOERR_BEGIN_ATOMIC = IOERR | (29 << 8) - IOERR_COMMIT_ATOMIC = IOERR | (30 << 8) - IOERR_ROLLBACK_ATOMIC = IOERR | (31 << 8) - IOERR_DATA = IOERR | (32 << 8) - IOERR_CORRUPTFS = IOERR | (33 << 8) - IOERR_IN_PAGE = IOERR | (34 << 8) - LOCKED_SHAREDCACHE = LOCKED | (1 << 8) - LOCKED_VTAB = LOCKED | (2 << 8) - BUSY_RECOVERY = BUSY | (1 << 8) - BUSY_SNAPSHOT = BUSY | (2 << 8) - BUSY_TIMEOUT = BUSY | (3 << 8) - CANTOPEN_NOTEMPDIR = CANTOPEN | (1 << 8) - CANTOPEN_ISDIR = CANTOPEN | (2 << 8) - CANTOPEN_FULLPATH = CANTOPEN | (3 << 8) - CANTOPEN_CONVPATH = CANTOPEN | (4 << 8) - CANTOPEN_DIRTYWAL = CANTOPEN | (5 << 8) /* Not Used */ - CANTOPEN_SYMLINK = CANTOPEN | (6 << 8) - CORRUPT_VTAB = CORRUPT | (1 << 8) - CORRUPT_SEQUENCE = CORRUPT | (2 << 8) - CORRUPT_INDEX = CORRUPT | (3 << 8) - READONLY_RECOVERY = READONLY | (1 << 8) - READONLY_CANTLOCK = READONLY | (2 << 8) - READONLY_ROLLBACK = READONLY | (3 << 8) - READONLY_DBMOVED = READONLY | (4 << 8) - READONLY_CANTINIT = READONLY | (5 << 8) - READONLY_DIRECTORY = READONLY | (6 << 8) - ABORT_ROLLBACK = ABORT | (2 << 8) - CONSTRAINT_CHECK = CONSTRAINT | (1 << 8) - CONSTRAINT_COMMITHOOK = CONSTRAINT | (2 << 8) - CONSTRAINT_FOREIGNKEY = CONSTRAINT | (3 << 8) - CONSTRAINT_FUNCTION = CONSTRAINT | (4 << 8) - CONSTRAINT_NOTNULL = CONSTRAINT | (5 << 8) - CONSTRAINT_PRIMARYKEY = CONSTRAINT | (6 << 8) - CONSTRAINT_TRIGGER = CONSTRAINT | (7 << 8) - CONSTRAINT_UNIQUE = CONSTRAINT | (8 << 8) - CONSTRAINT_VTAB = CONSTRAINT | (9 << 8) - CONSTRAINT_ROWID = CONSTRAINT | (10 << 8) - CONSTRAINT_PINNED = CONSTRAINT | (11 << 8) - CONSTRAINT_DATATYPE = CONSTRAINT | (12 << 8) - NOTICE_RECOVER_WAL = NOTICE | (1 << 8) - NOTICE_RECOVER_ROLLBACK = NOTICE | (2 << 8) - NOTICE_RBU = NOTICE | (3 << 8) - WARNING_AUTOINDEX = WARNING | (1 << 8) - AUTH_USER = AUTH | (1 << 8) - - OK_LOAD_PERMANENTLY = OK | (1 << 8) - OK_SYMLINK = OK | (2 << 8) /* internal use only */ -) diff --git a/vendor/github.com/ncruces/go-sqlite3/internal/util/error.go b/vendor/github.com/ncruces/go-sqlite3/internal/util/error.go deleted file mode 100644 index 2aecac96e..000000000 --- a/vendor/github.com/ncruces/go-sqlite3/internal/util/error.go +++ /dev/null @@ -1,116 +0,0 @@ -package util - -import ( - "runtime" - "strconv" -) - -type ErrorString string - -func (e ErrorString) Error() string { return string(e) } - -const ( - NilErr = ErrorString("sqlite3: invalid memory address or null pointer dereference") - OOMErr = ErrorString("sqlite3: out of memory") - RangeErr = ErrorString("sqlite3: index out of range") - NoNulErr = ErrorString("sqlite3: missing NUL terminator") - NoBinaryErr = ErrorString("sqlite3: no SQLite binary embed/set/loaded") - BadBinaryErr = ErrorString("sqlite3: invalid SQLite binary embed/set/loaded") - TimeErr = ErrorString("sqlite3: invalid time value") - WhenceErr = ErrorString("sqlite3: invalid whence") - OffsetErr = ErrorString("sqlite3: invalid offset") - TailErr = ErrorString("sqlite3: multiple statements") - IsolationErr = ErrorString("sqlite3: unsupported isolation level") - ValueErr = ErrorString("sqlite3: unsupported value") - NoVFSErr = ErrorString("sqlite3: no such vfs: ") -) - -func AssertErr() ErrorString { - msg := "sqlite3: assertion failed" - if _, file, line, ok := runtime.Caller(1); ok { - msg += " (" + file + ":" + strconv.Itoa(line) + ")" - } - return ErrorString(msg) -} - -func ErrorCodeString(rc uint32) string { - switch rc { - case ABORT_ROLLBACK: - return "sqlite3: abort due to ROLLBACK" - case ROW: - return "sqlite3: another row available" - case DONE: - return "sqlite3: no more rows available" - } - switch rc & 0xff { - case OK: - return "sqlite3: not an error" - case ERROR: - return "sqlite3: SQL logic error" - case INTERNAL: - break - case PERM: - return "sqlite3: access permission denied" - case ABORT: - return "sqlite3: query aborted" - case BUSY: - return "sqlite3: database is locked" - case LOCKED: - return "sqlite3: database table is locked" - case NOMEM: - return "sqlite3: out of memory" - case READONLY: - return "sqlite3: attempt to write a readonly database" - case INTERRUPT: - return "sqlite3: interrupted" - case IOERR: - return "sqlite3: disk I/O error" - case CORRUPT: - return "sqlite3: database disk image is malformed" - case NOTFOUND: - return "sqlite3: unknown operation" - case FULL: - return "sqlite3: database or disk is full" - case CANTOPEN: - return "sqlite3: unable to open database file" - case PROTOCOL: - return "sqlite3: locking protocol" - case FORMAT: - break - case SCHEMA: - return "sqlite3: database schema has changed" - case TOOBIG: - return "sqlite3: string or blob too big" - case CONSTRAINT: - return "sqlite3: constraint failed" - case MISMATCH: - return "sqlite3: datatype mismatch" - case MISUSE: - return "sqlite3: bad parameter or other API misuse" - case NOLFS: - break - case AUTH: - return "sqlite3: authorization denied" - case EMPTY: - break - case RANGE: - return "sqlite3: column index out of range" - case NOTADB: - return "sqlite3: file is not a database" - case NOTICE: - return "sqlite3: notification message" - case WARNING: - return "sqlite3: warning message" - } - return "sqlite3: unknown error" -} - -type ErrorJoiner []error - -func (j *ErrorJoiner) Join(errs ...error) { - for _, err := range errs { - if err != nil { - *j = append(*j, err) - } - } -} diff --git a/vendor/github.com/ncruces/go-sqlite3/internal/util/func.go b/vendor/github.com/ncruces/go-sqlite3/internal/util/func.go deleted file mode 100644 index e705f3181..000000000 --- a/vendor/github.com/ncruces/go-sqlite3/internal/util/func.go +++ /dev/null @@ -1,202 +0,0 @@ -package util - -import ( - "context" - - "github.com/tetratelabs/wazero" - "github.com/tetratelabs/wazero/api" -) - -type funcVI[T0 i32] func(context.Context, api.Module, T0) - -func (fn funcVI[T0]) Call(ctx context.Context, mod api.Module, stack []uint64) { - fn(ctx, mod, T0(stack[0])) -} - -func ExportFuncVI[T0 i32](mod wazero.HostModuleBuilder, name string, fn func(context.Context, api.Module, T0)) { - mod.NewFunctionBuilder(). - WithGoModuleFunction(funcVI[T0](fn), - []api.ValueType{api.ValueTypeI32}, nil). - Export(name) -} - -type funcVII[T0, T1 i32] func(context.Context, api.Module, T0, T1) - -func (fn funcVII[T0, T1]) Call(ctx context.Context, mod api.Module, stack []uint64) { - _ = stack[1] // prevent bounds check on every slice access - fn(ctx, mod, T0(stack[0]), T1(stack[1])) -} - -func ExportFuncVII[T0, T1 i32](mod wazero.HostModuleBuilder, name string, fn func(context.Context, api.Module, T0, T1)) { - mod.NewFunctionBuilder(). - WithGoModuleFunction(funcVII[T0, T1](fn), - []api.ValueType{api.ValueTypeI32, api.ValueTypeI32}, nil). - Export(name) -} - -type funcVIII[T0, T1, T2 i32] func(context.Context, api.Module, T0, T1, T2) - -func (fn funcVIII[T0, T1, T2]) Call(ctx context.Context, mod api.Module, stack []uint64) { - _ = stack[2] // prevent bounds check on every slice access - fn(ctx, mod, T0(stack[0]), T1(stack[1]), T2(stack[2])) -} - -func ExportFuncVIII[T0, T1, T2 i32](mod wazero.HostModuleBuilder, name string, fn func(context.Context, api.Module, T0, T1, T2)) { - mod.NewFunctionBuilder(). - WithGoModuleFunction(funcVIII[T0, T1, T2](fn), - []api.ValueType{api.ValueTypeI32, api.ValueTypeI32, api.ValueTypeI32}, nil). - Export(name) -} - -type funcVIIII[T0, T1, T2, T3 i32] func(context.Context, api.Module, T0, T1, T2, T3) - -func (fn funcVIIII[T0, T1, T2, T3]) Call(ctx context.Context, mod api.Module, stack []uint64) { - _ = stack[3] // prevent bounds check on every slice access - fn(ctx, mod, T0(stack[0]), T1(stack[1]), T2(stack[2]), T3(stack[3])) -} - -func ExportFuncVIIII[T0, T1, T2, T3 i32](mod wazero.HostModuleBuilder, name string, fn func(context.Context, api.Module, T0, T1, T2, T3)) { - mod.NewFunctionBuilder(). - WithGoModuleFunction(funcVIIII[T0, T1, T2, T3](fn), - []api.ValueType{api.ValueTypeI32, api.ValueTypeI32, api.ValueTypeI32, api.ValueTypeI32}, nil). - Export(name) -} - -type funcVIIIII[T0, T1, T2, T3, T4 i32] func(context.Context, api.Module, T0, T1, T2, T3, T4) - -func (fn funcVIIIII[T0, T1, T2, T3, T4]) Call(ctx context.Context, mod api.Module, stack []uint64) { - _ = stack[4] // prevent bounds check on every slice access - fn(ctx, mod, T0(stack[0]), T1(stack[1]), T2(stack[2]), T3(stack[3]), T4(stack[4])) -} - -func ExportFuncVIIIII[T0, T1, T2, T3, T4 i32](mod wazero.HostModuleBuilder, name string, fn func(context.Context, api.Module, T0, T1, T2, T3, T4)) { - mod.NewFunctionBuilder(). - WithGoModuleFunction(funcVIIIII[T0, T1, T2, T3, T4](fn), - []api.ValueType{api.ValueTypeI32, api.ValueTypeI32, api.ValueTypeI32, api.ValueTypeI32, api.ValueTypeI32}, nil). - Export(name) -} - -type funcVIIIIJ[T0, T1, T2, T3 i32, T4 i64] func(context.Context, api.Module, T0, T1, T2, T3, T4) - -func (fn funcVIIIIJ[T0, T1, T2, T3, T4]) Call(ctx context.Context, mod api.Module, stack []uint64) { - _ = stack[4] // prevent bounds check on every slice access - fn(ctx, mod, T0(stack[0]), T1(stack[1]), T2(stack[2]), T3(stack[3]), T4(stack[4])) -} - -func ExportFuncVIIIIJ[T0, T1, T2, T3 i32, T4 i64](mod wazero.HostModuleBuilder, name string, fn func(context.Context, api.Module, T0, T1, T2, T3, T4)) { - mod.NewFunctionBuilder(). - WithGoModuleFunction(funcVIIIIJ[T0, T1, T2, T3, T4](fn), - []api.ValueType{api.ValueTypeI32, api.ValueTypeI32, api.ValueTypeI32, api.ValueTypeI32, api.ValueTypeI64}, nil). - Export(name) -} - -type funcII[TR, T0 i32] func(context.Context, api.Module, T0) TR - -func (fn funcII[TR, T0]) Call(ctx context.Context, mod api.Module, stack []uint64) { - stack[0] = uint64(fn(ctx, mod, T0(stack[0]))) -} - -func ExportFuncII[TR, T0 i32](mod wazero.HostModuleBuilder, name string, fn func(context.Context, api.Module, T0) TR) { - mod.NewFunctionBuilder(). - WithGoModuleFunction(funcII[TR, T0](fn), - []api.ValueType{api.ValueTypeI32}, []api.ValueType{api.ValueTypeI32}). - Export(name) -} - -type funcIII[TR, T0, T1 i32] func(context.Context, api.Module, T0, T1) TR - -func (fn funcIII[TR, T0, T1]) Call(ctx context.Context, mod api.Module, stack []uint64) { - _ = stack[1] // prevent bounds check on every slice access - stack[0] = uint64(fn(ctx, mod, T0(stack[0]), T1(stack[1]))) -} - -func ExportFuncIII[TR, T0, T1 i32](mod wazero.HostModuleBuilder, name string, fn func(context.Context, api.Module, T0, T1) TR) { - mod.NewFunctionBuilder(). - WithGoModuleFunction(funcIII[TR, T0, T1](fn), - []api.ValueType{api.ValueTypeI32, api.ValueTypeI32}, []api.ValueType{api.ValueTypeI32}). - Export(name) -} - -type funcIIII[TR, T0, T1, T2 i32] func(context.Context, api.Module, T0, T1, T2) TR - -func (fn funcIIII[TR, T0, T1, T2]) Call(ctx context.Context, mod api.Module, stack []uint64) { - _ = stack[2] // prevent bounds check on every slice access - stack[0] = uint64(fn(ctx, mod, T0(stack[0]), T1(stack[1]), T2(stack[2]))) -} - -func ExportFuncIIII[TR, T0, T1, T2 i32](mod wazero.HostModuleBuilder, name string, fn func(context.Context, api.Module, T0, T1, T2) TR) { - mod.NewFunctionBuilder(). - WithGoModuleFunction(funcIIII[TR, T0, T1, T2](fn), - []api.ValueType{api.ValueTypeI32, api.ValueTypeI32, api.ValueTypeI32}, []api.ValueType{api.ValueTypeI32}). - Export(name) -} - -type funcIIIII[TR, T0, T1, T2, T3 i32] func(context.Context, api.Module, T0, T1, T2, T3) TR - -func (fn funcIIIII[TR, T0, T1, T2, T3]) Call(ctx context.Context, mod api.Module, stack []uint64) { - _ = stack[3] // prevent bounds check on every slice access - stack[0] = uint64(fn(ctx, mod, T0(stack[0]), T1(stack[1]), T2(stack[2]), T3(stack[3]))) -} - -func ExportFuncIIIII[TR, T0, T1, T2, T3 i32](mod wazero.HostModuleBuilder, name string, fn func(context.Context, api.Module, T0, T1, T2, T3) TR) { - mod.NewFunctionBuilder(). - WithGoModuleFunction(funcIIIII[TR, T0, T1, T2, T3](fn), - []api.ValueType{api.ValueTypeI32, api.ValueTypeI32, api.ValueTypeI32, api.ValueTypeI32}, []api.ValueType{api.ValueTypeI32}). - Export(name) -} - -type funcIIIIII[TR, T0, T1, T2, T3, T4 i32] func(context.Context, api.Module, T0, T1, T2, T3, T4) TR - -func (fn funcIIIIII[TR, T0, T1, T2, T3, T4]) Call(ctx context.Context, mod api.Module, stack []uint64) { - _ = stack[4] // prevent bounds check on every slice access - stack[0] = uint64(fn(ctx, mod, T0(stack[0]), T1(stack[1]), T2(stack[2]), T3(stack[3]), T4(stack[4]))) -} - -func ExportFuncIIIIII[TR, T0, T1, T2, T3, T4 i32](mod wazero.HostModuleBuilder, name string, fn func(context.Context, api.Module, T0, T1, T2, T3, T4) TR) { - mod.NewFunctionBuilder(). - WithGoModuleFunction(funcIIIIII[TR, T0, T1, T2, T3, T4](fn), - []api.ValueType{api.ValueTypeI32, api.ValueTypeI32, api.ValueTypeI32, api.ValueTypeI32, api.ValueTypeI32}, []api.ValueType{api.ValueTypeI32}). - Export(name) -} - -type funcIIIIIII[TR, T0, T1, T2, T3, T4, T5 i32] func(context.Context, api.Module, T0, T1, T2, T3, T4, T5) TR - -func (fn funcIIIIIII[TR, T0, T1, T2, T3, T4, T5]) Call(ctx context.Context, mod api.Module, stack []uint64) { - _ = stack[5] // prevent bounds check on every slice access - stack[0] = uint64(fn(ctx, mod, T0(stack[0]), T1(stack[1]), T2(stack[2]), T3(stack[3]), T4(stack[4]), T5(stack[5]))) -} - -func ExportFuncIIIIIII[TR, T0, T1, T2, T3, T4, T5 i32](mod wazero.HostModuleBuilder, name string, fn func(context.Context, api.Module, T0, T1, T2, T3, T4, T5) TR) { - mod.NewFunctionBuilder(). - WithGoModuleFunction(funcIIIIIII[TR, T0, T1, T2, T3, T4, T5](fn), - []api.ValueType{api.ValueTypeI32, api.ValueTypeI32, api.ValueTypeI32, api.ValueTypeI32, api.ValueTypeI32, api.ValueTypeI32}, []api.ValueType{api.ValueTypeI32}). - Export(name) -} - -type funcIIIIJ[TR, T0, T1, T2 i32, T3 i64] func(context.Context, api.Module, T0, T1, T2, T3) TR - -func (fn funcIIIIJ[TR, T0, T1, T2, T3]) Call(ctx context.Context, mod api.Module, stack []uint64) { - _ = stack[3] // prevent bounds check on every slice access - stack[0] = uint64(fn(ctx, mod, T0(stack[0]), T1(stack[1]), T2(stack[2]), T3(stack[3]))) -} - -func ExportFuncIIIIJ[TR, T0, T1, T2 i32, T3 i64](mod wazero.HostModuleBuilder, name string, fn func(context.Context, api.Module, T0, T1, T2, T3) TR) { - mod.NewFunctionBuilder(). - WithGoModuleFunction(funcIIIIJ[TR, T0, T1, T2, T3](fn), - []api.ValueType{api.ValueTypeI32, api.ValueTypeI32, api.ValueTypeI32, api.ValueTypeI64}, []api.ValueType{api.ValueTypeI32}). - Export(name) -} - -type funcIIJ[TR, T0 i32, T1 i64] func(context.Context, api.Module, T0, T1) TR - -func (fn funcIIJ[TR, T0, T1]) Call(ctx context.Context, mod api.Module, stack []uint64) { - _ = stack[1] // prevent bounds check on every slice access - stack[0] = uint64(fn(ctx, mod, T0(stack[0]), T1(stack[1]))) -} - -func ExportFuncIIJ[TR, T0 i32, T1 i64](mod wazero.HostModuleBuilder, name string, fn func(context.Context, api.Module, T0, T1) TR) { - mod.NewFunctionBuilder(). - WithGoModuleFunction(funcIIJ[TR, T0, T1](fn), - []api.ValueType{api.ValueTypeI32, api.ValueTypeI64}, []api.ValueType{api.ValueTypeI32}). - Export(name) -} diff --git a/vendor/github.com/ncruces/go-sqlite3/internal/util/handle.go b/vendor/github.com/ncruces/go-sqlite3/internal/util/handle.go deleted file mode 100644 index f9f39b449..000000000 --- a/vendor/github.com/ncruces/go-sqlite3/internal/util/handle.go +++ /dev/null @@ -1,70 +0,0 @@ -package util - -import ( - "context" - "io" -) - -type handleState struct { - handles []any - holes int -} - -func (s *handleState) CloseNotify(ctx context.Context, exitCode uint32) { - for _, h := range s.handles { - if c, ok := h.(io.Closer); ok { - c.Close() - } - } - s.handles = nil - s.holes = 0 -} - -func GetHandle(ctx context.Context, id Ptr_t) any { - if id == 0 { - return nil - } - s := ctx.Value(moduleKey{}).(*moduleState) - return s.handles[^id] -} - -func DelHandle(ctx context.Context, id Ptr_t) error { - if id == 0 { - return nil - } - s := ctx.Value(moduleKey{}).(*moduleState) - a := s.handles[^id] - s.handles[^id] = nil - if l := Ptr_t(len(s.handles)); l == ^id { - s.handles = s.handles[:l-1] - } else { - s.holes++ - } - if c, ok := a.(io.Closer); ok { - return c.Close() - } - return nil -} - -func AddHandle(ctx context.Context, a any) Ptr_t { - if a == nil { - panic(NilErr) - } - - s := ctx.Value(moduleKey{}).(*moduleState) - - // Find an empty slot. - if s.holes > cap(s.handles)-len(s.handles) { - for id, h := range s.handles { - if h == nil { - s.holes-- - s.handles[id] = a - return ^Ptr_t(id) - } - } - } - - // Add a new slot. - s.handles = append(s.handles, a) - return -Ptr_t(len(s.handles)) -} diff --git a/vendor/github.com/ncruces/go-sqlite3/internal/util/json.go b/vendor/github.com/ncruces/go-sqlite3/internal/util/json.go deleted file mode 100644 index 846237405..000000000 --- a/vendor/github.com/ncruces/go-sqlite3/internal/util/json.go +++ /dev/null @@ -1,50 +0,0 @@ -package util - -import ( - "encoding/json" - "math" - "strconv" - "time" - "unsafe" -) - -type JSON struct{ Value any } - -func (j JSON) Scan(value any) error { - var buf []byte - - switch v := value.(type) { - case []byte: - buf = v - case string: - buf = unsafe.Slice(unsafe.StringData(v), len(v)) - case int64: - buf = strconv.AppendInt(nil, v, 10) - case float64: - buf = AppendNumber(nil, v) - case time.Time: - buf = append(buf, '"') - buf = v.AppendFormat(buf, time.RFC3339Nano) - buf = append(buf, '"') - case nil: - buf = []byte("null") - default: - panic(AssertErr()) - } - - return json.Unmarshal(buf, j.Value) -} - -func AppendNumber(dst []byte, f float64) []byte { - switch { - case math.IsNaN(f): - dst = append(dst, "null"...) - case math.IsInf(f, 1): - dst = append(dst, "9.0e999"...) - case math.IsInf(f, -1): - dst = append(dst, "-9.0e999"...) - default: - return strconv.AppendFloat(dst, f, 'g', -1, 64) - } - return dst -} diff --git a/vendor/github.com/ncruces/go-sqlite3/internal/util/math.go b/vendor/github.com/ncruces/go-sqlite3/internal/util/math.go deleted file mode 100644 index a95f73764..000000000 --- a/vendor/github.com/ncruces/go-sqlite3/internal/util/math.go +++ /dev/null @@ -1,29 +0,0 @@ -package util - -import "math" - -func abs(n int) int { - if n < 0 { - return -n - } - return n -} - -func GCD(m, n int) int { - for n != 0 { - m, n = n, m%n - } - return abs(m) -} - -func LCM(m, n int) int { - if n == 0 { - return 0 - } - return abs(n) * (abs(m) / GCD(m, n)) -} - -// https://developer.nvidia.com/blog/lerp-faster-cuda/ -func Lerp(v0, v1, t float64) float64 { - return math.FMA(t, v1, math.FMA(-t, v0, v0)) -} diff --git a/vendor/github.com/ncruces/go-sqlite3/internal/util/mem.go b/vendor/github.com/ncruces/go-sqlite3/internal/util/mem.go deleted file mode 100644 index bfb1a6440..000000000 --- a/vendor/github.com/ncruces/go-sqlite3/internal/util/mem.go +++ /dev/null @@ -1,145 +0,0 @@ -package util - -import ( - "bytes" - "math" - - "github.com/tetratelabs/wazero/api" -) - -const ( - PtrLen = 4 - IntLen = 4 -) - -type ( - i8 interface{ ~int8 | ~uint8 } - i32 interface{ ~int32 | ~uint32 } - i64 interface{ ~int64 | ~uint64 } - - Stk_t = uint64 - Ptr_t uint32 - Res_t int32 -) - -func View(mod api.Module, ptr Ptr_t, size int64) []byte { - if ptr == 0 { - panic(NilErr) - } - if size == 0 { - return nil - } - if uint64(size) > math.MaxUint32 { - panic(RangeErr) - } - buf, ok := mod.Memory().Read(uint32(ptr), uint32(size)) - if !ok { - panic(RangeErr) - } - return buf -} - -func Read[T i8](mod api.Module, ptr Ptr_t) T { - if ptr == 0 { - panic(NilErr) - } - v, ok := mod.Memory().ReadByte(uint32(ptr)) - if !ok { - panic(RangeErr) - } - return T(v) -} - -func Write[T i8](mod api.Module, ptr Ptr_t, v T) { - if ptr == 0 { - panic(NilErr) - } - ok := mod.Memory().WriteByte(uint32(ptr), uint8(v)) - if !ok { - panic(RangeErr) - } -} - -func Read32[T i32](mod api.Module, ptr Ptr_t) T { - if ptr == 0 { - panic(NilErr) - } - v, ok := mod.Memory().ReadUint32Le(uint32(ptr)) - if !ok { - panic(RangeErr) - } - return T(v) -} - -func Write32[T i32](mod api.Module, ptr Ptr_t, v T) { - if ptr == 0 { - panic(NilErr) - } - ok := mod.Memory().WriteUint32Le(uint32(ptr), uint32(v)) - if !ok { - panic(RangeErr) - } -} - -func Read64[T i64](mod api.Module, ptr Ptr_t) T { - if ptr == 0 { - panic(NilErr) - } - v, ok := mod.Memory().ReadUint64Le(uint32(ptr)) - if !ok { - panic(RangeErr) - } - return T(v) -} - -func Write64[T i64](mod api.Module, ptr Ptr_t, v T) { - if ptr == 0 { - panic(NilErr) - } - ok := mod.Memory().WriteUint64Le(uint32(ptr), uint64(v)) - if !ok { - panic(RangeErr) - } -} - -func ReadFloat64(mod api.Module, ptr Ptr_t) float64 { - return math.Float64frombits(Read64[uint64](mod, ptr)) -} - -func WriteFloat64(mod api.Module, ptr Ptr_t, v float64) { - Write64(mod, ptr, math.Float64bits(v)) -} - -func ReadString(mod api.Module, ptr Ptr_t, maxlen int64) string { - if ptr == 0 { - panic(NilErr) - } - if maxlen <= 0 { - return "" - } - mem := mod.Memory() - maxlen = min(maxlen, math.MaxInt32-1) + 1 - buf, ok := mem.Read(uint32(ptr), uint32(maxlen)) - if !ok { - buf, ok = mem.Read(uint32(ptr), mem.Size()-uint32(ptr)) - if !ok { - panic(RangeErr) - } - } - if i := bytes.IndexByte(buf, 0); i < 0 { - panic(NoNulErr) - } else { - return string(buf[:i]) - } -} - -func WriteBytes(mod api.Module, ptr Ptr_t, b []byte) { - buf := View(mod, ptr, int64(len(b))) - copy(buf, b) -} - -func WriteString(mod api.Module, ptr Ptr_t, s string) { - buf := View(mod, ptr, int64(len(s))+1) - buf[len(s)] = 0 - copy(buf, s) -} diff --git a/vendor/github.com/ncruces/go-sqlite3/internal/util/mmap_other.go b/vendor/github.com/ncruces/go-sqlite3/internal/util/mmap_other.go deleted file mode 100644 index 720977b8d..000000000 --- a/vendor/github.com/ncruces/go-sqlite3/internal/util/mmap_other.go +++ /dev/null @@ -1,5 +0,0 @@ -//go:build !unix - -package util - -type mmapState struct{} diff --git a/vendor/github.com/ncruces/go-sqlite3/internal/util/mmap_unix.go b/vendor/github.com/ncruces/go-sqlite3/internal/util/mmap_unix.go deleted file mode 100644 index 42a247529..000000000 --- a/vendor/github.com/ncruces/go-sqlite3/internal/util/mmap_unix.go +++ /dev/null @@ -1,87 +0,0 @@ -//go:build unix - -package util - -import ( - "context" - "os" - "unsafe" - - "github.com/tetratelabs/wazero/api" - "golang.org/x/sys/unix" -) - -type mmapState struct { - regions []*MappedRegion -} - -func (s *mmapState) new(ctx context.Context, mod api.Module, size int32) *MappedRegion { - // Find unused region. - for _, r := range s.regions { - if !r.used && r.size == size { - return r - } - } - - // Allocate page aligned memmory. - alloc := mod.ExportedFunction("aligned_alloc") - stack := [...]Stk_t{ - Stk_t(unix.Getpagesize()), - Stk_t(size), - } - if err := alloc.CallWithStack(ctx, stack[:]); err != nil { - panic(err) - } - if stack[0] == 0 { - panic(OOMErr) - } - - // Save the newly allocated region. - ptr := Ptr_t(stack[0]) - buf := View(mod, ptr, int64(size)) - ret := &MappedRegion{ - Ptr: ptr, - size: size, - addr: unsafe.Pointer(&buf[0]), - } - s.regions = append(s.regions, ret) - return ret -} - -type MappedRegion struct { - addr unsafe.Pointer - Ptr Ptr_t - size int32 - used bool -} - -func MapRegion(ctx context.Context, mod api.Module, f *os.File, offset int64, size int32, readOnly bool) (*MappedRegion, error) { - s := ctx.Value(moduleKey{}).(*moduleState) - r := s.new(ctx, mod, size) - err := r.mmap(f, offset, readOnly) - if err != nil { - return nil, err - } - return r, nil -} - -func (r *MappedRegion) Unmap() error { - // We can't munmap the region, otherwise it could be remaped. - // Instead, convert it to a protected, private, anonymous mapping. - // If successful, it can be reused for a subsequent mmap. - _, err := unix.MmapPtr(-1, 0, r.addr, uintptr(r.size), - unix.PROT_NONE, unix.MAP_PRIVATE|unix.MAP_FIXED|unix.MAP_ANON) - r.used = err != nil - return err -} - -func (r *MappedRegion) mmap(f *os.File, offset int64, readOnly bool) error { - prot := unix.PROT_READ - if !readOnly { - prot |= unix.PROT_WRITE - } - _, err := unix.MmapPtr(int(f.Fd()), offset, r.addr, uintptr(r.size), - prot, unix.MAP_SHARED|unix.MAP_FIXED) - r.used = err == nil - return err -} diff --git a/vendor/github.com/ncruces/go-sqlite3/internal/util/mmap_windows.go b/vendor/github.com/ncruces/go-sqlite3/internal/util/mmap_windows.go deleted file mode 100644 index 913a5f733..000000000 --- a/vendor/github.com/ncruces/go-sqlite3/internal/util/mmap_windows.go +++ /dev/null @@ -1,51 +0,0 @@ -package util - -import ( - "context" - "os" - "reflect" - "unsafe" - - "github.com/tetratelabs/wazero/api" - "golang.org/x/sys/windows" -) - -type MappedRegion struct { - windows.Handle - Data []byte - addr uintptr -} - -func MapRegion(ctx context.Context, mod api.Module, f *os.File, offset int64, size int32) (*MappedRegion, error) { - h, err := windows.CreateFileMapping(windows.Handle(f.Fd()), nil, windows.PAGE_READWRITE, 0, 0, nil) - if h == 0 { - return nil, err - } - - a, err := windows.MapViewOfFile(h, windows.FILE_MAP_WRITE, - uint32(offset>>32), uint32(offset), uintptr(size)) - if a == 0 { - windows.CloseHandle(h) - return nil, err - } - - ret := &MappedRegion{Handle: h, addr: a} - // SliceHeader, although deprecated, avoids a go vet warning. - sh := (*reflect.SliceHeader)(unsafe.Pointer(&ret.Data)) - sh.Len = int(size) - sh.Cap = int(size) - sh.Data = a - return ret, nil -} - -func (r *MappedRegion) Unmap() error { - if r.Data == nil { - return nil - } - err := windows.UnmapViewOfFile(r.addr) - if err != nil { - return err - } - r.Data = nil - return windows.CloseHandle(r.Handle) -} diff --git a/vendor/github.com/ncruces/go-sqlite3/internal/util/module.go b/vendor/github.com/ncruces/go-sqlite3/internal/util/module.go deleted file mode 100644 index ba5754a32..000000000 --- a/vendor/github.com/ncruces/go-sqlite3/internal/util/module.go +++ /dev/null @@ -1,25 +0,0 @@ -package util - -import ( - "context" - - "github.com/tetratelabs/wazero/experimental" - - "github.com/ncruces/go-sqlite3/internal/alloc" -) - -type ConnKey struct{} - -type moduleKey struct{} -type moduleState struct { - mmapState - handleState -} - -func NewContext(ctx context.Context) context.Context { - state := new(moduleState) - ctx = experimental.WithMemoryAllocator(ctx, experimental.MemoryAllocatorFunc(alloc.NewMemory)) - ctx = experimental.WithCloseNotifier(ctx, state) - ctx = context.WithValue(ctx, moduleKey{}, state) - return ctx -} diff --git a/vendor/github.com/ncruces/go-sqlite3/internal/util/pointer.go b/vendor/github.com/ncruces/go-sqlite3/internal/util/pointer.go deleted file mode 100644 index eae4dae17..000000000 --- a/vendor/github.com/ncruces/go-sqlite3/internal/util/pointer.go +++ /dev/null @@ -1,11 +0,0 @@ -package util - -type Pointer[T any] struct{ Value T } - -func (p Pointer[T]) unwrap() any { return p.Value } - -type PointerUnwrap interface{ unwrap() any } - -func UnwrapPointer(p PointerUnwrap) any { - return p.unwrap() -} diff --git a/vendor/github.com/ncruces/go-sqlite3/internal/util/reflect.go b/vendor/github.com/ncruces/go-sqlite3/internal/util/reflect.go deleted file mode 100644 index 3104a7cf3..000000000 --- a/vendor/github.com/ncruces/go-sqlite3/internal/util/reflect.go +++ /dev/null @@ -1,10 +0,0 @@ -package util - -import "reflect" - -func ReflectType(v reflect.Value) reflect.Type { - if v.Kind() != reflect.Invalid { - return v.Type() - } - return nil -} diff --git a/vendor/github.com/ncruces/go-sqlite3/internal/util/set.go b/vendor/github.com/ncruces/go-sqlite3/internal/util/set.go deleted file mode 100644 index 9cfd5abd1..000000000 --- a/vendor/github.com/ncruces/go-sqlite3/internal/util/set.go +++ /dev/null @@ -1,12 +0,0 @@ -package util - -type Set[E comparable] map[E]struct{} - -func (s Set[E]) Add(v E) { - s[v] = struct{}{} -} - -func (s Set[E]) Contains(v E) bool { - _, ok := s[v] - return ok -} diff --git a/vendor/github.com/ncruces/go-sqlite3/json.go b/vendor/github.com/ncruces/go-sqlite3/json.go deleted file mode 100644 index 2b762c092..000000000 --- a/vendor/github.com/ncruces/go-sqlite3/json.go +++ /dev/null @@ -1,12 +0,0 @@ -package sqlite3 - -import "github.com/ncruces/go-sqlite3/internal/util" - -// JSON returns a value that can be used as an argument to -// [database/sql.DB.Exec], [database/sql.Row.Scan] and similar methods to -// store value as JSON, or decode JSON into value. -// JSON should NOT be used with [Stmt.BindJSON], [Stmt.ColumnJSON], -// [Value.JSON], or [Context.ResultJSON]. -func JSON(value any) any { - return util.JSON{Value: value} -} diff --git a/vendor/github.com/ncruces/go-sqlite3/pointer.go b/vendor/github.com/ncruces/go-sqlite3/pointer.go deleted file mode 100644 index 0e2418b99..000000000 --- a/vendor/github.com/ncruces/go-sqlite3/pointer.go +++ /dev/null @@ -1,13 +0,0 @@ -package sqlite3 - -import "github.com/ncruces/go-sqlite3/internal/util" - -// Pointer returns a pointer to a value that can be used as an argument to -// [database/sql.DB.Exec] and similar methods. -// Pointer should NOT be used with [Stmt.BindPointer], -// [Value.Pointer], or [Context.ResultPointer]. -// -// https://sqlite.org/bindptr.html -func Pointer[T any](value T) any { - return util.Pointer[T]{Value: value} -} diff --git a/vendor/github.com/ncruces/go-sqlite3/quote.go b/vendor/github.com/ncruces/go-sqlite3/quote.go deleted file mode 100644 index abe516deb..000000000 --- a/vendor/github.com/ncruces/go-sqlite3/quote.go +++ /dev/null @@ -1,140 +0,0 @@ -package sqlite3 - -import ( - "bytes" - "math" - "reflect" - "strconv" - "strings" - "time" - "unsafe" - - "github.com/ncruces/go-sqlite3/internal/util" -) - -// Quote escapes and quotes a value -// making it safe to embed in SQL text. -// Strings with embedded NUL characters are truncated. -// -// https://sqlite.org/lang_corefunc.html#quote -func Quote(value any) string { - switch v := value.(type) { - case nil: - return "NULL" - case bool: - if v { - return "1" - } else { - return "0" - } - - case int: - return strconv.Itoa(v) - case int64: - return strconv.FormatInt(v, 10) - case float64: - switch { - case math.IsNaN(v): - return "NULL" - case math.IsInf(v, 1): - return "9.0e999" - case math.IsInf(v, -1): - return "-9.0e999" - } - return strconv.FormatFloat(v, 'g', -1, 64) - case time.Time: - return "'" + v.Format(time.RFC3339Nano) + "'" - - case string: - if i := strings.IndexByte(v, 0); i >= 0 { - v = v[:i] - } - - buf := make([]byte, 2+len(v)+strings.Count(v, "'")) - buf[0] = '\'' - i := 1 - for _, b := range []byte(v) { - if b == '\'' { - buf[i] = b - i += 1 - } - buf[i] = b - i += 1 - } - buf[len(buf)-1] = '\'' - return unsafe.String(&buf[0], len(buf)) - - case []byte: - buf := make([]byte, 3+2*len(v)) - buf[1] = '\'' - buf[0] = 'x' - i := 2 - for _, b := range v { - const hex = "0123456789ABCDEF" - buf[i+0] = hex[b/16] - buf[i+1] = hex[b%16] - i += 2 - } - buf[len(buf)-1] = '\'' - return unsafe.String(&buf[0], len(buf)) - - case ZeroBlob: - buf := bytes.Repeat([]byte("0"), int(3+2*int64(v))) - buf[1] = '\'' - buf[0] = 'x' - buf[len(buf)-1] = '\'' - return unsafe.String(&buf[0], len(buf)) - } - - v := reflect.ValueOf(value) - k := v.Kind() - - if k == reflect.Interface || k == reflect.Pointer { - if v.IsNil() { - return "NULL" - } - v = v.Elem() - k = v.Kind() - } - - switch { - case v.CanInt(): - return strconv.FormatInt(v.Int(), 10) - case v.CanUint(): - return strconv.FormatUint(v.Uint(), 10) - case v.CanFloat(): - return Quote(v.Float()) - case k == reflect.Bool: - return Quote(v.Bool()) - case k == reflect.String: - return Quote(v.String()) - case (k == reflect.Slice || k == reflect.Array && v.CanAddr()) && - v.Type().Elem().Kind() == reflect.Uint8: - return Quote(v.Bytes()) - } - - panic(util.ValueErr) -} - -// QuoteIdentifier escapes and quotes an identifier -// making it safe to embed in SQL text. -// Strings with embedded NUL characters panic. -func QuoteIdentifier(id string) string { - if strings.IndexByte(id, 0) >= 0 { - panic(util.ValueErr) - } - - buf := make([]byte, 2+len(id)+strings.Count(id, `"`)) - buf[0] = '"' - i := 1 - for _, b := range []byte(id) { - if b == '"' { - buf[i] = b - i += 1 - } - buf[i] = b - i += 1 - } - buf[len(buf)-1] = '"' - return unsafe.String(&buf[0], len(buf)) -} diff --git a/vendor/github.com/ncruces/go-sqlite3/registry.go b/vendor/github.com/ncruces/go-sqlite3/registry.go deleted file mode 100644 index 043d69eeb..000000000 --- a/vendor/github.com/ncruces/go-sqlite3/registry.go +++ /dev/null @@ -1,30 +0,0 @@ -package sqlite3 - -import "sync" - -var ( - // +checklocks:extRegistryMtx - extRegistry []func(*Conn) error - extRegistryMtx sync.RWMutex -) - -// AutoExtension causes the entryPoint function to be invoked -// for each new database connection that is created. -// -// https://sqlite.org/c3ref/auto_extension.html -func AutoExtension(entryPoint func(*Conn) error) { - extRegistryMtx.Lock() - defer extRegistryMtx.Unlock() - extRegistry = append(extRegistry, entryPoint) -} - -func initExtensions(c *Conn) error { - extRegistryMtx.RLock() - defer extRegistryMtx.RUnlock() - for _, f := range extRegistry { - if err := f(c); err != nil { - return err - } - } - return nil -} diff --git a/vendor/github.com/ncruces/go-sqlite3/sqlite.go b/vendor/github.com/ncruces/go-sqlite3/sqlite.go deleted file mode 100644 index 8203603e7..000000000 --- a/vendor/github.com/ncruces/go-sqlite3/sqlite.go +++ /dev/null @@ -1,353 +0,0 @@ -// Package sqlite3 wraps the C SQLite API. -package sqlite3 - -import ( - "context" - "math/bits" - "os" - "sync" - "unsafe" - - "github.com/tetratelabs/wazero" - "github.com/tetratelabs/wazero/api" - - "github.com/ncruces/go-sqlite3/internal/util" - "github.com/ncruces/go-sqlite3/vfs" -) - -// Configure SQLite Wasm. -// -// Importing package embed initializes [Binary] -// with an appropriate build of SQLite: -// -// import _ "github.com/ncruces/go-sqlite3/embed" -var ( - Binary []byte // Wasm binary to load. - Path string // Path to load the binary from. - - RuntimeConfig wazero.RuntimeConfig -) - -// Initialize decodes and compiles the SQLite Wasm binary. -// This is called implicitly when the first connection is openned, -// but is potentially slow, so you may want to call it at a more convenient time. -func Initialize() error { - instance.once.Do(compileSQLite) - return instance.err -} - -var instance struct { - runtime wazero.Runtime - compiled wazero.CompiledModule - err error - once sync.Once -} - -func compileSQLite() { - ctx := context.Background() - cfg := RuntimeConfig - if cfg == nil { - if util.CompilerSupported() { - cfg = wazero.NewRuntimeConfigCompiler() - } else { - cfg = wazero.NewRuntimeConfigInterpreter() - } - if bits.UintSize < 64 { - cfg = cfg.WithMemoryLimitPages(512) // 32MB - } else { - cfg = cfg.WithMemoryLimitPages(4096) // 256MB - } - cfg = cfg.WithCoreFeatures(api.CoreFeaturesV2) - } - - instance.runtime = wazero.NewRuntimeWithConfig(ctx, cfg) - - env := instance.runtime.NewHostModuleBuilder("env") - env = vfs.ExportHostFunctions(env) - env = exportCallbacks(env) - _, instance.err = env.Instantiate(ctx) - if instance.err != nil { - return - } - - bin := Binary - if bin == nil && Path != "" { - bin, instance.err = os.ReadFile(Path) - if instance.err != nil { - return - } - } - if bin == nil { - instance.err = util.NoBinaryErr - return - } - - instance.compiled, instance.err = instance.runtime.CompileModule(ctx, bin) -} - -type sqlite struct { - ctx context.Context - mod api.Module - funcs struct { - fn [32]api.Function - id [32]*byte - mask uint32 - } - stack [9]stk_t -} - -func instantiateSQLite() (sqlt *sqlite, err error) { - if err := Initialize(); err != nil { - return nil, err - } - - sqlt = new(sqlite) - sqlt.ctx = util.NewContext(context.Background()) - - sqlt.mod, err = instance.runtime.InstantiateModule(sqlt.ctx, - instance.compiled, wazero.NewModuleConfig().WithName("")) - if err != nil { - return nil, err - } - if sqlt.getfn("sqlite3_progress_handler_go") == nil { - return nil, util.BadBinaryErr - } - return sqlt, nil -} - -func (sqlt *sqlite) close() error { - return sqlt.mod.Close(sqlt.ctx) -} - -func (sqlt *sqlite) error(rc res_t, handle ptr_t, sql ...string) error { - if rc == _OK { - return nil - } - - err := Error{code: rc} - - if err.Code() == NOMEM || err.ExtendedCode() == IOERR_NOMEM { - panic(util.OOMErr) - } - - if ptr := ptr_t(sqlt.call("sqlite3_errstr", stk_t(rc))); ptr != 0 { - err.str = util.ReadString(sqlt.mod, ptr, _MAX_NAME) - } - - if handle != 0 { - if ptr := ptr_t(sqlt.call("sqlite3_errmsg", stk_t(handle))); ptr != 0 { - err.msg = util.ReadString(sqlt.mod, ptr, _MAX_LENGTH) - } - - if len(sql) != 0 { - if i := int32(sqlt.call("sqlite3_error_offset", stk_t(handle))); i != -1 { - err.sql = sql[0][i:] - } - } - } - - switch err.msg { - case err.str, "not an error": - err.msg = "" - } - return &err -} - -func (sqlt *sqlite) getfn(name string) api.Function { - c := &sqlt.funcs - p := unsafe.StringData(name) - for i := range c.id { - if c.id[i] == p { - c.id[i] = nil - c.mask &^= uint32(1) << i - return c.fn[i] - } - } - return sqlt.mod.ExportedFunction(name) -} - -func (sqlt *sqlite) putfn(name string, fn api.Function) { - c := &sqlt.funcs - p := unsafe.StringData(name) - i := bits.TrailingZeros32(^c.mask) - if i < 32 { - c.id[i] = p - c.fn[i] = fn - c.mask |= uint32(1) << i - } else { - c.id[0] = p - c.fn[0] = fn - c.mask = uint32(1) - } -} - -func (sqlt *sqlite) call(name string, params ...stk_t) stk_t { - copy(sqlt.stack[:], params) - fn := sqlt.getfn(name) - err := fn.CallWithStack(sqlt.ctx, sqlt.stack[:]) - if err != nil { - panic(err) - } - sqlt.putfn(name, fn) - return stk_t(sqlt.stack[0]) -} - -func (sqlt *sqlite) free(ptr ptr_t) { - if ptr == 0 { - return - } - sqlt.call("sqlite3_free", stk_t(ptr)) -} - -func (sqlt *sqlite) new(size int64) ptr_t { - ptr := ptr_t(sqlt.call("sqlite3_malloc64", stk_t(size))) - if ptr == 0 && size != 0 { - panic(util.OOMErr) - } - return ptr -} - -func (sqlt *sqlite) realloc(ptr ptr_t, size int64) ptr_t { - ptr = ptr_t(sqlt.call("sqlite3_realloc64", stk_t(ptr), stk_t(size))) - if ptr == 0 && size != 0 { - panic(util.OOMErr) - } - return ptr -} - -func (sqlt *sqlite) newBytes(b []byte) ptr_t { - if (*[0]byte)(b) == nil { - return 0 - } - size := len(b) - if size == 0 { - size = 1 - } - ptr := sqlt.new(int64(size)) - util.WriteBytes(sqlt.mod, ptr, b) - return ptr -} - -func (sqlt *sqlite) newString(s string) ptr_t { - ptr := sqlt.new(int64(len(s)) + 1) - util.WriteString(sqlt.mod, ptr, s) - return ptr -} - -const arenaSize = 4096 - -func (sqlt *sqlite) newArena() arena { - return arena{ - sqlt: sqlt, - base: sqlt.new(arenaSize), - } -} - -type arena struct { - sqlt *sqlite - ptrs []ptr_t - base ptr_t - next int32 -} - -func (a *arena) free() { - if a.sqlt == nil { - return - } - for _, ptr := range a.ptrs { - a.sqlt.free(ptr) - } - a.sqlt.free(a.base) - a.sqlt = nil -} - -func (a *arena) mark() (reset func()) { - ptrs := len(a.ptrs) - next := a.next - return func() { - rest := a.ptrs[ptrs:] - for _, ptr := range a.ptrs[:ptrs] { - a.sqlt.free(ptr) - } - a.ptrs = rest - a.next = next - } -} - -func (a *arena) new(size int64) ptr_t { - // Align the next address, to 4 or 8 bytes. - if size&7 != 0 { - a.next = (a.next + 3) &^ 3 - } else { - a.next = (a.next + 7) &^ 7 - } - if size <= arenaSize-int64(a.next) { - ptr := a.base + ptr_t(a.next) - a.next += int32(size) - return ptr_t(ptr) - } - ptr := a.sqlt.new(size) - a.ptrs = append(a.ptrs, ptr) - return ptr_t(ptr) -} - -func (a *arena) bytes(b []byte) ptr_t { - if (*[0]byte)(b) == nil { - return 0 - } - ptr := a.new(int64(len(b))) - util.WriteBytes(a.sqlt.mod, ptr, b) - return ptr -} - -func (a *arena) string(s string) ptr_t { - ptr := a.new(int64(len(s)) + 1) - util.WriteString(a.sqlt.mod, ptr, s) - return ptr -} - -func exportCallbacks(env wazero.HostModuleBuilder) wazero.HostModuleBuilder { - util.ExportFuncII(env, "go_progress_handler", progressCallback) - util.ExportFuncIII(env, "go_busy_timeout", timeoutCallback) - util.ExportFuncIII(env, "go_busy_handler", busyCallback) - util.ExportFuncII(env, "go_commit_hook", commitCallback) - 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) - util.ExportFuncVI(env, "go_destroy", destroyCallback) - util.ExportFuncVIIII(env, "go_func", funcCallback) - util.ExportFuncVIIIII(env, "go_step", stepCallback) - util.ExportFuncVIII(env, "go_final", finalCallback) - util.ExportFuncVII(env, "go_value", valueCallback) - util.ExportFuncVIIII(env, "go_inverse", inverseCallback) - util.ExportFuncVIIII(env, "go_collation_needed", collationCallback) - util.ExportFuncIIIIII(env, "go_compare", compareCallback) - util.ExportFuncIIIIII(env, "go_vtab_create", vtabModuleCallback(xCreate)) - util.ExportFuncIIIIII(env, "go_vtab_connect", vtabModuleCallback(xConnect)) - util.ExportFuncII(env, "go_vtab_disconnect", vtabDisconnectCallback) - util.ExportFuncII(env, "go_vtab_destroy", vtabDestroyCallback) - util.ExportFuncIII(env, "go_vtab_best_index", vtabBestIndexCallback) - util.ExportFuncIIIII(env, "go_vtab_update", vtabUpdateCallback) - util.ExportFuncIII(env, "go_vtab_rename", vtabRenameCallback) - util.ExportFuncIIIII(env, "go_vtab_find_function", vtabFindFuncCallback) - util.ExportFuncII(env, "go_vtab_begin", vtabBeginCallback) - util.ExportFuncII(env, "go_vtab_sync", vtabSyncCallback) - util.ExportFuncII(env, "go_vtab_commit", vtabCommitCallback) - util.ExportFuncII(env, "go_vtab_rollback", vtabRollbackCallback) - util.ExportFuncIII(env, "go_vtab_savepoint", vtabSavepointCallback) - util.ExportFuncIII(env, "go_vtab_release", vtabReleaseCallback) - util.ExportFuncIII(env, "go_vtab_rollback_to", vtabRollbackToCallback) - util.ExportFuncIIIIII(env, "go_vtab_integrity", vtabIntegrityCallback) - util.ExportFuncIII(env, "go_cur_open", cursorOpenCallback) - util.ExportFuncII(env, "go_cur_close", cursorCloseCallback) - util.ExportFuncIIIIII(env, "go_cur_filter", cursorFilterCallback) - util.ExportFuncII(env, "go_cur_next", cursorNextCallback) - util.ExportFuncII(env, "go_cur_eof", cursorEOFCallback) - util.ExportFuncIIII(env, "go_cur_column", cursorColumnCallback) - util.ExportFuncIII(env, "go_cur_rowid", cursorRowIDCallback) - return env -} diff --git a/vendor/github.com/ncruces/go-sqlite3/stmt.go b/vendor/github.com/ncruces/go-sqlite3/stmt.go deleted file mode 100644 index 4e17d1039..000000000 --- a/vendor/github.com/ncruces/go-sqlite3/stmt.go +++ /dev/null @@ -1,682 +0,0 @@ -package sqlite3 - -import ( - "encoding/json" - "math" - "strconv" - "time" - - "github.com/ncruces/go-sqlite3/internal/util" -) - -// Stmt is a prepared statement object. -// -// https://sqlite.org/c3ref/stmt.html -type Stmt struct { - c *Conn - err error - sql string - handle ptr_t -} - -// Close destroys the prepared statement object. -// -// It is safe to close a nil, zero or closed Stmt. -// -// https://sqlite.org/c3ref/finalize.html -func (s *Stmt) Close() error { - if s == nil || s.handle == 0 { - return nil - } - - rc := res_t(s.c.call("sqlite3_finalize", stk_t(s.handle))) - stmts := s.c.stmts - for i := range stmts { - if s == stmts[i] { - l := len(stmts) - 1 - stmts[i] = stmts[l] - stmts[l] = nil - s.c.stmts = stmts[:l] - break - } - } - - s.handle = 0 - return s.c.error(rc) -} - -// Conn returns the database connection to which the prepared statement belongs. -// -// https://sqlite.org/c3ref/db_handle.html -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 { - ptr := ptr_t(s.c.call("sqlite3_expanded_sql", stk_t(s.handle))) - sql := util.ReadString(s.c.mod, ptr, _MAX_SQL_LENGTH) - s.c.free(ptr) - return sql -} - -// ReadOnly returns true if and only if the statement -// makes no direct changes to the content of the database file. -// -// https://sqlite.org/c3ref/stmt_readonly.html -func (s *Stmt) ReadOnly() bool { - b := int32(s.c.call("sqlite3_stmt_readonly", stk_t(s.handle))) - return b != 0 -} - -// Reset resets the prepared statement object. -// -// https://sqlite.org/c3ref/reset.html -func (s *Stmt) Reset() error { - rc := res_t(s.c.call("sqlite3_reset", stk_t(s.handle))) - s.err = nil - return s.c.error(rc) -} - -// Busy determines if a prepared statement has been reset. -// -// https://sqlite.org/c3ref/stmt_busy.html -func (s *Stmt) Busy() bool { - rc := res_t(s.c.call("sqlite3_stmt_busy", stk_t(s.handle))) - return rc != 0 -} - -// Step evaluates the SQL statement. -// If the SQL statement being executed returns any data, -// then true is returned each time a new row of data is ready for processing by the caller. -// The values may be accessed using the Column access functions. -// Step is called again to retrieve the next row of data. -// If an error has occurred, Step returns false; -// call [Stmt.Err] or [Stmt.Reset] to get the error. -// -// https://sqlite.org/c3ref/step.html -func (s *Stmt) Step() bool { - s.c.checkInterrupt(s.c.handle) - rc := res_t(s.c.call("sqlite3_step", stk_t(s.handle))) - switch rc { - case _ROW: - s.err = nil - return true - case _DONE: - s.err = nil - default: - s.err = s.c.error(rc) - } - return false -} - -// Err gets the last error occurred during [Stmt.Step]. -// Err returns nil after [Stmt.Reset] is called. -// -// https://sqlite.org/c3ref/step.html -func (s *Stmt) Err() error { - return s.err -} - -// Exec is a convenience function that repeatedly calls [Stmt.Step] until it returns false, -// then calls [Stmt.Reset] to reset the statement and get any error that occurred. -func (s *Stmt) Exec() error { - for s.Step() { - } - return s.Reset() -} - -// Status monitors the performance characteristics of prepared statements. -// -// https://sqlite.org/c3ref/stmt_status.html -func (s *Stmt) Status(op StmtStatus, reset bool) int { - if op > STMTSTATUS_FILTER_HIT && op != STMTSTATUS_MEMUSED { - return 0 - } - var i int32 - if reset { - i = 1 - } - n := int32(s.c.call("sqlite3_stmt_status", stk_t(s.handle), - stk_t(op), stk_t(i))) - return int(n) -} - -// ClearBindings resets all bindings on the prepared statement. -// -// https://sqlite.org/c3ref/clear_bindings.html -func (s *Stmt) ClearBindings() error { - rc := res_t(s.c.call("sqlite3_clear_bindings", stk_t(s.handle))) - return s.c.error(rc) -} - -// BindCount returns the number of SQL parameters in the prepared statement. -// -// https://sqlite.org/c3ref/bind_parameter_count.html -func (s *Stmt) BindCount() int { - n := int32(s.c.call("sqlite3_bind_parameter_count", - stk_t(s.handle))) - return int(n) -} - -// BindIndex returns the index of a parameter in the prepared statement -// given its name. -// -// https://sqlite.org/c3ref/bind_parameter_index.html -func (s *Stmt) BindIndex(name string) int { - defer s.c.arena.mark()() - namePtr := s.c.arena.string(name) - i := int32(s.c.call("sqlite3_bind_parameter_index", - stk_t(s.handle), stk_t(namePtr))) - return int(i) -} - -// BindName returns the name of a parameter in the prepared statement. -// The leftmost SQL parameter has an index of 1. -// -// https://sqlite.org/c3ref/bind_parameter_name.html -func (s *Stmt) BindName(param int) string { - ptr := ptr_t(s.c.call("sqlite3_bind_parameter_name", - stk_t(s.handle), stk_t(param))) - if ptr == 0 { - return "" - } - return util.ReadString(s.c.mod, ptr, _MAX_NAME) -} - -// BindBool binds a bool to the prepared statement. -// The leftmost SQL parameter has an index of 1. -// SQLite does not have a separate boolean storage class. -// Instead, boolean values are stored as integers 0 (false) and 1 (true). -// -// https://sqlite.org/c3ref/bind_blob.html -func (s *Stmt) BindBool(param int, value bool) error { - var i int64 - if value { - i = 1 - } - return s.BindInt64(param, i) -} - -// BindInt binds an int to the prepared statement. -// The leftmost SQL parameter has an index of 1. -// -// https://sqlite.org/c3ref/bind_blob.html -func (s *Stmt) BindInt(param int, value int) error { - return s.BindInt64(param, int64(value)) -} - -// BindInt64 binds an int64 to the prepared statement. -// The leftmost SQL parameter has an index of 1. -// -// https://sqlite.org/c3ref/bind_blob.html -func (s *Stmt) BindInt64(param int, value int64) error { - rc := res_t(s.c.call("sqlite3_bind_int64", - stk_t(s.handle), stk_t(param), stk_t(value))) - return s.c.error(rc) -} - -// BindFloat binds a float64 to the prepared statement. -// The leftmost SQL parameter has an index of 1. -// -// https://sqlite.org/c3ref/bind_blob.html -func (s *Stmt) BindFloat(param int, value float64) error { - rc := res_t(s.c.call("sqlite3_bind_double", - stk_t(s.handle), stk_t(param), - stk_t(math.Float64bits(value)))) - return s.c.error(rc) -} - -// BindText binds a string to the prepared statement. -// The leftmost SQL parameter has an index of 1. -// -// https://sqlite.org/c3ref/bind_blob.html -func (s *Stmt) BindText(param int, value string) error { - if len(value) > _MAX_LENGTH { - return TOOBIG - } - ptr := s.c.newString(value) - rc := res_t(s.c.call("sqlite3_bind_text_go", - stk_t(s.handle), stk_t(param), - stk_t(ptr), stk_t(len(value)))) - return s.c.error(rc) -} - -// BindRawText binds a []byte to the prepared statement as text. -// The leftmost SQL parameter has an index of 1. -// Binding a nil slice is the same as calling [Stmt.BindNull]. -// -// https://sqlite.org/c3ref/bind_blob.html -func (s *Stmt) BindRawText(param int, value []byte) error { - if len(value) > _MAX_LENGTH { - return TOOBIG - } - ptr := s.c.newBytes(value) - rc := res_t(s.c.call("sqlite3_bind_text_go", - stk_t(s.handle), stk_t(param), - stk_t(ptr), stk_t(len(value)))) - return s.c.error(rc) -} - -// BindBlob binds a []byte to the prepared statement. -// The leftmost SQL parameter has an index of 1. -// Binding a nil slice is the same as calling [Stmt.BindNull]. -// -// https://sqlite.org/c3ref/bind_blob.html -func (s *Stmt) BindBlob(param int, value []byte) error { - if len(value) > _MAX_LENGTH { - return TOOBIG - } - ptr := s.c.newBytes(value) - rc := res_t(s.c.call("sqlite3_bind_blob_go", - stk_t(s.handle), stk_t(param), - stk_t(ptr), stk_t(len(value)))) - return s.c.error(rc) -} - -// BindZeroBlob binds a zero-filled, length n BLOB to the prepared statement. -// The leftmost SQL parameter has an index of 1. -// -// https://sqlite.org/c3ref/bind_blob.html -func (s *Stmt) BindZeroBlob(param int, n int64) error { - rc := res_t(s.c.call("sqlite3_bind_zeroblob64", - stk_t(s.handle), stk_t(param), stk_t(n))) - return s.c.error(rc) -} - -// BindNull binds a NULL to the prepared statement. -// The leftmost SQL parameter has an index of 1. -// -// https://sqlite.org/c3ref/bind_blob.html -func (s *Stmt) BindNull(param int) error { - rc := res_t(s.c.call("sqlite3_bind_null", - stk_t(s.handle), stk_t(param))) - return s.c.error(rc) -} - -// BindTime binds a [time.Time] to the prepared statement. -// The leftmost SQL parameter has an index of 1. -// -// https://sqlite.org/c3ref/bind_blob.html -func (s *Stmt) BindTime(param int, value time.Time, format TimeFormat) error { - switch format { - case TimeFormatDefault, TimeFormatAuto, time.RFC3339Nano: - return s.bindRFC3339Nano(param, value) - } - switch v := format.Encode(value).(type) { - case string: - return s.BindText(param, v) - case int64: - return s.BindInt64(param, v) - case float64: - return s.BindFloat(param, v) - default: - panic(util.AssertErr()) - } -} - -func (s *Stmt) bindRFC3339Nano(param int, value time.Time) error { - const maxlen = int64(len(time.RFC3339Nano)) + 5 - - ptr := s.c.new(maxlen) - buf := util.View(s.c.mod, ptr, maxlen) - buf = value.AppendFormat(buf[:0], time.RFC3339Nano) - - rc := res_t(s.c.call("sqlite3_bind_text_go", - stk_t(s.handle), stk_t(param), - stk_t(ptr), stk_t(len(buf)))) - return s.c.error(rc) -} - -// BindPointer binds a NULL to the prepared statement, just like [Stmt.BindNull], -// but it also associates ptr with that NULL value such that it can be retrieved -// within an application-defined SQL function using [Value.Pointer]. -// The leftmost SQL parameter has an index of 1. -// -// https://sqlite.org/c3ref/bind_blob.html -func (s *Stmt) BindPointer(param int, ptr any) error { - valPtr := util.AddHandle(s.c.ctx, ptr) - rc := res_t(s.c.call("sqlite3_bind_pointer_go", - stk_t(s.handle), stk_t(param), stk_t(valPtr))) - return s.c.error(rc) -} - -// BindJSON binds the JSON encoding of value to the prepared statement. -// The leftmost SQL parameter has an index of 1. -// -// https://sqlite.org/c3ref/bind_blob.html -func (s *Stmt) BindJSON(param int, value any) error { - data, err := json.Marshal(value) - if err != nil { - return err - } - return s.BindRawText(param, data) -} - -// BindValue binds a copy of value to the prepared statement. -// The leftmost SQL parameter has an index of 1. -// -// https://sqlite.org/c3ref/bind_blob.html -func (s *Stmt) BindValue(param int, value Value) error { - if value.c != s.c { - return MISUSE - } - rc := res_t(s.c.call("sqlite3_bind_value", - stk_t(s.handle), stk_t(param), stk_t(value.handle))) - return s.c.error(rc) -} - -// DataCount resets the number of columns in a result set. -// -// https://sqlite.org/c3ref/data_count.html -func (s *Stmt) DataCount() int { - n := int32(s.c.call("sqlite3_data_count", - stk_t(s.handle))) - return int(n) -} - -// ColumnCount returns the number of columns in a result set. -// -// https://sqlite.org/c3ref/column_count.html -func (s *Stmt) ColumnCount() int { - n := int32(s.c.call("sqlite3_column_count", - stk_t(s.handle))) - return int(n) -} - -// ColumnName returns the name of the result column. -// The leftmost column of the result set has the index 0. -// -// https://sqlite.org/c3ref/column_name.html -func (s *Stmt) ColumnName(col int) string { - ptr := ptr_t(s.c.call("sqlite3_column_name", - stk_t(s.handle), stk_t(col))) - if ptr == 0 { - panic(util.OOMErr) - } - return util.ReadString(s.c.mod, ptr, _MAX_NAME) -} - -// ColumnType returns the initial [Datatype] of the result column. -// The leftmost column of the result set has the index 0. -// -// https://sqlite.org/c3ref/column_blob.html -func (s *Stmt) ColumnType(col int) Datatype { - return Datatype(s.c.call("sqlite3_column_type", - stk_t(s.handle), stk_t(col))) -} - -// ColumnDeclType returns the declared datatype of the result column. -// The leftmost column of the result set has the index 0. -// -// https://sqlite.org/c3ref/column_decltype.html -func (s *Stmt) ColumnDeclType(col int) string { - ptr := ptr_t(s.c.call("sqlite3_column_decltype", - stk_t(s.handle), stk_t(col))) - if ptr == 0 { - return "" - } - return util.ReadString(s.c.mod, ptr, _MAX_NAME) -} - -// ColumnDatabaseName returns the name of the database -// that is the origin of a particular result column. -// The leftmost column of the result set has the index 0. -// -// https://sqlite.org/c3ref/column_database_name.html -func (s *Stmt) ColumnDatabaseName(col int) string { - ptr := ptr_t(s.c.call("sqlite3_column_database_name", - stk_t(s.handle), stk_t(col))) - if ptr == 0 { - return "" - } - return util.ReadString(s.c.mod, ptr, _MAX_NAME) -} - -// ColumnTableName returns the name of the table -// that is the origin of a particular result column. -// The leftmost column of the result set has the index 0. -// -// https://sqlite.org/c3ref/column_database_name.html -func (s *Stmt) ColumnTableName(col int) string { - ptr := ptr_t(s.c.call("sqlite3_column_table_name", - stk_t(s.handle), stk_t(col))) - if ptr == 0 { - return "" - } - return util.ReadString(s.c.mod, ptr, _MAX_NAME) -} - -// ColumnOriginName returns the name of the table column -// that is the origin of a particular result column. -// The leftmost column of the result set has the index 0. -// -// https://sqlite.org/c3ref/column_database_name.html -func (s *Stmt) ColumnOriginName(col int) string { - ptr := ptr_t(s.c.call("sqlite3_column_origin_name", - stk_t(s.handle), stk_t(col))) - if ptr == 0 { - return "" - } - return util.ReadString(s.c.mod, ptr, _MAX_NAME) -} - -// ColumnBool returns the value of the result column as a bool. -// The leftmost column of the result set has the index 0. -// SQLite does not have a separate boolean storage class. -// Instead, boolean values are retrieved as numbers, -// with 0 converted to false and any other value to true. -// -// https://sqlite.org/c3ref/column_blob.html -func (s *Stmt) ColumnBool(col int) bool { - return s.ColumnFloat(col) != 0 -} - -// ColumnInt returns the value of the result column as an int. -// The leftmost column of the result set has the index 0. -// -// https://sqlite.org/c3ref/column_blob.html -func (s *Stmt) ColumnInt(col int) int { - return int(s.ColumnInt64(col)) -} - -// ColumnInt64 returns the value of the result column as an int64. -// The leftmost column of the result set has the index 0. -// -// https://sqlite.org/c3ref/column_blob.html -func (s *Stmt) ColumnInt64(col int) int64 { - return int64(s.c.call("sqlite3_column_int64", - stk_t(s.handle), stk_t(col))) -} - -// ColumnFloat returns the value of the result column as a float64. -// The leftmost column of the result set has the index 0. -// -// https://sqlite.org/c3ref/column_blob.html -func (s *Stmt) ColumnFloat(col int) float64 { - f := uint64(s.c.call("sqlite3_column_double", - stk_t(s.handle), stk_t(col))) - return math.Float64frombits(f) -} - -// ColumnTime returns the value of the result column as a [time.Time]. -// The leftmost column of the result set has the index 0. -// -// https://sqlite.org/c3ref/column_blob.html -func (s *Stmt) ColumnTime(col int, format TimeFormat) time.Time { - var v any - switch s.ColumnType(col) { - case INTEGER: - v = s.ColumnInt64(col) - case FLOAT: - v = s.ColumnFloat(col) - case TEXT, BLOB: - v = s.ColumnText(col) - case NULL: - return time.Time{} - default: - panic(util.AssertErr()) - } - t, err := format.Decode(v) - if err != nil { - s.err = err - } - return t -} - -// ColumnText returns the value of the result column as a string. -// The leftmost column of the result set has the index 0. -// -// https://sqlite.org/c3ref/column_blob.html -func (s *Stmt) ColumnText(col int) string { - return string(s.ColumnRawText(col)) -} - -// ColumnBlob appends to buf and returns -// the value of the result column as a []byte. -// The leftmost column of the result set has the index 0. -// -// https://sqlite.org/c3ref/column_blob.html -func (s *Stmt) ColumnBlob(col int, buf []byte) []byte { - return append(buf, s.ColumnRawBlob(col)...) -} - -// ColumnRawText returns the value of the result column as a []byte. -// The []byte is owned by SQLite and may be invalidated by -// subsequent calls to [Stmt] methods. -// The leftmost column of the result set has the index 0. -// -// https://sqlite.org/c3ref/column_blob.html -func (s *Stmt) ColumnRawText(col int) []byte { - ptr := ptr_t(s.c.call("sqlite3_column_text", - stk_t(s.handle), stk_t(col))) - return s.columnRawBytes(col, ptr) -} - -// ColumnRawBlob returns the value of the result column as a []byte. -// The []byte is owned by SQLite and may be invalidated by -// subsequent calls to [Stmt] methods. -// The leftmost column of the result set has the index 0. -// -// https://sqlite.org/c3ref/column_blob.html -func (s *Stmt) ColumnRawBlob(col int) []byte { - ptr := ptr_t(s.c.call("sqlite3_column_blob", - stk_t(s.handle), stk_t(col))) - return s.columnRawBytes(col, ptr) -} - -func (s *Stmt) columnRawBytes(col int, ptr ptr_t) []byte { - if ptr == 0 { - rc := res_t(s.c.call("sqlite3_errcode", stk_t(s.c.handle))) - if rc != _ROW && rc != _DONE { - s.err = s.c.error(rc) - } - return nil - } - - n := int32(s.c.call("sqlite3_column_bytes", - stk_t(s.handle), stk_t(col))) - return util.View(s.c.mod, ptr, int64(n)) -} - -// ColumnJSON parses the JSON-encoded value of the result column -// and stores it in the value pointed to by ptr. -// The leftmost column of the result set has the index 0. -// -// https://sqlite.org/c3ref/column_blob.html -func (s *Stmt) ColumnJSON(col int, ptr any) error { - var data []byte - switch s.ColumnType(col) { - case NULL: - data = []byte("null") - case TEXT: - data = s.ColumnRawText(col) - case BLOB: - data = s.ColumnRawBlob(col) - case INTEGER: - data = strconv.AppendInt(nil, s.ColumnInt64(col), 10) - case FLOAT: - data = util.AppendNumber(nil, s.ColumnFloat(col)) - default: - panic(util.AssertErr()) - } - return json.Unmarshal(data, ptr) -} - -// ColumnValue returns the unprotected value of the result column. -// The leftmost column of the result set has the index 0. -// -// https://sqlite.org/c3ref/column_blob.html -func (s *Stmt) ColumnValue(col int) Value { - ptr := ptr_t(s.c.call("sqlite3_column_value", - stk_t(s.handle), stk_t(col))) - return Value{ - c: s.c, - unprot: true, - handle: ptr, - } -} - -// Columns populates result columns into the provided slice. -// The slice must have [Stmt.ColumnCount] length. -// -// [INTEGER] columns will be retrieved as int64 values, -// [FLOAT] as float64, [NULL] as nil, -// [TEXT] as string, and [BLOB] as []byte. -// Any []byte are owned by SQLite and may be invalidated by -// subsequent calls to [Stmt] methods. -func (s *Stmt) Columns(dest ...any) error { - defer s.c.arena.mark()() - count := int64(len(dest)) - typePtr := s.c.arena.new(count) - dataPtr := s.c.arena.new(count * 8) - - rc := res_t(s.c.call("sqlite3_columns_go", - stk_t(s.handle), stk_t(count), stk_t(typePtr), stk_t(dataPtr))) - if err := s.c.error(rc); err != nil { - return err - } - - types := util.View(s.c.mod, typePtr, count) - - // Avoid bounds checks on types below. - if len(types) != len(dest) { - panic(util.AssertErr()) - } - - for i := range dest { - switch types[i] { - case byte(INTEGER): - dest[i] = util.Read64[int64](s.c.mod, dataPtr) - case byte(FLOAT): - dest[i] = util.ReadFloat64(s.c.mod, dataPtr) - case byte(NULL): - dest[i] = nil - default: - ptr := util.Read32[ptr_t](s.c.mod, dataPtr+0) - if ptr == 0 { - dest[i] = []byte{} - continue - } - len := util.Read32[int32](s.c.mod, dataPtr+4) - buf := util.View(s.c.mod, ptr, int64(len)) - if types[i] == byte(TEXT) { - dest[i] = string(buf) - } else { - dest[i] = buf - } - } - dataPtr += 8 - } - return nil -} diff --git a/vendor/github.com/ncruces/go-sqlite3/time.go b/vendor/github.com/ncruces/go-sqlite3/time.go deleted file mode 100644 index d9c516c81..000000000 --- a/vendor/github.com/ncruces/go-sqlite3/time.go +++ /dev/null @@ -1,357 +0,0 @@ -package sqlite3 - -import ( - "math" - "strconv" - "strings" - "time" - - "github.com/ncruces/go-sqlite3/internal/util" - "github.com/ncruces/julianday" -) - -// TimeFormat specifies how to encode/decode time values. -// -// See the documentation for the [TimeFormatDefault] constant -// for formats recognized by SQLite. -// -// https://sqlite.org/lang_datefunc.html -type TimeFormat string - -// TimeFormats recognized by SQLite to encode/decode time values. -// -// https://sqlite.org/lang_datefunc.html#time_values -const ( - TimeFormatDefault TimeFormat = "" // time.RFC3339Nano - - // Text formats - TimeFormat1 TimeFormat = "2006-01-02" - TimeFormat2 TimeFormat = "2006-01-02 15:04" - TimeFormat3 TimeFormat = "2006-01-02 15:04:05" - TimeFormat4 TimeFormat = "2006-01-02 15:04:05.000" - TimeFormat5 TimeFormat = "2006-01-02T15:04" - TimeFormat6 TimeFormat = "2006-01-02T15:04:05" - TimeFormat7 TimeFormat = "2006-01-02T15:04:05.000" - TimeFormat8 TimeFormat = "15:04" - TimeFormat9 TimeFormat = "15:04:05" - TimeFormat10 TimeFormat = "15:04:05.000" - - TimeFormat2TZ = TimeFormat2 + "Z07:00" - TimeFormat3TZ = TimeFormat3 + "Z07:00" - TimeFormat4TZ = TimeFormat4 + "Z07:00" - TimeFormat5TZ = TimeFormat5 + "Z07:00" - TimeFormat6TZ = TimeFormat6 + "Z07:00" - TimeFormat7TZ = TimeFormat7 + "Z07:00" - TimeFormat8TZ = TimeFormat8 + "Z07:00" - TimeFormat9TZ = TimeFormat9 + "Z07:00" - TimeFormat10TZ = TimeFormat10 + "Z07:00" - - // Numeric formats - TimeFormatJulianDay TimeFormat = "julianday" - TimeFormatUnix TimeFormat = "unixepoch" - TimeFormatUnixFrac TimeFormat = "unixepoch_frac" - TimeFormatUnixMilli TimeFormat = "unixepoch_milli" // not an SQLite format - TimeFormatUnixMicro TimeFormat = "unixepoch_micro" // not an SQLite format - TimeFormatUnixNano TimeFormat = "unixepoch_nano" // not an SQLite format - - // Auto - TimeFormatAuto TimeFormat = "auto" -) - -// Encode encodes a time value using this format. -// -// [TimeFormatDefault] and [TimeFormatAuto] encode using [time.RFC3339Nano], -// with nanosecond accuracy, and preserving any timezone offset. -// -// This is the format used by the [database/sql] driver: -// [database/sql.Row.Scan] will decode as [time.Time] -// values encoded with [time.RFC3339Nano]. -// -// Time values encoded with [time.RFC3339Nano] cannot be sorted as strings -// to produce a time-ordered sequence. -// -// Assuming that the time zones of the time values are the same (e.g., all in UTC), -// and expressed using the same string (e.g., all "Z" or all "+00:00"), -// use the TIME [collating sequence] to produce a time-ordered sequence. -// -// Otherwise, use [TimeFormat7] for time-ordered encoding. -// -// Formats [TimeFormat1] through [TimeFormat10] -// convert time values to UTC before encoding. -// -// Returns a string for the text formats, -// a float64 for [TimeFormatJulianDay] and [TimeFormatUnixFrac], -// or an int64 for the other numeric formats. -// -// https://sqlite.org/lang_datefunc.html -// -// [collating sequence]: https://sqlite.org/datatype3.html#collating_sequences -func (f TimeFormat) Encode(t time.Time) any { - switch f { - // Numeric formats - case TimeFormatJulianDay: - return julianday.Float(t) - case TimeFormatUnix: - return t.Unix() - case TimeFormatUnixFrac: - return float64(t.Unix()) + float64(t.Nanosecond())*1e-9 - case TimeFormatUnixMilli: - return t.UnixMilli() - case TimeFormatUnixMicro: - return t.UnixMicro() - case TimeFormatUnixNano: - return t.UnixNano() - // Special formats. - case TimeFormatDefault, TimeFormatAuto: - f = time.RFC3339Nano - // SQLite assumes UTC if unspecified. - case - TimeFormat1, TimeFormat2, - TimeFormat3, TimeFormat4, - TimeFormat5, TimeFormat6, - TimeFormat7, TimeFormat8, - TimeFormat9, TimeFormat10: - t = t.UTC() - } - return t.Format(string(f)) -} - -// Decode decodes a time value using this format. -// -// The time value can be a string, an int64, or a float64. -// -// Formats [TimeFormat8] through [TimeFormat10] -// (and [TimeFormat8TZ] through [TimeFormat10TZ]) -// assume a date of 2000-01-01. -// -// The timezone indicator and fractional seconds are always optional -// for formats [TimeFormat2] through [TimeFormat10] -// (and [TimeFormat2TZ] through [TimeFormat10TZ]). -// -// [TimeFormatAuto] implements (and extends) the SQLite auto modifier. -// Julian day numbers are safe to use for historical dates, -// from 4712BC through 9999AD. -// Unix timestamps (expressed in seconds, milliseconds, microseconds, or nanoseconds) -// are safe to use for current events, from at least 1980 through at least 2260. -// Unix timestamps before 1980 and after 9999 may be misinterpreted as julian day numbers, -// or have the wrong time unit. -// -// https://sqlite.org/lang_datefunc.html -func (f TimeFormat) Decode(v any) (time.Time, error) { - if t, ok := v.(time.Time); ok { - return t, nil - } - switch f { - // Numeric formats. - case TimeFormatJulianDay: - switch v := v.(type) { - case string: - return julianday.Parse(v) - case float64: - return julianday.FloatTime(v), nil - case int64: - return julianday.Time(v, 0), nil - default: - return time.Time{}, util.TimeErr - } - - case TimeFormatUnix, TimeFormatUnixFrac: - if s, ok := v.(string); ok { - f, err := strconv.ParseFloat(s, 64) - if err != nil { - return time.Time{}, err - } - v = f - } - switch v := v.(type) { - case float64: - sec, frac := math.Modf(v) - nsec := math.Floor(frac * 1e9) - return time.Unix(int64(sec), int64(nsec)).UTC(), nil - case int64: - return time.Unix(v, 0).UTC(), nil - default: - return time.Time{}, util.TimeErr - } - - case TimeFormatUnixMilli: - if s, ok := v.(string); ok { - i, err := strconv.ParseInt(s, 10, 64) - if err != nil { - return time.Time{}, err - } - v = i - } - switch v := v.(type) { - case float64: - return time.UnixMilli(int64(math.Floor(v))).UTC(), nil - case int64: - return time.UnixMilli(v).UTC(), nil - default: - return time.Time{}, util.TimeErr - } - - case TimeFormatUnixMicro: - if s, ok := v.(string); ok { - i, err := strconv.ParseInt(s, 10, 64) - if err != nil { - return time.Time{}, err - } - v = i - } - switch v := v.(type) { - case float64: - return time.UnixMicro(int64(math.Floor(v))).UTC(), nil - case int64: - return time.UnixMicro(v).UTC(), nil - default: - return time.Time{}, util.TimeErr - } - - case TimeFormatUnixNano: - if s, ok := v.(string); ok { - i, err := strconv.ParseInt(s, 10, 64) - if err != nil { - return time.Time{}, util.TimeErr - } - v = i - } - switch v := v.(type) { - case float64: - return time.Unix(0, int64(math.Floor(v))).UTC(), nil - case int64: - return time.Unix(0, v).UTC(), nil - default: - return time.Time{}, util.TimeErr - } - - // Special formats. - case TimeFormatAuto: - switch s := v.(type) { - case string: - i, err := strconv.ParseInt(s, 10, 64) - if err == nil { - v = i - break - } - f, err := strconv.ParseFloat(s, 64) - if err == nil { - v = f - break - } - - dates := []TimeFormat{ - TimeFormat9, TimeFormat8, - TimeFormat6, TimeFormat5, - TimeFormat3, TimeFormat2, TimeFormat1, - } - for _, f := range dates { - t, err := f.Decode(s) - if err == nil { - return t, nil - } - } - } - switch v := v.(type) { - case float64: - if 0 <= v && v < 5373484.5 { - return TimeFormatJulianDay.Decode(v) - } - if v < 253402300800 { - return TimeFormatUnixFrac.Decode(v) - } - if v < 253402300800_000 { - return TimeFormatUnixMilli.Decode(v) - } - if v < 253402300800_000000 { - return TimeFormatUnixMicro.Decode(v) - } - return TimeFormatUnixNano.Decode(v) - case int64: - if 0 <= v && v < 5373485 { - return TimeFormatJulianDay.Decode(v) - } - if v < 253402300800 { - return TimeFormatUnixFrac.Decode(v) - } - if v < 253402300800_000 { - return TimeFormatUnixMilli.Decode(v) - } - if v < 253402300800_000000 { - return TimeFormatUnixMicro.Decode(v) - } - return TimeFormatUnixNano.Decode(v) - default: - return time.Time{}, util.TimeErr - } - - case - TimeFormat2, TimeFormat2TZ, - TimeFormat3, TimeFormat3TZ, - TimeFormat4, TimeFormat4TZ, - TimeFormat5, TimeFormat5TZ, - TimeFormat6, TimeFormat6TZ, - TimeFormat7, TimeFormat7TZ: - s, ok := v.(string) - if !ok { - return time.Time{}, util.TimeErr - } - return f.parseRelaxed(s) - - case - TimeFormat8, TimeFormat8TZ, - TimeFormat9, TimeFormat9TZ, - TimeFormat10, TimeFormat10TZ: - s, ok := v.(string) - if !ok { - return time.Time{}, util.TimeErr - } - t, err := f.parseRelaxed(s) - if err != nil { - return time.Time{}, err - } - return t.AddDate(2000, 0, 0), nil - - default: - s, ok := v.(string) - if !ok { - return time.Time{}, util.TimeErr - } - if f == "" { - f = time.RFC3339Nano - } - return time.Parse(string(f), s) - } -} - -func (f TimeFormat) parseRelaxed(s string) (time.Time, error) { - fs := string(f) - fs = strings.TrimSuffix(fs, "Z07:00") - fs = strings.TrimSuffix(fs, ".000") - t, err := time.Parse(fs+"Z07:00", s) - if err != nil { - return time.Parse(fs, s) - } - return t, nil -} - -// Scanner returns a [database/sql.Scanner] that can be used as an argument to -// [database/sql.Row.Scan] and similar methods to -// decode a time value into dest using this format. -func (f TimeFormat) Scanner(dest *time.Time) interface{ Scan(any) error } { - return timeScanner{dest, f} -} - -type timeScanner struct { - *time.Time - TimeFormat -} - -func (s timeScanner) Scan(src any) error { - var ok bool - var err error - if *s.Time, ok = src.(time.Time); !ok { - *s.Time, err = s.Decode(src) - } - return err -} diff --git a/vendor/github.com/ncruces/go-sqlite3/txn.go b/vendor/github.com/ncruces/go-sqlite3/txn.go deleted file mode 100644 index b24789f87..000000000 --- a/vendor/github.com/ncruces/go-sqlite3/txn.go +++ /dev/null @@ -1,309 +0,0 @@ -package sqlite3 - -import ( - "context" - "errors" - "math/rand" - "runtime" - "strconv" - "strings" - - "github.com/tetratelabs/wazero/api" - - "github.com/ncruces/go-sqlite3/internal/util" -) - -// Txn is an in-progress database transaction. -// -// https://sqlite.org/lang_transaction.html -type Txn struct { - c *Conn -} - -// Begin starts a deferred transaction. -// -// https://sqlite.org/lang_transaction.html -func (c *Conn) Begin() Txn { - // BEGIN even if interrupted. - err := c.txnExecInterrupted(`BEGIN DEFERRED`) - if err != nil { - panic(err) - } - 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 -func (c *Conn) BeginImmediate() (Txn, error) { - err := c.Exec(`BEGIN IMMEDIATE`) - if err != nil { - return Txn{}, err - } - return Txn{c}, nil -} - -// BeginExclusive starts an exclusive transaction. -// -// https://sqlite.org/lang_transaction.html -func (c *Conn) BeginExclusive() (Txn, error) { - err := c.Exec(`BEGIN EXCLUSIVE`) - if err != nil { - return Txn{}, err - } - return Txn{c}, nil -} - -// End calls either [Txn.Commit] or [Txn.Rollback] -// depending on whether *error points to a nil or non-nil error. -// -// This is meant to be deferred: -// -// func doWork(db *sqlite3.Conn) (err error) { -// tx := db.Begin() -// defer tx.End(&err) -// -// // ... do work in the transaction -// } -// -// https://sqlite.org/lang_transaction.html -func (tx Txn) End(errp *error) { - recovered := recover() - if recovered != nil { - defer panic(recovered) - } - - if *errp == nil && recovered == nil { - // Success path. - if tx.c.GetAutocommit() { // There is nothing to commit. - return - } - *errp = tx.Commit() - if *errp == nil { - return - } - // Fall through to the error path. - } - - // Error path. - if tx.c.GetAutocommit() { // There is nothing to rollback. - return - } - err := tx.Rollback() - if err != nil { - panic(err) - } -} - -// Commit commits the transaction. -// -// https://sqlite.org/lang_transaction.html -func (tx Txn) Commit() error { - return tx.c.Exec(`COMMIT`) -} - -// Rollback rolls back the transaction, -// even if the connection has been interrupted. -// -// https://sqlite.org/lang_transaction.html -func (tx Txn) Rollback() error { - return tx.c.txnExecInterrupted(`ROLLBACK`) -} - -// Savepoint is a marker within a transaction -// that allows for partial rollback. -// -// https://sqlite.org/lang_savepoint.html -type Savepoint struct { - c *Conn - name string -} - -// Savepoint establishes a new transaction savepoint. -// -// https://sqlite.org/lang_savepoint.html -func (c *Conn) Savepoint() Savepoint { - name := callerName() - if name == "" { - name = "sqlite3.Savepoint" - } - // Names can be reused, but this makes catching bugs more likely. - name = QuoteIdentifier(name + "_" + strconv.Itoa(int(rand.Int31()))) - - err := c.txnExecInterrupted(`SAVEPOINT ` + name) - if err != nil { - panic(err) - } - return Savepoint{c: c, name: name} -} - -func callerName() (name string) { - var pc [8]uintptr - n := runtime.Callers(3, pc[:]) - if n <= 0 { - return "" - } - frames := runtime.CallersFrames(pc[:n]) - frame, more := frames.Next() - for more && (strings.HasPrefix(frame.Function, "database/sql.") || - strings.HasPrefix(frame.Function, "github.com/ncruces/go-sqlite3/driver.")) { - frame, more = frames.Next() - } - return frame.Function -} - -// Release releases the savepoint rolling back any changes -// if *error points to a non-nil error. -// -// This is meant to be deferred: -// -// func doWork(db *sqlite3.Conn) (err error) { -// savept := db.Savepoint() -// defer savept.Release(&err) -// -// // ... do work in the transaction -// } -func (s Savepoint) Release(errp *error) { - recovered := recover() - if recovered != nil { - defer panic(recovered) - } - - if *errp == nil && recovered == nil { - // Success path. - if s.c.GetAutocommit() { // There is nothing to commit. - return - } - *errp = s.c.Exec(`RELEASE ` + s.name) - if *errp == nil { - return - } - // Fall through to the error path. - } - - // Error path. - if s.c.GetAutocommit() { // There is nothing to rollback. - return - } - // ROLLBACK and RELEASE even if interrupted. - err := s.c.txnExecInterrupted(`ROLLBACK TO ` + s.name + `; RELEASE ` + s.name) - if err != nil { - panic(err) - } -} - -// Rollback rolls the transaction back to the savepoint, -// even if the connection has been interrupted. -// Rollback does not release the savepoint. -// -// https://sqlite.org/lang_transaction.html -func (s Savepoint) Rollback() error { - // ROLLBACK even if interrupted. - return s.c.txnExecInterrupted(`ROLLBACK TO ` + s.name) -} - -func (c *Conn) txnExecInterrupted(sql string) error { - err := c.Exec(sql) - if errors.Is(err, INTERRUPT) { - old := c.SetInterrupt(context.Background()) - defer c.SetInterrupt(old) - err = c.Exec(sql) - } - return err -} - -// TxnState determines the transaction state of a database. -// -// https://sqlite.org/c3ref/txn_state.html -func (c *Conn) TxnState(schema string) TxnState { - var ptr ptr_t - if schema != "" { - defer c.arena.mark()() - ptr = c.arena.string(schema) - } - return TxnState(c.call("sqlite3_txn_state", stk_t(c.handle), stk_t(ptr))) -} - -// CommitHook registers a callback function to be invoked -// whenever a transaction is committed. -// Return true to allow the commit operation to continue normally. -// -// https://sqlite.org/c3ref/commit_hook.html -func (c *Conn) CommitHook(cb func() (ok bool)) { - var enable int32 - if cb != nil { - enable = 1 - } - c.call("sqlite3_commit_hook_go", stk_t(c.handle), stk_t(enable)) - c.commit = cb -} - -// RollbackHook registers a callback function to be invoked -// whenever a transaction is rolled back. -// -// https://sqlite.org/c3ref/commit_hook.html -func (c *Conn) RollbackHook(cb func()) { - var enable int32 - if cb != nil { - enable = 1 - } - c.call("sqlite3_rollback_hook_go", stk_t(c.handle), stk_t(enable)) - c.rollback = cb -} - -// UpdateHook registers a callback function to be invoked -// whenever a row is updated, inserted or deleted in a rowid table. -// -// https://sqlite.org/c3ref/update_hook.html -func (c *Conn) UpdateHook(cb func(action AuthorizerActionCode, schema, table string, rowid int64)) { - var enable int32 - if cb != nil { - enable = 1 - } - c.call("sqlite3_update_hook_go", stk_t(c.handle), stk_t(enable)) - c.update = cb -} - -func commitCallback(ctx context.Context, mod api.Module, pDB ptr_t) (rollback int32) { - if c, ok := ctx.Value(connKey{}).(*Conn); ok && c.handle == pDB && c.commit != nil { - if !c.commit() { - rollback = 1 - } - } - return rollback -} - -func rollbackCallback(ctx context.Context, mod api.Module, pDB ptr_t) { - if c, ok := ctx.Value(connKey{}).(*Conn); ok && c.handle == pDB && c.rollback != nil { - c.rollback() - } -} - -func updateCallback(ctx context.Context, mod api.Module, pDB ptr_t, action AuthorizerActionCode, zSchema, zTabName ptr_t, rowid int64) { - if c, ok := ctx.Value(connKey{}).(*Conn); ok && c.handle == pDB && c.update != nil { - schema := util.ReadString(mod, zSchema, _MAX_NAME) - table := util.ReadString(mod, zTabName, _MAX_NAME) - c.update(action, schema, table, rowid) - } -} - -// CacheFlush flushes caches to disk mid-transaction. -// -// https://sqlite.org/c3ref/db_cacheflush.html -func (c *Conn) CacheFlush() error { - rc := res_t(c.call("sqlite3_db_cacheflush", stk_t(c.handle))) - return c.error(rc) -} diff --git a/vendor/github.com/ncruces/go-sqlite3/util/osutil/open.go b/vendor/github.com/ncruces/go-sqlite3/util/osutil/open.go deleted file mode 100644 index 0242ad032..000000000 --- a/vendor/github.com/ncruces/go-sqlite3/util/osutil/open.go +++ /dev/null @@ -1,16 +0,0 @@ -//go:build !windows - -package osutil - -import ( - "io/fs" - "os" -) - -// OpenFile behaves the same as [os.OpenFile], -// except on Windows it sets [syscall.FILE_SHARE_DELETE]. -// -// See: https://go.dev/issue/32088#issuecomment-502850674 -func OpenFile(name string, flag int, perm fs.FileMode) (*os.File, error) { - return os.OpenFile(name, flag, perm) -} diff --git a/vendor/github.com/ncruces/go-sqlite3/util/osutil/open_windows.go b/vendor/github.com/ncruces/go-sqlite3/util/osutil/open_windows.go deleted file mode 100644 index febaf846e..000000000 --- a/vendor/github.com/ncruces/go-sqlite3/util/osutil/open_windows.go +++ /dev/null @@ -1,115 +0,0 @@ -package osutil - -import ( - "io/fs" - "os" - . "syscall" - "unsafe" -) - -// OpenFile behaves the same as [os.OpenFile], -// except on Windows it sets [syscall.FILE_SHARE_DELETE]. -// -// See: https://go.dev/issue/32088#issuecomment-502850674 -func OpenFile(name string, flag int, perm fs.FileMode) (*os.File, error) { - if name == "" { - return nil, &os.PathError{Op: "open", Path: name, Err: ENOENT} - } - r, e := syscallOpen(name, flag|O_CLOEXEC, uint32(perm.Perm())) - if e != nil { - return nil, &os.PathError{Op: "open", Path: name, Err: e} - } - return os.NewFile(uintptr(r), name), nil -} - -// syscallOpen is a copy of [syscall.Open] -// that uses [syscall.FILE_SHARE_DELETE]. -// -// https://go.dev/src/syscall/syscall_windows.go -func syscallOpen(path string, mode int, perm uint32) (fd Handle, err error) { - if len(path) == 0 { - return InvalidHandle, ERROR_FILE_NOT_FOUND - } - pathp, err := UTF16PtrFromString(path) - if err != nil { - return InvalidHandle, err - } - var access uint32 - switch mode & (O_RDONLY | O_WRONLY | O_RDWR) { - case O_RDONLY: - access = GENERIC_READ - case O_WRONLY: - access = GENERIC_WRITE - case O_RDWR: - access = GENERIC_READ | GENERIC_WRITE - } - if mode&O_CREAT != 0 { - access |= GENERIC_WRITE - } - if mode&O_APPEND != 0 { - access &^= GENERIC_WRITE - access |= FILE_APPEND_DATA - } - sharemode := uint32(FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE) - var sa *SecurityAttributes - if mode&O_CLOEXEC == 0 { - sa = makeInheritSa() - } - var createmode uint32 - switch { - case mode&(O_CREAT|O_EXCL) == (O_CREAT | O_EXCL): - createmode = CREATE_NEW - case mode&(O_CREAT|O_TRUNC) == (O_CREAT | O_TRUNC): - createmode = CREATE_ALWAYS - case mode&O_CREAT == O_CREAT: - createmode = OPEN_ALWAYS - case mode&O_TRUNC == O_TRUNC: - createmode = TRUNCATE_EXISTING - default: - createmode = OPEN_EXISTING - } - var attrs uint32 = FILE_ATTRIBUTE_NORMAL - if perm&S_IWRITE == 0 { - attrs = FILE_ATTRIBUTE_READONLY - if createmode == CREATE_ALWAYS { - const _ERROR_BAD_NETPATH = Errno(53) - // We have been asked to create a read-only file. - // If the file already exists, the semantics of - // the Unix open system call is to preserve the - // existing permissions. If we pass CREATE_ALWAYS - // and FILE_ATTRIBUTE_READONLY to CreateFile, - // and the file already exists, CreateFile will - // change the file permissions. - // Avoid that to preserve the Unix semantics. - h, e := CreateFile(pathp, access, sharemode, sa, TRUNCATE_EXISTING, FILE_ATTRIBUTE_NORMAL, 0) - switch e { - case ERROR_FILE_NOT_FOUND, _ERROR_BAD_NETPATH, ERROR_PATH_NOT_FOUND: - // File does not exist. These are the same - // errors as Errno.Is checks for ErrNotExist. - // Carry on to create the file. - default: - // Success or some different error. - return h, e - } - } - } - if createmode == OPEN_EXISTING && access == GENERIC_READ { - // Necessary for opening directory handles. - attrs |= FILE_FLAG_BACKUP_SEMANTICS - } - if mode&O_SYNC != 0 { - const _FILE_FLAG_WRITE_THROUGH = 0x80000000 - attrs |= _FILE_FLAG_WRITE_THROUGH - } - if mode&O_NONBLOCK != 0 { - attrs |= FILE_FLAG_OVERLAPPED - } - return CreateFile(pathp, access, sharemode, sa, createmode, attrs, 0) -} - -func makeInheritSa() *SecurityAttributes { - var sa SecurityAttributes - sa.Length = uint32(unsafe.Sizeof(sa)) - sa.InheritHandle = 1 - return &sa -} diff --git a/vendor/github.com/ncruces/go-sqlite3/util/osutil/osfs.go b/vendor/github.com/ncruces/go-sqlite3/util/osutil/osfs.go deleted file mode 100644 index 2e1195934..000000000 --- a/vendor/github.com/ncruces/go-sqlite3/util/osutil/osfs.go +++ /dev/null @@ -1,33 +0,0 @@ -package osutil - -import ( - "io/fs" - "os" -) - -// FS implements [fs.FS], [fs.StatFS], and [fs.ReadFileFS] -// using package [os]. -// -// This filesystem does not respect [fs.ValidPath] rules, -// and fails [testing/fstest.TestFS]! -// -// Still, it can be a useful tool to unify implementations -// that can access either the [os] filesystem or an [fs.FS]. -// It's OK to use this to open files, but you should avoid -// opening directories, resolving paths, or walking the file system. -type FS struct{} - -// Open implements [fs.FS]. -func (FS) Open(name string) (fs.File, error) { - return OpenFile(name, os.O_RDONLY, 0) -} - -// ReadFileFS implements [fs.StatFS]. -func (FS) Stat(name string) (fs.FileInfo, error) { - return os.Stat(name) -} - -// ReadFile implements [fs.ReadFileFS]. -func (FS) ReadFile(name string) ([]byte, error) { - return os.ReadFile(name) -} diff --git a/vendor/github.com/ncruces/go-sqlite3/util/osutil/osutil.go b/vendor/github.com/ncruces/go-sqlite3/util/osutil/osutil.go deleted file mode 100644 index 83444e906..000000000 --- a/vendor/github.com/ncruces/go-sqlite3/util/osutil/osutil.go +++ /dev/null @@ -1,2 +0,0 @@ -// Package osutil implements operating system utilities. -package osutil diff --git a/vendor/github.com/ncruces/go-sqlite3/util/sql3util/README.md b/vendor/github.com/ncruces/go-sqlite3/util/sql3util/README.md deleted file mode 100644 index 9f47f5a9f..000000000 --- a/vendor/github.com/ncruces/go-sqlite3/util/sql3util/README.md +++ /dev/null @@ -1,9 +0,0 @@ -# SQLite utility functions - -This package implements assorted SQLite utilities -useful to extension writers. - -It also wraps a [parser](https://github.com/marcobambini/sqlite-createtable-parser) -for the [`CREATE`](https://sqlite.org/lang_createtable.html) and -[`ALTER TABLE`](https://sqlite.org/lang_altertable.html) commands, -created by [Marco Bambini](https://github.com/marcobambini).
\ No newline at end of file diff --git a/vendor/github.com/ncruces/go-sqlite3/util/sql3util/arg.go b/vendor/github.com/ncruces/go-sqlite3/util/sql3util/arg.go deleted file mode 100644 index 3e8c728b0..000000000 --- a/vendor/github.com/ncruces/go-sqlite3/util/sql3util/arg.go +++ /dev/null @@ -1,65 +0,0 @@ -package sql3util - -import "strings" - -// NamedArg splits an named arg into a key and value, -// around an equals sign. -// Spaces are trimmed around both key and value. -func NamedArg(arg string) (key, val string) { - key, val, _ = strings.Cut(arg, "=") - key = strings.TrimSpace(key) - val = strings.TrimSpace(val) - return -} - -// Unquote unquotes a string. -// -// https://sqlite.org/lang_keywords.html -func Unquote(val string) string { - if len(val) < 2 { - return val - } - fst := val[0] - lst := val[len(val)-1] - rst := val[1 : len(val)-1] - if fst == '[' && lst == ']' { - return rst - } - if fst != lst { - return val - } - var old, new string - switch fst { - default: - return val - case '`': - old, new = "``", "`" - case '"': - old, new = `""`, `"` - case '\'': - old, new = `''`, `'` - } - return strings.ReplaceAll(rst, old, new) -} - -// ParseBool parses a boolean. -// -// https://sqlite.org/pragma.html#syntax -func ParseBool(s string) (b, ok bool) { - if len(s) == 0 { - return false, false - } - if s[0] == '0' { - return false, true - } - if '1' <= s[0] && s[0] <= '9' { - return true, true - } - switch strings.ToLower(s) { - case "true", "yes", "on": - return true, true - case "false", "no", "off": - return false, true - } - return false, false -} diff --git a/vendor/github.com/ncruces/go-sqlite3/util/sql3util/const.go b/vendor/github.com/ncruces/go-sqlite3/util/sql3util/const.go deleted file mode 100644 index 10e8af35a..000000000 --- a/vendor/github.com/ncruces/go-sqlite3/util/sql3util/const.go +++ /dev/null @@ -1,61 +0,0 @@ -package sql3util - -const ( - _NONE = iota - _MEMORY - _SYNTAX - _UNSUPPORTEDSQL -) - -type ConflictClause uint32 - -const ( - CONFLICT_NONE ConflictClause = iota - CONFLICT_ROLLBACK - CONFLICT_ABORT - CONFLICT_FAIL - CONFLICT_IGNORE - CONFLICT_REPLACE -) - -type OrderClause uint32 - -const ( - ORDER_NONE OrderClause = iota - ORDER_ASC - ORDER_DESC -) - -type FKAction uint32 - -const ( - FKACTION_NONE FKAction = iota - FKACTION_SETNULL - FKACTION_SETDEFAULT - FKACTION_CASCADE - FKACTION_RESTRICT - FKACTION_NOACTION -) - -type FKDefType uint32 - -const ( - DEFTYPE_NONE FKDefType = iota - DEFTYPE_DEFERRABLE - DEFTYPE_DEFERRABLE_INITIALLY_DEFERRED - DEFTYPE_DEFERRABLE_INITIALLY_IMMEDIATE - DEFTYPE_NOTDEFERRABLE - DEFTYPE_NOTDEFERRABLE_INITIALLY_DEFERRED - DEFTYPE_NOTDEFERRABLE_INITIALLY_IMMEDIATE -) - -type StatementType uint32 - -const ( - CREATE_UNKNOWN StatementType = iota - CREATE_TABLE - ALTER_RENAME_TABLE - ALTER_RENAME_COLUMN - ALTER_ADD_COLUMN - ALTER_DROP_COLUMN -) diff --git a/vendor/github.com/ncruces/go-sqlite3/util/sql3util/parse.go b/vendor/github.com/ncruces/go-sqlite3/util/sql3util/parse.go deleted file mode 100644 index 7dd76ceb1..000000000 --- a/vendor/github.com/ncruces/go-sqlite3/util/sql3util/parse.go +++ /dev/null @@ -1,210 +0,0 @@ -package sql3util - -import ( - "context" - _ "embed" - "sync" - - "github.com/tetratelabs/wazero" - "github.com/tetratelabs/wazero/api" - - "github.com/ncruces/go-sqlite3/internal/util" -) - -const ( - errp = 4 - sqlp = 8 -) - -var ( - //go:embed wasm/sql3parse_table.wasm - binary []byte - once sync.Once - runtime wazero.Runtime - compiled wazero.CompiledModule -) - -// ParseTable parses a [CREATE] or [ALTER TABLE] command. -// -// [CREATE]: https://sqlite.org/lang_createtable.html -// [ALTER TABLE]: https://sqlite.org/lang_altertable.html -func ParseTable(sql string) (_ *Table, err error) { - once.Do(func() { - ctx := context.Background() - cfg := wazero.NewRuntimeConfigInterpreter() - runtime = wazero.NewRuntimeWithConfig(ctx, cfg) - compiled, err = runtime.CompileModule(ctx, binary) - }) - if err != nil { - return nil, err - } - - ctx := context.Background() - mod, err := runtime.InstantiateModule(ctx, compiled, wazero.NewModuleConfig().WithName("")) - if err != nil { - return nil, err - } - defer mod.Close(ctx) - - if buf, ok := mod.Memory().Read(sqlp, uint32(len(sql))); ok { - copy(buf, sql) - } - - stack := [...]util.Stk_t{sqlp, util.Stk_t(len(sql)), errp} - err = mod.ExportedFunction("sql3parse_table").CallWithStack(ctx, stack[:]) - if err != nil { - return nil, err - } - - c, _ := mod.Memory().ReadUint32Le(errp) - switch c { - case _MEMORY: - panic(util.OOMErr) - case _SYNTAX: - return nil, util.ErrorString("sql3parse: invalid syntax") - case _UNSUPPORTEDSQL: - return nil, util.ErrorString("sql3parse: unsupported SQL") - } - - var tab Table - tab.load(mod, uint32(stack[0]), sql) - return &tab, nil -} - -// Table holds metadata about a table. -type Table struct { - Name string - Schema string - Comment string - IsTemporary bool - IsIfNotExists bool - IsWithoutRowID bool - IsStrict bool - Columns []Column - Type StatementType - CurrentName string - NewName string -} - -func (t *Table) load(mod api.Module, ptr uint32, sql string) { - t.Name = loadString(mod, ptr+0, sql) - t.Schema = loadString(mod, ptr+8, sql) - t.Comment = loadString(mod, ptr+16, sql) - - t.IsTemporary = loadBool(mod, ptr+24) - t.IsIfNotExists = loadBool(mod, ptr+25) - t.IsWithoutRowID = loadBool(mod, ptr+26) - t.IsStrict = loadBool(mod, ptr+27) - - t.Columns = loadSlice(mod, ptr+28, func(ptr uint32, ret *Column) { - p, _ := mod.Memory().ReadUint32Le(ptr) - ret.load(mod, p, sql) - }) - - t.Type = loadEnum[StatementType](mod, ptr+44) - t.CurrentName = loadString(mod, ptr+48, sql) - t.NewName = loadString(mod, ptr+56, sql) -} - -// Column holds metadata about a column. -type Column struct { - Name string - Type string - Length string - ConstraintName string - Comment string - IsPrimaryKey bool - IsAutoIncrement bool - IsNotNull bool - IsUnique bool - PKOrder OrderClause - PKConflictClause ConflictClause - NotNullConflictClause ConflictClause - UniqueConflictClause ConflictClause - CheckExpr string - DefaultExpr string - CollateName string - ForeignKeyClause *ForeignKey -} - -func (c *Column) load(mod api.Module, ptr uint32, sql string) { - c.Name = loadString(mod, ptr+0, sql) - c.Type = loadString(mod, ptr+8, sql) - c.Length = loadString(mod, ptr+16, sql) - c.ConstraintName = loadString(mod, ptr+24, sql) - c.Comment = loadString(mod, ptr+32, sql) - - c.IsPrimaryKey = loadBool(mod, ptr+40) - c.IsAutoIncrement = loadBool(mod, ptr+41) - c.IsNotNull = loadBool(mod, ptr+42) - c.IsUnique = loadBool(mod, ptr+43) - - c.PKOrder = loadEnum[OrderClause](mod, ptr+44) - c.PKConflictClause = loadEnum[ConflictClause](mod, ptr+48) - c.NotNullConflictClause = loadEnum[ConflictClause](mod, ptr+52) - c.UniqueConflictClause = loadEnum[ConflictClause](mod, ptr+56) - - c.CheckExpr = loadString(mod, ptr+60, sql) - c.DefaultExpr = loadString(mod, ptr+68, sql) - c.CollateName = loadString(mod, ptr+76, sql) - - if ptr, _ := mod.Memory().ReadUint32Le(ptr + 84); ptr != 0 { - c.ForeignKeyClause = &ForeignKey{} - c.ForeignKeyClause.load(mod, ptr, sql) - } -} - -type ForeignKey struct { - Table string - Columns []string - OnDelete FKAction - OnUpdate FKAction - Match string - Deferrable FKDefType -} - -func (f *ForeignKey) load(mod api.Module, ptr uint32, sql string) { - f.Table = loadString(mod, ptr+0, sql) - - f.Columns = loadSlice(mod, ptr+8, func(ptr uint32, ret *string) { - *ret = loadString(mod, ptr, sql) - }) - - f.OnDelete = loadEnum[FKAction](mod, ptr+16) - f.OnUpdate = loadEnum[FKAction](mod, ptr+20) - f.Match = loadString(mod, ptr+24, sql) - f.Deferrable = loadEnum[FKDefType](mod, ptr+32) -} - -func loadString(mod api.Module, ptr uint32, sql string) string { - off, _ := mod.Memory().ReadUint32Le(ptr + 0) - if off == 0 { - return "" - } - len, _ := mod.Memory().ReadUint32Le(ptr + 4) - return sql[off-sqlp : off+len-sqlp] -} - -func loadSlice[T any](mod api.Module, ptr uint32, fn func(uint32, *T)) []T { - ref, _ := mod.Memory().ReadUint32Le(ptr + 4) - if ref == 0 { - return nil - } - len, _ := mod.Memory().ReadUint32Le(ptr + 0) - ret := make([]T, len) - for i := range ret { - fn(ref, &ret[i]) - ref += 4 - } - return ret -} - -func loadEnum[T ~uint32](mod api.Module, ptr uint32) T { - val, _ := mod.Memory().ReadUint32Le(ptr) - return T(val) -} - -func loadBool(mod api.Module, ptr uint32) bool { - val, _ := mod.Memory().ReadByte(ptr) - return val != 0 -} diff --git a/vendor/github.com/ncruces/go-sqlite3/util/sql3util/sql3util.go b/vendor/github.com/ncruces/go-sqlite3/util/sql3util/sql3util.go deleted file mode 100644 index 6be61927d..000000000 --- a/vendor/github.com/ncruces/go-sqlite3/util/sql3util/sql3util.go +++ /dev/null @@ -1,9 +0,0 @@ -// Package sql3util implements SQLite utilities. -package sql3util - -// ValidPageSize returns true if s is a valid page size. -// -// https://sqlite.org/fileformat.html#pages -func ValidPageSize(s int) bool { - return 512 <= s && s <= 65536 && s&(s-1) == 0 -} diff --git a/vendor/github.com/ncruces/go-sqlite3/util/sql3util/wasm/sql3parse_table.wasm b/vendor/github.com/ncruces/go-sqlite3/util/sql3util/wasm/sql3parse_table.wasm Binary files differdeleted file mode 100644 index 4d3357ea1..000000000 --- a/vendor/github.com/ncruces/go-sqlite3/util/sql3util/wasm/sql3parse_table.wasm +++ /dev/null diff --git a/vendor/github.com/ncruces/go-sqlite3/value.go b/vendor/github.com/ncruces/go-sqlite3/value.go deleted file mode 100644 index a2399fba0..000000000 --- a/vendor/github.com/ncruces/go-sqlite3/value.go +++ /dev/null @@ -1,241 +0,0 @@ -package sqlite3 - -import ( - "encoding/json" - "math" - "strconv" - "time" - - "github.com/ncruces/go-sqlite3/internal/util" -) - -// Value is any value that can be stored in a database table. -// -// https://sqlite.org/c3ref/value.html -type Value struct { - c *Conn - handle ptr_t - unprot bool - copied bool -} - -func (v Value) protected() stk_t { - if v.unprot { - panic(util.ValueErr) - } - return stk_t(v.handle) -} - -// Dup makes a copy of the SQL value and returns a pointer to that copy. -// -// https://sqlite.org/c3ref/value_dup.html -func (v Value) Dup() *Value { - ptr := ptr_t(v.c.call("sqlite3_value_dup", stk_t(v.handle))) - return &Value{ - c: v.c, - copied: true, - handle: ptr, - } -} - -// Close frees an SQL value previously obtained by [Value.Dup]. -// -// https://sqlite.org/c3ref/value_dup.html -func (dup *Value) Close() error { - if !dup.copied { - panic(util.ValueErr) - } - dup.c.call("sqlite3_value_free", stk_t(dup.handle)) - dup.handle = 0 - return nil -} - -// Type returns the initial datatype of the value. -// -// https://sqlite.org/c3ref/value_blob.html -func (v Value) Type() Datatype { - return Datatype(v.c.call("sqlite3_value_type", v.protected())) -} - -// Type returns the numeric datatype of the value. -// -// https://sqlite.org/c3ref/value_blob.html -func (v Value) NumericType() Datatype { - return Datatype(v.c.call("sqlite3_value_numeric_type", v.protected())) -} - -// Bool returns the value as a bool. -// SQLite does not have a separate boolean storage class. -// Instead, boolean values are retrieved as numbers, -// with 0 converted to false and any other value to true. -// -// https://sqlite.org/c3ref/value_blob.html -func (v Value) Bool() bool { - return v.Float() != 0 -} - -// Int returns the value as an int. -// -// https://sqlite.org/c3ref/value_blob.html -func (v Value) Int() int { - return int(v.Int64()) -} - -// Int64 returns the value as an int64. -// -// https://sqlite.org/c3ref/value_blob.html -func (v Value) Int64() int64 { - return int64(v.c.call("sqlite3_value_int64", v.protected())) -} - -// Float returns the value as a float64. -// -// https://sqlite.org/c3ref/value_blob.html -func (v Value) Float() float64 { - f := uint64(v.c.call("sqlite3_value_double", v.protected())) - return math.Float64frombits(f) -} - -// Time returns the value as a [time.Time]. -// -// https://sqlite.org/c3ref/value_blob.html -func (v Value) Time(format TimeFormat) time.Time { - var a any - switch v.Type() { - case INTEGER: - a = v.Int64() - case FLOAT: - a = v.Float() - case TEXT, BLOB: - a = v.Text() - case NULL: - return time.Time{} - default: - panic(util.AssertErr()) - } - t, _ := format.Decode(a) - return t -} - -// Text returns the value as a string. -// -// https://sqlite.org/c3ref/value_blob.html -func (v Value) Text() string { - return string(v.RawText()) -} - -// Blob appends to buf and returns -// the value as a []byte. -// -// https://sqlite.org/c3ref/value_blob.html -func (v Value) Blob(buf []byte) []byte { - return append(buf, v.RawBlob()...) -} - -// RawText returns the value as a []byte. -// The []byte is owned by SQLite and may be invalidated by -// subsequent calls to [Value] methods. -// -// https://sqlite.org/c3ref/value_blob.html -func (v Value) RawText() []byte { - ptr := ptr_t(v.c.call("sqlite3_value_text", v.protected())) - return v.rawBytes(ptr) -} - -// RawBlob returns the value as a []byte. -// The []byte is owned by SQLite and may be invalidated by -// subsequent calls to [Value] methods. -// -// https://sqlite.org/c3ref/value_blob.html -func (v Value) RawBlob() []byte { - ptr := ptr_t(v.c.call("sqlite3_value_blob", v.protected())) - return v.rawBytes(ptr) -} - -func (v Value) rawBytes(ptr ptr_t) []byte { - if ptr == 0 { - return nil - } - - n := int32(v.c.call("sqlite3_value_bytes", v.protected())) - return util.View(v.c.mod, ptr, int64(n)) -} - -// Pointer gets the pointer associated with this value, -// or nil if it has no associated pointer. -func (v Value) Pointer() any { - ptr := ptr_t(v.c.call("sqlite3_value_pointer_go", v.protected())) - return util.GetHandle(v.c.ctx, ptr) -} - -// JSON parses a JSON-encoded value -// and stores the result in the value pointed to by ptr. -func (v Value) JSON(ptr any) error { - var data []byte - switch v.Type() { - case NULL: - data = []byte("null") - case TEXT: - data = v.RawText() - case BLOB: - data = v.RawBlob() - case INTEGER: - data = strconv.AppendInt(nil, v.Int64(), 10) - case FLOAT: - data = util.AppendNumber(nil, v.Float()) - default: - panic(util.AssertErr()) - } - return json.Unmarshal(data, ptr) -} - -// NoChange returns true if and only if the value is unchanged -// in a virtual table update operatiom. -// -// https://sqlite.org/c3ref/value_blob.html -func (v Value) NoChange() bool { - b := int32(v.c.call("sqlite3_value_nochange", v.protected())) - return b != 0 -} - -// FromBind returns true if value originated from a bound parameter. -// -// https://sqlite.org/c3ref/value_blob.html -func (v Value) FromBind() bool { - b := int32(v.c.call("sqlite3_value_frombind", v.protected())) - return b != 0 -} - -// InFirst returns the first element -// on the right-hand side of an IN constraint. -// -// https://sqlite.org/c3ref/vtab_in_first.html -func (v Value) InFirst() (Value, error) { - defer v.c.arena.mark()() - valPtr := v.c.arena.new(ptrlen) - rc := res_t(v.c.call("sqlite3_vtab_in_first", stk_t(v.handle), stk_t(valPtr))) - if err := v.c.error(rc); err != nil { - return Value{}, err - } - return Value{ - c: v.c, - handle: util.Read32[ptr_t](v.c.mod, valPtr), - }, nil -} - -// InNext returns the next element -// on the right-hand side of an IN constraint. -// -// https://sqlite.org/c3ref/vtab_in_first.html -func (v Value) InNext() (Value, error) { - defer v.c.arena.mark()() - valPtr := v.c.arena.new(ptrlen) - rc := res_t(v.c.call("sqlite3_vtab_in_next", stk_t(v.handle), stk_t(valPtr))) - if err := v.c.error(rc); err != nil { - return Value{}, err - } - return Value{ - c: v.c, - handle: util.Read32[ptr_t](v.c.mod, valPtr), - }, nil -} diff --git a/vendor/github.com/ncruces/go-sqlite3/vfs/README.md b/vendor/github.com/ncruces/go-sqlite3/vfs/README.md deleted file mode 100644 index 4e987ce3f..000000000 --- a/vendor/github.com/ncruces/go-sqlite3/vfs/README.md +++ /dev/null @@ -1,109 +0,0 @@ -# Go SQLite VFS API - -This package implements the SQLite [OS Interface](https://sqlite.org/vfs.html) (aka VFS). - -It replaces the default SQLite VFS with a **pure Go** implementation, -and exposes [interfaces](https://pkg.go.dev/github.com/ncruces/go-sqlite3/vfs#VFS) -that should allow you to implement your own [custom VFSes](#custom-vfses). - -Since it is a from scratch reimplementation, -there are naturally some ways it deviates from the original. - -The main differences are [file locking](#file-locking) and [WAL mode](#write-ahead-logging) support. - -### File Locking - -POSIX advisory locks, which SQLite uses on Unix, are -[broken by design](https://github.com/sqlite/sqlite/blob/b74eb0/src/os_unix.c#L1073-L1161). -Instead, on Linux and macOS, this package uses -[OFD locks](https://www.gnu.org/software/libc/manual/html_node/Open-File-Description-Locks.html) -to synchronize access to database files. - -This package can also use -[BSD locks](https://man.freebsd.org/cgi/man.cgi?query=flock&sektion=2), -albeit with reduced concurrency (`BEGIN IMMEDIATE` behaves like `BEGIN EXCLUSIVE`). -BSD locks are the default on BSD and illumos, -but you can opt into them with the `sqlite3_flock` build tag. - -On Windows, this package uses `LockFileEx` and `UnlockFileEx`, -like SQLite. - -You can also opt into a cross-platform locking implementation -with the `sqlite3_dotlk` build tag. - -Otherwise, file locking is not supported, and you must use -[`nolock=1`](https://sqlite.org/uri.html#urinolock) -(or [`immutable=1`](https://sqlite.org/uri.html#uriimmutable)) -to open database files. -To use the [`database/sql`](https://pkg.go.dev/database/sql) driver -with `nolock=1` you must disable connection pooling by calling -[`db.SetMaxOpenConns(1)`](https://pkg.go.dev/database/sql#DB.SetMaxOpenConns). - -You can use [`vfs.SupportsFileLocking`](https://pkg.go.dev/github.com/ncruces/go-sqlite3/vfs#SupportsFileLocking) -to check if your build supports file locking. - -### Write-Ahead Logging - -On Unix, this package may use `mmap` to implement -[shared-memory for the WAL-index](https://sqlite.org/wal.html#implementation_of_shared_memory_for_the_wal_index), -like SQLite. - -On Windows, this package may use `MapViewOfFile`, like SQLite. - -You can also opt into a cross-platform, in-process, memory sharing implementation -with the `sqlite3_dotlk` build tag. - -Otherwise, [WAL support is limited](https://sqlite.org/wal.html#noshm), -and `EXCLUSIVE` locking mode must be set to create, read, and write WAL databases. -To use `EXCLUSIVE` locking mode with the -[`database/sql`](https://pkg.go.dev/database/sql) driver -you must disable connection pooling by calling -[`db.SetMaxOpenConns(1)`](https://pkg.go.dev/database/sql#DB.SetMaxOpenConns). - -You can use [`vfs.SupportsSharedMemory`](https://pkg.go.dev/github.com/ncruces/go-sqlite3/vfs#SupportsSharedMemory) -to check if your build supports shared memory. - -### Batch-Atomic Write - -On Linux, this package may support -[batch-atomic writes](https://sqlite.org/cgi/src/technote/714) -on the F2FS filesystem. - -### Checksums - -This package can be [configured](https://pkg.go.dev/github.com/ncruces/go-sqlite3#Conn.EnableChecksums) -to add an 8-byte checksum to the end of every page in an SQLite database. -The checksum is added as each page is written -and verified as each page is read.\ -The checksum is intended to help detect database corruption -caused by random bit-flips in the mass storage device. - -The implementation is compatible with SQLite's -[Checksum VFS Shim](https://sqlite.org/cksumvfs.html). - -### Build Tags - -The VFS can be customized with a few build tags: -- `sqlite3_flock` forces the use of BSD locks. -- `sqlite3_dotlk` forces the use of dot-file locks. - -> [!IMPORTANT] -> The default configuration of this package is compatible with the standard -> [Unix and Windows SQLite VFSes](https://sqlite.org/vfs.html#multiple_vfses); -> `sqlite3_flock` builds are compatible with the -> [`unix-flock` VFS](https://sqlite.org/compile.html#enable_locking_style); -> `sqlite3_dotlk` builds are compatible with the -> [`unix-dotfile` VFS](https://sqlite.org/compile.html#enable_locking_style). -> If incompatible file locking is used, accessing databases concurrently with -> _other_ SQLite libraries will eventually corrupt data. - -### Custom VFSes - -- [`github.com/ncruces/go-sqlite3/vfs/memdb`](https://pkg.go.dev/github.com/ncruces/go-sqlite3/vfs/memdb) - implements an in-memory VFS. -- [`github.com/ncruces/go-sqlite3/vfs/readervfs`](https://pkg.go.dev/github.com/ncruces/go-sqlite3/vfs/readervfs) - implements a VFS for immutable databases. -- [`github.com/ncruces/go-sqlite3/vfs/adiantum`](https://pkg.go.dev/github.com/ncruces/go-sqlite3/vfs/adiantum) - wraps a VFS to offer encryption at rest. -- [`github.com/ncruces/go-sqlite3/vfs/xts`](https://pkg.go.dev/github.com/ncruces/go-sqlite3/vfs/xts) - wraps a VFS to offer encryption at rest. diff --git a/vendor/github.com/ncruces/go-sqlite3/vfs/api.go b/vendor/github.com/ncruces/go-sqlite3/vfs/api.go deleted file mode 100644 index d5bb3a7ae..000000000 --- a/vendor/github.com/ncruces/go-sqlite3/vfs/api.go +++ /dev/null @@ -1,216 +0,0 @@ -// Package vfs wraps the C SQLite VFS API. -package vfs - -import ( - "context" - "io" - - "github.com/tetratelabs/wazero/api" -) - -// A VFS defines the interface between the SQLite core and the underlying operating system. -// -// Use sqlite3.ErrorCode or sqlite3.ExtendedErrorCode to return specific error codes to SQLite. -// -// https://sqlite.org/c3ref/vfs.html -type VFS interface { - Open(name string, flags OpenFlag) (File, OpenFlag, error) - Delete(name string, syncDir bool) error - Access(name string, flags AccessFlag) (bool, error) - FullPathname(name string) (string, error) -} - -// VFSFilename extends VFS with the ability to use Filename -// objects for opening files. -// -// https://sqlite.org/c3ref/filename.html -type VFSFilename interface { - VFS - OpenFilename(name *Filename, flags OpenFlag) (File, OpenFlag, error) -} - -// A File represents an open file in the OS interface layer. -// -// Use sqlite3.ErrorCode or sqlite3.ExtendedErrorCode to return specific error codes to SQLite. -// In particular, sqlite3.BUSY is necessary to correctly implement lock methods. -// -// https://sqlite.org/c3ref/io_methods.html -type File interface { - Close() error - ReadAt(p []byte, off int64) (n int, err error) - WriteAt(p []byte, off int64) (n int, err error) - Truncate(size int64) error - Sync(flags SyncFlag) error - Size() (int64, error) - Lock(lock LockLevel) error - Unlock(lock LockLevel) error - CheckReservedLock() (bool, error) - SectorSize() int - DeviceCharacteristics() DeviceCharacteristic -} - -// FileUnwrap should be implemented by a File -// that wraps another File implementation. -type FileUnwrap interface { - File - Unwrap() File -} - -// FileLockState extends File to implement the -// SQLITE_FCNTL_LOCKSTATE file control opcode. -// -// https://sqlite.org/c3ref/c_fcntl_begin_atomic_write.html#sqlitefcntllockstate -type FileLockState interface { - File - LockState() LockLevel -} - -// FilePersistWAL extends File to implement the -// SQLITE_FCNTL_PERSIST_WAL file control opcode. -// -// https://sqlite.org/c3ref/c_fcntl_begin_atomic_write.html#sqlitefcntlpersistwal -type FilePersistWAL interface { - File - PersistWAL() bool - SetPersistWAL(bool) -} - -// FilePowersafeOverwrite extends File to implement the -// SQLITE_FCNTL_POWERSAFE_OVERWRITE file control opcode. -// -// https://sqlite.org/c3ref/c_fcntl_begin_atomic_write.html#sqlitefcntlpowersafeoverwrite -type FilePowersafeOverwrite interface { - File - PowersafeOverwrite() bool - SetPowersafeOverwrite(bool) -} - -// FileChunkSize extends File to implement the -// SQLITE_FCNTL_CHUNK_SIZE file control opcode. -// -// https://sqlite.org/c3ref/c_fcntl_begin_atomic_write.html#sqlitefcntlchunksize -type FileChunkSize interface { - File - ChunkSize(size int) -} - -// FileSizeHint extends File to implement the -// SQLITE_FCNTL_SIZE_HINT file control opcode. -// -// https://sqlite.org/c3ref/c_fcntl_begin_atomic_write.html#sqlitefcntlsizehint -type FileSizeHint interface { - File - SizeHint(size int64) error -} - -// FileHasMoved extends File to implement the -// SQLITE_FCNTL_HAS_MOVED file control opcode. -// -// https://sqlite.org/c3ref/c_fcntl_begin_atomic_write.html#sqlitefcntlhasmoved -type FileHasMoved interface { - File - HasMoved() (bool, error) -} - -// FileOverwrite extends File to implement the -// SQLITE_FCNTL_OVERWRITE file control opcode. -// -// https://sqlite.org/c3ref/c_fcntl_begin_atomic_write.html#sqlitefcntloverwrite -type FileOverwrite interface { - File - Overwrite() error -} - -// FileSync extends File to implement the -// SQLITE_FCNTL_SYNC file control opcode. -// -// https://sqlite.org/c3ref/c_fcntl_begin_atomic_write.html#sqlitefcntlsync -type FileSync interface { - File - SyncSuper(super string) error -} - -// FileCommitPhaseTwo extends File to implement the -// SQLITE_FCNTL_COMMIT_PHASETWO file control opcode. -// -// https://sqlite.org/c3ref/c_fcntl_begin_atomic_write.html#sqlitefcntlcommitphasetwo -type FileCommitPhaseTwo interface { - File - CommitPhaseTwo() error -} - -// FileBatchAtomicWrite extends File to implement the -// SQLITE_FCNTL_BEGIN_ATOMIC_WRITE, SQLITE_FCNTL_COMMIT_ATOMIC_WRITE -// and SQLITE_FCNTL_ROLLBACK_ATOMIC_WRITE file control opcodes. -// -// https://sqlite.org/c3ref/c_fcntl_begin_atomic_write.html#sqlitefcntlbeginatomicwrite -type FileBatchAtomicWrite interface { - File - BeginAtomicWrite() error - CommitAtomicWrite() error - RollbackAtomicWrite() error -} - -// FileCheckpoint extends File to implement the -// SQLITE_FCNTL_CKPT_START and SQLITE_FCNTL_CKPT_DONE -// file control opcodes. -// -// https://sqlite.org/c3ref/c_fcntl_begin_atomic_write.html#sqlitefcntlckptstart -type FileCheckpoint interface { - File - CheckpointStart() - CheckpointDone() -} - -// FilePragma extends File to implement the -// SQLITE_FCNTL_PRAGMA file control opcode. -// -// https://sqlite.org/c3ref/c_fcntl_begin_atomic_write.html#sqlitefcntlpragma -type FilePragma interface { - File - Pragma(name, value string) (string, error) -} - -// FileBusyHandler extends File to implement the -// SQLITE_FCNTL_BUSYHANDLER file control opcode. -// -// https://sqlite.org/c3ref/c_fcntl_begin_atomic_write.html#sqlitefcntlbusyhandler -type FileBusyHandler interface { - File - BusyHandler(func() bool) -} - -// FileSharedMemory extends File to possibly implement -// shared-memory for the WAL-index. -// The same shared-memory instance must be returned -// for the entire life of the file. -// It's OK for SharedMemory to return nil. -type FileSharedMemory interface { - File - SharedMemory() SharedMemory -} - -// SharedMemory is a shared-memory WAL-index implementation. -// Use [NewSharedMemory] to create a shared-memory. -type SharedMemory interface { - shmMap(context.Context, api.Module, int32, int32, bool) (ptr_t, _ErrorCode) - shmLock(int32, int32, _ShmFlag) _ErrorCode - shmUnmap(bool) - shmBarrier() - io.Closer -} - -type blockingSharedMemory interface { - SharedMemory - shmEnableBlocking(block bool) -} - -type fileControl interface { - File - fileControl(ctx context.Context, mod api.Module, op _FcntlOpcode, pArg ptr_t) _ErrorCode -} - -type filePDB interface { - File - SetDB(any) -} diff --git a/vendor/github.com/ncruces/go-sqlite3/vfs/cksm.go b/vendor/github.com/ncruces/go-sqlite3/vfs/cksm.go deleted file mode 100644 index 39493df99..000000000 --- a/vendor/github.com/ncruces/go-sqlite3/vfs/cksm.go +++ /dev/null @@ -1,157 +0,0 @@ -package vfs - -import ( - "bytes" - "context" - _ "embed" - "encoding/binary" - "strconv" - - "github.com/tetratelabs/wazero/api" - - "github.com/ncruces/go-sqlite3/internal/util" - "github.com/ncruces/go-sqlite3/util/sql3util" -) - -func cksmWrapFile(name *Filename, flags OpenFlag, file File) File { - // Checksum only main databases and WALs. - if flags&(OPEN_MAIN_DB|OPEN_WAL) == 0 { - return file - } - - cksm := cksmFile{File: file} - - if flags&OPEN_WAL != 0 { - main, _ := name.DatabaseFile().(cksmFile) - cksm.cksmFlags = main.cksmFlags - } else { - cksm.cksmFlags = new(cksmFlags) - cksm.isDB = true - } - - return cksm -} - -type cksmFile struct { - File - *cksmFlags - isDB bool -} - -type cksmFlags struct { - computeCksm bool - verifyCksm bool - inCkpt bool - pageSize int -} - -func (c cksmFile) ReadAt(p []byte, off int64) (n int, err error) { - n, err = c.File.ReadAt(p, off) - - // SQLite is reading the header of a database file. - if c.isDB && off == 0 && len(p) >= 100 && - bytes.HasPrefix(p, []byte("SQLite format 3\000")) { - c.init(p) - } - - // Verify checksums. - if c.verifyCksm && !c.inCkpt && len(p) == c.pageSize { - cksm1 := cksmCompute(p[:len(p)-8]) - cksm2 := *(*[8]byte)(p[len(p)-8:]) - if cksm1 != cksm2 { - return 0, _IOERR_DATA - } - } - return n, err -} - -func (c cksmFile) WriteAt(p []byte, off int64) (n int, err error) { - // SQLite is writing the first page of a database file. - if c.isDB && off == 0 && len(p) >= 100 && - bytes.HasPrefix(p, []byte("SQLite format 3\000")) { - c.init(p) - } - - // Compute checksums. - if c.computeCksm && !c.inCkpt && len(p) == c.pageSize { - *(*[8]byte)(p[len(p)-8:]) = cksmCompute(p[:len(p)-8]) - } - - return c.File.WriteAt(p, off) -} - -func (c cksmFile) Pragma(name string, value string) (string, error) { - switch name { - case "checksum_verification": - b, ok := sql3util.ParseBool(value) - if ok { - c.verifyCksm = b && c.computeCksm - } - if !c.verifyCksm { - return "0", nil - } - return "1", nil - - case "page_size": - if c.computeCksm { - // Do not allow page size changes on a checksum database. - return strconv.Itoa(c.pageSize), nil - } - } - return "", _NOTFOUND -} - -func (c cksmFile) DeviceCharacteristics() DeviceCharacteristic { - ret := c.File.DeviceCharacteristics() - if c.verifyCksm { - ret &^= IOCAP_SUBPAGE_READ - } - return ret -} - -func (c cksmFile) fileControl(ctx context.Context, mod api.Module, op _FcntlOpcode, pArg ptr_t) _ErrorCode { - switch op { - case _FCNTL_CKPT_START: - c.inCkpt = true - case _FCNTL_CKPT_DONE: - c.inCkpt = false - } - if rc := vfsFileControlImpl(ctx, mod, c, op, pArg); rc != _NOTFOUND { - return rc - } - return vfsFileControlImpl(ctx, mod, c.File, op, pArg) -} - -func (f *cksmFlags) init(header []byte) { - f.pageSize = 256 * int(binary.LittleEndian.Uint16(header[16:18])) - if r := header[20] == 8; r != f.computeCksm { - f.computeCksm = r - f.verifyCksm = r - } -} - -func cksmCompute(a []byte) (cksm [8]byte) { - var s1, s2 uint32 - for len(a) >= 8 { - s1 += binary.LittleEndian.Uint32(a[0:4]) + s2 - s2 += binary.LittleEndian.Uint32(a[4:8]) + s1 - a = a[8:] - } - if len(a) != 0 { - panic(util.AssertErr()) - } - binary.LittleEndian.PutUint32(cksm[0:4], s1) - binary.LittleEndian.PutUint32(cksm[4:8], s2) - return -} - -func (c cksmFile) SharedMemory() SharedMemory { - if f, ok := c.File.(FileSharedMemory); ok { - return f.SharedMemory() - } - return nil -} - -func (c cksmFile) Unwrap() File { - return c.File -} diff --git a/vendor/github.com/ncruces/go-sqlite3/vfs/const.go b/vendor/github.com/ncruces/go-sqlite3/vfs/const.go deleted file mode 100644 index dc3b0db83..000000000 --- a/vendor/github.com/ncruces/go-sqlite3/vfs/const.go +++ /dev/null @@ -1,248 +0,0 @@ -package vfs - -import "github.com/ncruces/go-sqlite3/internal/util" - -const ( - _MAX_NAME = 1e6 // Self-imposed limit for most NUL terminated strings. - _MAX_SQL_LENGTH = 1e9 - _MAX_PATHNAME = 1024 - _DEFAULT_SECTOR_SIZE = 4096 - - ptrlen = util.PtrLen -) - -type ( - stk_t = util.Stk_t - ptr_t = util.Ptr_t -) - -// https://sqlite.org/rescode.html -type _ErrorCode uint32 - -func (e _ErrorCode) Error() string { - return util.ErrorCodeString(uint32(e)) -} - -const ( - _OK _ErrorCode = util.OK - _ERROR _ErrorCode = util.ERROR - _PERM _ErrorCode = util.PERM - _BUSY _ErrorCode = util.BUSY - _READONLY _ErrorCode = util.READONLY - _IOERR _ErrorCode = util.IOERR - _NOTFOUND _ErrorCode = util.NOTFOUND - _CANTOPEN _ErrorCode = util.CANTOPEN - _IOERR_READ _ErrorCode = util.IOERR_READ - _IOERR_SHORT_READ _ErrorCode = util.IOERR_SHORT_READ - _IOERR_WRITE _ErrorCode = util.IOERR_WRITE - _IOERR_FSYNC _ErrorCode = util.IOERR_FSYNC - _IOERR_DIR_FSYNC _ErrorCode = util.IOERR_DIR_FSYNC - _IOERR_TRUNCATE _ErrorCode = util.IOERR_TRUNCATE - _IOERR_FSTAT _ErrorCode = util.IOERR_FSTAT - _IOERR_UNLOCK _ErrorCode = util.IOERR_UNLOCK - _IOERR_RDLOCK _ErrorCode = util.IOERR_RDLOCK - _IOERR_DELETE _ErrorCode = util.IOERR_DELETE - _IOERR_ACCESS _ErrorCode = util.IOERR_ACCESS - _IOERR_CHECKRESERVEDLOCK _ErrorCode = util.IOERR_CHECKRESERVEDLOCK - _IOERR_LOCK _ErrorCode = util.IOERR_LOCK - _IOERR_CLOSE _ErrorCode = util.IOERR_CLOSE - _IOERR_SHMOPEN _ErrorCode = util.IOERR_SHMOPEN - _IOERR_SHMSIZE _ErrorCode = util.IOERR_SHMSIZE - _IOERR_SHMLOCK _ErrorCode = util.IOERR_SHMLOCK - _IOERR_SHMMAP _ErrorCode = util.IOERR_SHMMAP - _IOERR_SEEK _ErrorCode = util.IOERR_SEEK - _IOERR_DELETE_NOENT _ErrorCode = util.IOERR_DELETE_NOENT - _IOERR_GETTEMPPATH _ErrorCode = util.IOERR_GETTEMPPATH - _IOERR_BEGIN_ATOMIC _ErrorCode = util.IOERR_BEGIN_ATOMIC - _IOERR_COMMIT_ATOMIC _ErrorCode = util.IOERR_COMMIT_ATOMIC - _IOERR_ROLLBACK_ATOMIC _ErrorCode = util.IOERR_ROLLBACK_ATOMIC - _IOERR_DATA _ErrorCode = util.IOERR_DATA - _BUSY_SNAPSHOT _ErrorCode = util.BUSY_SNAPSHOT - _CANTOPEN_FULLPATH _ErrorCode = util.CANTOPEN_FULLPATH - _CANTOPEN_ISDIR _ErrorCode = util.CANTOPEN_ISDIR - _READONLY_CANTINIT _ErrorCode = util.READONLY_CANTINIT - _OK_SYMLINK _ErrorCode = util.OK_SYMLINK -) - -// OpenFlag is a flag for the [VFS] Open method. -// -// https://sqlite.org/c3ref/c_open_autoproxy.html -type OpenFlag uint32 - -const ( - OPEN_READONLY OpenFlag = 0x00000001 /* Ok for sqlite3_open_v2() */ - OPEN_READWRITE OpenFlag = 0x00000002 /* Ok for sqlite3_open_v2() */ - OPEN_CREATE OpenFlag = 0x00000004 /* Ok for sqlite3_open_v2() */ - OPEN_DELETEONCLOSE OpenFlag = 0x00000008 /* VFS only */ - OPEN_EXCLUSIVE OpenFlag = 0x00000010 /* VFS only */ - OPEN_AUTOPROXY OpenFlag = 0x00000020 /* VFS only */ - OPEN_URI OpenFlag = 0x00000040 /* Ok for sqlite3_open_v2() */ - OPEN_MEMORY OpenFlag = 0x00000080 /* Ok for sqlite3_open_v2() */ - OPEN_MAIN_DB OpenFlag = 0x00000100 /* VFS only */ - OPEN_TEMP_DB OpenFlag = 0x00000200 /* VFS only */ - OPEN_TRANSIENT_DB OpenFlag = 0x00000400 /* VFS only */ - OPEN_MAIN_JOURNAL OpenFlag = 0x00000800 /* VFS only */ - OPEN_TEMP_JOURNAL OpenFlag = 0x00001000 /* VFS only */ - OPEN_SUBJOURNAL OpenFlag = 0x00002000 /* VFS only */ - OPEN_SUPER_JOURNAL OpenFlag = 0x00004000 /* VFS only */ - OPEN_NOMUTEX OpenFlag = 0x00008000 /* Ok for sqlite3_open_v2() */ - OPEN_FULLMUTEX OpenFlag = 0x00010000 /* Ok for sqlite3_open_v2() */ - OPEN_SHAREDCACHE OpenFlag = 0x00020000 /* Ok for sqlite3_open_v2() */ - OPEN_PRIVATECACHE OpenFlag = 0x00040000 /* Ok for sqlite3_open_v2() */ - OPEN_WAL OpenFlag = 0x00080000 /* VFS only */ - OPEN_NOFOLLOW OpenFlag = 0x01000000 /* Ok for sqlite3_open_v2() */ -) - -// AccessFlag is a flag for the [VFS] Access method. -// -// https://sqlite.org/c3ref/c_access_exists.html -type AccessFlag uint32 - -const ( - ACCESS_EXISTS AccessFlag = 0 - ACCESS_READWRITE AccessFlag = 1 /* Used by PRAGMA temp_store_directory */ - ACCESS_READ AccessFlag = 2 /* Unused */ -) - -// SyncFlag is a flag for the [File] Sync method. -// -// https://sqlite.org/c3ref/c_sync_dataonly.html -type SyncFlag uint32 - -const ( - SYNC_NORMAL SyncFlag = 0x00002 - SYNC_FULL SyncFlag = 0x00003 - SYNC_DATAONLY SyncFlag = 0x00010 -) - -// LockLevel is a value used with [File] Lock and Unlock methods. -// -// https://sqlite.org/c3ref/c_lock_exclusive.html -type LockLevel uint32 - -const ( - // No locks are held on the database. - // The database may be neither read nor written. - // Any internally cached data is considered suspect and subject to - // verification against the database file before being used. - // Other processes can read or write the database as their own locking - // states permit. - // This is the default state. - LOCK_NONE LockLevel = 0 /* xUnlock() only */ - - // The database may be read but not written. - // Any number of processes can hold SHARED locks at the same time, - // hence there can be many simultaneous readers. - // But no other thread or process is allowed to write to the database file - // while one or more SHARED locks are active. - LOCK_SHARED LockLevel = 1 /* xLock() or xUnlock() */ - - // A RESERVED lock means that the process is planning on writing to the - // database file at some point in the future but that it is currently just - // reading from the file. - // Only a single RESERVED lock may be active at one time, - // though multiple SHARED locks can coexist with a single RESERVED lock. - // RESERVED differs from PENDING in that new SHARED locks can be acquired - // while there is a RESERVED lock. - LOCK_RESERVED LockLevel = 2 /* xLock() only */ - - // A PENDING lock means that the process holding the lock wants to write to - // the database as soon as possible and is just waiting on all current - // SHARED locks to clear so that it can get an EXCLUSIVE lock. - // No new SHARED locks are permitted against the database if a PENDING lock - // is active, though existing SHARED locks are allowed to continue. - LOCK_PENDING LockLevel = 3 /* internal use only */ - - // An EXCLUSIVE lock is needed in order to write to the database file. - // Only one EXCLUSIVE lock is allowed on the file and no other locks of any - // kind are allowed to coexist with an EXCLUSIVE lock. - // In order to maximize concurrency, SQLite works to minimize the amount of - // time that EXCLUSIVE locks are held. - LOCK_EXCLUSIVE LockLevel = 4 /* xLock() only */ -) - -// DeviceCharacteristic is a flag retuned by the [File] DeviceCharacteristics method. -// -// https://sqlite.org/c3ref/c_iocap_atomic.html -type DeviceCharacteristic uint32 - -const ( - IOCAP_ATOMIC DeviceCharacteristic = 0x00000001 - IOCAP_ATOMIC512 DeviceCharacteristic = 0x00000002 - IOCAP_ATOMIC1K DeviceCharacteristic = 0x00000004 - IOCAP_ATOMIC2K DeviceCharacteristic = 0x00000008 - IOCAP_ATOMIC4K DeviceCharacteristic = 0x00000010 - IOCAP_ATOMIC8K DeviceCharacteristic = 0x00000020 - IOCAP_ATOMIC16K DeviceCharacteristic = 0x00000040 - IOCAP_ATOMIC32K DeviceCharacteristic = 0x00000080 - IOCAP_ATOMIC64K DeviceCharacteristic = 0x00000100 - IOCAP_SAFE_APPEND DeviceCharacteristic = 0x00000200 - IOCAP_SEQUENTIAL DeviceCharacteristic = 0x00000400 - IOCAP_UNDELETABLE_WHEN_OPEN DeviceCharacteristic = 0x00000800 - IOCAP_POWERSAFE_OVERWRITE DeviceCharacteristic = 0x00001000 - IOCAP_IMMUTABLE DeviceCharacteristic = 0x00002000 - IOCAP_BATCH_ATOMIC DeviceCharacteristic = 0x00004000 - IOCAP_SUBPAGE_READ DeviceCharacteristic = 0x00008000 -) - -// https://sqlite.org/c3ref/c_fcntl_begin_atomic_write.html -type _FcntlOpcode uint32 - -const ( - _FCNTL_LOCKSTATE _FcntlOpcode = 1 - _FCNTL_GET_LOCKPROXYFILE _FcntlOpcode = 2 - _FCNTL_SET_LOCKPROXYFILE _FcntlOpcode = 3 - _FCNTL_LAST_ERRNO _FcntlOpcode = 4 - _FCNTL_SIZE_HINT _FcntlOpcode = 5 - _FCNTL_CHUNK_SIZE _FcntlOpcode = 6 - _FCNTL_FILE_POINTER _FcntlOpcode = 7 - _FCNTL_SYNC_OMITTED _FcntlOpcode = 8 - _FCNTL_WIN32_AV_RETRY _FcntlOpcode = 9 - _FCNTL_PERSIST_WAL _FcntlOpcode = 10 - _FCNTL_OVERWRITE _FcntlOpcode = 11 - _FCNTL_VFSNAME _FcntlOpcode = 12 - _FCNTL_POWERSAFE_OVERWRITE _FcntlOpcode = 13 - _FCNTL_PRAGMA _FcntlOpcode = 14 - _FCNTL_BUSYHANDLER _FcntlOpcode = 15 - _FCNTL_TEMPFILENAME _FcntlOpcode = 16 - _FCNTL_MMAP_SIZE _FcntlOpcode = 18 - _FCNTL_TRACE _FcntlOpcode = 19 - _FCNTL_HAS_MOVED _FcntlOpcode = 20 - _FCNTL_SYNC _FcntlOpcode = 21 - _FCNTL_COMMIT_PHASETWO _FcntlOpcode = 22 - _FCNTL_WIN32_SET_HANDLE _FcntlOpcode = 23 - _FCNTL_WAL_BLOCK _FcntlOpcode = 24 - _FCNTL_ZIPVFS _FcntlOpcode = 25 - _FCNTL_RBU _FcntlOpcode = 26 - _FCNTL_VFS_POINTER _FcntlOpcode = 27 - _FCNTL_JOURNAL_POINTER _FcntlOpcode = 28 - _FCNTL_WIN32_GET_HANDLE _FcntlOpcode = 29 - _FCNTL_PDB _FcntlOpcode = 30 - _FCNTL_BEGIN_ATOMIC_WRITE _FcntlOpcode = 31 - _FCNTL_COMMIT_ATOMIC_WRITE _FcntlOpcode = 32 - _FCNTL_ROLLBACK_ATOMIC_WRITE _FcntlOpcode = 33 - _FCNTL_LOCK_TIMEOUT _FcntlOpcode = 34 - _FCNTL_DATA_VERSION _FcntlOpcode = 35 - _FCNTL_SIZE_LIMIT _FcntlOpcode = 36 - _FCNTL_CKPT_DONE _FcntlOpcode = 37 - _FCNTL_RESERVE_BYTES _FcntlOpcode = 38 - _FCNTL_CKPT_START _FcntlOpcode = 39 - _FCNTL_EXTERNAL_READER _FcntlOpcode = 40 - _FCNTL_CKSM_FILE _FcntlOpcode = 41 - _FCNTL_RESET_CACHE _FcntlOpcode = 42 - _FCNTL_NULL_IO _FcntlOpcode = 43 -) - -// https://sqlite.org/c3ref/c_shm_exclusive.html -type _ShmFlag uint32 - -const ( - _SHM_UNLOCK _ShmFlag = 1 - _SHM_LOCK _ShmFlag = 2 - _SHM_SHARED _ShmFlag = 4 - _SHM_EXCLUSIVE _ShmFlag = 8 - - _SHM_NLOCK = 8 - _SHM_BASE = 120 - _SHM_DMS = _SHM_BASE + _SHM_NLOCK -) diff --git a/vendor/github.com/ncruces/go-sqlite3/vfs/file.go b/vendor/github.com/ncruces/go-sqlite3/vfs/file.go deleted file mode 100644 index bc90555e7..000000000 --- a/vendor/github.com/ncruces/go-sqlite3/vfs/file.go +++ /dev/null @@ -1,222 +0,0 @@ -package vfs - -import ( - "errors" - "io" - "io/fs" - "os" - "path/filepath" - "syscall" - - "github.com/ncruces/go-sqlite3/util/osutil" -) - -type vfsOS struct{} - -func (vfsOS) FullPathname(path string) (string, error) { - path, err := filepath.Abs(path) - if err != nil { - return "", err - } - return path, testSymlinks(filepath.Dir(path)) -} - -func testSymlinks(path string) error { - p, err := filepath.EvalSymlinks(path) - if err != nil { - return err - } - if p != path { - return _OK_SYMLINK - } - return nil -} - -func (vfsOS) Delete(path string, syncDir bool) error { - err := os.Remove(path) - if errors.Is(err, fs.ErrNotExist) { - return _IOERR_DELETE_NOENT - } - if err != nil { - return err - } - if canSyncDirs && syncDir { - f, err := os.Open(filepath.Dir(path)) - if err != nil { - return _OK - } - defer f.Close() - err = osSync(f, false, false) - if err != nil { - return _IOERR_DIR_FSYNC - } - } - return nil -} - -func (vfsOS) Access(name string, flags AccessFlag) (bool, error) { - err := osAccess(name, flags) - if flags == ACCESS_EXISTS { - if errors.Is(err, fs.ErrNotExist) { - return false, nil - } - } else { - if errors.Is(err, fs.ErrPermission) { - return false, nil - } - } - return err == nil, err -} - -func (vfsOS) Open(name string, flags OpenFlag) (File, OpenFlag, error) { - // notest // OpenFilename is called instead - return nil, 0, _CANTOPEN -} - -func (vfsOS) OpenFilename(name *Filename, flags OpenFlag) (File, OpenFlag, error) { - oflags := _O_NOFOLLOW - if flags&OPEN_EXCLUSIVE != 0 { - oflags |= os.O_EXCL - } - if flags&OPEN_CREATE != 0 { - oflags |= os.O_CREATE - } - if flags&OPEN_READONLY != 0 { - oflags |= os.O_RDONLY - } - if flags&OPEN_READWRITE != 0 { - oflags |= os.O_RDWR - } - - var err error - var f *os.File - if name == nil { - f, err = os.CreateTemp("", "*.db") - } else { - f, err = osutil.OpenFile(name.String(), oflags, 0666) - } - if err != nil { - if name == nil { - return nil, flags, _IOERR_GETTEMPPATH - } - if errors.Is(err, syscall.EISDIR) { - return nil, flags, _CANTOPEN_ISDIR - } - return nil, flags, err - } - - if modeof := name.URIParameter("modeof"); modeof != "" { - if err = osSetMode(f, modeof); err != nil { - f.Close() - return nil, flags, _IOERR_FSTAT - } - } - if flags&OPEN_DELETEONCLOSE != 0 { - os.Remove(f.Name()) - } - - file := vfsFile{ - File: f, - psow: true, - readOnly: flags&OPEN_READONLY != 0, - syncDir: canSyncDirs && - flags&(OPEN_MAIN_JOURNAL|OPEN_SUPER_JOURNAL|OPEN_WAL) != 0 && - flags&(OPEN_CREATE) != 0, - shm: NewSharedMemory(name.String()+"-shm", flags), - } - return &file, flags, nil -} - -type vfsFile struct { - *os.File - shm SharedMemory - lock LockLevel - readOnly bool - keepWAL bool - syncDir bool - psow bool -} - -var ( - // Ensure these interfaces are implemented: - _ FileLockState = &vfsFile{} - _ FileHasMoved = &vfsFile{} - _ FileSizeHint = &vfsFile{} - _ FilePersistWAL = &vfsFile{} - _ FilePowersafeOverwrite = &vfsFile{} -) - -func (f *vfsFile) Close() error { - if f.shm != nil { - f.shm.Close() - } - f.Unlock(LOCK_NONE) - return f.File.Close() -} - -func (f *vfsFile) Sync(flags SyncFlag) error { - dataonly := (flags & SYNC_DATAONLY) != 0 - fullsync := (flags & 0x0f) == SYNC_FULL - - err := osSync(f.File, fullsync, dataonly) - if err != nil { - return err - } - if canSyncDirs && f.syncDir { - f.syncDir = false - d, err := os.Open(filepath.Dir(f.File.Name())) - if err != nil { - return nil - } - defer d.Close() - err = osSync(d, false, false) - if err != nil { - return _IOERR_DIR_FSYNC - } - } - return nil -} - -func (f *vfsFile) Size() (int64, error) { - return f.Seek(0, io.SeekEnd) -} - -func (f *vfsFile) SectorSize() int { - return _DEFAULT_SECTOR_SIZE -} - -func (f *vfsFile) DeviceCharacteristics() DeviceCharacteristic { - ret := IOCAP_SUBPAGE_READ - if osBatchAtomic(f.File) { - ret |= IOCAP_BATCH_ATOMIC - } - if f.psow { - ret |= IOCAP_POWERSAFE_OVERWRITE - } - return ret -} - -func (f *vfsFile) SizeHint(size int64) error { - return osAllocate(f.File, size) -} - -func (f *vfsFile) HasMoved() (bool, error) { - fi, err := f.Stat() - if err != nil { - return false, err - } - pi, err := os.Stat(f.Name()) - if errors.Is(err, fs.ErrNotExist) { - return true, nil - } - if err != nil { - return false, err - } - return !os.SameFile(fi, pi), nil -} - -func (f *vfsFile) LockState() LockLevel { return f.lock } -func (f *vfsFile) PowersafeOverwrite() bool { return f.psow } -func (f *vfsFile) PersistWAL() bool { return f.keepWAL } -func (f *vfsFile) SetPowersafeOverwrite(psow bool) { f.psow = psow } -func (f *vfsFile) SetPersistWAL(keepWAL bool) { f.keepWAL = keepWAL } diff --git a/vendor/github.com/ncruces/go-sqlite3/vfs/filename.go b/vendor/github.com/ncruces/go-sqlite3/vfs/filename.go deleted file mode 100644 index 965c3b1a6..000000000 --- a/vendor/github.com/ncruces/go-sqlite3/vfs/filename.go +++ /dev/null @@ -1,179 +0,0 @@ -package vfs - -import ( - "context" - "net/url" - - "github.com/tetratelabs/wazero/api" - - "github.com/ncruces/go-sqlite3/internal/util" -) - -// Filename is used by SQLite to pass filenames -// to the Open method of a VFS. -// -// https://sqlite.org/c3ref/filename.html -type Filename struct { - ctx context.Context - mod api.Module - zPath ptr_t - flags OpenFlag - stack [2]stk_t -} - -// GetFilename is an internal API users should not call directly. -func GetFilename(ctx context.Context, mod api.Module, id ptr_t, flags OpenFlag) *Filename { - if id == 0 { - return nil - } - return &Filename{ - ctx: ctx, - mod: mod, - zPath: id, - flags: flags, - } -} - -// String returns this filename as a string. -func (n *Filename) String() string { - if n == nil || n.zPath == 0 { - return "" - } - return util.ReadString(n.mod, n.zPath, _MAX_PATHNAME) -} - -// Database returns the name of the corresponding database file. -// -// https://sqlite.org/c3ref/filename_database.html -func (n *Filename) Database() string { - return n.path("sqlite3_filename_database") -} - -// Journal returns the name of the corresponding rollback journal file. -// -// https://sqlite.org/c3ref/filename_database.html -func (n *Filename) Journal() string { - return n.path("sqlite3_filename_journal") -} - -// Journal returns the name of the corresponding WAL file. -// -// https://sqlite.org/c3ref/filename_database.html -func (n *Filename) WAL() string { - return n.path("sqlite3_filename_wal") -} - -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] = stk_t(n.zPath) - fn := n.mod.ExportedFunction(method) - if err := fn.CallWithStack(n.ctx, n.stack[:]); err != nil { - panic(err) - } - return util.ReadString(n.mod, ptr_t(n.stack[0]), _MAX_PATHNAME) -} - -// DatabaseFile returns the main database [File] corresponding to a journal. -// -// https://sqlite.org/c3ref/database_file_object.html -func (n *Filename) DatabaseFile() File { - if n == nil || n.zPath == 0 { - return nil - } - if n.flags&(OPEN_MAIN_DB|OPEN_MAIN_JOURNAL|OPEN_WAL) == 0 { - return nil - } - - n.stack[0] = stk_t(n.zPath) - fn := n.mod.ExportedFunction("sqlite3_database_file_object") - if err := fn.CallWithStack(n.ctx, n.stack[:]); err != nil { - panic(err) - } - file, _ := vfsFileGet(n.ctx, n.mod, ptr_t(n.stack[0])).(File) - return file -} - -// URIParameter returns the value of a URI parameter. -// -// https://sqlite.org/c3ref/uri_boolean.html -func (n *Filename) URIParameter(key string) string { - if n == nil || n.zPath == 0 { - return "" - } - - uriKey := n.mod.ExportedFunction("sqlite3_uri_key") - n.stack[0] = stk_t(n.zPath) - n.stack[1] = stk_t(0) - if err := uriKey.CallWithStack(n.ctx, n.stack[:]); err != nil { - panic(err) - } - - ptr := ptr_t(n.stack[0]) - if ptr == 0 { - return "" - } - - // Parse the format from: - // https://github.com/sqlite/sqlite/blob/b74eb0/src/pager.c#L4797-L4840 - // This avoids having to alloc/free the key just to find a value. - for { - k := util.ReadString(n.mod, ptr, _MAX_NAME) - if k == "" { - return "" - } - ptr += ptr_t(len(k)) + 1 - - v := util.ReadString(n.mod, ptr, _MAX_NAME) - if k == key { - return v - } - ptr += ptr_t(len(v)) + 1 - } -} - -// URIParameters obtains values for URI parameters. -// -// https://sqlite.org/c3ref/uri_boolean.html -func (n *Filename) URIParameters() url.Values { - if n == nil || n.zPath == 0 { - return nil - } - - uriKey := n.mod.ExportedFunction("sqlite3_uri_key") - n.stack[0] = stk_t(n.zPath) - n.stack[1] = stk_t(0) - if err := uriKey.CallWithStack(n.ctx, n.stack[:]); err != nil { - panic(err) - } - - ptr := ptr_t(n.stack[0]) - if ptr == 0 { - return nil - } - - var params url.Values - - // Parse the format from: - // https://github.com/sqlite/sqlite/blob/b74eb0/src/pager.c#L4797-L4840 - // This is the only way to support multiple valued keys. - for { - k := util.ReadString(n.mod, ptr, _MAX_NAME) - if k == "" { - return params - } - ptr += ptr_t(len(k)) + 1 - - v := util.ReadString(n.mod, ptr, _MAX_NAME) - if params == nil { - params = url.Values{} - } - params.Add(k, v) - ptr += ptr_t(len(v)) + 1 - } -} diff --git a/vendor/github.com/ncruces/go-sqlite3/vfs/lock.go b/vendor/github.com/ncruces/go-sqlite3/vfs/lock.go deleted file mode 100644 index b28d83230..000000000 --- a/vendor/github.com/ncruces/go-sqlite3/vfs/lock.go +++ /dev/null @@ -1,128 +0,0 @@ -//go:build linux || darwin || windows || freebsd || openbsd || netbsd || dragonfly || illumos || sqlite3_flock || sqlite3_dotlk - -package vfs - -import "github.com/ncruces/go-sqlite3/internal/util" - -// SupportsFileLocking is false on platforms that do not support file locking. -// To open a database file on those platforms, -// you need to use the [nolock] or [immutable] URI parameters. -// -// [nolock]: https://sqlite.org/uri.html#urinolock -// [immutable]: https://sqlite.org/uri.html#uriimmutable -const SupportsFileLocking = true - -const ( - _PENDING_BYTE = 0x40000000 - _RESERVED_BYTE = (_PENDING_BYTE + 1) - _SHARED_FIRST = (_PENDING_BYTE + 2) - _SHARED_SIZE = 510 -) - -func (f *vfsFile) Lock(lock LockLevel) error { - switch { - case lock != LOCK_SHARED && lock != LOCK_RESERVED && lock != LOCK_EXCLUSIVE: - // Argument check. SQLite never explicitly requests a pending lock. - panic(util.AssertErr()) - case f.lock < LOCK_NONE || f.lock > LOCK_EXCLUSIVE: - // Connection state check. - panic(util.AssertErr()) - case f.lock == LOCK_NONE && lock > LOCK_SHARED: - // We never move from unlocked to anything higher than a shared lock. - panic(util.AssertErr()) - case f.lock != LOCK_SHARED && lock == LOCK_RESERVED: - // A shared lock is always held when a reserved lock is requested. - panic(util.AssertErr()) - } - - // If we already have an equal or more restrictive lock, do nothing. - if f.lock >= lock { - return nil - } - - // Do not allow any kind of write-lock on a read-only database. - if f.readOnly && lock >= LOCK_RESERVED { - return _IOERR_LOCK - } - - switch lock { - case LOCK_SHARED: - // Must be unlocked to get SHARED. - if f.lock != LOCK_NONE { - panic(util.AssertErr()) - } - if rc := osGetSharedLock(f.File); rc != _OK { - return rc - } - f.lock = LOCK_SHARED - return nil - - case LOCK_RESERVED: - // Must be SHARED to get RESERVED. - if f.lock != LOCK_SHARED { - panic(util.AssertErr()) - } - if rc := osGetReservedLock(f.File); rc != _OK { - return rc - } - f.lock = LOCK_RESERVED - return nil - - case LOCK_EXCLUSIVE: - // Must be SHARED, RESERVED or PENDING to get EXCLUSIVE. - if f.lock <= LOCK_NONE || f.lock >= LOCK_EXCLUSIVE { - panic(util.AssertErr()) - } - if rc := osGetExclusiveLock(f.File, &f.lock); rc != _OK { - return rc - } - f.lock = LOCK_EXCLUSIVE - return nil - - default: - panic(util.AssertErr()) - } -} - -func (f *vfsFile) Unlock(lock LockLevel) error { - switch { - case lock != LOCK_NONE && lock != LOCK_SHARED: - // Argument check. - panic(util.AssertErr()) - case f.lock < LOCK_NONE || f.lock > LOCK_EXCLUSIVE: - // Connection state check. - panic(util.AssertErr()) - } - - // If we don't have a more restrictive lock, do nothing. - if f.lock <= lock { - return nil - } - - switch lock { - case LOCK_SHARED: - rc := osDowngradeLock(f.File, f.lock) - f.lock = LOCK_SHARED - return rc - - case LOCK_NONE: - rc := osReleaseLock(f.File, f.lock) - f.lock = LOCK_NONE - return rc - - default: - panic(util.AssertErr()) - } -} - -func (f *vfsFile) CheckReservedLock() (bool, error) { - // Connection state check. - if f.lock < LOCK_NONE || f.lock > LOCK_EXCLUSIVE { - panic(util.AssertErr()) - } - - if f.lock >= LOCK_RESERVED { - return true, nil - } - return osCheckReservedLock(f.File) -} diff --git a/vendor/github.com/ncruces/go-sqlite3/vfs/lock_other.go b/vendor/github.com/ncruces/go-sqlite3/vfs/lock_other.go deleted file mode 100644 index 9bdfa3cf2..000000000 --- a/vendor/github.com/ncruces/go-sqlite3/vfs/lock_other.go +++ /dev/null @@ -1,23 +0,0 @@ -//go:build !(linux || darwin || windows || freebsd || openbsd || netbsd || dragonfly || illumos || sqlite3_flock || sqlite3_dotlk) - -package vfs - -// SupportsFileLocking is false on platforms that do not support file locking. -// To open a database file on those platforms, -// you need to use the [nolock] or [immutable] URI parameters. -// -// [nolock]: https://sqlite.org/uri.html#urinolock -// [immutable]: https://sqlite.org/uri.html#uriimmutable -const SupportsFileLocking = false - -func (f *vfsFile) Lock(LockLevel) error { - return _IOERR_LOCK -} - -func (f *vfsFile) Unlock(LockLevel) error { - return _IOERR_UNLOCK -} - -func (f *vfsFile) CheckReservedLock() (bool, error) { - return false, _IOERR_CHECKRESERVEDLOCK -} diff --git a/vendor/github.com/ncruces/go-sqlite3/vfs/memdb/README.md b/vendor/github.com/ncruces/go-sqlite3/vfs/memdb/README.md deleted file mode 100644 index 2e2611bf8..000000000 --- a/vendor/github.com/ncruces/go-sqlite3/vfs/memdb/README.md +++ /dev/null @@ -1,9 +0,0 @@ -# Go `memdb` SQLite VFS - -This package implements the [`"memdb"`](https://sqlite.org/src/doc/tip/src/memdb.c) -SQLite VFS in pure Go. - -It has some benefits over the C version: -- the memory backing the database needs not be contiguous, -- the database can grow/shrink incrementally without copying, -- reader-writer concurrency is slightly improved.
\ No newline at end of file diff --git a/vendor/github.com/ncruces/go-sqlite3/vfs/memdb/api.go b/vendor/github.com/ncruces/go-sqlite3/vfs/memdb/api.go deleted file mode 100644 index eb12eba09..000000000 --- a/vendor/github.com/ncruces/go-sqlite3/vfs/memdb/api.go +++ /dev/null @@ -1,100 +0,0 @@ -// Package memdb implements the "memdb" SQLite VFS. -// -// The "memdb" [vfs.VFS] allows the same in-memory database to be shared -// among multiple database connections in the same process, -// as long as the database name begins with "/". -// -// Importing package memdb registers the VFS: -// -// import _ "github.com/ncruces/go-sqlite3/vfs/memdb" -package memdb - -import ( - "fmt" - "net/url" - "sync" - "testing" - - "github.com/ncruces/go-sqlite3/vfs" -) - -func init() { - vfs.Register("memdb", memVFS{}) -} - -var ( - memoryMtx sync.Mutex - // +checklocks:memoryMtx - memoryDBs = map[string]*memDB{} -) - -// Create creates a shared memory database, -// using data as its initial contents. -// The new database takes ownership of data, -// and the caller should not use data after this call. -func Create(name string, data []byte) { - memoryMtx.Lock() - defer memoryMtx.Unlock() - - db := &memDB{ - refs: 1, - name: name, - size: int64(len(data)), - } - - // Convert data from WAL/2 to rollback journal. - if len(data) >= 20 && (false || - data[18] == 2 && data[19] == 2 || - data[18] == 3 && data[19] == 3) { - data[18] = 1 - data[19] = 1 - } - - sectors := divRoundUp(db.size, sectorSize) - db.data = make([]*[sectorSize]byte, sectors) - for i := range db.data { - sector := data[i*sectorSize:] - if len(sector) >= sectorSize { - db.data[i] = (*[sectorSize]byte)(sector) - } else { - db.data[i] = new([sectorSize]byte) - copy((*db.data[i])[:], sector) - } - } - - memoryDBs[name] = db -} - -// Delete deletes a shared memory database. -func Delete(name string) { - memoryMtx.Lock() - 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 deleted file mode 100644 index 419fd1c64..000000000 --- a/vendor/github.com/ncruces/go-sqlite3/vfs/memdb/memdb.go +++ /dev/null @@ -1,308 +0,0 @@ -package memdb - -import ( - "io" - "runtime" - "sync" - "time" - - "github.com/ncruces/go-sqlite3" - "github.com/ncruces/go-sqlite3/vfs" -) - -const sectorSize = 65536 - -// Ensure sectorSize is a multiple of 64K (the largest page size). -var _ [0]struct{} = [sectorSize & 65535]struct{}{} - -type memVFS struct{} - -func (memVFS) Open(name string, flags vfs.OpenFlag) (vfs.File, vfs.OpenFlag, error) { - // For simplicity, we do not support reading or writing data - // across "sector" boundaries. - // - // This is not a problem for most SQLite file types: - // - databases, which only do page aligned reads/writes; - // - temp journals, as used by the sorter, which does the same: - // https://github.com/sqlite/sqlite/blob/b74eb0/src/vdbesort.c#L409-L412 - // - // We refuse to open all other file types, - // but returning OPEN_MEMORY means SQLite won't ask us to. - const types = vfs.OPEN_MAIN_DB | - vfs.OPEN_TEMP_DB | - vfs.OPEN_TEMP_JOURNAL - if flags&types == 0 { - // notest // OPEN_MEMORY - return nil, flags, sqlite3.CANTOPEN - } - - // A shared database has a name that begins with "/". - shared := len(name) > 1 && name[0] == '/' - - var db *memDB - if shared { - name = name[1:] - memoryMtx.Lock() - defer memoryMtx.Unlock() - db = memoryDBs[name] - } - if db == nil { - if flags&vfs.OPEN_CREATE == 0 { - return nil, flags, sqlite3.CANTOPEN - } - db = &memDB{name: name} - } - if shared { - db.refs++ // +checklocksforce: memoryMtx is held - memoryDBs[name] = db - } - - return &memFile{ - memDB: db, - readOnly: flags&vfs.OPEN_READONLY != 0, - }, flags | vfs.OPEN_MEMORY, nil -} - -func (memVFS) Delete(name string, dirSync bool) error { - return sqlite3.IOERR_DELETE_NOENT // used to delete journals -} - -func (memVFS) Access(name string, flag vfs.AccessFlag) (bool, error) { - return false, nil // used to check for journals -} - -func (memVFS) FullPathname(name string) (string, error) { - return name, nil -} - -type memDB struct { - name string - - // +checklocks:dataMtx - data []*[sectorSize]byte - // +checklocks:dataMtx - size int64 - - // +checklocks:memoryMtx - refs int32 - - shared int32 // +checklocks:lockMtx - pending bool // +checklocks:lockMtx - reserved bool // +checklocks:lockMtx - - lockMtx sync.Mutex - dataMtx sync.RWMutex -} - -func (m *memDB) release() { - memoryMtx.Lock() - defer memoryMtx.Unlock() - if m.refs--; m.refs == 0 && m == memoryDBs[m.name] { - delete(memoryDBs, m.name) - } -} - -type memFile struct { - *memDB - lock vfs.LockLevel - readOnly bool -} - -var ( - // Ensure these interfaces are implemented: - _ vfs.FileLockState = &memFile{} - _ vfs.FileSizeHint = &memFile{} -) - -func (m *memFile) Close() error { - m.release() - return m.Unlock(vfs.LOCK_NONE) -} - -func (m *memFile) ReadAt(b []byte, off int64) (n int, err error) { - m.dataMtx.RLock() - defer m.dataMtx.RUnlock() - - if off >= m.size { - return 0, io.EOF - } - - base := off / sectorSize - rest := off % sectorSize - have := int64(sectorSize) - if base == int64(len(m.data))-1 { - have = modRoundUp(m.size, sectorSize) - } - n = copy(b, (*m.data[base])[rest:have]) - if n < len(b) { - // notest // assume reads are page aligned - return 0, io.ErrNoProgress - } - return n, nil -} - -func (m *memFile) WriteAt(b []byte, off int64) (n int, err error) { - m.dataMtx.Lock() - defer m.dataMtx.Unlock() - - base := off / sectorSize - rest := off % sectorSize - for base >= int64(len(m.data)) { - m.data = append(m.data, new([sectorSize]byte)) - } - n = copy((*m.data[base])[rest:], b) - if n < len(b) { - // notest // assume writes are page aligned - return n, io.ErrShortWrite - } - if size := off + int64(len(b)); size > m.size { - m.size = size - } - return n, nil -} - -func (m *memFile) Truncate(size int64) error { - m.dataMtx.Lock() - defer m.dataMtx.Unlock() - return m.truncate(size) -} - -// +checklocks:m.dataMtx -func (m *memFile) truncate(size int64) error { - if size < m.size { - base := size / sectorSize - rest := size % sectorSize - if rest != 0 { - clear((*m.data[base])[rest:]) - } - } - sectors := divRoundUp(size, sectorSize) - for sectors > int64(len(m.data)) { - m.data = append(m.data, new([sectorSize]byte)) - } - clear(m.data[sectors:]) - m.data = m.data[:sectors] - m.size = size - return nil -} - -func (m *memFile) Sync(flag vfs.SyncFlag) error { - return nil -} - -func (m *memFile) Size() (int64, error) { - m.dataMtx.RLock() - defer m.dataMtx.RUnlock() - return m.size, nil -} - -const spinWait = 25 * time.Microsecond - -func (m *memFile) Lock(lock vfs.LockLevel) error { - if m.lock >= lock { - return nil - } - - if m.readOnly && lock >= vfs.LOCK_RESERVED { - return sqlite3.IOERR_LOCK - } - - m.lockMtx.Lock() - defer m.lockMtx.Unlock() - - switch lock { - case vfs.LOCK_SHARED: - if m.pending { - return sqlite3.BUSY - } - m.shared++ - - case vfs.LOCK_RESERVED: - if m.reserved { - return sqlite3.BUSY - } - m.reserved = true - - case vfs.LOCK_EXCLUSIVE: - if m.lock < vfs.LOCK_PENDING { - m.lock = vfs.LOCK_PENDING - m.pending = true - } - - for before := time.Now(); m.shared > 1; { - if time.Since(before) > spinWait { - return sqlite3.BUSY - } - m.lockMtx.Unlock() - runtime.Gosched() - m.lockMtx.Lock() - } - } - - m.lock = lock - return nil -} - -func (m *memFile) Unlock(lock vfs.LockLevel) error { - if m.lock <= lock { - return nil - } - - m.lockMtx.Lock() - defer m.lockMtx.Unlock() - - if m.lock >= vfs.LOCK_RESERVED { - m.reserved = false - } - if m.lock >= vfs.LOCK_PENDING { - m.pending = false - } - if lock < vfs.LOCK_SHARED { - m.shared-- - } - m.lock = lock - return nil -} - -func (m *memFile) CheckReservedLock() (bool, error) { - // notest // OPEN_MEMORY - if m.lock >= vfs.LOCK_RESERVED { - return true, nil - } - m.lockMtx.Lock() - defer m.lockMtx.Unlock() - return m.reserved, nil -} - -func (m *memFile) SectorSize() int { - // notest // IOCAP_POWERSAFE_OVERWRITE - return sectorSize -} - -func (m *memFile) DeviceCharacteristics() vfs.DeviceCharacteristic { - return vfs.IOCAP_ATOMIC | - vfs.IOCAP_SEQUENTIAL | - vfs.IOCAP_SAFE_APPEND | - vfs.IOCAP_POWERSAFE_OVERWRITE -} - -func (m *memFile) SizeHint(size int64) error { - m.dataMtx.Lock() - defer m.dataMtx.Unlock() - if size > m.size { - return m.truncate(size) - } - return nil -} - -func (m *memFile) LockState() vfs.LockLevel { - return m.lock -} - -func divRoundUp(a, b int64) int64 { - return (a + b - 1) / b -} - -func modRoundUp(a, b int64) int64 { - return b - (b-a%b)%b -} diff --git a/vendor/github.com/ncruces/go-sqlite3/vfs/os_bsd.go b/vendor/github.com/ncruces/go-sqlite3/vfs/os_bsd.go deleted file mode 100644 index 4f6fadef4..000000000 --- a/vendor/github.com/ncruces/go-sqlite3/vfs/os_bsd.go +++ /dev/null @@ -1,101 +0,0 @@ -//go:build ((freebsd || openbsd || netbsd || dragonfly || illumos) && !sqlite3_dotlk) || sqlite3_flock - -package vfs - -import ( - "os" - - "golang.org/x/sys/unix" -) - -func osGetSharedLock(file *os.File) _ErrorCode { - return osFlock(file, unix.LOCK_SH|unix.LOCK_NB, _IOERR_RDLOCK) -} - -func osGetReservedLock(file *os.File) _ErrorCode { - rc := osFlock(file, unix.LOCK_EX|unix.LOCK_NB, _IOERR_LOCK) - if rc == _BUSY { - // The documentation states that a lock is upgraded by - // releasing the previous lock, then acquiring the new lock. - // Going over the source code of various BSDs, though, - // with LOCK_NB, the lock is not released, - // and EAGAIN is returned holding the shared lock. - // Still, if we're already in a transaction, we want to abort it, - // so return BUSY_SNAPSHOT here. If there's no transaction active, - // SQLite will change this back to SQLITE_BUSY, - // and invoke the busy handler if appropriate. - return _BUSY_SNAPSHOT - } - return rc -} - -func osGetExclusiveLock(file *os.File, state *LockLevel) _ErrorCode { - if *state >= LOCK_RESERVED { - return _OK - } - return osGetReservedLock(file) -} - -func osDowngradeLock(file *os.File, _ LockLevel) _ErrorCode { - rc := osFlock(file, unix.LOCK_SH|unix.LOCK_NB, _IOERR_RDLOCK) - if rc == _BUSY { - // The documentation states that a lock is downgraded by - // releasing the previous lock then acquiring the new lock. - // Going over the source code of various BSDs, though, - // with LOCK_SH|LOCK_NB this should never happen. - // Return IOERR_RDLOCK, as BUSY would cause an assert to fail. - return _IOERR_RDLOCK - } - return _OK -} - -func osReleaseLock(file *os.File, _ LockLevel) _ErrorCode { - err := unix.Flock(int(file.Fd()), unix.LOCK_UN) - if err != nil { - return _IOERR_UNLOCK - } - return _OK -} - -func osCheckReservedLock(file *os.File) (bool, _ErrorCode) { - // Test the RESERVED lock with fcntl(F_GETLK). - // This only works on systems where fcntl and flock are compatible. - // However, SQLite only calls this while holding a shared lock, - // so the difference is immaterial. - lock, rc := osTestLock(file, _RESERVED_BYTE, 1) - return lock == unix.F_WRLCK, rc -} - -func osFlock(file *os.File, how int, def _ErrorCode) _ErrorCode { - err := unix.Flock(int(file.Fd()), how) - return osLockErrorCode(err, def) -} - -func osReadLock(file *os.File, start, len int64) _ErrorCode { - return osLock(file, unix.F_RDLCK, start, len, _IOERR_RDLOCK) -} - -func osWriteLock(file *os.File, start, len int64) _ErrorCode { - return osLock(file, unix.F_WRLCK, start, len, _IOERR_LOCK) -} - -func osLock(file *os.File, typ int16, start, len int64, def _ErrorCode) _ErrorCode { - err := unix.FcntlFlock(file.Fd(), unix.F_SETLK, &unix.Flock_t{ - Type: typ, - Start: start, - Len: len, - }) - return osLockErrorCode(err, def) -} - -func osUnlock(file *os.File, start, len int64) _ErrorCode { - err := unix.FcntlFlock(file.Fd(), unix.F_SETLK, &unix.Flock_t{ - Type: unix.F_UNLCK, - Start: start, - Len: len, - }) - if err != nil { - return _IOERR_UNLOCK - } - return _OK -} diff --git a/vendor/github.com/ncruces/go-sqlite3/vfs/os_darwin.go b/vendor/github.com/ncruces/go-sqlite3/vfs/os_darwin.go deleted file mode 100644 index 07de7c3d8..000000000 --- a/vendor/github.com/ncruces/go-sqlite3/vfs/os_darwin.go +++ /dev/null @@ -1,97 +0,0 @@ -//go:build !sqlite3_flock - -package vfs - -import ( - "io" - "os" - "runtime" - "time" - - "golang.org/x/sys/unix" -) - -const ( - // https://github.com/apple/darwin-xnu/blob/main/bsd/sys/fcntl.h - _F_OFD_SETLK = 90 - _F_OFD_SETLKW = 91 - _F_OFD_SETLKWTIMEOUT = 93 -) - -type flocktimeout_t struct { - fl unix.Flock_t - timeout unix.Timespec -} - -func osSync(file *os.File, fullsync, _ /*dataonly*/ bool) error { - if fullsync { - return file.Sync() - } - return unix.Fsync(int(file.Fd())) -} - -func osAllocate(file *os.File, size int64) error { - off, err := file.Seek(0, io.SeekEnd) - if err != nil { - return err - } - if size <= off { - return nil - } - - store := unix.Fstore_t{ - Flags: unix.F_ALLOCATEALL | unix.F_ALLOCATECONTIG, - Posmode: unix.F_PEOFPOSMODE, - Offset: 0, - Length: size - off, - } - - // Try to get a continuous chunk of disk space. - err = unix.FcntlFstore(file.Fd(), unix.F_PREALLOCATE, &store) - if err != nil { - // OK, perhaps we are too fragmented, allocate non-continuous. - store.Flags = unix.F_ALLOCATEALL - unix.FcntlFstore(file.Fd(), unix.F_PREALLOCATE, &store) - } - return file.Truncate(size) -} - -func osReadLock(file *os.File, start, len int64, timeout time.Duration) _ErrorCode { - return osLock(file, unix.F_RDLCK, start, len, timeout, _IOERR_RDLOCK) -} - -func osWriteLock(file *os.File, start, len int64, timeout time.Duration) _ErrorCode { - return osLock(file, unix.F_WRLCK, start, len, timeout, _IOERR_LOCK) -} - -func osLock(file *os.File, typ int16, start, len int64, timeout time.Duration, def _ErrorCode) _ErrorCode { - lock := &flocktimeout_t{fl: unix.Flock_t{ - Type: typ, - Start: start, - Len: len, - }} - var err error - switch { - case timeout == 0: - err = unix.FcntlFlock(file.Fd(), _F_OFD_SETLK, &lock.fl) - case timeout < 0: - err = unix.FcntlFlock(file.Fd(), _F_OFD_SETLKW, &lock.fl) - 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) -} - -func osUnlock(file *os.File, start, len int64) _ErrorCode { - err := unix.FcntlFlock(file.Fd(), _F_OFD_SETLK, &unix.Flock_t{ - Type: unix.F_UNLCK, - Start: start, - Len: len, - }) - if err != nil { - return _IOERR_UNLOCK - } - return _OK -} diff --git a/vendor/github.com/ncruces/go-sqlite3/vfs/os_dotlk.go b/vendor/github.com/ncruces/go-sqlite3/vfs/os_dotlk.go deleted file mode 100644 index 7a9c38897..000000000 --- a/vendor/github.com/ncruces/go-sqlite3/vfs/os_dotlk.go +++ /dev/null @@ -1,143 +0,0 @@ -//go:build sqlite3_dotlk - -package vfs - -import ( - "errors" - "io/fs" - "os" - "sync" - - "github.com/ncruces/go-sqlite3/internal/dotlk" -) - -var ( - // +checklocks:vfsDotLocksMtx - vfsDotLocks = map[string]*vfsDotLocker{} - vfsDotLocksMtx sync.Mutex -) - -type vfsDotLocker struct { - shared int // +checklocks:vfsDotLocksMtx - pending *os.File // +checklocks:vfsDotLocksMtx - reserved *os.File // +checklocks:vfsDotLocksMtx -} - -func osGetSharedLock(file *os.File) _ErrorCode { - vfsDotLocksMtx.Lock() - defer vfsDotLocksMtx.Unlock() - - name := file.Name() - locker := vfsDotLocks[name] - if locker == nil { - if err := dotlk.TryLock(name + ".lock"); err != nil { - if errors.Is(err, fs.ErrExist) { - return _BUSY // Another process has the lock. - } - return _IOERR_LOCK - } - locker = &vfsDotLocker{} - vfsDotLocks[name] = locker - } - - if locker.pending != nil { - return _BUSY - } - locker.shared++ - return _OK -} - -func osGetReservedLock(file *os.File) _ErrorCode { - vfsDotLocksMtx.Lock() - defer vfsDotLocksMtx.Unlock() - - name := file.Name() - locker := vfsDotLocks[name] - if locker == nil { - return _IOERR_LOCK - } - - if locker.reserved != nil && locker.reserved != file { - return _BUSY - } - locker.reserved = file - return _OK -} - -func osGetExclusiveLock(file *os.File, _ *LockLevel) _ErrorCode { - vfsDotLocksMtx.Lock() - defer vfsDotLocksMtx.Unlock() - - name := file.Name() - locker := vfsDotLocks[name] - if locker == nil { - return _IOERR_LOCK - } - - if locker.pending != nil && locker.pending != file { - return _BUSY - } - locker.pending = file - if locker.shared > 1 { - return _BUSY - } - return _OK -} - -func osDowngradeLock(file *os.File, _ LockLevel) _ErrorCode { - vfsDotLocksMtx.Lock() - defer vfsDotLocksMtx.Unlock() - - name := file.Name() - locker := vfsDotLocks[name] - if locker == nil { - return _IOERR_UNLOCK - } - - if locker.reserved == file { - locker.reserved = nil - } - if locker.pending == file { - locker.pending = nil - } - return _OK -} - -func osReleaseLock(file *os.File, state LockLevel) _ErrorCode { - vfsDotLocksMtx.Lock() - defer vfsDotLocksMtx.Unlock() - - name := file.Name() - locker := vfsDotLocks[name] - if locker == nil { - return _IOERR_UNLOCK - } - - if locker.shared == 1 { - if err := dotlk.Unlock(name + ".lock"); err != nil { - return _IOERR_UNLOCK - } - delete(vfsDotLocks, name) - } - - if locker.reserved == file { - locker.reserved = nil - } - if locker.pending == file { - locker.pending = nil - } - locker.shared-- - return _OK -} - -func osCheckReservedLock(file *os.File) (bool, _ErrorCode) { - vfsDotLocksMtx.Lock() - defer vfsDotLocksMtx.Unlock() - - name := file.Name() - locker := vfsDotLocks[name] - if locker == nil { - return false, _OK - } - return locker.reserved != nil, _OK -} 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 deleted file mode 100644 index 36614309d..000000000 --- a/vendor/github.com/ncruces/go-sqlite3/vfs/os_f2fs_linux.go +++ /dev/null @@ -1,37 +0,0 @@ -//go:build amd64 || arm64 || riscv64 - -package vfs - -import ( - "os" - - "golang.org/x/sys/unix" -) - -const ( - // https://godbolt.org/z/1PcK5vea3 - _F2FS_IOC_START_ATOMIC_WRITE = 62721 - _F2FS_IOC_COMMIT_ATOMIC_WRITE = 62722 - _F2FS_IOC_ABORT_ATOMIC_WRITE = 62725 - _F2FS_IOC_GET_FEATURES = 2147808524 // -2147158772 - _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 -} - -func (f *vfsFile) BeginAtomicWrite() error { - return unix.IoctlSetInt(int(f.Fd()), _F2FS_IOC_START_ATOMIC_WRITE, 0) -} - -func (f *vfsFile) CommitAtomicWrite() error { - return unix.IoctlSetInt(int(f.Fd()), _F2FS_IOC_COMMIT_ATOMIC_WRITE, 0) -} - -func (f *vfsFile) RollbackAtomicWrite() error { - return unix.IoctlSetInt(int(f.Fd()), _F2FS_IOC_ABORT_ATOMIC_WRITE, 0) -} diff --git a/vendor/github.com/ncruces/go-sqlite3/vfs/os_linux.go b/vendor/github.com/ncruces/go-sqlite3/vfs/os_linux.go deleted file mode 100644 index 6199c7b00..000000000 --- a/vendor/github.com/ncruces/go-sqlite3/vfs/os_linux.go +++ /dev/null @@ -1,58 +0,0 @@ -//go:build !sqlite3_flock - -package vfs - -import ( - "os" - "time" - - "golang.org/x/sys/unix" -) - -func osSync(file *os.File, _ /*fullsync*/, _ /*dataonly*/ bool) error { - // SQLite trusts Linux's fdatasync for all fsync's. - return unix.Fdatasync(int(file.Fd())) -} - -func osAllocate(file *os.File, size int64) error { - if size == 0 { - return nil - } - return unix.Fallocate(int(file.Fd()), 0, 0, size) -} - -func osReadLock(file *os.File, start, len int64, timeout time.Duration) _ErrorCode { - return osLock(file, unix.F_RDLCK, start, len, timeout, _IOERR_RDLOCK) -} - -func osWriteLock(file *os.File, start, len int64, timeout time.Duration) _ErrorCode { - return osLock(file, unix.F_WRLCK, start, len, timeout, _IOERR_LOCK) -} - -func osLock(file *os.File, typ int16, start, len int64, timeout time.Duration, def _ErrorCode) _ErrorCode { - lock := unix.Flock_t{ - Type: typ, - Start: start, - Len: len, - } - var err error - switch { - case timeout < 0: - err = unix.FcntlFlock(file.Fd(), unix.F_OFD_SETLKW, &lock) - default: - err = unix.FcntlFlock(file.Fd(), unix.F_OFD_SETLK, &lock) - } - return osLockErrorCode(err, def) -} - -func osUnlock(file *os.File, start, len int64) _ErrorCode { - err := unix.FcntlFlock(file.Fd(), unix.F_OFD_SETLK, &unix.Flock_t{ - Type: unix.F_UNLCK, - Start: start, - Len: len, - }) - if err != nil { - return _IOERR_UNLOCK - } - return _OK -} diff --git a/vendor/github.com/ncruces/go-sqlite3/vfs/os_ofd.go b/vendor/github.com/ncruces/go-sqlite3/vfs/os_ofd.go deleted file mode 100644 index d93050e8a..000000000 --- a/vendor/github.com/ncruces/go-sqlite3/vfs/os_ofd.go +++ /dev/null @@ -1,59 +0,0 @@ -//go:build (linux || darwin) && !(sqlite3_flock || sqlite3_dotlk) - -package vfs - -import ( - "os" - "time" - - "golang.org/x/sys/unix" -) - -func osGetSharedLock(file *os.File) _ErrorCode { - // Test the PENDING lock before acquiring a new SHARED lock. - if lock, _ := osTestLock(file, _PENDING_BYTE, 1); lock == unix.F_WRLCK { - return _BUSY - } - // Acquire the SHARED lock. - return osReadLock(file, _SHARED_FIRST, _SHARED_SIZE, 0) -} - -func osGetReservedLock(file *os.File) _ErrorCode { - // Acquire the RESERVED lock. - return osWriteLock(file, _RESERVED_BYTE, 1, 0) -} - -func osGetExclusiveLock(file *os.File, state *LockLevel) _ErrorCode { - if *state == LOCK_RESERVED { - // A PENDING lock is needed before acquiring an EXCLUSIVE lock. - if rc := osWriteLock(file, _PENDING_BYTE, 1, -1); rc != _OK { - return rc - } - *state = LOCK_PENDING - } - // Acquire the EXCLUSIVE lock. - return osWriteLock(file, _SHARED_FIRST, _SHARED_SIZE, time.Millisecond) -} - -func osDowngradeLock(file *os.File, state LockLevel) _ErrorCode { - if state >= LOCK_EXCLUSIVE { - // Downgrade to a SHARED lock. - if rc := osReadLock(file, _SHARED_FIRST, _SHARED_SIZE, 0); rc != _OK { - // notest // this should never happen - return _IOERR_RDLOCK - } - } - // Release the PENDING and RESERVED locks. - return osUnlock(file, _PENDING_BYTE, 2) -} - -func osReleaseLock(file *os.File, _ LockLevel) _ErrorCode { - // Release all locks. - return osUnlock(file, 0, 0) -} - -func osCheckReservedLock(file *os.File) (bool, _ErrorCode) { - // Test the RESERVED lock. - lock, rc := osTestLock(file, _RESERVED_BYTE, 1) - return lock == unix.F_WRLCK, rc -} diff --git a/vendor/github.com/ncruces/go-sqlite3/vfs/os_std.go b/vendor/github.com/ncruces/go-sqlite3/vfs/os_std.go deleted file mode 100644 index 0d0ca24c9..000000000 --- a/vendor/github.com/ncruces/go-sqlite3/vfs/os_std.go +++ /dev/null @@ -1,50 +0,0 @@ -//go:build !unix - -package vfs - -import ( - "io/fs" - "os" -) - -const ( - _O_NOFOLLOW = 0 - canSyncDirs = false -) - -func osAccess(path string, flags AccessFlag) error { - fi, err := os.Stat(path) - if err != nil { - return err - } - if flags == ACCESS_EXISTS { - return nil - } - - const ( - S_IREAD = 0400 - S_IWRITE = 0200 - S_IEXEC = 0100 - ) - - var want fs.FileMode = S_IREAD - if flags == ACCESS_READWRITE { - want |= S_IWRITE - } - if fi.IsDir() { - want |= S_IEXEC - } - if fi.Mode()&want != want { - return fs.ErrPermission - } - return nil -} - -func osSetMode(file *os.File, modeof string) error { - fi, err := os.Stat(modeof) - if err != nil { - return err - } - file.Chmod(fi.Mode()) - return nil -} diff --git a/vendor/github.com/ncruces/go-sqlite3/vfs/os_std_alloc.go b/vendor/github.com/ncruces/go-sqlite3/vfs/os_std_alloc.go deleted file mode 100644 index 4dd1bb32c..000000000 --- a/vendor/github.com/ncruces/go-sqlite3/vfs/os_std_alloc.go +++ /dev/null @@ -1,19 +0,0 @@ -//go:build !(linux || darwin) || sqlite3_flock - -package vfs - -import ( - "io" - "os" -) - -func osAllocate(file *os.File, size int64) error { - off, err := file.Seek(0, io.SeekEnd) - if err != nil { - return err - } - if size <= off { - return nil - } - return file.Truncate(size) -} diff --git a/vendor/github.com/ncruces/go-sqlite3/vfs/os_std_atomic.go b/vendor/github.com/ncruces/go-sqlite3/vfs/os_std_atomic.go deleted file mode 100644 index 10a0c8470..000000000 --- a/vendor/github.com/ncruces/go-sqlite3/vfs/os_std_atomic.go +++ /dev/null @@ -1,9 +0,0 @@ -//go:build !linux || !(amd64 || arm64 || riscv64) - -package vfs - -import "os" - -func osBatchAtomic(*os.File) bool { - return false -} diff --git a/vendor/github.com/ncruces/go-sqlite3/vfs/os_std_sync.go b/vendor/github.com/ncruces/go-sqlite3/vfs/os_std_sync.go deleted file mode 100644 index b32e83e08..000000000 --- a/vendor/github.com/ncruces/go-sqlite3/vfs/os_std_sync.go +++ /dev/null @@ -1,9 +0,0 @@ -//go:build !(linux || darwin) || sqlite3_flock - -package vfs - -import "os" - -func osSync(file *os.File, _ /*fullsync*/, _ /*dataonly*/ bool) error { - return file.Sync() -} diff --git a/vendor/github.com/ncruces/go-sqlite3/vfs/os_unix.go b/vendor/github.com/ncruces/go-sqlite3/vfs/os_unix.go deleted file mode 100644 index c4f9ba870..000000000 --- a/vendor/github.com/ncruces/go-sqlite3/vfs/os_unix.go +++ /dev/null @@ -1,76 +0,0 @@ -//go:build unix - -package vfs - -import ( - "os" - "syscall" - - "golang.org/x/sys/unix" -) - -const ( - _O_NOFOLLOW = unix.O_NOFOLLOW - canSyncDirs = true -) - -func osAccess(path string, flags AccessFlag) error { - var access uint32 // unix.F_OK - switch flags { - case ACCESS_READWRITE: - access = unix.R_OK | unix.W_OK - case ACCESS_READ: - access = unix.R_OK - } - return unix.Access(path, access) -} - -func osSetMode(file *os.File, modeof string) error { - fi, err := os.Stat(modeof) - if err != nil { - return err - } - file.Chmod(fi.Mode()) - if sys, ok := fi.Sys().(*syscall.Stat_t); ok { - file.Chown(int(sys.Uid), int(sys.Gid)) - } - return nil -} - -func osTestLock(file *os.File, start, len int64) (int16, _ErrorCode) { - lock := unix.Flock_t{ - Type: unix.F_WRLCK, - Start: start, - Len: len, - } - if unix.FcntlFlock(file.Fd(), unix.F_GETLK, &lock) != nil { - return 0, _IOERR_CHECKRESERVEDLOCK - } - return lock.Type, _OK -} - -func osLockErrorCode(err error, def _ErrorCode) _ErrorCode { - if err == nil { - return _OK - } - if errno, ok := err.(unix.Errno); ok { - switch errno { - case - unix.EACCES, - unix.EAGAIN, - unix.EBUSY, - unix.EINTR, - unix.ENOLCK, - unix.EDEADLK, - unix.ETIMEDOUT: - return _BUSY - case unix.EPERM: - return _PERM - } - // notest // usually EWOULDBLOCK == EAGAIN - if errno == unix.EWOULDBLOCK && unix.EWOULDBLOCK != unix.EAGAIN { - return _BUSY - } - } - return def -} diff --git a/vendor/github.com/ncruces/go-sqlite3/vfs/os_windows.go b/vendor/github.com/ncruces/go-sqlite3/vfs/os_windows.go deleted file mode 100644 index 0398f4760..000000000 --- a/vendor/github.com/ncruces/go-sqlite3/vfs/os_windows.go +++ /dev/null @@ -1,195 +0,0 @@ -//go:build !sqlite3_dotlk - -package vfs - -import ( - "os" - "time" - - "golang.org/x/sys/windows" -) - -func osGetSharedLock(file *os.File) _ErrorCode { - // Acquire the PENDING lock temporarily before acquiring a new SHARED lock. - rc := osReadLock(file, _PENDING_BYTE, 1, 0) - if rc == _OK { - // Acquire the SHARED lock. - rc = osReadLock(file, _SHARED_FIRST, _SHARED_SIZE, 0) - - // Release the PENDING lock. - osUnlock(file, _PENDING_BYTE, 1) - } - return rc -} - -func osGetReservedLock(file *os.File) _ErrorCode { - // Acquire the RESERVED lock. - return osWriteLock(file, _RESERVED_BYTE, 1, 0) -} - -func osGetExclusiveLock(file *os.File, state *LockLevel) _ErrorCode { - // A PENDING lock is needed before releasing the SHARED lock. - if *state < LOCK_PENDING { - // If we were RESERVED, we can block indefinitely. - var timeout time.Duration - if *state == LOCK_RESERVED { - timeout = -1 - } - if rc := osWriteLock(file, _PENDING_BYTE, 1, timeout); rc != _OK { - return rc - } - *state = LOCK_PENDING - } - - // Release the SHARED lock. - osUnlock(file, _SHARED_FIRST, _SHARED_SIZE) - - // Acquire the EXCLUSIVE lock. - // Can't wait here, because the file is not OVERLAPPED. - rc := osWriteLock(file, _SHARED_FIRST, _SHARED_SIZE, 0) - - if rc != _OK { - // Reacquire the SHARED lock. - if rc := osReadLock(file, _SHARED_FIRST, _SHARED_SIZE, 0); rc != _OK { - // notest // this should never happen - return _IOERR_RDLOCK - } - } - return rc -} - -func osDowngradeLock(file *os.File, state LockLevel) _ErrorCode { - if state >= LOCK_EXCLUSIVE { - // Release the EXCLUSIVE lock while holding the PENDING lock. - osUnlock(file, _SHARED_FIRST, _SHARED_SIZE) - - // Reacquire the SHARED lock. - if rc := osReadLock(file, _SHARED_FIRST, _SHARED_SIZE, 0); rc != _OK { - // notest // this should never happen - return _IOERR_RDLOCK - } - } - - // Release the PENDING and RESERVED locks. - if state >= LOCK_RESERVED { - osUnlock(file, _RESERVED_BYTE, 1) - } - if state >= LOCK_PENDING { - osUnlock(file, _PENDING_BYTE, 1) - } - return _OK -} - -func osReleaseLock(file *os.File, state LockLevel) _ErrorCode { - // Release all locks, PENDING must be last. - if state >= LOCK_RESERVED { - osUnlock(file, _RESERVED_BYTE, 1) - } - if state >= LOCK_SHARED { - osUnlock(file, _SHARED_FIRST, _SHARED_SIZE) - } - if state >= LOCK_PENDING { - osUnlock(file, _PENDING_BYTE, 1) - } - return _OK -} - -func osCheckReservedLock(file *os.File) (bool, _ErrorCode) { - // Test the RESERVED lock. - rc := osLock(file, 0, _RESERVED_BYTE, 1, 0, _IOERR_CHECKRESERVEDLOCK) - if rc == _BUSY { - return true, _OK - } - if rc == _OK { - // Release the RESERVED lock. - osUnlock(file, _RESERVED_BYTE, 1) - } - return false, rc -} - -func osReadLock(file *os.File, start, len uint32, timeout time.Duration) _ErrorCode { - return osLock(file, 0, start, len, timeout, _IOERR_RDLOCK) -} - -func osWriteLock(file *os.File, start, len uint32, timeout time.Duration) _ErrorCode { - return osLock(file, windows.LOCKFILE_EXCLUSIVE_LOCK, start, len, timeout, _IOERR_LOCK) -} - -func osLock(file *os.File, flags, start, len uint32, timeout time.Duration, def _ErrorCode) _ErrorCode { - var err error - switch { - case timeout == 0: - err = osLockEx(file, flags|windows.LOCKFILE_FAIL_IMMEDIATELY, start, len) - case timeout < 0: - err = osLockEx(file, flags, start, len) - default: - err = osLockExTimeout(file, flags, start, len, timeout) - } - return osLockErrorCode(err, def) -} - -func osUnlock(file *os.File, start, len uint32) _ErrorCode { - err := windows.UnlockFileEx(windows.Handle(file.Fd()), - 0, len, 0, &windows.Overlapped{Offset: start}) - if err == windows.ERROR_NOT_LOCKED { - return _OK - } - if err != nil { - return _IOERR_UNLOCK - } - return _OK -} - -func osLockEx(file *os.File, flags, start, len uint32) error { - return windows.LockFileEx(windows.Handle(file.Fd()), flags, - 0, len, 0, &windows.Overlapped{Offset: start}) -} - -func osLockExTimeout(file *os.File, flags, start, len uint32, timeout time.Duration) error { - event, err := windows.CreateEvent(nil, 1, 0, nil) - if err != nil { - return err - } - defer windows.CloseHandle(event) - - fd := windows.Handle(file.Fd()) - overlapped := &windows.Overlapped{ - Offset: start, - HEvent: event, - } - - err = windows.LockFileEx(fd, flags, 0, len, 0, overlapped) - if err != windows.ERROR_IO_PENDING { - return err - } - - ms := (timeout + time.Millisecond - 1) / time.Millisecond - rc, err := windows.WaitForSingleObject(event, uint32(ms)) - if rc == windows.WAIT_OBJECT_0 { - return nil - } - defer windows.CancelIoEx(fd, overlapped) - - if err != nil { - return err - } - return windows.Errno(rc) -} - -func osLockErrorCode(err error, def _ErrorCode) _ErrorCode { - if err == nil { - return _OK - } - if errno, ok := err.(windows.Errno); ok { - // https://devblogs.microsoft.com/oldnewthing/20140905-00/?p=63 - switch errno { - case - windows.ERROR_LOCK_VIOLATION, - windows.ERROR_OPERATION_ABORTED, - windows.ERROR_IO_PENDING, - windows.WAIT_TIMEOUT: - return _BUSY - } - } - return def -} diff --git a/vendor/github.com/ncruces/go-sqlite3/vfs/registry.go b/vendor/github.com/ncruces/go-sqlite3/vfs/registry.go deleted file mode 100644 index 42a2106fb..000000000 --- a/vendor/github.com/ncruces/go-sqlite3/vfs/registry.go +++ /dev/null @@ -1,48 +0,0 @@ -package vfs - -import "sync" - -var ( - // +checklocks:vfsRegistryMtx - vfsRegistry map[string]VFS - vfsRegistryMtx sync.RWMutex -) - -// Find returns a VFS given its name. -// If there is no match, nil is returned. -// If name is empty, the default VFS is returned. -// -// https://sqlite.org/c3ref/vfs_find.html -func Find(name string) VFS { - if name == "" || name == "os" { - return vfsOS{} - } - vfsRegistryMtx.RLock() - defer vfsRegistryMtx.RUnlock() - return vfsRegistry[name] -} - -// Register registers a VFS. -// Empty and "os" are reserved names. -// -// https://sqlite.org/c3ref/vfs_find.html -func Register(name string, vfs VFS) { - if name == "" || name == "os" { - return - } - vfsRegistryMtx.Lock() - defer vfsRegistryMtx.Unlock() - if vfsRegistry == nil { - vfsRegistry = map[string]VFS{} - } - vfsRegistry[name] = vfs -} - -// Unregister unregisters a VFS. -// -// https://sqlite.org/c3ref/vfs_find.html -func Unregister(name string) { - vfsRegistryMtx.Lock() - defer vfsRegistryMtx.Unlock() - delete(vfsRegistry, name) -} diff --git a/vendor/github.com/ncruces/go-sqlite3/vfs/shm.go b/vendor/github.com/ncruces/go-sqlite3/vfs/shm.go deleted file mode 100644 index f28955289..000000000 --- a/vendor/github.com/ncruces/go-sqlite3/vfs/shm.go +++ /dev/null @@ -1,26 +0,0 @@ -//go:build ((linux || darwin || windows || freebsd || openbsd || netbsd || dragonfly || illumos) && (386 || arm || amd64 || arm64 || riscv64 || ppc64le)) || sqlite3_flock || sqlite3_dotlk - -package vfs - -// SupportsSharedMemory is false on platforms that do not support shared memory. -// To use [WAL without shared-memory], you need to set [EXCLUSIVE locking mode]. -// -// [WAL without shared-memory]: https://sqlite.org/wal.html#noshm -// [EXCLUSIVE locking mode]: https://sqlite.org/pragma.html#pragma_locking_mode -const SupportsSharedMemory = true - -func (f *vfsFile) SharedMemory() SharedMemory { return f.shm } - -// NewSharedMemory returns a shared-memory WAL-index -// backed by a file with the given path. -// It will return nil if shared-memory is not supported, -// or not appropriate for the given flags. -// Only [OPEN_MAIN_DB] databases may need a WAL-index. -// You must ensure all concurrent accesses to a database -// use shared-memory instances created with the same path. -func NewSharedMemory(path string, flags OpenFlag) SharedMemory { - if flags&OPEN_MAIN_DB == 0 || flags&(OPEN_DELETEONCLOSE|OPEN_MEMORY) != 0 { - return nil - } - return &vfsShm{path: path} -} diff --git a/vendor/github.com/ncruces/go-sqlite3/vfs/shm_bsd.go b/vendor/github.com/ncruces/go-sqlite3/vfs/shm_bsd.go deleted file mode 100644 index 11e7bb2fd..000000000 --- a/vendor/github.com/ncruces/go-sqlite3/vfs/shm_bsd.go +++ /dev/null @@ -1,250 +0,0 @@ -//go:build ((freebsd || openbsd || netbsd || dragonfly || illumos) && (386 || arm || amd64 || arm64 || riscv64 || ppc64le) && !sqlite3_dotlk) || sqlite3_flock - -package vfs - -import ( - "context" - "errors" - "io" - "io/fs" - "os" - "sync" - - "github.com/tetratelabs/wazero/api" - "golang.org/x/sys/unix" - - "github.com/ncruces/go-sqlite3/internal/util" -) - -type vfsShmParent struct { - *os.File - info os.FileInfo - - refs int // +checklocks:vfsShmListMtx - - lock [_SHM_NLOCK]int8 // +checklocks:Mutex - sync.Mutex -} - -var ( - // +checklocks:vfsShmListMtx - vfsShmList []*vfsShmParent - vfsShmListMtx sync.Mutex -) - -type vfsShm struct { - *vfsShmParent - path string - lock [_SHM_NLOCK]bool - regions []*util.MappedRegion -} - -func (s *vfsShm) Close() error { - if s.vfsShmParent == nil { - return nil - } - - vfsShmListMtx.Lock() - defer vfsShmListMtx.Unlock() - - // Unlock everything. - s.shmLock(0, _SHM_NLOCK, _SHM_UNLOCK) - - // Decrease reference count. - if s.vfsShmParent.refs > 0 { - s.vfsShmParent.refs-- - s.vfsShmParent = nil - return nil - } - - err := s.File.Close() - for i, g := range vfsShmList { - if g == s.vfsShmParent { - vfsShmList[i] = nil - s.vfsShmParent = nil - return err - } - } - panic(util.AssertErr()) -} - -func (s *vfsShm) shmOpen() _ErrorCode { - if s.vfsShmParent != nil { - return _OK - } - - var f *os.File - // Close file on error. - // Keep this here to avoid confusing checklocks. - defer func() { f.Close() }() - - vfsShmListMtx.Lock() - defer vfsShmListMtx.Unlock() - - // Stat file without opening it. - // Closing it would release all POSIX locks on it. - fi, err := os.Stat(s.path) - if err != nil && !errors.Is(err, fs.ErrNotExist) { - return _IOERR_FSTAT - } - - // Find a shared file, increase the reference count. - for _, g := range vfsShmList { - if g != nil && os.SameFile(fi, g.info) { - s.vfsShmParent = g - g.refs++ - return _OK - } - } - - // Always open file read-write, as it will be shared. - f, err = os.OpenFile(s.path, - os.O_RDWR|os.O_CREATE|_O_NOFOLLOW, 0666) - if err != nil { - return _CANTOPEN - } - - // Dead man's switch. - if lock, rc := osTestLock(f, _SHM_DMS, 1); rc != _OK { - return _IOERR_LOCK - } else if lock == unix.F_WRLCK { - return _BUSY - } else if lock == unix.F_UNLCK { - if rc := osWriteLock(f, _SHM_DMS, 1); rc != _OK { - return rc - } - if err := f.Truncate(0); err != nil { - return _IOERR_SHMOPEN - } - } - if rc := osReadLock(f, _SHM_DMS, 1); rc != _OK { - return rc - } - - fi, err = f.Stat() - if err != nil { - return _IOERR_FSTAT - } - - // Add the new shared file. - s.vfsShmParent = &vfsShmParent{ - File: f, - info: fi, - } - f = nil // Don't close the file. - for i, g := range vfsShmList { - if g == nil { - vfsShmList[i] = s.vfsShmParent - return _OK - } - } - vfsShmList = append(vfsShmList, s.vfsShmParent) - return _OK -} - -func (s *vfsShm) shmMap(ctx context.Context, mod api.Module, id, size int32, extend bool) (ptr_t, _ErrorCode) { - // Ensure size is a multiple of the OS page size. - if int(size)&(unix.Getpagesize()-1) != 0 { - return 0, _IOERR_SHMMAP - } - - if rc := s.shmOpen(); rc != _OK { - return 0, rc - } - - // Check if file is big enough. - o, err := s.Seek(0, io.SeekEnd) - if err != nil { - return 0, _IOERR_SHMSIZE - } - if n := (int64(id) + 1) * int64(size); n > o { - if !extend { - return 0, _OK - } - if osAllocate(s.File, n) != nil { - return 0, _IOERR_SHMSIZE - } - } - - r, err := util.MapRegion(ctx, mod, s.File, int64(id)*int64(size), size, false) - if err != nil { - return 0, _IOERR_SHMMAP - } - s.regions = append(s.regions, r) - return r.Ptr, _OK -} - -func (s *vfsShm) shmLock(offset, n int32, flags _ShmFlag) _ErrorCode { - s.Lock() - defer s.Unlock() - - // Check if we can obtain/release locks locally. - rc := s.shmMemLock(offset, n, flags) - if rc != _OK { - return rc - } - - // Obtain/release the appropriate file locks. - switch { - case flags&_SHM_UNLOCK != 0: - // Relasing a shared lock decrements the counter, - // but may leave parts of the range still locked. - begin, end := offset, offset+n - for i := begin; i < end; i++ { - if s.vfsShmParent.lock[i] != 0 { - if i > begin { - rc |= osUnlock(s.File, _SHM_BASE+int64(begin), int64(i-begin)) - } - begin = i + 1 - } - } - if end > begin { - rc |= osUnlock(s.File, _SHM_BASE+int64(begin), int64(end-begin)) - } - return rc - case flags&_SHM_SHARED != 0: - // Acquiring a new shared lock on the file is only necessary - // if there was a new shared lock in the range. - for i := offset; i < offset+n; i++ { - if s.vfsShmParent.lock[i] == 1 { - rc = osReadLock(s.File, _SHM_BASE+int64(offset), int64(n)) - break - } - } - case flags&_SHM_EXCLUSIVE != 0: - // Acquiring an exclusive lock on the file is always necessary. - rc = osWriteLock(s.File, _SHM_BASE+int64(offset), int64(n)) - default: - panic(util.AssertErr()) - } - - // Release the local locks we had acquired. - if rc != _OK { - s.shmMemLock(offset, n, flags^(_SHM_UNLOCK|_SHM_LOCK)) - } - return rc -} - -func (s *vfsShm) shmUnmap(delete bool) { - if s.vfsShmParent == nil { - return - } - - // Unmap regions. - for _, r := range s.regions { - r.Unmap() - } - s.regions = nil - - // Close the file. - if delete { - os.Remove(s.path) - } - s.Close() -} - -func (s *vfsShm) shmBarrier() { - s.Lock() - //lint:ignore SA2001 memory barrier. - s.Unlock() -} diff --git a/vendor/github.com/ncruces/go-sqlite3/vfs/shm_copy.go b/vendor/github.com/ncruces/go-sqlite3/vfs/shm_copy.go deleted file mode 100644 index db8ddb4b8..000000000 --- a/vendor/github.com/ncruces/go-sqlite3/vfs/shm_copy.go +++ /dev/null @@ -1,87 +0,0 @@ -//go:build (windows && (386 || arm || amd64 || arm64 || riscv64 || ppc64le)) || sqlite3_dotlk - -package vfs - -import ( - "unsafe" - - "github.com/ncruces/go-sqlite3/internal/util" -) - -const ( - _WALINDEX_HDR_SIZE = 136 - _WALINDEX_PGSZ = 32768 -) - -// This seems a safe way of keeping the WAL-index in sync. -// -// The WAL-index file starts with a header, -// and the index doesn't meaningfully change if the header doesn't change. -// -// The header starts with two 48 byte, checksummed, copies of the same information, -// which are accessed independently between memory barriers. -// The checkpoint information that follows uses 4 byte aligned words. -// -// Finally, we have the WAL-index hash tables, -// which are only modified holding the exclusive WAL_WRITE_LOCK. -// -// Since all the data is either redundant+checksummed, -// 4 byte aligned, or modified under an exclusive lock, -// the copies below should correctly keep memory in sync. -// -// https://sqlite.org/walformat.html#the_wal_index_file_format - -func (s *vfsShm) shmAcquire(ptr *_ErrorCode) { - if ptr != nil && *ptr != _OK { - return - } - if len(s.ptrs) == 0 || shmEqual(s.shadow[0][:], s.shared[0][:]) { - return - } - // Copies modified words from shared to private memory. - for id, p := range s.ptrs { - shared := shmPage(s.shared[id][:]) - shadow := shmPage(s.shadow[id][:]) - privat := shmPage(util.View(s.mod, p, _WALINDEX_PGSZ)) - for i, shared := range shared { - if shadow[i] != shared { - shadow[i] = shared - privat[i] = shared - } - } - } -} - -func (s *vfsShm) shmRelease() { - if len(s.ptrs) == 0 || shmEqual(s.shadow[0][:], util.View(s.mod, s.ptrs[0], _WALINDEX_HDR_SIZE)) { - return - } - // Copies modified words from private to shared memory. - for id, p := range s.ptrs { - shared := shmPage(s.shared[id][:]) - shadow := shmPage(s.shadow[id][:]) - privat := shmPage(util.View(s.mod, p, _WALINDEX_PGSZ)) - for i, privat := range privat { - if shadow[i] != privat { - shadow[i] = privat - shared[i] = privat - } - } - } -} - -func (s *vfsShm) shmBarrier() { - s.Lock() - s.shmAcquire(nil) - s.shmRelease() - s.Unlock() -} - -func shmPage(s []byte) *[_WALINDEX_PGSZ / 4]uint32 { - p := (*uint32)(unsafe.Pointer(unsafe.SliceData(s))) - return (*[_WALINDEX_PGSZ / 4]uint32)(unsafe.Slice(p, _WALINDEX_PGSZ/4)) -} - -func shmEqual(v1, v2 []byte) bool { - return *(*[_WALINDEX_HDR_SIZE]byte)(v1[:]) == *(*[_WALINDEX_HDR_SIZE]byte)(v2[:]) -} diff --git a/vendor/github.com/ncruces/go-sqlite3/vfs/shm_dotlk.go b/vendor/github.com/ncruces/go-sqlite3/vfs/shm_dotlk.go deleted file mode 100644 index cb697a9c8..000000000 --- a/vendor/github.com/ncruces/go-sqlite3/vfs/shm_dotlk.go +++ /dev/null @@ -1,178 +0,0 @@ -//go:build sqlite3_dotlk - -package vfs - -import ( - "context" - "errors" - "io/fs" - "sync" - - "github.com/tetratelabs/wazero/api" - - "github.com/ncruces/go-sqlite3/internal/dotlk" - "github.com/ncruces/go-sqlite3/internal/util" -) - -type vfsShmParent struct { - shared [][_WALINDEX_PGSZ]byte - refs int // +checklocks:vfsShmListMtx - - lock [_SHM_NLOCK]int8 // +checklocks:Mutex - sync.Mutex -} - -var ( - // +checklocks:vfsShmListMtx - vfsShmList = map[string]*vfsShmParent{} - vfsShmListMtx sync.Mutex -) - -type vfsShm struct { - *vfsShmParent - mod api.Module - alloc api.Function - free api.Function - path string - shadow [][_WALINDEX_PGSZ]byte - ptrs []ptr_t - stack [1]stk_t - lock [_SHM_NLOCK]bool -} - -func (s *vfsShm) Close() error { - if s.vfsShmParent == nil { - return nil - } - - vfsShmListMtx.Lock() - defer vfsShmListMtx.Unlock() - - // Unlock everything. - s.shmLock(0, _SHM_NLOCK, _SHM_UNLOCK) - - // Decrease reference count. - if s.vfsShmParent.refs > 0 { - s.vfsShmParent.refs-- - s.vfsShmParent = nil - return nil - } - - if err := dotlk.Unlock(s.path); err != nil { - return _IOERR_UNLOCK - } - delete(vfsShmList, s.path) - s.vfsShmParent = nil - return nil -} - -func (s *vfsShm) shmOpen() _ErrorCode { - if s.vfsShmParent != nil { - return _OK - } - - vfsShmListMtx.Lock() - defer vfsShmListMtx.Unlock() - - // Find a shared buffer, increase the reference count. - if g, ok := vfsShmList[s.path]; ok { - s.vfsShmParent = g - g.refs++ - return _OK - } - - // Dead man's switch. - err := dotlk.LockShm(s.path) - if errors.Is(err, fs.ErrExist) { - return _BUSY - } - if err != nil { - return _IOERR_LOCK - } - - // Add the new shared buffer. - s.vfsShmParent = &vfsShmParent{} - vfsShmList[s.path] = s.vfsShmParent - return _OK -} - -func (s *vfsShm) shmMap(ctx context.Context, mod api.Module, id, size int32, extend bool) (ptr_t, _ErrorCode) { - if size != _WALINDEX_PGSZ { - return 0, _IOERR_SHMMAP - } - if s.mod == nil { - s.mod = mod - s.free = mod.ExportedFunction("sqlite3_free") - s.alloc = mod.ExportedFunction("sqlite3_malloc64") - } - if rc := s.shmOpen(); rc != _OK { - return 0, rc - } - - s.Lock() - defer s.Unlock() - defer s.shmAcquire(nil) - - // Extend shared memory. - if int(id) >= len(s.shared) { - if !extend { - return 0, _OK - } - s.shared = append(s.shared, make([][_WALINDEX_PGSZ]byte, int(id)-len(s.shared)+1)...) - } - - // Allocate shadow memory. - if int(id) >= len(s.shadow) { - s.shadow = append(s.shadow, make([][_WALINDEX_PGSZ]byte, int(id)-len(s.shadow)+1)...) - } - - // Allocate local memory. - for int(id) >= len(s.ptrs) { - s.stack[0] = stk_t(size) - if err := s.alloc.CallWithStack(ctx, s.stack[:]); err != nil { - panic(err) - } - if s.stack[0] == 0 { - panic(util.OOMErr) - } - clear(util.View(s.mod, ptr_t(s.stack[0]), _WALINDEX_PGSZ)) - s.ptrs = append(s.ptrs, ptr_t(s.stack[0])) - } - - s.shadow[0][4] = 1 - return s.ptrs[id], _OK -} - -func (s *vfsShm) shmLock(offset, n int32, flags _ShmFlag) (rc _ErrorCode) { - s.Lock() - defer s.Unlock() - - switch { - case flags&_SHM_LOCK != 0: - defer s.shmAcquire(&rc) - case flags&_SHM_EXCLUSIVE != 0: - s.shmRelease() - } - - return s.shmMemLock(offset, n, flags) -} - -func (s *vfsShm) shmUnmap(delete bool) { - if s.vfsShmParent == nil { - return - } - defer s.Close() - - s.Lock() - s.shmRelease() - defer s.Unlock() - - for _, p := range s.ptrs { - s.stack[0] = stk_t(p) - if err := s.free.CallWithStack(context.Background(), s.stack[:]); err != nil { - panic(err) - } - } - s.ptrs = nil - s.shadow = nil -} diff --git a/vendor/github.com/ncruces/go-sqlite3/vfs/shm_memlk.go b/vendor/github.com/ncruces/go-sqlite3/vfs/shm_memlk.go deleted file mode 100644 index 5c8071ebe..000000000 --- a/vendor/github.com/ncruces/go-sqlite3/vfs/shm_memlk.go +++ /dev/null @@ -1,53 +0,0 @@ -//go:build ((freebsd || openbsd || netbsd || dragonfly || illumos) && (386 || arm || amd64 || arm64 || riscv64 || ppc64le)) || sqlite3_flock || sqlite3_dotlk - -package vfs - -import "github.com/ncruces/go-sqlite3/internal/util" - -// +checklocks:s.Mutex -func (s *vfsShm) shmMemLock(offset, n int32, flags _ShmFlag) _ErrorCode { - switch { - case flags&_SHM_UNLOCK != 0: - for i := offset; i < offset+n; i++ { - if s.lock[i] { - if s.vfsShmParent.lock[i] <= 0 { - s.vfsShmParent.lock[i] = 0 - } else { - s.vfsShmParent.lock[i]-- - } - s.lock[i] = false - } - } - case flags&_SHM_SHARED != 0: - for i := offset; i < offset+n; i++ { - if !s.lock[i] && - s.vfsShmParent.lock[i]+1 <= 0 { - return _BUSY - } - } - for i := offset; i < offset+n; i++ { - if !s.lock[i] { - s.vfsShmParent.lock[i]++ - s.lock[i] = true - } - } - case flags&_SHM_EXCLUSIVE != 0: - for i := offset; i < offset+n; i++ { - if s.lock[i] { - // SQLite never requests an exclusive lock that it already holds. - panic(util.AssertErr()) - } - if s.vfsShmParent.lock[i] != 0 { - return _BUSY - } - } - for i := offset; i < offset+n; i++ { - s.vfsShmParent.lock[i] = -1 - s.lock[i] = true - } - default: - panic(util.AssertErr()) - } - - return _OK -} diff --git a/vendor/github.com/ncruces/go-sqlite3/vfs/shm_ofd.go b/vendor/github.com/ncruces/go-sqlite3/vfs/shm_ofd.go deleted file mode 100644 index b0f50fcb5..000000000 --- a/vendor/github.com/ncruces/go-sqlite3/vfs/shm_ofd.go +++ /dev/null @@ -1,176 +0,0 @@ -//go:build (linux || darwin) && (386 || arm || amd64 || arm64 || riscv64 || ppc64le) && !(sqlite3_flock || sqlite3_dotlk) - -package vfs - -import ( - "context" - "io" - "os" - "sync" - "time" - - "github.com/tetratelabs/wazero/api" - "golang.org/x/sys/unix" - - "github.com/ncruces/go-sqlite3/internal/util" -) - -type vfsShm struct { - *os.File - path string - regions []*util.MappedRegion - readOnly bool - fileLock bool - blocking bool - sync.Mutex -} - -var _ blockingSharedMemory = &vfsShm{} - -func (s *vfsShm) shmOpen() _ErrorCode { - if s.File == nil { - f, err := os.OpenFile(s.path, - os.O_RDWR|os.O_CREATE|_O_NOFOLLOW, 0666) - if err != nil { - f, err = os.OpenFile(s.path, - os.O_RDONLY|os.O_CREATE|_O_NOFOLLOW, 0666) - s.readOnly = true - } - if err != nil { - return _CANTOPEN - } - s.File = f - } - if s.fileLock { - return _OK - } - - // Dead man's switch. - if lock, rc := osTestLock(s.File, _SHM_DMS, 1); rc != _OK { - return _IOERR_LOCK - } else if lock == unix.F_WRLCK { - return _BUSY - } else if lock == unix.F_UNLCK { - if s.readOnly { - return _READONLY_CANTINIT - } - // Do not use a blocking lock here. - // If the lock cannot be obtained immediately, - // it means some other connection is truncating the file. - // And after it has done so, it will not release its lock, - // but only downgrade it to a shared lock. - // So no point in blocking here. - // The call below to obtain the shared DMS lock may use a blocking lock. - if rc := osWriteLock(s.File, _SHM_DMS, 1, 0); rc != _OK { - return rc - } - if err := s.Truncate(0); err != nil { - return _IOERR_SHMOPEN - } - } - rc := osReadLock(s.File, _SHM_DMS, 1, time.Millisecond) - s.fileLock = rc == _OK - return rc -} - -func (s *vfsShm) shmMap(ctx context.Context, mod api.Module, id, size int32, extend bool) (ptr_t, _ErrorCode) { - // Ensure size is a multiple of the OS page size. - if int(size)&(unix.Getpagesize()-1) != 0 { - return 0, _IOERR_SHMMAP - } - - if rc := s.shmOpen(); rc != _OK { - return 0, rc - } - - // Check if file is big enough. - o, err := s.Seek(0, io.SeekEnd) - if err != nil { - return 0, _IOERR_SHMSIZE - } - if n := (int64(id) + 1) * int64(size); n > o { - if !extend { - return 0, _OK - } - if s.readOnly || osAllocate(s.File, n) != nil { - return 0, _IOERR_SHMSIZE - } - } - - r, err := util.MapRegion(ctx, mod, s.File, int64(id)*int64(size), size, s.readOnly) - if err != nil { - return 0, _IOERR_SHMMAP - } - s.regions = append(s.regions, r) - if s.readOnly { - return r.Ptr, _READONLY - } - return r.Ptr, _OK -} - -func (s *vfsShm) shmLock(offset, n int32, flags _ShmFlag) _ErrorCode { - // Argument check. - switch { - case n <= 0: - panic(util.AssertErr()) - case offset < 0 || offset+n > _SHM_NLOCK: - panic(util.AssertErr()) - case n != 1 && flags&_SHM_EXCLUSIVE == 0: - panic(util.AssertErr()) - } - switch flags { - case - _SHM_LOCK | _SHM_SHARED, - _SHM_LOCK | _SHM_EXCLUSIVE, - _SHM_UNLOCK | _SHM_SHARED, - _SHM_UNLOCK | _SHM_EXCLUSIVE: - // - default: - panic(util.AssertErr()) - } - - var timeout time.Duration - if s.blocking { - timeout = time.Millisecond - } - - switch { - case flags&_SHM_UNLOCK != 0: - return osUnlock(s.File, _SHM_BASE+int64(offset), int64(n)) - case flags&_SHM_SHARED != 0: - return osReadLock(s.File, _SHM_BASE+int64(offset), int64(n), timeout) - case flags&_SHM_EXCLUSIVE != 0: - return osWriteLock(s.File, _SHM_BASE+int64(offset), int64(n), timeout) - default: - panic(util.AssertErr()) - } -} - -func (s *vfsShm) shmUnmap(delete bool) { - if s.File == nil { - return - } - - // Unmap regions. - for _, r := range s.regions { - r.Unmap() - } - s.regions = nil - - // Close the file. - if delete { - os.Remove(s.path) - } - s.Close() - s.File = nil -} - -func (s *vfsShm) shmBarrier() { - s.Lock() - //lint:ignore SA2001 memory barrier. - s.Unlock() -} - -func (s *vfsShm) shmEnableBlocking(block bool) { - s.blocking = block -} diff --git a/vendor/github.com/ncruces/go-sqlite3/vfs/shm_other.go b/vendor/github.com/ncruces/go-sqlite3/vfs/shm_other.go deleted file mode 100644 index 69319f07d..000000000 --- a/vendor/github.com/ncruces/go-sqlite3/vfs/shm_other.go +++ /dev/null @@ -1,21 +0,0 @@ -//go:build !(((linux || darwin || windows || freebsd || openbsd || netbsd || dragonfly || illumos) && (386 || arm || amd64 || arm64 || riscv64 || ppc64le)) || sqlite3_flock || sqlite3_dotlk) - -package vfs - -// SupportsSharedMemory is false on platforms that do not support shared memory. -// To use [WAL without shared-memory], you need to set [EXCLUSIVE locking mode]. -// -// [WAL without shared-memory]: https://sqlite.org/wal.html#noshm -// [EXCLUSIVE locking mode]: https://sqlite.org/pragma.html#pragma_locking_mode -const SupportsSharedMemory = false - -// NewSharedMemory returns a shared-memory WAL-index -// backed by a file with the given path. -// It will return nil if shared-memory is not supported, -// or not appropriate for the given flags. -// Only [OPEN_MAIN_DB] databases may need a WAL-index. -// You must ensure all concurrent accesses to a database -// use shared-memory instances created with the same path. -func NewSharedMemory(path string, flags OpenFlag) SharedMemory { - return nil -} diff --git a/vendor/github.com/ncruces/go-sqlite3/vfs/shm_windows.go b/vendor/github.com/ncruces/go-sqlite3/vfs/shm_windows.go deleted file mode 100644 index ed2e93f8e..000000000 --- a/vendor/github.com/ncruces/go-sqlite3/vfs/shm_windows.go +++ /dev/null @@ -1,190 +0,0 @@ -//go:build (386 || arm || amd64 || arm64 || riscv64 || ppc64le) && !sqlite3_dotlk - -package vfs - -import ( - "context" - "io" - "os" - "sync" - "syscall" - "time" - - "github.com/tetratelabs/wazero/api" - "golang.org/x/sys/windows" - - "github.com/ncruces/go-sqlite3/internal/util" - "github.com/ncruces/go-sqlite3/util/osutil" -) - -type vfsShm struct { - *os.File - mod api.Module - alloc api.Function - free api.Function - path string - regions []*util.MappedRegion - shared [][]byte - shadow [][_WALINDEX_PGSZ]byte - ptrs []ptr_t - stack [1]stk_t - fileLock bool - blocking bool - sync.Mutex -} - -var _ blockingSharedMemory = &vfsShm{} - -func (s *vfsShm) Close() error { - // Unmap regions. - for _, r := range s.regions { - r.Unmap() - } - s.regions = nil - - // Close the file. - return s.File.Close() -} - -func (s *vfsShm) shmOpen() _ErrorCode { - if s.File == nil { - f, err := osutil.OpenFile(s.path, - os.O_RDWR|os.O_CREATE|syscall.O_NONBLOCK, 0666) - if err != nil { - return _CANTOPEN - } - s.File = f - } - if s.fileLock { - return _OK - } - - // Dead man's switch. - if rc := osWriteLock(s.File, _SHM_DMS, 1, 0); rc == _OK { - err := s.Truncate(0) - osUnlock(s.File, _SHM_DMS, 1) - if err != nil { - return _IOERR_SHMOPEN - } - } - rc := osReadLock(s.File, _SHM_DMS, 1, time.Millisecond) - s.fileLock = rc == _OK - return rc -} - -func (s *vfsShm) shmMap(ctx context.Context, mod api.Module, id, size int32, extend bool) (_ ptr_t, rc _ErrorCode) { - // Ensure size is a multiple of the OS page size. - if size != _WALINDEX_PGSZ || (windows.Getpagesize()-1)&_WALINDEX_PGSZ != 0 { - return 0, _IOERR_SHMMAP - } - if s.mod == nil { - s.mod = mod - s.free = mod.ExportedFunction("sqlite3_free") - s.alloc = mod.ExportedFunction("sqlite3_malloc64") - } - if rc := s.shmOpen(); rc != _OK { - return 0, rc - } - - defer s.shmAcquire(&rc) - - // Check if file is big enough. - o, err := s.Seek(0, io.SeekEnd) - if err != nil { - return 0, _IOERR_SHMSIZE - } - if n := (int64(id) + 1) * int64(size); n > o { - if !extend { - return 0, _OK - } - if osAllocate(s.File, n) != nil { - return 0, _IOERR_SHMSIZE - } - } - - // Maps regions into memory. - for int(id) >= len(s.shared) { - r, err := util.MapRegion(ctx, mod, s.File, int64(id)*int64(size), size) - if err != nil { - return 0, _IOERR_SHMMAP - } - s.regions = append(s.regions, r) - s.shared = append(s.shared, r.Data) - } - - // Allocate shadow memory. - if int(id) >= len(s.shadow) { - s.shadow = append(s.shadow, make([][_WALINDEX_PGSZ]byte, int(id)-len(s.shadow)+1)...) - } - - // Allocate local memory. - for int(id) >= len(s.ptrs) { - s.stack[0] = stk_t(size) - if err := s.alloc.CallWithStack(ctx, s.stack[:]); err != nil { - panic(err) - } - if s.stack[0] == 0 { - panic(util.OOMErr) - } - clear(util.View(s.mod, ptr_t(s.stack[0]), _WALINDEX_PGSZ)) - s.ptrs = append(s.ptrs, ptr_t(s.stack[0])) - } - - s.shadow[0][4] = 1 - return s.ptrs[id], _OK -} - -func (s *vfsShm) shmLock(offset, n int32, flags _ShmFlag) (rc _ErrorCode) { - var timeout time.Duration - if s.blocking { - timeout = time.Millisecond - } - - switch { - case flags&_SHM_LOCK != 0: - defer s.shmAcquire(&rc) - case flags&_SHM_EXCLUSIVE != 0: - s.shmRelease() - } - - switch { - case flags&_SHM_UNLOCK != 0: - return osUnlock(s.File, _SHM_BASE+uint32(offset), uint32(n)) - case flags&_SHM_SHARED != 0: - return osReadLock(s.File, _SHM_BASE+uint32(offset), uint32(n), timeout) - case flags&_SHM_EXCLUSIVE != 0: - return osWriteLock(s.File, _SHM_BASE+uint32(offset), uint32(n), timeout) - default: - panic(util.AssertErr()) - } -} - -func (s *vfsShm) shmUnmap(delete bool) { - if s.File == nil { - return - } - - s.shmRelease() - - // Free local memory. - for _, p := range s.ptrs { - s.stack[0] = stk_t(p) - if err := s.free.CallWithStack(context.Background(), s.stack[:]); err != nil { - panic(err) - } - } - s.ptrs = nil - s.shadow = nil - s.shared = nil - - // Close the file. - s.Close() - s.File = nil - if delete { - os.Remove(s.path) - } -} - -func (s *vfsShm) shmEnableBlocking(block bool) { - s.blocking = block -} diff --git a/vendor/github.com/ncruces/go-sqlite3/vfs/vfs.go b/vendor/github.com/ncruces/go-sqlite3/vfs/vfs.go deleted file mode 100644 index ca105fff6..000000000 --- a/vendor/github.com/ncruces/go-sqlite3/vfs/vfs.go +++ /dev/null @@ -1,485 +0,0 @@ -package vfs - -import ( - "context" - "crypto/rand" - "io" - "reflect" - "strings" - "time" - - "github.com/tetratelabs/wazero" - "github.com/tetratelabs/wazero/api" - - "github.com/ncruces/go-sqlite3/internal/util" - "github.com/ncruces/go-sqlite3/util/sql3util" - "github.com/ncruces/julianday" -) - -// ExportHostFunctions is an internal API users need not call directly. -// -// ExportHostFunctions registers the required VFS host functions -// with the provided env module. -func ExportHostFunctions(env wazero.HostModuleBuilder) wazero.HostModuleBuilder { - util.ExportFuncII(env, "go_vfs_find", vfsFind) - util.ExportFuncIIJ(env, "go_localtime", vfsLocaltime) - util.ExportFuncIIII(env, "go_randomness", vfsRandomness) - util.ExportFuncIII(env, "go_sleep", vfsSleep) - util.ExportFuncIII(env, "go_current_time_64", vfsCurrentTime64) - util.ExportFuncIIIII(env, "go_full_pathname", vfsFullPathname) - util.ExportFuncIIII(env, "go_delete", vfsDelete) - util.ExportFuncIIIII(env, "go_access", vfsAccess) - util.ExportFuncIIIIIII(env, "go_open", vfsOpen) - util.ExportFuncII(env, "go_close", vfsClose) - util.ExportFuncIIIIJ(env, "go_read", vfsRead) - util.ExportFuncIIIIJ(env, "go_write", vfsWrite) - util.ExportFuncIIJ(env, "go_truncate", vfsTruncate) - util.ExportFuncIII(env, "go_sync", vfsSync) - util.ExportFuncIII(env, "go_file_size", vfsFileSize) - util.ExportFuncIIII(env, "go_file_control", vfsFileControl) - util.ExportFuncII(env, "go_sector_size", vfsSectorSize) - util.ExportFuncII(env, "go_device_characteristics", vfsDeviceCharacteristics) - util.ExportFuncIII(env, "go_lock", vfsLock) - util.ExportFuncIII(env, "go_unlock", vfsUnlock) - util.ExportFuncIII(env, "go_check_reserved_lock", vfsCheckReservedLock) - util.ExportFuncIIIIII(env, "go_shm_map", vfsShmMap) - util.ExportFuncIIIII(env, "go_shm_lock", vfsShmLock) - util.ExportFuncIII(env, "go_shm_unmap", vfsShmUnmap) - util.ExportFuncVI(env, "go_shm_barrier", vfsShmBarrier) - return env -} - -func vfsFind(ctx context.Context, mod api.Module, zVfsName ptr_t) uint32 { - name := util.ReadString(mod, zVfsName, _MAX_NAME) - if vfs := Find(name); vfs != nil && vfs != (vfsOS{}) { - return 1 - } - return 0 -} - -func vfsLocaltime(ctx context.Context, mod api.Module, pTm ptr_t, t int64) _ErrorCode { - tm := time.Unix(t, 0) - var isdst int32 - if tm.IsDST() { - isdst = 1 - } - - const size = 32 / 8 - // https://pubs.opengroup.org/onlinepubs/7908799/xsh/time.h.html - util.Write32(mod, pTm+0*size, int32(tm.Second())) - util.Write32(mod, pTm+1*size, int32(tm.Minute())) - util.Write32(mod, pTm+2*size, int32(tm.Hour())) - util.Write32(mod, pTm+3*size, int32(tm.Day())) - util.Write32(mod, pTm+4*size, int32(tm.Month()-time.January)) - util.Write32(mod, pTm+5*size, int32(tm.Year()-1900)) - util.Write32(mod, pTm+6*size, int32(tm.Weekday()-time.Sunday)) - util.Write32(mod, pTm+7*size, int32(tm.YearDay()-1)) - util.Write32(mod, pTm+8*size, isdst) - return _OK -} - -func vfsRandomness(ctx context.Context, mod api.Module, pVfs ptr_t, nByte int32, zByte ptr_t) uint32 { - mem := util.View(mod, zByte, int64(nByte)) - n, _ := rand.Reader.Read(mem) - return uint32(n) -} - -func vfsSleep(ctx context.Context, mod api.Module, pVfs ptr_t, nMicro int32) _ErrorCode { - time.Sleep(time.Duration(nMicro) * time.Microsecond) - return _OK -} - -func vfsCurrentTime64(ctx context.Context, mod api.Module, pVfs, piNow ptr_t) _ErrorCode { - day, nsec := julianday.Date(time.Now()) - msec := day*86_400_000 + nsec/1_000_000 - util.Write64(mod, piNow, msec) - return _OK -} - -func vfsFullPathname(ctx context.Context, mod api.Module, pVfs, zRelative ptr_t, nFull int32, zFull ptr_t) _ErrorCode { - vfs := vfsGet(mod, pVfs) - path := util.ReadString(mod, zRelative, _MAX_PATHNAME) - - path, err := vfs.FullPathname(path) - - if len(path) >= int(nFull) { - return _CANTOPEN_FULLPATH - } - util.WriteString(mod, zFull, path) - - return vfsErrorCode(err, _CANTOPEN_FULLPATH) -} - -func vfsDelete(ctx context.Context, mod api.Module, pVfs, zPath ptr_t, syncDir int32) _ErrorCode { - vfs := vfsGet(mod, pVfs) - path := util.ReadString(mod, zPath, _MAX_PATHNAME) - - err := vfs.Delete(path, syncDir != 0) - return vfsErrorCode(err, _IOERR_DELETE) -} - -func vfsAccess(ctx context.Context, mod api.Module, pVfs, zPath ptr_t, flags AccessFlag, pResOut ptr_t) _ErrorCode { - vfs := vfsGet(mod, pVfs) - path := util.ReadString(mod, zPath, _MAX_PATHNAME) - - ok, err := vfs.Access(path, flags) - var res int32 - if ok { - res = 1 - } - util.Write32(mod, pResOut, res) - return vfsErrorCode(err, _IOERR_ACCESS) -} - -func vfsOpen(ctx context.Context, mod api.Module, pVfs, zPath, pFile ptr_t, flags OpenFlag, pOutFlags, pOutVFS ptr_t) _ErrorCode { - vfs := vfsGet(mod, pVfs) - name := GetFilename(ctx, mod, zPath, flags) - - var file File - var err error - if ffs, ok := vfs.(VFSFilename); ok { - file, flags, err = ffs.OpenFilename(name, flags) - } else { - file, flags, err = vfs.Open(name.String(), flags) - } - if err != nil { - return vfsErrorCode(err, _CANTOPEN) - } - - if file, ok := file.(FilePowersafeOverwrite); ok { - if b, ok := sql3util.ParseBool(name.URIParameter("psow")); ok { - file.SetPowersafeOverwrite(b) - } - } - if file, ok := file.(FileSharedMemory); ok && - pOutVFS != 0 && file.SharedMemory() != nil { - util.Write32(mod, pOutVFS, int32(1)) - } - if pOutFlags != 0 { - util.Write32(mod, pOutFlags, flags) - } - file = cksmWrapFile(name, flags, file) - vfsFileRegister(ctx, mod, pFile, file) - return _OK -} - -func vfsClose(ctx context.Context, mod api.Module, pFile ptr_t) _ErrorCode { - err := vfsFileClose(ctx, mod, pFile) - return vfsErrorCode(err, _IOERR_CLOSE) -} - -func vfsRead(ctx context.Context, mod api.Module, pFile, zBuf ptr_t, iAmt int32, iOfst int64) _ErrorCode { - file := vfsFileGet(ctx, mod, pFile).(File) - buf := util.View(mod, zBuf, int64(iAmt)) - - n, err := file.ReadAt(buf, iOfst) - if n == int(iAmt) { - return _OK - } - if err != io.EOF { - return vfsErrorCode(err, _IOERR_READ) - } - clear(buf[n:]) - return _IOERR_SHORT_READ -} - -func vfsWrite(ctx context.Context, mod api.Module, pFile, zBuf ptr_t, iAmt int32, iOfst int64) _ErrorCode { - file := vfsFileGet(ctx, mod, pFile).(File) - buf := util.View(mod, zBuf, int64(iAmt)) - - _, err := file.WriteAt(buf, iOfst) - return vfsErrorCode(err, _IOERR_WRITE) -} - -func vfsTruncate(ctx context.Context, mod api.Module, pFile ptr_t, nByte int64) _ErrorCode { - file := vfsFileGet(ctx, mod, pFile).(File) - err := file.Truncate(nByte) - return vfsErrorCode(err, _IOERR_TRUNCATE) -} - -func vfsSync(ctx context.Context, mod api.Module, pFile ptr_t, flags SyncFlag) _ErrorCode { - file := vfsFileGet(ctx, mod, pFile).(File) - err := file.Sync(flags) - return vfsErrorCode(err, _IOERR_FSYNC) -} - -func vfsFileSize(ctx context.Context, mod api.Module, pFile, pSize ptr_t) _ErrorCode { - file := vfsFileGet(ctx, mod, pFile).(File) - size, err := file.Size() - util.Write64(mod, pSize, size) - return vfsErrorCode(err, _IOERR_SEEK) -} - -func vfsLock(ctx context.Context, mod api.Module, pFile ptr_t, eLock LockLevel) _ErrorCode { - file := vfsFileGet(ctx, mod, pFile).(File) - err := file.Lock(eLock) - return vfsErrorCode(err, _IOERR_LOCK) -} - -func vfsUnlock(ctx context.Context, mod api.Module, pFile ptr_t, eLock LockLevel) _ErrorCode { - file := vfsFileGet(ctx, mod, pFile).(File) - err := file.Unlock(eLock) - return vfsErrorCode(err, _IOERR_UNLOCK) -} - -func vfsCheckReservedLock(ctx context.Context, mod api.Module, pFile, pResOut ptr_t) _ErrorCode { - file := vfsFileGet(ctx, mod, pFile).(File) - locked, err := file.CheckReservedLock() - - var res int32 - if locked { - res = 1 - } - util.Write32(mod, pResOut, res) - return vfsErrorCode(err, _IOERR_CHECKRESERVEDLOCK) -} - -func vfsFileControl(ctx context.Context, mod api.Module, pFile ptr_t, op _FcntlOpcode, pArg ptr_t) _ErrorCode { - file := vfsFileGet(ctx, mod, pFile).(File) - if file, ok := file.(fileControl); ok { - return file.fileControl(ctx, mod, op, pArg) - } - return vfsFileControlImpl(ctx, mod, file, op, pArg) -} - -func vfsFileControlImpl(ctx context.Context, mod api.Module, file File, op _FcntlOpcode, pArg ptr_t) _ErrorCode { - switch op { - case _FCNTL_LOCKSTATE: - if file, ok := file.(FileLockState); ok { - if lk := file.LockState(); lk <= LOCK_EXCLUSIVE { - util.Write32(mod, pArg, lk) - return _OK - } - } - - case _FCNTL_PERSIST_WAL: - if file, ok := file.(FilePersistWAL); ok { - if i := util.Read32[int32](mod, pArg); i >= 0 { - file.SetPersistWAL(i != 0) - } else if file.PersistWAL() { - util.Write32(mod, pArg, int32(1)) - } else { - util.Write32(mod, pArg, int32(0)) - } - return _OK - } - - case _FCNTL_POWERSAFE_OVERWRITE: - if file, ok := file.(FilePowersafeOverwrite); ok { - if i := util.Read32[int32](mod, pArg); i >= 0 { - file.SetPowersafeOverwrite(i != 0) - } else if file.PowersafeOverwrite() { - util.Write32(mod, pArg, int32(1)) - } else { - util.Write32(mod, pArg, int32(0)) - } - return _OK - } - - case _FCNTL_CHUNK_SIZE: - if file, ok := file.(FileChunkSize); ok { - size := util.Read32[int32](mod, pArg) - file.ChunkSize(int(size)) - return _OK - } - - case _FCNTL_SIZE_HINT: - if file, ok := file.(FileSizeHint); ok { - size := util.Read64[int64](mod, pArg) - err := file.SizeHint(size) - return vfsErrorCode(err, _IOERR_TRUNCATE) - } - - case _FCNTL_HAS_MOVED: - if file, ok := file.(FileHasMoved); ok { - moved, err := file.HasMoved() - var val uint32 - if moved { - val = 1 - } - util.Write32(mod, pArg, val) - return vfsErrorCode(err, _IOERR_FSTAT) - } - - case _FCNTL_OVERWRITE: - if file, ok := file.(FileOverwrite); ok { - err := file.Overwrite() - return vfsErrorCode(err, _IOERR) - } - - case _FCNTL_SYNC: - if file, ok := file.(FileSync); ok { - var name string - if pArg != 0 { - name = util.ReadString(mod, pArg, _MAX_PATHNAME) - } - err := file.SyncSuper(name) - return vfsErrorCode(err, _IOERR) - } - - case _FCNTL_COMMIT_PHASETWO: - if file, ok := file.(FileCommitPhaseTwo); ok { - err := file.CommitPhaseTwo() - return vfsErrorCode(err, _IOERR) - } - - case _FCNTL_BEGIN_ATOMIC_WRITE: - if file, ok := file.(FileBatchAtomicWrite); ok { - err := file.BeginAtomicWrite() - return vfsErrorCode(err, _IOERR_BEGIN_ATOMIC) - } - case _FCNTL_COMMIT_ATOMIC_WRITE: - if file, ok := file.(FileBatchAtomicWrite); ok { - err := file.CommitAtomicWrite() - return vfsErrorCode(err, _IOERR_COMMIT_ATOMIC) - } - case _FCNTL_ROLLBACK_ATOMIC_WRITE: - if file, ok := file.(FileBatchAtomicWrite); ok { - err := file.RollbackAtomicWrite() - return vfsErrorCode(err, _IOERR_ROLLBACK_ATOMIC) - } - - case _FCNTL_CKPT_START: - if file, ok := file.(FileCheckpoint); ok { - file.CheckpointStart() - return _OK - } - case _FCNTL_CKPT_DONE: - if file, ok := file.(FileCheckpoint); ok { - file.CheckpointDone() - return _OK - } - - case _FCNTL_PRAGMA: - if file, ok := file.(FilePragma); ok { - ptr := util.Read32[ptr_t](mod, pArg+1*ptrlen) - name := util.ReadString(mod, ptr, _MAX_SQL_LENGTH) - var value string - if ptr := util.Read32[ptr_t](mod, pArg+2*ptrlen); ptr != 0 { - value = util.ReadString(mod, ptr, _MAX_SQL_LENGTH) - } - - out, err := file.Pragma(strings.ToLower(name), value) - - ret := vfsErrorCode(err, _ERROR) - if ret == _ERROR { - out = err.Error() - } - if out != "" { - fn := mod.ExportedFunction("sqlite3_malloc64") - stack := [...]stk_t{stk_t(len(out) + 1)} - if err := fn.CallWithStack(ctx, stack[:]); err != nil { - panic(err) - } - util.Write32(mod, pArg, ptr_t(stack[0])) - util.WriteString(mod, ptr_t(stack[0]), out) - } - return ret - } - - case _FCNTL_BUSYHANDLER: - if file, ok := file.(FileBusyHandler); ok { - arg := util.Read64[stk_t](mod, pArg) - fn := mod.ExportedFunction("sqlite3_invoke_busy_handler_go") - file.BusyHandler(func() bool { - stack := [...]stk_t{arg} - if err := fn.CallWithStack(ctx, stack[:]); err != nil { - panic(err) - } - return uint32(stack[0]) != 0 - }) - return _OK - } - - case _FCNTL_LOCK_TIMEOUT: - if file, ok := file.(FileSharedMemory); ok { - if shm, ok := file.SharedMemory().(blockingSharedMemory); ok { - shm.shmEnableBlocking(util.Read32[uint32](mod, pArg) != 0) - return _OK - } - } - - case _FCNTL_PDB: - if file, ok := file.(filePDB); ok { - file.SetDB(ctx.Value(util.ConnKey{})) - return _OK - } - } - - return _NOTFOUND -} - -func vfsSectorSize(ctx context.Context, mod api.Module, pFile ptr_t) uint32 { - file := vfsFileGet(ctx, mod, pFile).(File) - return uint32(file.SectorSize()) -} - -func vfsDeviceCharacteristics(ctx context.Context, mod api.Module, pFile ptr_t) DeviceCharacteristic { - file := vfsFileGet(ctx, mod, pFile).(File) - return file.DeviceCharacteristics() -} - -func vfsShmBarrier(ctx context.Context, mod api.Module, pFile ptr_t) { - shm := vfsFileGet(ctx, mod, pFile).(FileSharedMemory).SharedMemory() - shm.shmBarrier() -} - -func vfsShmMap(ctx context.Context, mod api.Module, pFile ptr_t, iRegion, szRegion, bExtend int32, pp ptr_t) _ErrorCode { - shm := vfsFileGet(ctx, mod, pFile).(FileSharedMemory).SharedMemory() - p, rc := shm.shmMap(ctx, mod, iRegion, szRegion, bExtend != 0) - util.Write32(mod, pp, p) - return rc -} - -func vfsShmLock(ctx context.Context, mod api.Module, pFile ptr_t, offset, n int32, flags _ShmFlag) _ErrorCode { - shm := vfsFileGet(ctx, mod, pFile).(FileSharedMemory).SharedMemory() - return shm.shmLock(offset, n, flags) -} - -func vfsShmUnmap(ctx context.Context, mod api.Module, pFile ptr_t, bDelete int32) _ErrorCode { - shm := vfsFileGet(ctx, mod, pFile).(FileSharedMemory).SharedMemory() - shm.shmUnmap(bDelete != 0) - return _OK -} - -func vfsGet(mod api.Module, pVfs ptr_t) VFS { - var name string - if pVfs != 0 { - const zNameOffset = 16 - ptr := util.Read32[ptr_t](mod, pVfs+zNameOffset) - name = util.ReadString(mod, ptr, _MAX_NAME) - } - if vfs := Find(name); vfs != nil { - return vfs - } - panic(util.NoVFSErr + util.ErrorString(name)) -} - -func vfsFileRegister(ctx context.Context, mod api.Module, pFile ptr_t, file File) { - const fileHandleOffset = 4 - id := util.AddHandle(ctx, file) - util.Write32(mod, pFile+fileHandleOffset, id) -} - -func vfsFileGet(ctx context.Context, mod api.Module, pFile ptr_t) any { - const fileHandleOffset = 4 - id := util.Read32[ptr_t](mod, pFile+fileHandleOffset) - return util.GetHandle(ctx, id) -} - -func vfsFileClose(ctx context.Context, mod api.Module, pFile ptr_t) error { - const fileHandleOffset = 4 - id := util.Read32[ptr_t](mod, pFile+fileHandleOffset) - return util.DelHandle(ctx, id) -} - -func vfsErrorCode(err error, def _ErrorCode) _ErrorCode { - if err == nil { - return _OK - } - switch v := reflect.ValueOf(err); v.Kind() { - case reflect.Uint8, reflect.Uint16, reflect.Uint32: - return _ErrorCode(v.Uint()) - } - return def -} diff --git a/vendor/github.com/ncruces/go-sqlite3/vtab.go b/vendor/github.com/ncruces/go-sqlite3/vtab.go deleted file mode 100644 index 278195e92..000000000 --- a/vendor/github.com/ncruces/go-sqlite3/vtab.go +++ /dev/null @@ -1,682 +0,0 @@ -package sqlite3 - -import ( - "context" - "errors" - "reflect" - - "github.com/tetratelabs/wazero/api" - - "github.com/ncruces/go-sqlite3/internal/util" -) - -// CreateModule registers a new virtual table module name. -// If create is nil, the virtual table is eponymous. -// -// https://sqlite.org/c3ref/create_module.html -func CreateModule[T VTab](db *Conn, name string, create, connect VTabConstructor[T]) error { - var flags int - - const ( - VTAB_CREATOR = 0x001 - VTAB_DESTROYER = 0x002 - VTAB_UPDATER = 0x004 - VTAB_RENAMER = 0x008 - VTAB_OVERLOADER = 0x010 - VTAB_CHECKER = 0x020 - VTAB_TXN = 0x040 - VTAB_SAVEPOINTER = 0x080 - VTAB_SHADOWTABS = 0x100 - ) - - if create != nil { - flags |= VTAB_CREATOR - } - - vtab := reflect.TypeOf(connect).Out(0) - if implements[VTabDestroyer](vtab) { - flags |= VTAB_DESTROYER - } - if implements[VTabUpdater](vtab) { - flags |= VTAB_UPDATER - } - if implements[VTabRenamer](vtab) { - flags |= VTAB_RENAMER - } - if implements[VTabOverloader](vtab) { - flags |= VTAB_OVERLOADER - } - if implements[VTabChecker](vtab) { - flags |= VTAB_CHECKER - } - if implements[VTabTxn](vtab) { - flags |= VTAB_TXN - } - if implements[VTabSavepointer](vtab) { - flags |= VTAB_SAVEPOINTER - } - if implements[VTabShadowTabler](vtab) { - flags |= VTAB_SHADOWTABS - } - - var modulePtr ptr_t - defer db.arena.mark()() - namePtr := db.arena.string(name) - if connect != nil { - modulePtr = util.AddHandle(db.ctx, module[T]{create, connect}) - } - rc := res_t(db.call("sqlite3_create_module_go", stk_t(db.handle), - stk_t(namePtr), stk_t(flags), stk_t(modulePtr))) - return db.error(rc) -} - -func implements[T any](typ reflect.Type) bool { - var ptr *T - return typ.Implements(reflect.TypeOf(ptr).Elem()) -} - -// DeclareVTab declares the schema of a virtual table. -// -// https://sqlite.org/c3ref/declare_vtab.html -func (c *Conn) DeclareVTab(sql string) error { - defer c.arena.mark()() - sqlPtr := c.arena.string(sql) - rc := res_t(c.call("sqlite3_declare_vtab", stk_t(c.handle), stk_t(sqlPtr))) - return c.error(rc) -} - -// VTabConflictMode is a virtual table conflict resolution mode. -// -// https://sqlite.org/c3ref/c_fail.html -type VTabConflictMode uint8 - -const ( - VTAB_ROLLBACK VTabConflictMode = 1 - VTAB_IGNORE VTabConflictMode = 2 - VTAB_FAIL VTabConflictMode = 3 - VTAB_ABORT VTabConflictMode = 4 - VTAB_REPLACE VTabConflictMode = 5 -) - -// VTabOnConflict determines the virtual table conflict policy. -// -// https://sqlite.org/c3ref/vtab_on_conflict.html -func (c *Conn) VTabOnConflict() VTabConflictMode { - return VTabConflictMode(c.call("sqlite3_vtab_on_conflict", stk_t(c.handle))) -} - -// VTabConfigOption is a virtual table configuration option. -// -// https://sqlite.org/c3ref/c_vtab_constraint_support.html -type VTabConfigOption uint8 - -const ( - VTAB_CONSTRAINT_SUPPORT VTabConfigOption = 1 - VTAB_INNOCUOUS VTabConfigOption = 2 - VTAB_DIRECTONLY VTabConfigOption = 3 - VTAB_USES_ALL_SCHEMAS VTabConfigOption = 4 -) - -// VTabConfig configures various facets of the virtual table interface. -// -// https://sqlite.org/c3ref/vtab_config.html -func (c *Conn) VTabConfig(op VTabConfigOption, args ...any) error { - var i int32 - if op == VTAB_CONSTRAINT_SUPPORT && len(args) > 0 { - if b, ok := args[0].(bool); ok && b { - i = 1 - } - } - rc := res_t(c.call("sqlite3_vtab_config_go", stk_t(c.handle), stk_t(op), stk_t(i))) - return c.error(rc) -} - -// VTabConstructor is a virtual table constructor function. -type VTabConstructor[T VTab] func(db *Conn, module, schema, table string, arg ...string) (T, error) - -type module[T VTab] [2]VTabConstructor[T] - -type vtabConstructor int - -const ( - xCreate vtabConstructor = 0 - xConnect vtabConstructor = 1 -) - -// A VTab describes a particular instance of the virtual table. -// A VTab may optionally implement [io.Closer] to free resources. -// -// https://sqlite.org/c3ref/vtab.html -type VTab interface { - // https://sqlite.org/vtab.html#xbestindex - BestIndex(*IndexInfo) error - // https://sqlite.org/vtab.html#xopen - Open() (VTabCursor, error) -} - -// A VTabDestroyer allows a virtual table to drop persistent state. -type VTabDestroyer interface { - VTab - // https://sqlite.org/vtab.html#sqlite3_module.xDestroy - Destroy() error -} - -// A VTabUpdater allows a virtual table to be updated. -type VTabUpdater interface { - VTab - // https://sqlite.org/vtab.html#xupdate - Update(arg ...Value) (rowid int64, err error) -} - -// A VTabRenamer allows a virtual table to be renamed. -type VTabRenamer interface { - VTab - // https://sqlite.org/vtab.html#xrename - Rename(new string) error -} - -// A VTabOverloader allows a virtual table to overload SQL functions. -type VTabOverloader interface { - VTab - // https://sqlite.org/vtab.html#xfindfunction - FindFunction(arg int, name string) (ScalarFunction, IndexConstraintOp) -} - -// A VTabShadowTabler allows a virtual table to protect the content -// of shadow tables from being corrupted by hostile SQL. -// -// Implementing this interface signals that a virtual table named -// "mumble" reserves all table names starting with "mumble_". -type VTabShadowTabler interface { - VTab - // https://sqlite.org/vtab.html#the_xshadowname_method - ShadowTables() -} - -// A VTabChecker allows a virtual table to report errors -// to the PRAGMA integrity_check and PRAGMA quick_check commands. -// -// Integrity should return an error if it finds problems in the content of the virtual table, -// but should avoid returning a (wrapped) [Error], [ErrorCode] or [ExtendedErrorCode], -// as those indicate the Integrity method itself encountered problems -// while trying to evaluate the virtual table content. -type VTabChecker interface { - VTab - // https://sqlite.org/vtab.html#xintegrity - Integrity(schema, table string, flags int) error -} - -// A VTabTxn allows a virtual table to implement -// transactions with two-phase commit. -// -// Anything that is required as part of a commit that may fail -// should be performed in the Sync() callback. -// Current versions of SQLite ignore any errors -// returned by Commit() and Rollback(). -type VTabTxn interface { - VTab - // https://sqlite.org/vtab.html#xBegin - Begin() error - // https://sqlite.org/vtab.html#xsync - Sync() error - // https://sqlite.org/vtab.html#xcommit - Commit() error - // https://sqlite.org/vtab.html#xrollback - Rollback() error -} - -// A VTabSavepointer allows a virtual table to implement -// nested transactions. -// -// https://sqlite.org/vtab.html#xsavepoint -type VTabSavepointer interface { - VTabTxn - Savepoint(id int) error - Release(id int) error - RollbackTo(id int) error -} - -// A VTabCursor describes cursors that point -// into the virtual table and are used -// to loop through the virtual table. -// A VTabCursor may optionally implement -// [io.Closer] to free resources. -// -// https://sqlite.org/c3ref/vtab_cursor.html -type VTabCursor interface { - // https://sqlite.org/vtab.html#xfilter - Filter(idxNum int, idxStr string, arg ...Value) error - // https://sqlite.org/vtab.html#xnext - Next() error - // https://sqlite.org/vtab.html#xeof - EOF() bool - // https://sqlite.org/vtab.html#xcolumn - Column(ctx Context, n int) error - // https://sqlite.org/vtab.html#xrowid - RowID() (int64, error) -} - -// An IndexInfo describes virtual table indexing information. -// -// https://sqlite.org/c3ref/index_info.html -type IndexInfo struct { - // Inputs - Constraint []IndexConstraint - OrderBy []IndexOrderBy - ColumnsUsed uint64 - // Outputs - ConstraintUsage []IndexConstraintUsage - IdxNum int - IdxStr string - IdxFlags IndexScanFlag - OrderByConsumed bool - EstimatedCost float64 - EstimatedRows int64 - // Internal - c *Conn - handle ptr_t -} - -// An IndexConstraint describes virtual table indexing constraint information. -// -// https://sqlite.org/c3ref/index_info.html -type IndexConstraint struct { - Column int - Op IndexConstraintOp - Usable bool -} - -// An IndexOrderBy describes virtual table indexing order by information. -// -// https://sqlite.org/c3ref/index_info.html -type IndexOrderBy struct { - Column int - Desc bool -} - -// An IndexConstraintUsage describes how virtual table indexing constraints will be used. -// -// https://sqlite.org/c3ref/index_info.html -type IndexConstraintUsage struct { - ArgvIndex int - Omit bool -} - -// RHSValue returns the value of the right-hand operand of a constraint -// if the right-hand operand is known. -// -// https://sqlite.org/c3ref/vtab_rhs_value.html -func (idx *IndexInfo) RHSValue(column int) (Value, error) { - defer idx.c.arena.mark()() - valPtr := idx.c.arena.new(ptrlen) - rc := res_t(idx.c.call("sqlite3_vtab_rhs_value", stk_t(idx.handle), - stk_t(column), stk_t(valPtr))) - if err := idx.c.error(rc); err != nil { - return Value{}, err - } - return Value{ - c: idx.c, - handle: util.Read32[ptr_t](idx.c.mod, valPtr), - }, nil -} - -// Collation returns the name of the collation for a virtual table constraint. -// -// https://sqlite.org/c3ref/vtab_collation.html -func (idx *IndexInfo) Collation(column int) string { - ptr := ptr_t(idx.c.call("sqlite3_vtab_collation", stk_t(idx.handle), - stk_t(column))) - return util.ReadString(idx.c.mod, ptr, _MAX_NAME) -} - -// Distinct determines if a virtual table query is DISTINCT. -// -// https://sqlite.org/c3ref/vtab_distinct.html -func (idx *IndexInfo) Distinct() int { - i := int32(idx.c.call("sqlite3_vtab_distinct", stk_t(idx.handle))) - return int(i) -} - -// In identifies and handles IN constraints. -// -// https://sqlite.org/c3ref/vtab_in.html -func (idx *IndexInfo) In(column, handle int) bool { - b := int32(idx.c.call("sqlite3_vtab_in", stk_t(idx.handle), - stk_t(column), stk_t(handle))) - return b != 0 -} - -func (idx *IndexInfo) load() { - // https://sqlite.org/c3ref/index_info.html - mod := idx.c.mod - ptr := idx.handle - - nConstraint := util.Read32[int32](mod, ptr+0) - idx.Constraint = make([]IndexConstraint, nConstraint) - idx.ConstraintUsage = make([]IndexConstraintUsage, nConstraint) - idx.OrderBy = make([]IndexOrderBy, util.Read32[int32](mod, ptr+8)) - - constraintPtr := util.Read32[ptr_t](mod, ptr+4) - constraint := idx.Constraint - for i := range idx.Constraint { - constraint[i] = IndexConstraint{ - Column: int(util.Read32[int32](mod, constraintPtr+0)), - Op: util.Read[IndexConstraintOp](mod, constraintPtr+4), - Usable: util.Read[byte](mod, constraintPtr+5) != 0, - } - constraintPtr += 12 - } - - orderByPtr := util.Read32[ptr_t](mod, ptr+12) - orderBy := idx.OrderBy - for i := range orderBy { - orderBy[i] = IndexOrderBy{ - Column: int(util.Read32[int32](mod, orderByPtr+0)), - Desc: util.Read[byte](mod, orderByPtr+4) != 0, - } - orderByPtr += 8 - } - - idx.EstimatedCost = util.ReadFloat64(mod, ptr+40) - idx.EstimatedRows = util.Read64[int64](mod, ptr+48) - idx.ColumnsUsed = util.Read64[uint64](mod, ptr+64) -} - -func (idx *IndexInfo) save() { - // https://sqlite.org/c3ref/index_info.html - mod := idx.c.mod - ptr := idx.handle - - usagePtr := util.Read32[ptr_t](mod, ptr+16) - for _, usage := range idx.ConstraintUsage { - util.Write32(mod, usagePtr+0, int32(usage.ArgvIndex)) - if usage.Omit { - util.Write(mod, usagePtr+4, int8(1)) - } - usagePtr += 8 - } - - util.Write32(mod, ptr+20, int32(idx.IdxNum)) - if idx.IdxStr != "" { - util.Write32(mod, ptr+24, idx.c.newString(idx.IdxStr)) - util.Write32(mod, ptr+28, int32(1)) // needToFreeIdxStr - } - if idx.OrderByConsumed { - util.Write32(mod, ptr+32, int32(1)) - } - util.WriteFloat64(mod, ptr+40, idx.EstimatedCost) - util.Write64(mod, ptr+48, idx.EstimatedRows) - util.Write32(mod, ptr+56, idx.IdxFlags) -} - -// IndexConstraintOp is a virtual table constraint operator code. -// -// https://sqlite.org/c3ref/c_index_constraint_eq.html -type IndexConstraintOp uint8 - -const ( - INDEX_CONSTRAINT_EQ IndexConstraintOp = 2 - INDEX_CONSTRAINT_GT IndexConstraintOp = 4 - INDEX_CONSTRAINT_LE IndexConstraintOp = 8 - INDEX_CONSTRAINT_LT IndexConstraintOp = 16 - INDEX_CONSTRAINT_GE IndexConstraintOp = 32 - INDEX_CONSTRAINT_MATCH IndexConstraintOp = 64 - INDEX_CONSTRAINT_LIKE IndexConstraintOp = 65 - INDEX_CONSTRAINT_GLOB IndexConstraintOp = 66 - INDEX_CONSTRAINT_REGEXP IndexConstraintOp = 67 - INDEX_CONSTRAINT_NE IndexConstraintOp = 68 - INDEX_CONSTRAINT_ISNOT IndexConstraintOp = 69 - INDEX_CONSTRAINT_ISNOTNULL IndexConstraintOp = 70 - INDEX_CONSTRAINT_ISNULL IndexConstraintOp = 71 - INDEX_CONSTRAINT_IS IndexConstraintOp = 72 - INDEX_CONSTRAINT_LIMIT IndexConstraintOp = 73 - INDEX_CONSTRAINT_OFFSET IndexConstraintOp = 74 - INDEX_CONSTRAINT_FUNCTION IndexConstraintOp = 150 -) - -// IndexScanFlag is a virtual table scan flag. -// -// https://sqlite.org/c3ref/c_index_scan_unique.html -type IndexScanFlag uint32 - -const ( - INDEX_SCAN_UNIQUE IndexScanFlag = 1 -) - -func vtabModuleCallback(i vtabConstructor) func(_ context.Context, _ api.Module, _ ptr_t, _ int32, _, _, _ ptr_t) res_t { - return func(ctx context.Context, mod api.Module, pMod ptr_t, nArg int32, pArg, ppVTab, pzErr ptr_t) res_t { - arg := make([]reflect.Value, 1+nArg) - arg[0] = reflect.ValueOf(ctx.Value(connKey{})) - - for i := range nArg { - ptr := util.Read32[ptr_t](mod, pArg+ptr_t(i)*ptrlen) - arg[i+1] = reflect.ValueOf(util.ReadString(mod, ptr, _MAX_SQL_LENGTH)) - } - - module := vtabGetHandle(ctx, mod, pMod) - val := reflect.ValueOf(module).Index(int(i)).Call(arg) - err, _ := val[1].Interface().(error) - if err == nil { - vtabPutHandle(ctx, mod, ppVTab, val[0].Interface()) - } - - return vtabError(ctx, mod, pzErr, _PTR_ERROR, err) - } -} - -func vtabDisconnectCallback(ctx context.Context, mod api.Module, pVTab ptr_t) res_t { - err := vtabDelHandle(ctx, mod, pVTab) - return vtabError(ctx, mod, 0, _PTR_ERROR, err) -} - -func vtabDestroyCallback(ctx context.Context, mod api.Module, pVTab ptr_t) res_t { - vtab := vtabGetHandle(ctx, mod, pVTab).(VTabDestroyer) - err := errors.Join(vtab.Destroy(), vtabDelHandle(ctx, mod, pVTab)) - return vtabError(ctx, mod, 0, _PTR_ERROR, err) -} - -func vtabBestIndexCallback(ctx context.Context, mod api.Module, pVTab, pIdxInfo ptr_t) res_t { - var info IndexInfo - info.handle = pIdxInfo - info.c = ctx.Value(connKey{}).(*Conn) - info.load() - - vtab := vtabGetHandle(ctx, mod, pVTab).(VTab) - err := vtab.BestIndex(&info) - - info.save() - return vtabError(ctx, mod, pVTab, _VTAB_ERROR, err) -} - -func vtabUpdateCallback(ctx context.Context, mod api.Module, pVTab ptr_t, nArg int32, pArg, pRowID ptr_t) res_t { - vtab := vtabGetHandle(ctx, mod, pVTab).(VTabUpdater) - - db := ctx.Value(connKey{}).(*Conn) - args := make([]Value, nArg) - callbackArgs(db, args, pArg) - rowID, err := vtab.Update(args...) - if err == nil { - util.Write64(mod, pRowID, rowID) - } - - return vtabError(ctx, mod, pVTab, _VTAB_ERROR, err) -} - -func vtabRenameCallback(ctx context.Context, mod api.Module, pVTab, zNew ptr_t) res_t { - vtab := vtabGetHandle(ctx, mod, pVTab).(VTabRenamer) - err := vtab.Rename(util.ReadString(mod, zNew, _MAX_NAME)) - return vtabError(ctx, mod, pVTab, _VTAB_ERROR, err) -} - -func vtabFindFuncCallback(ctx context.Context, mod api.Module, pVTab ptr_t, nArg int32, zName, pxFunc ptr_t) int32 { - vtab := vtabGetHandle(ctx, mod, pVTab).(VTabOverloader) - f, op := vtab.FindFunction(int(nArg), util.ReadString(mod, zName, _MAX_NAME)) - if op != 0 { - var wrapper ptr_t - wrapper = util.AddHandle(ctx, func(c Context, arg ...Value) { - defer util.DelHandle(ctx, wrapper) - f(c, arg...) - }) - util.Write32(mod, pxFunc, wrapper) - } - return int32(op) -} - -func vtabIntegrityCallback(ctx context.Context, mod api.Module, pVTab, zSchema, zTabName ptr_t, mFlags uint32, pzErr ptr_t) res_t { - vtab := vtabGetHandle(ctx, mod, pVTab).(VTabChecker) - schema := util.ReadString(mod, zSchema, _MAX_NAME) - table := util.ReadString(mod, zTabName, _MAX_NAME) - err := vtab.Integrity(schema, table, int(mFlags)) - // xIntegrity should return OK - even if it finds problems in the content of the virtual table. - // https://sqlite.org/vtab.html#xintegrity - vtabError(ctx, mod, pzErr, _PTR_ERROR, err) - _, code := errorCode(err, _OK) - return code -} - -func vtabBeginCallback(ctx context.Context, mod api.Module, pVTab ptr_t) res_t { - vtab := vtabGetHandle(ctx, mod, pVTab).(VTabTxn) - err := vtab.Begin() - return vtabError(ctx, mod, pVTab, _VTAB_ERROR, err) -} - -func vtabSyncCallback(ctx context.Context, mod api.Module, pVTab ptr_t) res_t { - vtab := vtabGetHandle(ctx, mod, pVTab).(VTabTxn) - err := vtab.Sync() - return vtabError(ctx, mod, pVTab, _VTAB_ERROR, err) -} - -func vtabCommitCallback(ctx context.Context, mod api.Module, pVTab ptr_t) res_t { - vtab := vtabGetHandle(ctx, mod, pVTab).(VTabTxn) - err := vtab.Commit() - return vtabError(ctx, mod, pVTab, _VTAB_ERROR, err) -} - -func vtabRollbackCallback(ctx context.Context, mod api.Module, pVTab ptr_t) res_t { - vtab := vtabGetHandle(ctx, mod, pVTab).(VTabTxn) - err := vtab.Rollback() - return vtabError(ctx, mod, pVTab, _VTAB_ERROR, err) -} - -func vtabSavepointCallback(ctx context.Context, mod api.Module, pVTab ptr_t, id int32) res_t { - vtab := vtabGetHandle(ctx, mod, pVTab).(VTabSavepointer) - err := vtab.Savepoint(int(id)) - return vtabError(ctx, mod, pVTab, _VTAB_ERROR, err) -} - -func vtabReleaseCallback(ctx context.Context, mod api.Module, pVTab ptr_t, id int32) res_t { - vtab := vtabGetHandle(ctx, mod, pVTab).(VTabSavepointer) - err := vtab.Release(int(id)) - return vtabError(ctx, mod, pVTab, _VTAB_ERROR, err) -} - -func vtabRollbackToCallback(ctx context.Context, mod api.Module, pVTab ptr_t, id int32) res_t { - vtab := vtabGetHandle(ctx, mod, pVTab).(VTabSavepointer) - err := vtab.RollbackTo(int(id)) - return vtabError(ctx, mod, pVTab, _VTAB_ERROR, err) -} - -func cursorOpenCallback(ctx context.Context, mod api.Module, pVTab, ppCur ptr_t) res_t { - vtab := vtabGetHandle(ctx, mod, pVTab).(VTab) - - cursor, err := vtab.Open() - if err == nil { - vtabPutHandle(ctx, mod, ppCur, cursor) - } - - return vtabError(ctx, mod, pVTab, _VTAB_ERROR, err) -} - -func cursorCloseCallback(ctx context.Context, mod api.Module, pCur ptr_t) res_t { - err := vtabDelHandle(ctx, mod, pCur) - return vtabError(ctx, mod, 0, _VTAB_ERROR, err) -} - -func cursorFilterCallback(ctx context.Context, mod api.Module, pCur ptr_t, idxNum int32, idxStr ptr_t, nArg int32, pArg ptr_t) res_t { - cursor := vtabGetHandle(ctx, mod, pCur).(VTabCursor) - db := ctx.Value(connKey{}).(*Conn) - args := make([]Value, nArg) - callbackArgs(db, args, pArg) - var idxName string - if idxStr != 0 { - idxName = util.ReadString(mod, idxStr, _MAX_LENGTH) - } - err := cursor.Filter(int(idxNum), idxName, args...) - return vtabError(ctx, mod, pCur, _CURSOR_ERROR, err) -} - -func cursorEOFCallback(ctx context.Context, mod api.Module, pCur ptr_t) int32 { - cursor := vtabGetHandle(ctx, mod, pCur).(VTabCursor) - if cursor.EOF() { - return 1 - } - return 0 -} - -func cursorNextCallback(ctx context.Context, mod api.Module, pCur ptr_t) res_t { - cursor := vtabGetHandle(ctx, mod, pCur).(VTabCursor) - err := cursor.Next() - return vtabError(ctx, mod, pCur, _CURSOR_ERROR, err) -} - -func cursorColumnCallback(ctx context.Context, mod api.Module, pCur, pCtx ptr_t, n int32) res_t { - cursor := vtabGetHandle(ctx, mod, pCur).(VTabCursor) - db := ctx.Value(connKey{}).(*Conn) - err := cursor.Column(Context{db, pCtx}, int(n)) - return vtabError(ctx, mod, pCur, _CURSOR_ERROR, err) -} - -func cursorRowIDCallback(ctx context.Context, mod api.Module, pCur, pRowID ptr_t) res_t { - cursor := vtabGetHandle(ctx, mod, pCur).(VTabCursor) - - rowID, err := cursor.RowID() - if err == nil { - util.Write64(mod, pRowID, rowID) - } - - return vtabError(ctx, mod, pCur, _CURSOR_ERROR, err) -} - -const ( - _PTR_ERROR = iota - _VTAB_ERROR - _CURSOR_ERROR -) - -func vtabError(ctx context.Context, mod api.Module, ptr ptr_t, kind uint32, err error) res_t { - const zErrMsgOffset = 8 - msg, code := errorCode(err, ERROR) - if msg != "" && ptr != 0 { - switch kind { - case _VTAB_ERROR: - ptr = ptr + zErrMsgOffset // zErrMsg - case _CURSOR_ERROR: - ptr = util.Read32[ptr_t](mod, ptr) + zErrMsgOffset // pVTab->zErrMsg - } - db := ctx.Value(connKey{}).(*Conn) - if ptr := util.Read32[ptr_t](mod, ptr); ptr != 0 { - db.free(ptr) - } - util.Write32(mod, ptr, db.newString(msg)) - } - return code -} - -func vtabGetHandle(ctx context.Context, mod api.Module, ptr ptr_t) any { - const handleOffset = 4 - handle := util.Read32[ptr_t](mod, ptr-handleOffset) - return util.GetHandle(ctx, handle) -} - -func vtabDelHandle(ctx context.Context, mod api.Module, ptr ptr_t) error { - const handleOffset = 4 - handle := util.Read32[ptr_t](mod, ptr-handleOffset) - return util.DelHandle(ctx, handle) -} - -func vtabPutHandle(ctx context.Context, mod api.Module, pptr ptr_t, val any) { - const handleOffset = 4 - handle := util.AddHandle(ctx, val) - ptr := util.Read32[ptr_t](mod, pptr) - util.Write32(mod, ptr-handleOffset, handle) -} |