mirror of
https://github.com/superseriousbusiness/gotosocial.git
synced 2025-10-29 11:22:25 -05:00
[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>
This commit is contained in:
parent
e7cd8bb43e
commit
ff950e94bb
32 changed files with 706 additions and 317 deletions
27
vendor/github.com/ncruces/go-sqlite3/conn.go
generated
vendored
27
vendor/github.com/ncruces/go-sqlite3/conn.go
generated
vendored
|
|
@ -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),
|
||||
|
|
|
|||
16
vendor/github.com/ncruces/go-sqlite3/context.go
generated
vendored
16
vendor/github.com/ncruces/go-sqlite3/context.go
generated
vendored
|
|
@ -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
|
||||
|
|
|
|||
107
vendor/github.com/ncruces/go-sqlite3/driver/driver.go
generated
vendored
107
vendor/github.com/ncruces/go-sqlite3/driver/driver.go
generated
vendored
|
|
@ -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
|
||||
}
|
||||
|
|
|
|||
2
vendor/github.com/ncruces/go-sqlite3/internal/util/json.go
generated
vendored
2
vendor/github.com/ncruces/go-sqlite3/internal/util/json.go
generated
vendored
|
|
@ -1,3 +1,5 @@
|
|||
//go:build !goexperiment.jsonv2
|
||||
|
||||
package util
|
||||
|
||||
import (
|
||||
|
|
|
|||
52
vendor/github.com/ncruces/go-sqlite3/internal/util/json_v2.go
generated
vendored
Normal file
52
vendor/github.com/ncruces/go-sqlite3/internal/util/json_v2.go
generated
vendored
Normal file
|
|
@ -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
|
||||
}
|
||||
83
vendor/github.com/ncruces/go-sqlite3/json.go
generated
vendored
83
vendor/github.com/ncruces/go-sqlite3/json.go
generated
vendored
|
|
@ -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) }
|
||||
|
|
|
|||
113
vendor/github.com/ncruces/go-sqlite3/json_v2.go
generated
vendored
Normal file
113
vendor/github.com/ncruces/go-sqlite3/json_v2.go
generated
vendored
Normal file
|
|
@ -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
|
||||
}
|
||||
8
vendor/github.com/ncruces/go-sqlite3/sqlite.go
generated
vendored
8
vendor/github.com/ncruces/go-sqlite3/sqlite.go
generated
vendored
|
|
@ -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: "):])
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
40
vendor/github.com/ncruces/go-sqlite3/stmt.go
generated
vendored
40
vendor/github.com/ncruces/go-sqlite3/stmt.go
generated
vendored
|
|
@ -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) }
|
||||
|
|
|
|||
2
vendor/github.com/ncruces/go-sqlite3/time.go
generated
vendored
2
vendor/github.com/ncruces/go-sqlite3/time.go
generated
vendored
|
|
@ -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:
|
||||
|
|
|
|||
23
vendor/github.com/ncruces/go-sqlite3/value.go
generated
vendored
23
vendor/github.com/ncruces/go-sqlite3/value.go
generated
vendored
|
|
@ -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.
|
||||
//
|
||||
|
|
|
|||
4
vendor/github.com/ncruces/go-sqlite3/vfs/const.go
generated
vendored
4
vendor/github.com/ncruces/go-sqlite3/vfs/const.go
generated
vendored
|
|
@ -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.
|
||||
|
|
|
|||
68
vendor/github.com/ncruces/go-sqlite3/vfs/file.go
generated
vendored
68
vendor/github.com/ncruces/go-sqlite3/vfs/file.go
generated
vendored
|
|
@ -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
|
||||
}
|
||||
}
|
||||
|
|
|
|||
2
vendor/github.com/ncruces/go-sqlite3/vfs/lock.go
generated
vendored
2
vendor/github.com/ncruces/go-sqlite3/vfs/lock.go
generated
vendored
|
|
@ -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
|
||||
}
|
||||
|
||||
|
|
|
|||
5
vendor/github.com/ncruces/go-sqlite3/vfs/memdb/README.md
generated
vendored
5
vendor/github.com/ncruces/go-sqlite3/vfs/memdb/README.md
generated
vendored
|
|
@ -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.
|
||||
- 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.
|
||||
19
vendor/github.com/ncruces/go-sqlite3/vfs/memdb/api.go
generated
vendored
19
vendor/github.com/ncruces/go-sqlite3/vfs/memdb/api.go
generated
vendored
|
|
@ -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)
|
||||
|
||||
|
|
|
|||
22
vendor/github.com/ncruces/go-sqlite3/vfs/os_darwin.go
generated
vendored
22
vendor/github.com/ncruces/go-sqlite3/vfs/os_darwin.go
generated
vendored
|
|
@ -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
|
||||
}
|
||||
|
|
|
|||
2
vendor/github.com/ncruces/go-sqlite3/vfs/os_linux.go
generated
vendored
2
vendor/github.com/ncruces/go-sqlite3/vfs/os_linux.go
generated
vendored
|
|
@ -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()))
|
||||
|
|
|
|||
2
vendor/github.com/ncruces/go-sqlite3/vfs/os_std_sync.go
generated
vendored
2
vendor/github.com/ncruces/go-sqlite3/vfs/os_std_sync.go
generated
vendored
|
|
@ -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()
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue