diff options
| author | 2025-10-03 15:29:41 +0200 | |
|---|---|---|
| committer | 2025-10-03 15:29:41 +0200 | |
| commit | ff950e94bb8a2e1b3c905bdba4c44d0232704b18 (patch) | |
| tree | a6aedfd6a89438f400bc20c90457552e4176f1ba /vendor/github.com | |
| parent | [chore] Use bulk updates + fewer loops in status rethreading migration (#4459) (diff) | |
| download | gotosocial-ff950e94bb8a2e1b3c905bdba4c44d0232704b18.tar.xz | |
[chore] update dependencies (#4468)
- github.com/ncruces/go-sqlite3
- codeberg.org/gruf/go-mempool
- codeberg.org/gruf/go-structr (changes related on the above) *
- codeberg.org/gruf/go-mutexes (changes related on the above) *
* this is largely just fiddling around with package internals in structr and mutexes to rely on changes in mempool, which added a new concurrency-safe pool
Reviewed-on: https://codeberg.org/superseriousbusiness/gotosocial/pulls/4468
Co-authored-by: kim <grufwub@gmail.com>
Co-committed-by: kim <grufwub@gmail.com>
Diffstat (limited to 'vendor/github.com')
19 files changed, 414 insertions, 183 deletions
diff --git a/vendor/github.com/ncruces/go-sqlite3/conn.go b/vendor/github.com/ncruces/go-sqlite3/conn.go index 7e88d8c85..a7eca1652 100644 --- a/vendor/github.com/ncruces/go-sqlite3/conn.go +++ b/vendor/github.com/ncruces/go-sqlite3/conn.go @@ -444,20 +444,27 @@ func (c *Conn) Status(op DBStatus, reset bool) (current, highwater int, err erro // 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) + var ( + declTypePtr ptr_t + collSeqPtr ptr_t + notNullPtr ptr_t + primaryKeyPtr ptr_t + autoIncPtr ptr_t + columnPtr ptr_t + schemaPtr ptr_t + ) + if column != "" { + declTypePtr = c.arena.new(ptrlen) + collSeqPtr = c.arena.new(ptrlen) + notNullPtr = c.arena.new(ptrlen) + primaryKeyPtr = c.arena.new(ptrlen) + autoIncPtr = c.arena.new(ptrlen) + columnPtr = c.arena.string(column) + } 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), diff --git a/vendor/github.com/ncruces/go-sqlite3/context.go b/vendor/github.com/ncruces/go-sqlite3/context.go index 154c228cf..269bf52f9 100644 --- a/vendor/github.com/ncruces/go-sqlite3/context.go +++ b/vendor/github.com/ncruces/go-sqlite3/context.go @@ -1,7 +1,6 @@ package sqlite3 import ( - "encoding/json" "errors" "math" "time" @@ -173,21 +172,6 @@ func (ctx Context) ResultPointer(ptr any) { 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) { - err := json.NewEncoder(callbackWriter(func(p []byte) (int, error) { - ctx.ResultRawText(p[:len(p)-1]) // remove the newline - return 0, nil - })).Encode(value) - - if err != nil { - ctx.ResultError(err) - return // notest - } -} - // ResultValue sets the result of the function to a copy of [Value]. // // https://sqlite.org/c3ref/result_blob.html diff --git a/vendor/github.com/ncruces/go-sqlite3/driver/driver.go b/vendor/github.com/ncruces/go-sqlite3/driver/driver.go index 27496f6cb..5d2847369 100644 --- a/vendor/github.com/ncruces/go-sqlite3/driver/driver.go +++ b/vendor/github.com/ncruces/go-sqlite3/driver/driver.go @@ -607,14 +607,24 @@ func (r resultRowsAffected) RowsAffected() (int64, error) { 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 + _ANY scantype = iota + _INT + _REAL + _TEXT + _BLOB + _NULL + _BOOL _TIME + _NOT_NULL +) + +var ( + _ [0]struct{} = [scantype(sqlite3.INTEGER) - _INT]struct{}{} + _ [0]struct{} = [scantype(sqlite3.FLOAT) - _REAL]struct{}{} + _ [0]struct{} = [scantype(sqlite3.TEXT) - _TEXT]struct{}{} + _ [0]struct{} = [scantype(sqlite3.BLOB) - _BLOB]struct{}{} + _ [0]struct{} = [scantype(sqlite3.NULL) - _NULL]struct{}{} + _ [0]struct{} = [_NOT_NULL & (_NOT_NULL - 1)]struct{}{} ) func scanFromDecl(decl string) scantype { @@ -644,8 +654,8 @@ type rows struct { *stmt names []string types []string - nulls []bool scans []scantype + dest []driver.Value } var ( @@ -675,34 +685,36 @@ func (r *rows) Columns() []string { func (r *rows) scanType(index int) scantype { if r.scans == nil { - count := r.Stmt.ColumnCount() + count := len(r.names) scans := make([]scantype, count) for i := range scans { scans[i] = scanFromDecl(strings.ToUpper(r.Stmt.ColumnDeclType(i))) } r.scans = scans } - return r.scans[index] + return r.scans[index] &^ _NOT_NULL } func (r *rows) loadColumnMetadata() { - if r.nulls == nil { + if r.types == nil { c := r.Stmt.Conn() - count := r.Stmt.ColumnCount() - nulls := make([]bool, count) + count := len(r.names) types := make([]string, count) scans := make([]scantype, count) - for i := range nulls { + for i := range types { + var notnull bool if col := r.Stmt.ColumnOriginName(i); col != "" { - types[i], _, nulls[i], _, _, _ = c.TableColumnMetadata( + types[i], _, notnull, _, _, _ = c.TableColumnMetadata( r.Stmt.ColumnDatabaseName(i), r.Stmt.ColumnTableName(i), col) types[i] = strings.ToUpper(types[i]) scans[i] = scanFromDecl(types[i]) + if notnull { + scans[i] |= _NOT_NULL + } } } - r.nulls = nulls r.types = types r.scans = scans } @@ -721,15 +733,13 @@ func (r *rows) ColumnTypeDatabaseTypeName(index int) string { func (r *rows) ColumnTypeNullable(index int) (nullable, ok bool) { r.loadColumnMetadata() - if r.nulls[index] { - return false, true - } - return true, false + nullable = r.scans[index]&^_NOT_NULL == 0 + return nullable, !nullable } func (r *rows) ColumnTypeScanType(index int) (typ reflect.Type) { r.loadColumnMetadata() - scan := r.scans[index] + scan := r.scans[index] &^ _NOT_NULL if r.Stmt.Busy() { // SQLite is dynamically typed and we now have a row. @@ -772,6 +782,7 @@ func (r *rows) ColumnTypeScanType(index int) (typ reflect.Type) { } func (r *rows) Next(dest []driver.Value) error { + r.dest = nil c := r.Stmt.Conn() if old := c.SetInterrupt(r.ctx); old != r.ctx { defer c.SetInterrupt(old) @@ -790,18 +801,7 @@ func (r *rows) Next(dest []driver.Value) error { } for i := range dest { scan := r.scanType(i) - switch v := dest[i].(type) { - case int64: - if scan == _BOOL { - switch v { - case 1: - dest[i] = true - case 0: - dest[i] = false - } - continue - } - case []byte: + if v, ok := dest[i].([]byte); ok { if len(v) == cap(v) { // a BLOB continue } @@ -816,38 +816,49 @@ func (r *rows) Next(dest []driver.Value) error { } } dest[i] = string(v) - case float64: - break - default: - continue } - if scan == _TIME { + switch scan { + case _TIME: t, err := r.tmRead.Decode(dest[i]) if err == nil { dest[i] = t - continue + } + case _BOOL: + switch dest[i] { + case int64(0): + dest[i] = false + case int64(1): + dest[i] = true } } } + r.dest = dest return nil } -func (r *rows) ScanColumn(dest any, index int) error { +func (r *rows) ScanColumn(dest any, index int) (err error) { // notest // Go 1.26 - var ptr *time.Time + var tm *time.Time + var ok *bool switch d := dest.(type) { case *time.Time: - ptr = d + tm = d case *sql.NullTime: - ptr = &d.Time + tm = &d.Time + ok = &d.Valid case *sql.Null[time.Time]: - ptr = &d.V + tm = &d.V + ok = &d.Valid default: return driver.ErrSkip } - if t := r.Stmt.ColumnTime(index, r.tmRead); !t.IsZero() { - *ptr = t - return nil + value := r.dest[index] + *tm, err = r.tmRead.Decode(value) + if ok != nil { + *ok = err == nil + if value == nil { + return nil + } } - return driver.ErrSkip + return err } diff --git a/vendor/github.com/ncruces/go-sqlite3/internal/util/json.go b/vendor/github.com/ncruces/go-sqlite3/internal/util/json.go index 846237405..f582734cf 100644 --- a/vendor/github.com/ncruces/go-sqlite3/internal/util/json.go +++ b/vendor/github.com/ncruces/go-sqlite3/internal/util/json.go @@ -1,3 +1,5 @@ +//go:build !goexperiment.jsonv2 + package util import ( diff --git a/vendor/github.com/ncruces/go-sqlite3/internal/util/json_v2.go b/vendor/github.com/ncruces/go-sqlite3/internal/util/json_v2.go new file mode 100644 index 000000000..2fb052233 --- /dev/null +++ b/vendor/github.com/ncruces/go-sqlite3/internal/util/json_v2.go @@ -0,0 +1,52 @@ +//go:build goexperiment.jsonv2 + +package util + +import ( + "encoding/json/v2" + "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/json.go b/vendor/github.com/ncruces/go-sqlite3/json.go index 2b762c092..78195f2e3 100644 --- a/vendor/github.com/ncruces/go-sqlite3/json.go +++ b/vendor/github.com/ncruces/go-sqlite3/json.go @@ -1,6 +1,13 @@ +//go:build !goexperiment.jsonv2 + package sqlite3 -import "github.com/ncruces/go-sqlite3/internal/util" +import ( + "encoding/json" + "strconv" + + "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 @@ -10,3 +17,77 @@ import "github.com/ncruces/go-sqlite3/internal/util" func JSON(value any) any { return util.JSON{Value: value} } + +// 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) { + err := json.NewEncoder(callbackWriter(func(p []byte) (int, error) { + ctx.ResultRawText(p[:len(p)-1]) // remove the newline + return 0, nil + })).Encode(value) + + if err != nil { + ctx.ResultError(err) + return // notest + } +} + +// 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 { + return json.NewEncoder(callbackWriter(func(p []byte) (int, error) { + return 0, s.BindRawText(param, p[:len(p)-1]) // remove the newline + })).Encode(value) +} + +// 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) +} + +// 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) +} + +type callbackWriter func(p []byte) (int, error) + +func (fn callbackWriter) Write(p []byte) (int, error) { return fn(p) } diff --git a/vendor/github.com/ncruces/go-sqlite3/json_v2.go b/vendor/github.com/ncruces/go-sqlite3/json_v2.go new file mode 100644 index 000000000..4b74bc7a4 --- /dev/null +++ b/vendor/github.com/ncruces/go-sqlite3/json_v2.go @@ -0,0 +1,113 @@ +//go:build goexperiment.jsonv2 + +package sqlite3 + +import ( + "encoding/json/v2" + "strconv" + + "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} +} + +// 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) { + w := bytesWriter{sqlite: ctx.c.sqlite} + if err := json.MarshalWrite(&w, value); err != nil { + ctx.c.free(w.ptr) + ctx.ResultError(err) + return // notest + } + ctx.c.call("sqlite3_result_text_go", + stk_t(ctx.handle), stk_t(w.ptr), stk_t(len(w.buf))) +} + +// 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 { + w := bytesWriter{sqlite: s.c.sqlite} + if err := json.MarshalWrite(&w, value); err != nil { + s.c.free(w.ptr) + return err + } + rc := res_t(s.c.call("sqlite3_bind_text_go", + stk_t(s.handle), stk_t(param), + stk_t(w.ptr), stk_t(len(w.buf)))) + return s.c.error(rc) +} + +// 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) +} + +// 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) +} + +type bytesWriter struct { + *sqlite + buf []byte + ptr ptr_t +} + +func (b *bytesWriter) Write(p []byte) (n int, err error) { + if len(p) > cap(b.buf)-len(b.buf) { + want := int64(len(b.buf)) + int64(len(p)) + grow := int64(cap(b.buf)) + grow += grow >> 1 + want = max(want, grow) + b.ptr = b.realloc(b.ptr, want) + b.buf = util.View(b.mod, b.ptr, want)[:len(b.buf)] + } + b.buf = append(b.buf, p...) + return len(p), nil +} diff --git a/vendor/github.com/ncruces/go-sqlite3/sqlite.go b/vendor/github.com/ncruces/go-sqlite3/sqlite.go index c05a86fde..fb64ac5c0 100644 --- a/vendor/github.com/ncruces/go-sqlite3/sqlite.go +++ b/vendor/github.com/ncruces/go-sqlite3/sqlite.go @@ -5,6 +5,7 @@ import ( "context" "math/bits" "os" + "strings" "sync" "unsafe" @@ -128,11 +129,10 @@ func (sqlt *sqlite) error(rc res_t, handle ptr_t, sql ...string) error { var msg, query string if ptr := ptr_t(sqlt.call("sqlite3_errmsg", stk_t(handle))); ptr != 0 { msg = util.ReadString(sqlt.mod, ptr, _MAX_LENGTH) - switch { - case msg == "not an error": - msg = "" - case msg == util.ErrorCodeString(uint32(rc))[len("sqlite3: "):]: + if msg == "not an error" { msg = "" + } else { + msg = strings.TrimPrefix(msg, util.ErrorCodeString(uint32(rc))[len("sqlite3: "):]) } } diff --git a/vendor/github.com/ncruces/go-sqlite3/stmt.go b/vendor/github.com/ncruces/go-sqlite3/stmt.go index 706182f9f..e2523b6cb 100644 --- a/vendor/github.com/ncruces/go-sqlite3/stmt.go +++ b/vendor/github.com/ncruces/go-sqlite3/stmt.go @@ -1,9 +1,7 @@ package sqlite3 import ( - "encoding/json" "math" - "strconv" "time" "github.com/ncruces/go-sqlite3/internal/util" @@ -362,16 +360,6 @@ func (s *Stmt) BindPointer(param int, ptr any) error { 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 { - return json.NewEncoder(callbackWriter(func(p []byte) (int, error) { - return 0, s.BindRawText(param, p[:len(p)-1]) // remove the newline - })).Encode(value) -} - // BindValue binds a copy of value to the prepared statement. // The leftmost SQL parameter has an index of 1. // @@ -598,30 +586,6 @@ func (s *Stmt) columnRawBytes(col int, ptr ptr_t, nul int32) []byte { return util.View(s.c.mod, ptr, int64(n+nul))[: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. // @@ -748,7 +712,3 @@ func (s *Stmt) columns(count int64) ([]byte, ptr_t, error) { return util.View(s.c.mod, typePtr, count), dataPtr, nil } - -type callbackWriter func(p []byte) (int, error) - -func (fn callbackWriter) Write(p []byte) (int, error) { return fn(p) } diff --git a/vendor/github.com/ncruces/go-sqlite3/time.go b/vendor/github.com/ncruces/go-sqlite3/time.go index d9c516c81..19bcd2b0b 100644 --- a/vendor/github.com/ncruces/go-sqlite3/time.go +++ b/vendor/github.com/ncruces/go-sqlite3/time.go @@ -94,7 +94,7 @@ func (f TimeFormat) Encode(t time.Time) any { case TimeFormatUnix: return t.Unix() case TimeFormatUnixFrac: - return float64(t.Unix()) + float64(t.Nanosecond())*1e-9 + return math.FMA(1e-9, float64(t.Nanosecond()), float64(t.Unix())) case TimeFormatUnixMilli: return t.UnixMilli() case TimeFormatUnixMicro: diff --git a/vendor/github.com/ncruces/go-sqlite3/value.go b/vendor/github.com/ncruces/go-sqlite3/value.go index 6806e9a79..994743f82 100644 --- a/vendor/github.com/ncruces/go-sqlite3/value.go +++ b/vendor/github.com/ncruces/go-sqlite3/value.go @@ -1,9 +1,7 @@ package sqlite3 import ( - "encoding/json" "math" - "strconv" "time" "github.com/ncruces/go-sqlite3/internal/util" @@ -162,27 +160,6 @@ func (v Value) Pointer() any { 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. // diff --git a/vendor/github.com/ncruces/go-sqlite3/vfs/const.go b/vendor/github.com/ncruces/go-sqlite3/vfs/const.go index 11afb1254..9ed67e385 100644 --- a/vendor/github.com/ncruces/go-sqlite3/vfs/const.go +++ b/vendor/github.com/ncruces/go-sqlite3/vfs/const.go @@ -94,6 +94,10 @@ const ( OPEN_PRIVATECACHE OpenFlag = 0x00040000 /* Ok for sqlite3_open_v2() */ OPEN_WAL OpenFlag = 0x00080000 /* VFS only */ OPEN_NOFOLLOW OpenFlag = 0x01000000 /* Ok for sqlite3_open_v2() */ + _FLAG_ATOMIC OpenFlag = 0x10000000 + _FLAG_KEEP_WAL OpenFlag = 0x20000000 + _FLAG_PSOW OpenFlag = 0x40000000 + _FLAG_SYNC_DIR OpenFlag = 0x80000000 ) // AccessFlag is a flag for the [VFS] Access method. diff --git a/vendor/github.com/ncruces/go-sqlite3/vfs/file.go b/vendor/github.com/ncruces/go-sqlite3/vfs/file.go index 06906c961..bdebdf6aa 100644 --- a/vendor/github.com/ncruces/go-sqlite3/vfs/file.go +++ b/vendor/github.com/ncruces/go-sqlite3/vfs/file.go @@ -51,7 +51,7 @@ func (vfsOS) Delete(path string, syncDir bool) error { return _OK } defer f.Close() - err = osSync(f, false, false) + err = osSync(f, 0, SYNC_FULL) if err != nil { return _IOERR_DIR_FSYNC } @@ -131,27 +131,24 @@ func (vfsOS) OpenFilename(name *Filename, flags OpenFlag) (File, OpenFlag, error } file := vfsFile{ - File: f, - psow: true, - atomic: osBatchAtomic(f), - readOnly: flags&OPEN_READONLY != 0, - syncDir: isUnix && isCreate && isJournl, - delete: !isUnix && flags&OPEN_DELETEONCLOSE != 0, - shm: NewSharedMemory(name.String()+"-shm", flags), + File: f, + flags: flags | _FLAG_PSOW, + shm: NewSharedMemory(name.String()+"-shm", flags), + } + if osBatchAtomic(f) { + file.flags |= _FLAG_ATOMIC + } + if isUnix && isCreate && isJournl { + file.flags |= _FLAG_SYNC_DIR } return &file, flags, nil } type vfsFile struct { *os.File - shm SharedMemory - lock LockLevel - readOnly bool - keepWAL bool - syncDir bool - atomic bool - delete bool - psow bool + shm SharedMemory + lock LockLevel + flags OpenFlag } var ( @@ -164,7 +161,7 @@ var ( ) func (f *vfsFile) Close() error { - if f.delete { + if !isUnix && f.flags&OPEN_DELETEONCLOSE != 0 { defer os.Remove(f.Name()) } if f.shm != nil { @@ -183,21 +180,18 @@ func (f *vfsFile) WriteAt(p []byte, off int64) (n int, err error) { } func (f *vfsFile) Sync(flags SyncFlag) error { - dataonly := (flags & SYNC_DATAONLY) != 0 - fullsync := (flags & 0x0f) == SYNC_FULL - - err := osSync(f.File, fullsync, dataonly) + err := osSync(f.File, f.flags, flags) if err != nil { return err } - if isUnix && f.syncDir { - f.syncDir = false + if isUnix && f.flags&_FLAG_SYNC_DIR != 0 { + f.flags ^= _FLAG_SYNC_DIR d, err := os.Open(filepath.Dir(f.File.Name())) if err != nil { return nil } defer d.Close() - err = osSync(d, false, false) + err = osSync(f.File, f.flags, flags) if err != nil { return _IOERR_DIR_FSYNC } @@ -215,10 +209,10 @@ func (f *vfsFile) SectorSize() int { func (f *vfsFile) DeviceCharacteristics() DeviceCharacteristic { ret := IOCAP_SUBPAGE_READ - if f.atomic { + if f.flags&_FLAG_ATOMIC != 0 { ret |= IOCAP_BATCH_ATOMIC } - if f.psow { + if f.flags&_FLAG_PSOW != 0 { ret |= IOCAP_POWERSAFE_OVERWRITE } if runtime.GOOS == "windows" { @@ -249,8 +243,20 @@ func (f *vfsFile) HasMoved() (bool, error) { 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 } +func (f *vfsFile) LockState() LockLevel { return f.lock } +func (f *vfsFile) PowersafeOverwrite() bool { return f.flags&_FLAG_PSOW != 0 } +func (f *vfsFile) PersistWAL() bool { return f.flags&_FLAG_KEEP_WAL != 0 } + +func (f *vfsFile) SetPowersafeOverwrite(psow bool) { + f.flags &^= _FLAG_PSOW + if psow { + f.flags |= _FLAG_PSOW + } +} + +func (f *vfsFile) SetPersistWAL(keepWAL bool) { + f.flags &^= _FLAG_KEEP_WAL + if keepWAL { + f.flags |= _FLAG_KEEP_WAL + } +} diff --git a/vendor/github.com/ncruces/go-sqlite3/vfs/lock.go b/vendor/github.com/ncruces/go-sqlite3/vfs/lock.go index b28d83230..253057aea 100644 --- a/vendor/github.com/ncruces/go-sqlite3/vfs/lock.go +++ b/vendor/github.com/ncruces/go-sqlite3/vfs/lock.go @@ -41,7 +41,7 @@ func (f *vfsFile) Lock(lock LockLevel) error { } // Do not allow any kind of write-lock on a read-only database. - if f.readOnly && lock >= LOCK_RESERVED { + if lock >= LOCK_RESERVED && f.flags&OPEN_READONLY != 0 { return _IOERR_LOCK } diff --git a/vendor/github.com/ncruces/go-sqlite3/vfs/memdb/README.md b/vendor/github.com/ncruces/go-sqlite3/vfs/memdb/README.md index 2e2611bf8..e37db1be6 100644 --- a/vendor/github.com/ncruces/go-sqlite3/vfs/memdb/README.md +++ b/vendor/github.com/ncruces/go-sqlite3/vfs/memdb/README.md @@ -6,4 +6,7 @@ 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 +- reader-writer concurrency is slightly improved. + +[`memdb.TestDB`](https://pkg.go.dev/github.com/ncruces/go-sqlite3/vfs/memdb#TestDB) +is the preferred way to setup an in-memory database for testing.
\ 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 index eb12eba09..a12819855 100644 --- a/vendor/github.com/ncruces/go-sqlite3/vfs/memdb/api.go +++ b/vendor/github.com/ncruces/go-sqlite3/vfs/memdb/api.go @@ -10,6 +10,7 @@ package memdb import ( + "crypto/rand" "fmt" "net/url" "sync" @@ -74,11 +75,27 @@ func Delete(name string) { // 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. +// Returns a URI filename appropriate to call Open with. // Each subsequent call to TestDB returns a unique database. +// +// func Test_something(t *testing.T) { +// t.Parallel() +// dsn := memdb.TestDB(t, url.Values{ +// "_pragma": {"busy_timeout(1000)"}, +// }) +// +// db, err := sql.Open("sqlite3", dsn) +// if err != nil { +// t.Fatal(err) +// } +// defer db.Close() +// +// // ... +// } func TestDB(tb testing.TB, params ...url.Values) string { tb.Helper() - name := fmt.Sprintf("%s_%p", tb.Name(), tb) + name := fmt.Sprintf("%s_%s", tb.Name(), rand.Text()) tb.Cleanup(func() { Delete(name) }) Create(name, nil) diff --git a/vendor/github.com/ncruces/go-sqlite3/vfs/os_darwin.go b/vendor/github.com/ncruces/go-sqlite3/vfs/os_darwin.go index ee08e9a7b..9bb8b559c 100644 --- a/vendor/github.com/ncruces/go-sqlite3/vfs/os_darwin.go +++ b/vendor/github.com/ncruces/go-sqlite3/vfs/os_darwin.go @@ -23,12 +23,26 @@ type flocktimeout_t struct { timeout unix.Timespec } -func osSync(file *os.File, fullsync, _ /*dataonly*/ bool) error { - if fullsync { - return file.Sync() +func osSync(file *os.File, open OpenFlag, sync SyncFlag) error { + var cmd int + if sync&SYNC_FULL == SYNC_FULL { + // For rollback journals all we really need is a barrier. + if open&OPEN_MAIN_JOURNAL != 0 { + cmd = unix.F_BARRIERFSYNC + } else { + cmd = unix.F_FULLFSYNC + } } + + fd := file.Fd() for { - err := unix.Fsync(int(file.Fd())) + err := error(unix.ENOTSUP) + if cmd != 0 { + _, err = unix.FcntlInt(fd, cmd, 0) + } + if err == unix.ENOTSUP { + err = unix.Fsync(int(fd)) + } if err != unix.EINTR { return err } diff --git a/vendor/github.com/ncruces/go-sqlite3/vfs/os_linux.go b/vendor/github.com/ncruces/go-sqlite3/vfs/os_linux.go index d112c5a99..893f1512c 100644 --- a/vendor/github.com/ncruces/go-sqlite3/vfs/os_linux.go +++ b/vendor/github.com/ncruces/go-sqlite3/vfs/os_linux.go @@ -10,7 +10,7 @@ import ( "golang.org/x/sys/unix" ) -func osSync(file *os.File, _ /*fullsync*/, _ /*dataonly*/ bool) error { +func osSync(file *os.File, _ OpenFlag, _ SyncFlag) error { // SQLite trusts Linux's fdatasync for all fsync's. for { err := unix.Fdatasync(int(file.Fd())) 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 index b32e83e08..87427d9ed 100644 --- a/vendor/github.com/ncruces/go-sqlite3/vfs/os_std_sync.go +++ b/vendor/github.com/ncruces/go-sqlite3/vfs/os_std_sync.go @@ -4,6 +4,6 @@ package vfs import "os" -func osSync(file *os.File, _ /*fullsync*/, _ /*dataonly*/ bool) error { +func osSync(file *os.File, _ OpenFlag, _ SyncFlag) error { return file.Sync() } |
