SQLite 3.51.3.

This commit is contained in:
Nuno Cruces
2026-03-18 17:56:27 +00:00
parent 1008ddc5cb
commit 361fdc52fa
24 changed files with 73 additions and 68 deletions
+3 -3
View File
@@ -112,7 +112,7 @@ func (b *Blob) Read(p []byte) (n int, err error) {
err = io.EOF
}
copy(p, b.c.wrp.Slice(b.bufptr, want))
copy(p, b.c.wrp.Bytes(b.bufptr, want))
return int(want), err
}
@@ -142,7 +142,7 @@ func (b *Blob) WriteTo(w io.Writer) (n int64, err error) {
return n, err
}
mem := b.c.wrp.Slice(b.bufptr, want)
mem := b.c.wrp.Bytes(b.bufptr, want)
m, err := w.Write(mem[:want])
b.offset += int64(m)
n += int64(m)
@@ -204,7 +204,7 @@ func (b *Blob) ReadFrom(r io.Reader) (n int64, err error) {
}
for {
mem := b.c.wrp.Slice(b.bufptr, want)
mem := b.c.wrp.Bytes(b.bufptr, want)
m, err := r.Read(mem[:want])
if m > 0 {
rc := res_t(b.c.wrp.Xsqlite3_blob_write(int32(b.handle),
+3 -2
View File
@@ -180,7 +180,7 @@ const (
PREPARE_NORMALIZE PrepareFlag = 0x02
PREPARE_NO_VTAB PrepareFlag = 0x04
PREPARE_DONT_LOG PrepareFlag = 0x10
PREPARE_FROM_DDL PrepareFlag = 0x20
// PREPARE_FROM_DDL PrepareFlag = 0x20
)
// FunctionFlag is a flag that can be passed to
@@ -267,6 +267,7 @@ const (
DBCONFIG_ENABLE_ATTACH_CREATE DBConfig = 1020
DBCONFIG_ENABLE_ATTACH_WRITE DBConfig = 1021
DBCONFIG_ENABLE_COMMENTS DBConfig = 1022
// SQLITE_DBCONFIG_FP_DIGITS DBConfig = 1023
// DBCONFIG_MAX DBConfig = 1022
)
@@ -308,7 +309,7 @@ const (
LIMIT_VARIABLE_NUMBER LimitCategory = 9
LIMIT_TRIGGER_DEPTH LimitCategory = 10
LIMIT_WORKER_THREADS LimitCategory = 11
LIMIT_PARSER_DEPTH LimitCategory = 12
// LIMIT_PARSER_DEPTH LimitCategory = 12
)
// AuthorizerActionCode are the integer action codes
+1 -1
View File
@@ -146,7 +146,7 @@ func (ctx Context) ResultTime(value time.Time, format TimeFormat) {
func (ctx Context) resultRFC3339Nano(value time.Time) {
const maxlen = 48
ptr := ctx.c.wrp.New(maxlen)
buf := ctx.c.wrp.Slice(ptr, maxlen)
buf := ctx.c.wrp.Bytes(ptr, maxlen)
buf = value.AppendFormat(buf[:0], time.RFC3339Nano)
_ = append(buf, 0)
+4 -4
View File
@@ -43,7 +43,7 @@ func declare(db *sqlite3.Conn, _, _, _ string, arg ...string) (ret *table, err e
// Row key query.
t.scan = "SELECT * FROM\n" + arg[0]
stmt, tail, err := db.PrepareFlags(t.scan, sqlite3.PREPARE_FROM_DDL)
stmt, tail, err := db.PrepareFlags(t.scan, 0 /*PREPARE_FROM_DDL*/)
if err != nil {
return nil, err
}
@@ -65,7 +65,7 @@ func declare(db *sqlite3.Conn, _, _, _ string, arg ...string) (ret *table, err e
stmt.Close()
// Column definition query.
stmt, tail, err = db.PrepareFlags("SELECT * FROM\n"+arg[1], sqlite3.PREPARE_FROM_DDL)
stmt, tail, err = db.PrepareFlags("SELECT * FROM\n"+arg[1], 0 /*PREPARE_FROM_DDL*/)
if err != nil {
return nil, err
}
@@ -89,7 +89,7 @@ func declare(db *sqlite3.Conn, _, _, _ string, arg ...string) (ret *table, err e
// Pivot cell query.
t.cell = "SELECT * FROM\n" + arg[2]
stmt, tail, err = db.PrepareFlags(t.cell, sqlite3.PREPARE_FROM_DDL)
stmt, tail, err = db.PrepareFlags(t.cell, 0 /*PREPARE_FROM_DDL*/)
if err != nil {
return nil, err
}
@@ -196,7 +196,7 @@ func (c *cursor) Filter(idxNum int, idxStr string, arg ...sqlite3.Value) error {
return err
}
const prepflags = sqlite3.PREPARE_DONT_LOG | sqlite3.PREPARE_FROM_DDL
const prepflags = sqlite3.PREPARE_DONT_LOG /*PREPARE_FROM_DDL*/
c.scan, _, err = c.table.db.PrepareFlags(idxStr, prepflags)
if err != nil {
+2 -2
View File
@@ -36,7 +36,7 @@ func declare(db *sqlite3.Conn, _, _, _ string, arg ...string) (*table, error) {
sql := "SELECT * FROM\n" + arg[0]
stmt, tail, err := db.PrepareFlags(sql,
sqlite3.PREPARE_PERSISTENT|sqlite3.PREPARE_FROM_DDL)
sqlite3.PREPARE_PERSISTENT /*PREPARE_FROM_DDL*/)
if err != nil {
return nil, err
}
@@ -135,7 +135,7 @@ func (t *table) Open() (_ sqlite3.VTabCursor, err error) {
t.inuse = true
} else {
stmt, _, err = t.stmt.Conn().PrepareFlags(t.sql,
sqlite3.PREPARE_DONT_LOG|sqlite3.PREPARE_FROM_DDL)
sqlite3.PREPARE_DONT_LOG /*PREPARE_FROM_DDL*/)
if err != nil {
return nil, err
}
+2 -2
View File
@@ -189,8 +189,8 @@ func (e *env) Xgo_collation_needed(pArg, pDB, eTextRep, zName int32) {
func (e *env) Xgo_compare(pApp, nKey1, pKey1, nKey2, pKey2 int32) int32 {
fn := e.GetHandle(ptr_t(pApp)).(CollatingFunction)
return int32(fn(
e.Slice(ptr_t(pKey1), int64(nKey1)),
e.Slice(ptr_t(pKey2), int64(nKey2))))
e.Bytes(ptr_t(pKey1), int64(nKey1)),
e.Bytes(ptr_t(pKey2), int64(nKey2))))
}
func (e *env) Xgo_func(pCtx, pApp, nArg, pArg int32) {
+2 -2
View File
@@ -1,9 +1,9 @@
module github.com/ncruces/go-sqlite3
go 1.24.0
go 1.26.0
require (
github.com/ncruces/go-sqlite3-wasm v0.0.0-20260312160048-b96020e92601
github.com/ncruces/go-sqlite3-wasm v1.0.1-0.20260318174050-59cb2401d3ff
github.com/ncruces/julianday v1.0.0
github.com/ncruces/sort v0.1.6
github.com/ncruces/wbt v1.0.0
+2 -2
View File
@@ -2,8 +2,8 @@ github.com/dchest/siphash v1.2.3 h1:QXwFc8cFOR2dSa/gE6o/HokBMWtLUaNDVd+22aKHeEA=
github.com/dchest/siphash v1.2.3/go.mod h1:0NvQU092bT0ipiFN++/rXm69QG9tVxLAlQHIXMPAkHc=
github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0=
github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/ncruces/go-sqlite3-wasm v0.0.0-20260312160048-b96020e92601 h1:XHbLfN7k+bFuWz9OWfZVert0feJUAs/ngRewsn3EW4I=
github.com/ncruces/go-sqlite3-wasm v0.0.0-20260312160048-b96020e92601/go.mod h1:CLtq3B4C0mgdclnRUUkn4pLYYo1MsugQNXWjjAIxoPo=
github.com/ncruces/go-sqlite3-wasm v1.0.1-0.20260318174050-59cb2401d3ff h1:jabe/IWMvK2glihBo1hWsF4Cz+wsZ4YJq9W9pQPX8wI=
github.com/ncruces/go-sqlite3-wasm v1.0.1-0.20260318174050-59cb2401d3ff/go.mod h1:gaCJnWv69r9BPn0w7jAYg/CUht+PnTK8IIMB1K5C1uw=
github.com/ncruces/julianday v1.0.0 h1:fH0OKwa7NWvniGQtxdJRxAgkBMolni2BjDHaWTxqt7M=
github.com/ncruces/julianday v1.0.0/go.mod h1:Dusn2KvZrrovOMJuOt0TNXL6tB7U2E8kvza5fFc9G7g=
github.com/ncruces/sort v0.1.6 h1:TrsJfGRH1AoWoaeB4/+gCohot9+cA6u/INaH5agIhNk=
+5 -5
View File
@@ -18,7 +18,7 @@ type (
Res_t int32
)
func (mem *Memory) Slice(ptr Ptr_t, size int64) []byte {
func (mem *Memory) Bytes(ptr Ptr_t, size int64) []byte {
if ptr == 0 {
panic(errutil.NilErr)
}
@@ -98,19 +98,19 @@ func (mem *Memory) ReadString(ptr Ptr_t, maxlen int64) string {
if int64(len(buf)) > maxlen {
buf = buf[:maxlen]
}
if i := bytes.IndexByte(buf, 0); i >= 0 {
return string(buf[:i])
if before, _, ok := bytes.Cut(buf, []byte{0}); ok {
return string(before)
}
panic(errutil.NoNulErr)
}
func (mem *Memory) WriteBytes(ptr Ptr_t, b []byte) {
buf := mem.Slice(ptr, int64(len(b)))
buf := mem.Bytes(ptr, int64(len(b)))
copy(buf, b)
}
func (mem *Memory) WriteString(ptr Ptr_t, s string) {
buf := mem.Slice(ptr, int64(len(s))+1)
buf := mem.Bytes(ptr, int64(len(s))+1)
buf[len(s)] = 0
copy(buf, s)
}
+4 -4
View File
@@ -4,16 +4,16 @@ package sqlite3_wrap
type Memory struct {
Buf []byte
Max int32
Max int64
}
func (m *Memory) Data() *[]byte {
func (m *Memory) Slice() *[]byte {
return &m.Buf
}
func (m *Memory) Grow(delta, _ int32) int32 {
func (m *Memory) Grow(delta, _ int64) int64 {
len := len(m.Buf)
old := int32(len >> 16)
old := int64(len >> 16)
if delta == 0 {
return old
}
+4 -4
View File
@@ -10,21 +10,21 @@ import (
type Memory struct {
Buf []byte
Max int32
Max int64
com int
}
func (m *Memory) Data() *[]byte {
func (m *Memory) Slice() *[]byte {
return &m.Buf
}
func (m *Memory) Grow(delta, _ int32) int32 {
func (m *Memory) Grow(delta, _ int64) int64 {
if m.Buf == nil {
m.allocate(uint64(m.Max) << 16)
}
len := len(m.Buf)
old := int32(len >> 16)
old := int64(len >> 16)
if delta == 0 {
return old
}
+4 -4
View File
@@ -10,22 +10,22 @@ import (
type Memory struct {
Buf []byte
Max int32
Max int64
com int
ptr uintptr
}
func (m *Memory) Data() *[]byte {
func (m *Memory) Slice() *[]byte {
return &m.Buf
}
func (m *Memory) Grow(delta, _ int32) int32 {
func (m *Memory) Grow(delta, _ int64) int64 {
if m.Buf == nil {
m.allocate(uint64(m.Max) << 16)
}
len := len(m.Buf)
old := int32(len >> 16)
old := int64(len >> 16)
if delta == 0 {
return old
}
+1 -1
View File
@@ -38,7 +38,7 @@ func (w *Wrapper) newRegion(size int32) *MappedRegion {
}
// Save the newly allocated region.
buf := w.Slice(ptr, int64(size))
buf := w.Bytes(ptr, int64(size))
ret := &MappedRegion{
Ptr: ptr,
size: size,
+1 -1
View File
@@ -108,7 +108,7 @@ func (b *bytesWriter) Write(p []byte) (n int, err error) {
grow += grow >> 1
want = max(want, grow)
b.ptr = b.wrp.Realloc(b.ptr, want)
b.buf = b.wrp.Slice(b.ptr, want)[:len(b.buf)]
b.buf = b.wrp.Bytes(b.ptr, want)[:len(b.buf)]
}
b.buf = append(b.buf, p...)
_ = append(b.buf, 0)
+6 -6
View File
@@ -325,7 +325,7 @@ func (s *Stmt) BindTime(param int, value time.Time, format TimeFormat) error {
func (s *Stmt) bindRFC3339Nano(param int, value time.Time) error {
const maxlen = 48
ptr := s.c.wrp.New(maxlen)
buf := s.c.wrp.Slice(ptr, maxlen)
buf := s.c.wrp.Bytes(ptr, maxlen)
buf = value.AppendFormat(buf[:0], time.RFC3339Nano)
_ = append(buf, 0)
@@ -570,7 +570,7 @@ func (s *Stmt) columnRawBytes(col int, ptr ptr_t, nul int32) []byte {
n := int32(s.c.wrp.Xsqlite3_column_bytes(
int32(s.handle), int32(col)))
return s.c.wrp.Slice(ptr, int64(n+nul))[:n]
return s.c.wrp.Bytes(ptr, int64(n+nul))[:n]
}
// ColumnValue returns the unprotected value of the result column.
@@ -617,7 +617,7 @@ func (s *Stmt) Columns(dest ...any) error {
len := int32(mem.Read32(ptr + 4))
if len != 0 {
ptr := ptr_t(mem.Read32(ptr))
buf := mem.Slice(ptr, int64(len))
buf := mem.Bytes(ptr, int64(len))
dest[i] = string(buf)
} else {
dest[i] = ""
@@ -626,7 +626,7 @@ func (s *Stmt) Columns(dest ...any) error {
len := int32(mem.Read32(ptr + 4))
if len != 0 {
ptr := ptr_t(mem.Read32(ptr))
buf := mem.Slice(ptr, int64(len))
buf := mem.Bytes(ptr, int64(len))
tmp, _ := dest[i].([]byte)
dest[i] = append(tmp[:0], buf...)
} else {
@@ -677,7 +677,7 @@ func (s *Stmt) ColumnsRaw(dest ...any) error {
cap++
}
ptr := ptr_t(mem.Read32(ptr))
buf := mem.Slice(ptr, int64(cap))[:len]
buf := mem.Bytes(ptr, int64(cap))[:len]
dest[i] = buf
}
}
@@ -699,5 +699,5 @@ func (s *Stmt) columns(count int64) ([]byte, ptr_t, error) {
return nil, 0, err
}
return s.c.wrp.Slice(typePtr, count), dataPtr, nil
return s.c.wrp.Bytes(typePtr, count), dataPtr, nil
}
+4 -2
View File
@@ -1,9 +1,11 @@
package tests
import (
"bytes"
"encoding/json"
"math"
"math/bits"
"strings"
"testing"
"time"
@@ -269,10 +271,10 @@ func TestStmt(t *testing.T) {
if got := stmt.ColumnFloat(0); got != math.Pi {
t.Errorf("got %v, want π", got)
}
if got := stmt.ColumnText(0); got != "3.1415926535897931" {
if got := stmt.ColumnText(0); !strings.HasPrefix(got, "3.14159265358979") {
t.Errorf("got %q, want π", got)
}
if got := stmt.ColumnBlob(0, nil); string(got) != "3.1415926535897931" {
if got := stmt.ColumnBlob(0, nil); !bytes.HasPrefix(got, []byte("3.14159265358979")) {
t.Errorf("got %q, want π", got)
}
var got float64
+8 -7
View File
@@ -16,12 +16,13 @@ import (
// [ALTER TABLE]: https://sqlite.org/lang_altertable.html
func ParseTable(sql string) (_ *Table, err error) {
mod := parser.New()
errp := mod.Xmalloc(4)
mem := mod.Xmemory().Slice()
sqlp := mod.Xmalloc(int32(len(sql) + 1))
copy(mod.Memory[sqlp:], sql)
errp := mod.Xmalloc(4)
copy((*mem)[sqlp:], sql)
res := mod.Xsql3parse_table(sqlp, int32(len(sql)), errp)
c := binary.LittleEndian.Uint32(mod.Memory[errp:])
c := binary.LittleEndian.Uint32((*mem)[errp:])
switch c {
case _MEMORY:
panic(errutil.OOMErr)
@@ -32,7 +33,7 @@ func ParseTable(sql string) (_ *Table, err error) {
}
var tab Table
tab.load(mod.Memory, uint32(res), uint32(sqlp), sql)
tab.load(*mem, uint32(res), uint32(sqlp), sql)
return &tab, nil
}
@@ -306,10 +307,10 @@ func loadBool(mem []byte, ptr uint32) bool {
return val != 0
}
type libc struct{ *parser.Module }
type libc struct{ memory *[]byte }
func (l *libc) Init(m *parser.Module) { l.Module = m }
func (l *libc) Init(m *parser.Module) { l.memory = m.Xmemory().Slice() }
func (l *libc) Xstrlen(v0 int32) int32 {
return int32(bytes.IndexByte(l.Memory[v0:], 0))
return int32(bytes.IndexByte((*l.memory)[v0:], 0))
}
+1 -1
View File
@@ -148,7 +148,7 @@ func (v Value) rawBytes(ptr ptr_t, nul int32) []byte {
}
n := int32(v.c.wrp.Xsqlite3_value_bytes(int32(v.handle)))
return v.c.wrp.Slice(ptr, int64(n+nul))[:n]
return v.c.wrp.Bytes(ptr, int64(n+nul))[:n]
}
// Pointer gets the pointer associated with this value,
+3 -3
View File
@@ -40,7 +40,7 @@ func (s *vfsShm) shmAcquire(errp *error) {
for id, p := range s.ptrs {
shared := shmPage(s.shared[id][:])
shadow := shmPage(s.shadow[id][:])
privat := shmPage(s.wrp.Slice(p, _WALINDEX_PGSZ))
privat := shmPage(s.wrp.Bytes(p, _WALINDEX_PGSZ))
for i, shared := range shared {
if shadow[i] != shared {
shadow[i] = shared
@@ -51,14 +51,14 @@ func (s *vfsShm) shmAcquire(errp *error) {
}
func (s *vfsShm) shmRelease() {
if len(s.ptrs) == 0 || shmEqual(s.shadow[0][:], s.wrp.Slice(s.ptrs[0], _WALINDEX_HDR_SIZE)) {
if len(s.ptrs) == 0 || shmEqual(s.shadow[0][:], s.wrp.Bytes(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(s.wrp.Slice(p, _WALINDEX_PGSZ))
privat := shmPage(s.wrp.Bytes(p, _WALINDEX_PGSZ))
for i, privat := range privat {
if shadow[i] != privat {
shadow[i] = privat
+1 -1
View File
@@ -125,7 +125,7 @@ func (s *vfsShm) shmMap(wrp *sqlite3_wrap.Wrapper, id, size int32, extend bool)
if ptr == 0 {
panic(errutil.OOMErr)
}
clear(wrp.Slice(ptr_t(ptr), _WALINDEX_PGSZ))
clear(wrp.Bytes(ptr_t(ptr), _WALINDEX_PGSZ))
s.ptrs = append(s.ptrs, ptr_t(ptr))
}
+1 -1
View File
@@ -111,7 +111,7 @@ func (s *vfsShm) shmMap(wrp *sqlite3_wrap.Wrapper, id, size int32, extend bool)
if ptr == 0 {
panic(errutil.OOMErr)
}
clear(wrp.Slice(ptr_t(ptr), _WALINDEX_PGSZ))
clear(wrp.Bytes(ptr_t(ptr), _WALINDEX_PGSZ))
s.ptrs = append(s.ptrs, ptr_t(ptr))
}
+2 -2
View File
@@ -86,7 +86,7 @@ func vfsClose(wrp *sqlite3_wrap.Wrapper, pFile ptr_t) _ErrorCode {
//go:linkname vfsRead
func vfsRead(wrp *sqlite3_wrap.Wrapper, pFile, zBuf ptr_t, iAmt int32, iOfst int64) _ErrorCode {
file := vfsFileGet(wrp, pFile).(File)
buf := wrp.Slice(zBuf, int64(iAmt))
buf := wrp.Bytes(zBuf, int64(iAmt))
n, err := file.ReadAt(buf, iOfst)
if n == int(iAmt) {
@@ -102,7 +102,7 @@ func vfsRead(wrp *sqlite3_wrap.Wrapper, pFile, zBuf ptr_t, iAmt int32, iOfst int
//go:linkname vfsWrite
func vfsWrite(wrp *sqlite3_wrap.Wrapper, pFile, zBuf ptr_t, iAmt int32, iOfst int64) _ErrorCode {
file := vfsFileGet(wrp, pFile).(File)
buf := wrp.Slice(zBuf, int64(iAmt))
buf := wrp.Bytes(zBuf, int64(iAmt))
_, err := file.WriteAt(buf, iOfst)
return vfsErrorCode(wrp, err, _IOERR_WRITE)
+6 -5
View File
@@ -25,7 +25,7 @@ func WithMaxMemory(ctx context.Context, max int64) context.Context {
if max < 0 || max > 65536*65536 {
panic(errutil.OOMErr)
}
return context.WithValue(ctx, configKey{}, int32(max/65536))
return context.WithValue(ctx, configKey{}, max/65536)
}
var _ sqlite3_wasm.Xenv = &env{}
@@ -37,16 +37,17 @@ func createWrapper(ctx context.Context) (*sqlite3_wrap.Wrapper, error) {
if bits.UintSize < 64 {
mem.Max = 512 // 32MB
}
if max, ok := ctx.Value(configKey{}).(int32); ok {
if max, ok := ctx.Value(configKey{}).(int64); ok {
mem.Max = max
}
mem.Grow(5, mem.Max) // 320KB
env := &env{&sqlite3_wrap.Wrapper{Memory: mem}}
sqlite3_wasm.New(mem, env)
env.Module = sqlite3_wasm.New(env)
env.X_initialize()
return env.Wrapper, nil
}
func (e *env) Init(m *sqlite3_wasm.Module) { e.Module = m }
func (e *env) Xmemory() sqlite3_wasm.Memory { return e.Memory }
// Math functions.
@@ -199,7 +200,7 @@ func (e *env) Xstrcpy(d, s int32) int32 {
// VFS functions.
func (e *env) Xgo_randomness(pVfs, nByte, zByte int32) int32 {
mem := e.Slice(ptr_t(zByte), int64(nByte))
mem := e.Bytes(ptr_t(zByte), int64(nByte))
n, _ := rand.Reader.Read(mem)
return int32(n)
}
+3 -3
View File
@@ -61,7 +61,7 @@ func Test_sqlite_newArena(t *testing.T) {
if ptr == 0 {
t.Fatalf("got nullptr")
}
if got := wrp.Slice(ptr, int64(len(title))); string(got) != title {
if got := wrp.Bytes(ptr, int64(len(title))); string(got) != title {
t.Errorf("got %q, want %q", got, title)
}
@@ -89,7 +89,7 @@ func Test_sqlite_newBytes(t *testing.T) {
}
want := buf
if got := wrp.Slice(ptr, int64(len(want))); !bytes.Equal(got, want) {
if got := wrp.Bytes(ptr, int64(len(want))); !bytes.Equal(got, want) {
t.Errorf("got %q, want %q", got, want)
}
}
@@ -115,7 +115,7 @@ func Test_sqlite_newString(t *testing.T) {
}
want := str + "\000"
if got := wrp.Slice(ptr, int64(len(want))); string(got) != want {
if got := wrp.Bytes(ptr, int64(len(want))); string(got) != want {
t.Errorf("got %q, want %q", got, want)
}
}