[chore] bump ncruces go-sqlite3 => v0.23.0 (#3785)

* bump ncruces go-sqlite3 => v0.23.0

* whoops, add missing vendor changes...
This commit is contained in:
kim 2025-02-13 08:53:40 +00:00 committed by GitHub
parent fccb0bc102
commit 24f6760c0e
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
40 changed files with 836 additions and 833 deletions

2
go.mod
View file

@ -48,7 +48,7 @@ require (
github.com/miekg/dns v1.1.63 github.com/miekg/dns v1.1.63
github.com/minio/minio-go/v7 v7.0.85 github.com/minio/minio-go/v7 v7.0.85
github.com/mitchellh/mapstructure v1.5.0 github.com/mitchellh/mapstructure v1.5.0
github.com/ncruces/go-sqlite3 v0.22.0 github.com/ncruces/go-sqlite3 v0.23.0
github.com/oklog/ulid v1.3.1 github.com/oklog/ulid v1.3.1
github.com/prometheus/client_golang v1.20.5 github.com/prometheus/client_golang v1.20.5
github.com/rivo/uniseg v0.4.7 github.com/rivo/uniseg v0.4.7

4
go.sum generated
View file

@ -424,8 +424,8 @@ github.com/moul/http2curl v1.0.0 h1:dRMWoAtb+ePxMlLkrCbAqh4TlPHXvoGUSQ323/9Zahs=
github.com/moul/http2curl v1.0.0/go.mod h1:8UbvGypXm98wA/IqH45anm5Y2Z6ep6O31QGOAZ3H0fQ= github.com/moul/http2curl v1.0.0/go.mod h1:8UbvGypXm98wA/IqH45anm5Y2Z6ep6O31QGOAZ3H0fQ=
github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 h1:C3w9PqII01/Oq1c1nUAm88MOHcQC9l5mIlSMApZMrHA= github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 h1:C3w9PqII01/Oq1c1nUAm88MOHcQC9l5mIlSMApZMrHA=
github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ= github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ=
github.com/ncruces/go-sqlite3 v0.22.0 h1:FkGSBhd0TY6e66k1LVhyEpA+RnG/8QkQNed5pjIk4cs= github.com/ncruces/go-sqlite3 v0.23.0 h1:90j/ar8Ywu2AtsfDl5WhO9sgP/rNk76BcKGIzAHO8AQ=
github.com/ncruces/go-sqlite3 v0.22.0/go.mod h1:ueXOZXYZS2OFQirCU3mHneDwJm5fGKHrtccYBeGEV7M= github.com/ncruces/go-sqlite3 v0.23.0/go.mod h1:gq2nriHSczOs11SqGW5+0X+SgLdkdj4K+j4F/AhQ+8g=
github.com/ncruces/go-strftime v0.1.9 h1:bY0MQC28UADQmHmaF5dgpLmImcShSi2kHU9XLdhx/f4= github.com/ncruces/go-strftime v0.1.9 h1:bY0MQC28UADQmHmaF5dgpLmImcShSi2kHU9XLdhx/f4=
github.com/ncruces/go-strftime v0.1.9/go.mod h1:Fwc5htZGVVkseilnfgOVb9mKy6w1naJmn9CehxcKcls= github.com/ncruces/go-strftime v0.1.9/go.mod h1:Fwc5htZGVVkseilnfgOVb9mKy6w1naJmn9CehxcKcls=
github.com/ncruces/julianday v1.0.0 h1:fH0OKwa7NWvniGQtxdJRxAgkBMolni2BjDHaWTxqt7M= github.com/ncruces/julianday v1.0.0 h1:fH0OKwa7NWvniGQtxdJRxAgkBMolni2BjDHaWTxqt7M=

View file

@ -5,6 +5,9 @@
*.so *.so
*.dylib *.dylib
# Go workspace
go.work*
# Test binary, built with `go test -c` # Test binary, built with `go test -c`
*.test *.test

View file

@ -5,8 +5,8 @@
// https://sqlite.org/c3ref/backup.html // https://sqlite.org/c3ref/backup.html
type Backup struct { type Backup struct {
c *Conn c *Conn
handle uint32 handle ptr_t
otherc uint32 otherc ptr_t
} }
// Backup backs up srcDB on the src connection to the "main" database in dstURI. // Backup backs up srcDB on the src connection to the "main" database in dstURI.
@ -61,7 +61,7 @@ func (src *Conn) BackupInit(srcDB, dstURI string) (*Backup, error) {
return src.backupInit(dst, "main", src.handle, srcDB) return src.backupInit(dst, "main", src.handle, srcDB)
} }
func (c *Conn) backupInit(dst uint32, dstName string, src uint32, srcName string) (*Backup, error) { func (c *Conn) backupInit(dst ptr_t, dstName string, src ptr_t, srcName string) (*Backup, error) {
defer c.arena.mark()() defer c.arena.mark()()
dstPtr := c.arena.string(dstName) dstPtr := c.arena.string(dstName)
srcPtr := c.arena.string(srcName) srcPtr := c.arena.string(srcName)
@ -71,19 +71,19 @@ func (c *Conn) backupInit(dst uint32, dstName string, src uint32, srcName string
other = src other = src
} }
r := c.call("sqlite3_backup_init", ptr := ptr_t(c.call("sqlite3_backup_init",
uint64(dst), uint64(dstPtr), stk_t(dst), stk_t(dstPtr),
uint64(src), uint64(srcPtr)) stk_t(src), stk_t(srcPtr)))
if r == 0 { if ptr == 0 {
defer c.closeDB(other) defer c.closeDB(other)
r = c.call("sqlite3_errcode", uint64(dst)) rc := res_t(c.call("sqlite3_errcode", stk_t(dst)))
return nil, c.sqlite.error(r, dst) return nil, c.sqlite.error(rc, dst)
} }
return &Backup{ return &Backup{
c: c, c: c,
otherc: other, otherc: other,
handle: uint32(r), handle: ptr,
}, nil }, nil
} }
@ -97,10 +97,10 @@ func (b *Backup) Close() error {
return nil return nil
} }
r := b.c.call("sqlite3_backup_finish", uint64(b.handle)) rc := res_t(b.c.call("sqlite3_backup_finish", stk_t(b.handle)))
b.c.closeDB(b.otherc) b.c.closeDB(b.otherc)
b.handle = 0 b.handle = 0
return b.c.error(r) return b.c.error(rc)
} }
// Step copies up to nPage pages between the source and destination databases. // Step copies up to nPage pages between the source and destination databases.
@ -108,11 +108,11 @@ func (b *Backup) Close() error {
// //
// https://sqlite.org/c3ref/backup_finish.html#sqlite3backupstep // https://sqlite.org/c3ref/backup_finish.html#sqlite3backupstep
func (b *Backup) Step(nPage int) (done bool, err error) { func (b *Backup) Step(nPage int) (done bool, err error) {
r := b.c.call("sqlite3_backup_step", uint64(b.handle), uint64(nPage)) rc := res_t(b.c.call("sqlite3_backup_step", stk_t(b.handle), stk_t(nPage)))
if r == _DONE { if rc == _DONE {
return true, nil return true, nil
} }
return false, b.c.error(r) return false, b.c.error(rc)
} }
// Remaining returns the number of pages still to be backed up // Remaining returns the number of pages still to be backed up
@ -120,8 +120,8 @@ func (b *Backup) Step(nPage int) (done bool, err error) {
// //
// https://sqlite.org/c3ref/backup_finish.html#sqlite3backupremaining // https://sqlite.org/c3ref/backup_finish.html#sqlite3backupremaining
func (b *Backup) Remaining() int { func (b *Backup) Remaining() int {
r := b.c.call("sqlite3_backup_remaining", uint64(b.handle)) n := int32(b.c.call("sqlite3_backup_remaining", stk_t(b.handle)))
return int(int32(r)) return int(n)
} }
// PageCount returns the total number of pages in the source database // PageCount returns the total number of pages in the source database
@ -129,6 +129,6 @@ func (b *Backup) Remaining() int {
// //
// https://sqlite.org/c3ref/backup_finish.html#sqlite3backuppagecount // https://sqlite.org/c3ref/backup_finish.html#sqlite3backuppagecount
func (b *Backup) PageCount() int { func (b *Backup) PageCount() int {
r := b.c.call("sqlite3_backup_pagecount", uint64(b.handle)) n := int32(b.c.call("sqlite3_backup_pagecount", stk_t(b.handle)))
return int(int32(r)) return int(n)
} }

View file

@ -20,8 +20,8 @@ type Blob struct {
c *Conn c *Conn
bytes int64 bytes int64
offset int64 offset int64
handle uint32 handle ptr_t
bufptr uint32 bufptr ptr_t
buflen int64 buflen int64
} }
@ -37,23 +37,23 @@ func (c *Conn) OpenBlob(db, table, column string, row int64, write bool) (*Blob,
tablePtr := c.arena.string(table) tablePtr := c.arena.string(table)
columnPtr := c.arena.string(column) columnPtr := c.arena.string(column)
var flags uint64 var flags int32
if write { if write {
flags = 1 flags = 1
} }
c.checkInterrupt(c.handle) c.checkInterrupt(c.handle)
r := c.call("sqlite3_blob_open", uint64(c.handle), rc := res_t(c.call("sqlite3_blob_open", stk_t(c.handle),
uint64(dbPtr), uint64(tablePtr), uint64(columnPtr), stk_t(dbPtr), stk_t(tablePtr), stk_t(columnPtr),
uint64(row), flags, uint64(blobPtr)) stk_t(row), stk_t(flags), stk_t(blobPtr)))
if err := c.error(r); err != nil { if err := c.error(rc); err != nil {
return nil, err return nil, err
} }
blob := Blob{c: c} blob := Blob{c: c}
blob.handle = util.ReadUint32(c.mod, blobPtr) blob.handle = util.Read32[ptr_t](c.mod, blobPtr)
blob.bytes = int64(c.call("sqlite3_blob_bytes", uint64(blob.handle))) blob.bytes = int64(int32(c.call("sqlite3_blob_bytes", stk_t(blob.handle))))
return &blob, nil return &blob, nil
} }
@ -67,10 +67,10 @@ func (b *Blob) Close() error {
return nil return nil
} }
r := b.c.call("sqlite3_blob_close", uint64(b.handle)) rc := res_t(b.c.call("sqlite3_blob_close", stk_t(b.handle)))
b.c.free(b.bufptr) b.c.free(b.bufptr)
b.handle = 0 b.handle = 0
return b.c.error(r) return b.c.error(rc)
} }
// Size returns the size of the BLOB in bytes. // Size returns the size of the BLOB in bytes.
@ -94,13 +94,13 @@ func (b *Blob) Read(p []byte) (n int, err error) {
want = avail want = avail
} }
if want > b.buflen { if want > b.buflen {
b.bufptr = b.c.realloc(b.bufptr, uint64(want)) b.bufptr = b.c.realloc(b.bufptr, want)
b.buflen = want b.buflen = want
} }
r := b.c.call("sqlite3_blob_read", uint64(b.handle), rc := res_t(b.c.call("sqlite3_blob_read", stk_t(b.handle),
uint64(b.bufptr), uint64(want), uint64(b.offset)) stk_t(b.bufptr), stk_t(want), stk_t(b.offset)))
err = b.c.error(r) err = b.c.error(rc)
if err != nil { if err != nil {
return 0, err return 0, err
} }
@ -109,7 +109,7 @@ func (b *Blob) Read(p []byte) (n int, err error) {
err = io.EOF err = io.EOF
} }
copy(p, util.View(b.c.mod, b.bufptr, uint64(want))) copy(p, util.View(b.c.mod, b.bufptr, want))
return int(want), err return int(want), err
} }
@ -127,19 +127,19 @@ func (b *Blob) WriteTo(w io.Writer) (n int64, err error) {
want = avail want = avail
} }
if want > b.buflen { if want > b.buflen {
b.bufptr = b.c.realloc(b.bufptr, uint64(want)) b.bufptr = b.c.realloc(b.bufptr, want)
b.buflen = want b.buflen = want
} }
for want > 0 { for want > 0 {
r := b.c.call("sqlite3_blob_read", uint64(b.handle), rc := res_t(b.c.call("sqlite3_blob_read", stk_t(b.handle),
uint64(b.bufptr), uint64(want), uint64(b.offset)) stk_t(b.bufptr), stk_t(want), stk_t(b.offset)))
err = b.c.error(r) err = b.c.error(rc)
if err != nil { if err != nil {
return n, err return n, err
} }
mem := util.View(b.c.mod, b.bufptr, uint64(want)) mem := util.View(b.c.mod, b.bufptr, want)
m, err := w.Write(mem[:want]) m, err := w.Write(mem[:want])
b.offset += int64(m) b.offset += int64(m)
n += int64(m) n += int64(m)
@ -165,14 +165,14 @@ func (b *Blob) WriteTo(w io.Writer) (n int64, err error) {
func (b *Blob) Write(p []byte) (n int, err error) { func (b *Blob) Write(p []byte) (n int, err error) {
want := int64(len(p)) want := int64(len(p))
if want > b.buflen { if want > b.buflen {
b.bufptr = b.c.realloc(b.bufptr, uint64(want)) b.bufptr = b.c.realloc(b.bufptr, want)
b.buflen = want b.buflen = want
} }
util.WriteBytes(b.c.mod, b.bufptr, p) util.WriteBytes(b.c.mod, b.bufptr, p)
r := b.c.call("sqlite3_blob_write", uint64(b.handle), rc := res_t(b.c.call("sqlite3_blob_write", stk_t(b.handle),
uint64(b.bufptr), uint64(want), uint64(b.offset)) stk_t(b.bufptr), stk_t(want), stk_t(b.offset)))
err = b.c.error(r) err = b.c.error(rc)
if err != nil { if err != nil {
return 0, err return 0, err
} }
@ -196,17 +196,17 @@ func (b *Blob) ReadFrom(r io.Reader) (n int64, err error) {
want = 1 want = 1
} }
if want > b.buflen { if want > b.buflen {
b.bufptr = b.c.realloc(b.bufptr, uint64(want)) b.bufptr = b.c.realloc(b.bufptr, want)
b.buflen = want b.buflen = want
} }
for { for {
mem := util.View(b.c.mod, b.bufptr, uint64(want)) mem := util.View(b.c.mod, b.bufptr, want)
m, err := r.Read(mem[:want]) m, err := r.Read(mem[:want])
if m > 0 { if m > 0 {
r := b.c.call("sqlite3_blob_write", uint64(b.handle), rc := res_t(b.c.call("sqlite3_blob_write", stk_t(b.handle),
uint64(b.bufptr), uint64(m), uint64(b.offset)) stk_t(b.bufptr), stk_t(m), stk_t(b.offset)))
err := b.c.error(r) err := b.c.error(rc)
if err != nil { if err != nil {
return n, err return n, err
} }
@ -254,8 +254,8 @@ func (b *Blob) Seek(offset int64, whence int) (int64, error) {
// https://sqlite.org/c3ref/blob_reopen.html // https://sqlite.org/c3ref/blob_reopen.html
func (b *Blob) Reopen(row int64) error { func (b *Blob) Reopen(row int64) error {
b.c.checkInterrupt(b.c.handle) b.c.checkInterrupt(b.c.handle)
err := b.c.error(b.c.call("sqlite3_blob_reopen", uint64(b.handle), uint64(row))) err := b.c.error(res_t(b.c.call("sqlite3_blob_reopen", stk_t(b.handle), stk_t(row))))
b.bytes = int64(b.c.call("sqlite3_blob_bytes", uint64(b.handle))) b.bytes = int64(int32(b.c.call("sqlite3_blob_bytes", stk_t(b.handle))))
b.offset = 0 b.offset = 0
return err return err
} }

View file

@ -32,7 +32,7 @@ func (c *Conn) Config(op DBConfig, arg ...bool) (bool, error) {
defer c.arena.mark()() defer c.arena.mark()()
argsPtr := c.arena.new(intlen + ptrlen) argsPtr := c.arena.new(intlen + ptrlen)
var flag int var flag int32
switch { switch {
case len(arg) == 0: case len(arg) == 0:
flag = -1 flag = -1
@ -40,31 +40,31 @@ func (c *Conn) Config(op DBConfig, arg ...bool) (bool, error) {
flag = 1 flag = 1
} }
util.WriteUint32(c.mod, argsPtr+0*ptrlen, uint32(flag)) util.Write32(c.mod, argsPtr+0*ptrlen, flag)
util.WriteUint32(c.mod, argsPtr+1*ptrlen, argsPtr) util.Write32(c.mod, argsPtr+1*ptrlen, argsPtr)
r := c.call("sqlite3_db_config", uint64(c.handle), rc := res_t(c.call("sqlite3_db_config", stk_t(c.handle),
uint64(op), uint64(argsPtr)) stk_t(op), stk_t(argsPtr)))
return util.ReadUint32(c.mod, argsPtr) != 0, c.error(r) return util.Read32[uint32](c.mod, argsPtr) != 0, c.error(rc)
} }
// ConfigLog sets up the error logging callback for the connection. // ConfigLog sets up the error logging callback for the connection.
// //
// https://sqlite.org/errlog.html // https://sqlite.org/errlog.html
func (c *Conn) ConfigLog(cb func(code ExtendedErrorCode, msg string)) error { func (c *Conn) ConfigLog(cb func(code ExtendedErrorCode, msg string)) error {
var enable uint64 var enable int32
if cb != nil { if cb != nil {
enable = 1 enable = 1
} }
r := c.call("sqlite3_config_log_go", enable) rc := res_t(c.call("sqlite3_config_log_go", stk_t(enable)))
if err := c.error(r); err != nil { if err := c.error(rc); err != nil {
return err return err
} }
c.log = cb c.log = cb
return nil return nil
} }
func logCallback(ctx context.Context, mod api.Module, _, iCode, zMsg uint32) { 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 { if c, ok := ctx.Value(connKey{}).(*Conn); ok && c.log != nil {
msg := util.ReadString(mod, zMsg, _MAX_LENGTH) msg := util.ReadString(mod, zMsg, _MAX_LENGTH)
c.log(xErrorCode(iCode), msg) c.log(xErrorCode(iCode), msg)
@ -88,93 +88,93 @@ func (c *Conn) FileControl(schema string, op FcntlOpcode, arg ...any) (any, erro
defer c.arena.mark()() defer c.arena.mark()()
ptr := c.arena.new(max(ptrlen, intlen)) ptr := c.arena.new(max(ptrlen, intlen))
var schemaPtr uint32 var schemaPtr ptr_t
if schema != "" { if schema != "" {
schemaPtr = c.arena.string(schema) schemaPtr = c.arena.string(schema)
} }
var rc uint64 var rc res_t
var res any var ret any
switch op { switch op {
default: default:
return nil, MISUSE return nil, MISUSE
case FCNTL_RESET_CACHE: case FCNTL_RESET_CACHE:
rc = c.call("sqlite3_file_control", rc = res_t(c.call("sqlite3_file_control",
uint64(c.handle), uint64(schemaPtr), stk_t(c.handle), stk_t(schemaPtr),
uint64(op), 0) stk_t(op), 0))
case FCNTL_PERSIST_WAL, FCNTL_POWERSAFE_OVERWRITE: case FCNTL_PERSIST_WAL, FCNTL_POWERSAFE_OVERWRITE:
var flag int var flag int32
switch { switch {
case len(arg) == 0: case len(arg) == 0:
flag = -1 flag = -1
case arg[0]: case arg[0]:
flag = 1 flag = 1
} }
util.WriteUint32(c.mod, ptr, uint32(flag)) util.Write32(c.mod, ptr, flag)
rc = c.call("sqlite3_file_control", rc = res_t(c.call("sqlite3_file_control",
uint64(c.handle), uint64(schemaPtr), stk_t(c.handle), stk_t(schemaPtr),
uint64(op), uint64(ptr)) stk_t(op), stk_t(ptr)))
res = util.ReadUint32(c.mod, ptr) != 0 ret = util.Read32[uint32](c.mod, ptr) != 0
case FCNTL_CHUNK_SIZE: case FCNTL_CHUNK_SIZE:
util.WriteUint32(c.mod, ptr, uint32(arg[0].(int))) util.Write32(c.mod, ptr, int32(arg[0].(int)))
rc = c.call("sqlite3_file_control", rc = res_t(c.call("sqlite3_file_control",
uint64(c.handle), uint64(schemaPtr), stk_t(c.handle), stk_t(schemaPtr),
uint64(op), uint64(ptr)) stk_t(op), stk_t(ptr)))
case FCNTL_RESERVE_BYTES: case FCNTL_RESERVE_BYTES:
bytes := -1 bytes := -1
if len(arg) > 0 { if len(arg) > 0 {
bytes = arg[0].(int) bytes = arg[0].(int)
} }
util.WriteUint32(c.mod, ptr, uint32(bytes)) util.Write32(c.mod, ptr, int32(bytes))
rc = c.call("sqlite3_file_control", rc = res_t(c.call("sqlite3_file_control",
uint64(c.handle), uint64(schemaPtr), stk_t(c.handle), stk_t(schemaPtr),
uint64(op), uint64(ptr)) stk_t(op), stk_t(ptr)))
res = int(util.ReadUint32(c.mod, ptr)) ret = int(util.Read32[int32](c.mod, ptr))
case FCNTL_DATA_VERSION: case FCNTL_DATA_VERSION:
rc = c.call("sqlite3_file_control", rc = res_t(c.call("sqlite3_file_control",
uint64(c.handle), uint64(schemaPtr), stk_t(c.handle), stk_t(schemaPtr),
uint64(op), uint64(ptr)) stk_t(op), stk_t(ptr)))
res = util.ReadUint32(c.mod, ptr) ret = util.Read32[uint32](c.mod, ptr)
case FCNTL_LOCKSTATE: case FCNTL_LOCKSTATE:
rc = c.call("sqlite3_file_control", rc = res_t(c.call("sqlite3_file_control",
uint64(c.handle), uint64(schemaPtr), stk_t(c.handle), stk_t(schemaPtr),
uint64(op), uint64(ptr)) stk_t(op), stk_t(ptr)))
res = vfs.LockLevel(util.ReadUint32(c.mod, ptr)) ret = util.Read32[vfs.LockLevel](c.mod, ptr)
case FCNTL_VFS_POINTER: case FCNTL_VFS_POINTER:
rc = c.call("sqlite3_file_control", rc = res_t(c.call("sqlite3_file_control",
uint64(c.handle), uint64(schemaPtr), stk_t(c.handle), stk_t(schemaPtr),
uint64(op), uint64(ptr)) stk_t(op), stk_t(ptr)))
if rc == _OK { if rc == _OK {
const zNameOffset = 16 const zNameOffset = 16
ptr = util.ReadUint32(c.mod, ptr) ptr = util.Read32[ptr_t](c.mod, ptr)
ptr = util.ReadUint32(c.mod, ptr+zNameOffset) ptr = util.Read32[ptr_t](c.mod, ptr+zNameOffset)
name := util.ReadString(c.mod, ptr, _MAX_NAME) name := util.ReadString(c.mod, ptr, _MAX_NAME)
res = vfs.Find(name) ret = vfs.Find(name)
} }
case FCNTL_FILE_POINTER, FCNTL_JOURNAL_POINTER: case FCNTL_FILE_POINTER, FCNTL_JOURNAL_POINTER:
rc = c.call("sqlite3_file_control", rc = res_t(c.call("sqlite3_file_control",
uint64(c.handle), uint64(schemaPtr), stk_t(c.handle), stk_t(schemaPtr),
uint64(op), uint64(ptr)) stk_t(op), stk_t(ptr)))
if rc == _OK { if rc == _OK {
const fileHandleOffset = 4 const fileHandleOffset = 4
ptr = util.ReadUint32(c.mod, ptr) ptr = util.Read32[ptr_t](c.mod, ptr)
ptr = util.ReadUint32(c.mod, ptr+fileHandleOffset) ptr = util.Read32[ptr_t](c.mod, ptr+fileHandleOffset)
res = util.GetHandle(c.ctx, ptr) ret = util.GetHandle(c.ctx, ptr)
} }
} }
if err := c.error(rc); err != nil { if err := c.error(rc); err != nil {
return nil, err return nil, err
} }
return res, nil return ret, nil
} }
// Limit allows the size of various constructs to be // Limit allows the size of various constructs to be
@ -182,20 +182,20 @@ func (c *Conn) FileControl(schema string, op FcntlOpcode, arg ...any) (any, erro
// //
// https://sqlite.org/c3ref/limit.html // https://sqlite.org/c3ref/limit.html
func (c *Conn) Limit(id LimitCategory, value int) int { func (c *Conn) Limit(id LimitCategory, value int) int {
r := c.call("sqlite3_limit", uint64(c.handle), uint64(id), uint64(value)) v := int32(c.call("sqlite3_limit", stk_t(c.handle), stk_t(id), stk_t(value)))
return int(int32(r)) return int(v)
} }
// SetAuthorizer registers an authorizer callback with the database connection. // SetAuthorizer registers an authorizer callback with the database connection.
// //
// https://sqlite.org/c3ref/set_authorizer.html // https://sqlite.org/c3ref/set_authorizer.html
func (c *Conn) SetAuthorizer(cb func(action AuthorizerActionCode, name3rd, name4th, schema, inner string) AuthorizerReturnCode) error { func (c *Conn) SetAuthorizer(cb func(action AuthorizerActionCode, name3rd, name4th, schema, inner string) AuthorizerReturnCode) error {
var enable uint64 var enable int32
if cb != nil { if cb != nil {
enable = 1 enable = 1
} }
r := c.call("sqlite3_set_authorizer_go", uint64(c.handle), enable) rc := res_t(c.call("sqlite3_set_authorizer_go", stk_t(c.handle), stk_t(enable)))
if err := c.error(r); err != nil { if err := c.error(rc); err != nil {
return err return err
} }
c.authorizer = cb c.authorizer = cb
@ -203,7 +203,7 @@ func (c *Conn) SetAuthorizer(cb func(action AuthorizerActionCode, name3rd, name4
} }
func authorizerCallback(ctx context.Context, mod api.Module, pDB uint32, action AuthorizerActionCode, zName3rd, zName4th, zSchema, zInner uint32) (rc AuthorizerReturnCode) { 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 { if c, ok := ctx.Value(connKey{}).(*Conn); ok && c.handle == pDB && c.authorizer != nil {
var name3rd, name4th, schema, inner string var name3rd, name4th, schema, inner string
if zName3rd != 0 { if zName3rd != 0 {
@ -227,15 +227,15 @@ func authorizerCallback(ctx context.Context, mod api.Module, pDB uint32, action
// //
// https://sqlite.org/c3ref/trace_v2.html // https://sqlite.org/c3ref/trace_v2.html
func (c *Conn) Trace(mask TraceEvent, cb func(evt TraceEvent, arg1 any, arg2 any) error) error { func (c *Conn) Trace(mask TraceEvent, cb func(evt TraceEvent, arg1 any, arg2 any) error) error {
r := c.call("sqlite3_trace_go", uint64(c.handle), uint64(mask)) rc := res_t(c.call("sqlite3_trace_go", stk_t(c.handle), stk_t(mask)))
if err := c.error(r); err != nil { if err := c.error(rc); err != nil {
return err return err
} }
c.trace = cb c.trace = cb
return nil return nil
} }
func traceCallback(ctx context.Context, mod api.Module, evt TraceEvent, pDB, pArg1, pArg2 uint32) (rc uint32) { 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 { if c, ok := ctx.Value(connKey{}).(*Conn); ok && c.handle == pDB && c.trace != nil {
var arg1, arg2 any var arg1, arg2 any
if evt == TRACE_CLOSE { if evt == TRACE_CLOSE {
@ -248,7 +248,7 @@ func traceCallback(ctx context.Context, mod api.Module, evt TraceEvent, pDB, pAr
case TRACE_STMT: case TRACE_STMT:
arg2 = s.SQL() arg2 = s.SQL()
case TRACE_PROFILE: case TRACE_PROFILE:
arg2 = int64(util.ReadUint64(mod, pArg2)) arg2 = util.Read64[int64](mod, pArg2)
} }
break break
} }
@ -269,20 +269,20 @@ func (c *Conn) WALCheckpoint(schema string, mode CheckpointMode) (nLog, nCkpt in
nLogPtr := c.arena.new(ptrlen) nLogPtr := c.arena.new(ptrlen)
nCkptPtr := c.arena.new(ptrlen) nCkptPtr := c.arena.new(ptrlen)
schemaPtr := c.arena.string(schema) schemaPtr := c.arena.string(schema)
r := c.call("sqlite3_wal_checkpoint_v2", rc := res_t(c.call("sqlite3_wal_checkpoint_v2",
uint64(c.handle), uint64(schemaPtr), uint64(mode), stk_t(c.handle), stk_t(schemaPtr), stk_t(mode),
uint64(nLogPtr), uint64(nCkptPtr)) stk_t(nLogPtr), stk_t(nCkptPtr)))
nLog = int(int32(util.ReadUint32(c.mod, nLogPtr))) nLog = int(util.Read32[int32](c.mod, nLogPtr))
nCkpt = int(int32(util.ReadUint32(c.mod, nCkptPtr))) nCkpt = int(util.Read32[int32](c.mod, nCkptPtr))
return nLog, nCkpt, c.error(r) return nLog, nCkpt, c.error(rc)
} }
// WALAutoCheckpoint configures WAL auto-checkpoints. // WALAutoCheckpoint configures WAL auto-checkpoints.
// //
// https://sqlite.org/c3ref/wal_autocheckpoint.html // https://sqlite.org/c3ref/wal_autocheckpoint.html
func (c *Conn) WALAutoCheckpoint(pages int) error { func (c *Conn) WALAutoCheckpoint(pages int) error {
r := c.call("sqlite3_wal_autocheckpoint", uint64(c.handle), uint64(pages)) rc := res_t(c.call("sqlite3_wal_autocheckpoint", stk_t(c.handle), stk_t(pages)))
return c.error(r) return c.error(rc)
} }
// WALHook registers a callback function to be invoked // WALHook registers a callback function to be invoked
@ -290,15 +290,15 @@ func (c *Conn) WALAutoCheckpoint(pages int) error {
// //
// https://sqlite.org/c3ref/wal_hook.html // https://sqlite.org/c3ref/wal_hook.html
func (c *Conn) WALHook(cb func(db *Conn, schema string, pages int) error) { func (c *Conn) WALHook(cb func(db *Conn, schema string, pages int) error) {
var enable uint64 var enable int32
if cb != nil { if cb != nil {
enable = 1 enable = 1
} }
c.call("sqlite3_wal_hook_go", uint64(c.handle), enable) c.call("sqlite3_wal_hook_go", stk_t(c.handle), stk_t(enable))
c.wal = cb c.wal = cb
} }
func walCallback(ctx context.Context, mod api.Module, _, pDB, zSchema uint32, pages int32) (rc uint32) { 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 { if c, ok := ctx.Value(connKey{}).(*Conn); ok && c.handle == pDB && c.wal != nil {
schema := util.ReadString(mod, zSchema, _MAX_NAME) schema := util.ReadString(mod, zSchema, _MAX_NAME)
err := c.wal(c, schema, int(pages)) err := c.wal(c, schema, int(pages))
@ -311,15 +311,15 @@ func walCallback(ctx context.Context, mod api.Module, _, pDB, zSchema uint32, pa
// //
// https://sqlite.org/c3ref/autovacuum_pages.html // https://sqlite.org/c3ref/autovacuum_pages.html
func (c *Conn) AutoVacuumPages(cb func(schema string, dbPages, freePages, bytesPerPage uint) uint) error { func (c *Conn) AutoVacuumPages(cb func(schema string, dbPages, freePages, bytesPerPage uint) uint) error {
var funcPtr uint32 var funcPtr ptr_t
if cb != nil { if cb != nil {
funcPtr = util.AddHandle(c.ctx, cb) funcPtr = util.AddHandle(c.ctx, cb)
} }
r := c.call("sqlite3_autovacuum_pages_go", uint64(c.handle), uint64(funcPtr)) rc := res_t(c.call("sqlite3_autovacuum_pages_go", stk_t(c.handle), stk_t(funcPtr)))
return c.error(r) return c.error(rc)
} }
func autoVacuumCallback(ctx context.Context, mod api.Module, pApp, zSchema, nDbPage, nFreePage, nBytePerPage uint32) uint32 { 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) fn := util.GetHandle(ctx, pApp).(func(schema string, dbPages, freePages, bytesPerPage uint) uint)
schema := util.ReadString(mod, zSchema, _MAX_NAME) schema := util.ReadString(mod, zSchema, _MAX_NAME)
return uint32(fn(schema, uint(nDbPage), uint(nFreePage), uint(nBytePerPage))) return uint32(fn(schema, uint(nDbPage), uint(nFreePage), uint(nBytePerPage)))
@ -329,14 +329,14 @@ func autoVacuumCallback(ctx context.Context, mod api.Module, pApp, zSchema, nDbP
// //
// https://sqlite.org/c3ref/hard_heap_limit64.html // https://sqlite.org/c3ref/hard_heap_limit64.html
func (c *Conn) SoftHeapLimit(n int64) int64 { func (c *Conn) SoftHeapLimit(n int64) int64 {
return int64(c.call("sqlite3_soft_heap_limit64", uint64(n))) return int64(c.call("sqlite3_soft_heap_limit64", stk_t(n)))
} }
// HardHeapLimit imposes a hard limit on heap size. // HardHeapLimit imposes a hard limit on heap size.
// //
// https://sqlite.org/c3ref/hard_heap_limit64.html // https://sqlite.org/c3ref/hard_heap_limit64.html
func (c *Conn) HardHeapLimit(n int64) int64 { func (c *Conn) HardHeapLimit(n int64) int64 {
return int64(c.call("sqlite3_hard_heap_limit64", uint64(n))) return int64(c.call("sqlite3_hard_heap_limit64", stk_t(n)))
} }
// EnableChecksums enables checksums on a database. // EnableChecksums enables checksums on a database.

View file

@ -35,11 +35,11 @@ type Conn struct {
update func(AuthorizerActionCode, string, string, int64) update func(AuthorizerActionCode, string, string, int64)
commit func() bool commit func() bool
rollback func() rollback func()
arena arena
busy1st time.Time busy1st time.Time
busylst time.Time busylst time.Time
handle uint32 arena arena
handle ptr_t
} }
// Open calls [OpenFlags] with [OPEN_READWRITE], [OPEN_CREATE] and [OPEN_URI]. // Open calls [OpenFlags] with [OPEN_READWRITE], [OPEN_CREATE] and [OPEN_URI].
@ -70,7 +70,7 @@ func OpenFlags(filename string, flags OpenFlag) (*Conn, error) {
type connKey = util.ConnKey type connKey = util.ConnKey
func newConn(ctx context.Context, filename string, flags OpenFlag) (res *Conn, _ error) { func newConn(ctx context.Context, filename string, flags OpenFlag) (ret *Conn, _ error) {
err := ctx.Err() err := ctx.Err()
if err != nil { if err != nil {
return nil, err return nil, err
@ -82,7 +82,7 @@ func newConn(ctx context.Context, filename string, flags OpenFlag) (res *Conn, _
return nil, err return nil, err
} }
defer func() { defer func() {
if res == nil { if ret == nil {
c.Close() c.Close()
c.sqlite.close() c.sqlite.close()
} else { } else {
@ -91,7 +91,7 @@ func newConn(ctx context.Context, filename string, flags OpenFlag) (res *Conn, _
}() }()
c.ctx = context.WithValue(c.ctx, connKey{}, c) c.ctx = context.WithValue(c.ctx, connKey{}, c)
c.arena = c.newArena(1024) c.arena = c.newArena()
c.handle, err = c.openDB(filename, flags) c.handle, err = c.openDB(filename, flags)
if err == nil { if err == nil {
err = initExtensions(c) err = initExtensions(c)
@ -102,21 +102,21 @@ func newConn(ctx context.Context, filename string, flags OpenFlag) (res *Conn, _
return c, nil return c, nil
} }
func (c *Conn) openDB(filename string, flags OpenFlag) (uint32, error) { func (c *Conn) openDB(filename string, flags OpenFlag) (ptr_t, error) {
defer c.arena.mark()() defer c.arena.mark()()
connPtr := c.arena.new(ptrlen) connPtr := c.arena.new(ptrlen)
namePtr := c.arena.string(filename) namePtr := c.arena.string(filename)
flags |= OPEN_EXRESCODE flags |= OPEN_EXRESCODE
r := c.call("sqlite3_open_v2", uint64(namePtr), uint64(connPtr), uint64(flags), 0) rc := res_t(c.call("sqlite3_open_v2", stk_t(namePtr), stk_t(connPtr), stk_t(flags), 0))
handle := util.ReadUint32(c.mod, connPtr) handle := util.Read32[ptr_t](c.mod, connPtr)
if err := c.sqlite.error(r, handle); err != nil { if err := c.sqlite.error(rc, handle); err != nil {
c.closeDB(handle) c.closeDB(handle)
return 0, err return 0, err
} }
c.call("sqlite3_progress_handler_go", uint64(handle), 100) c.call("sqlite3_progress_handler_go", stk_t(handle), 100)
if flags|OPEN_URI != 0 && strings.HasPrefix(filename, "file:") { if flags|OPEN_URI != 0 && strings.HasPrefix(filename, "file:") {
var pragmas strings.Builder var pragmas strings.Builder
if _, after, ok := strings.Cut(filename, "?"); ok { if _, after, ok := strings.Cut(filename, "?"); ok {
@ -130,8 +130,8 @@ func (c *Conn) openDB(filename string, flags OpenFlag) (uint32, error) {
if pragmas.Len() != 0 { if pragmas.Len() != 0 {
c.checkInterrupt(handle) c.checkInterrupt(handle)
pragmaPtr := c.arena.string(pragmas.String()) pragmaPtr := c.arena.string(pragmas.String())
r := c.call("sqlite3_exec", uint64(handle), uint64(pragmaPtr), 0, 0, 0) rc := res_t(c.call("sqlite3_exec", stk_t(handle), stk_t(pragmaPtr), 0, 0, 0))
if err := c.sqlite.error(r, handle, pragmas.String()); err != nil { if err := c.sqlite.error(rc, handle, pragmas.String()); err != nil {
err = fmt.Errorf("sqlite3: invalid _pragma: %w", err) err = fmt.Errorf("sqlite3: invalid _pragma: %w", err)
c.closeDB(handle) c.closeDB(handle)
return 0, err return 0, err
@ -141,9 +141,9 @@ func (c *Conn) openDB(filename string, flags OpenFlag) (uint32, error) {
return handle, nil return handle, nil
} }
func (c *Conn) closeDB(handle uint32) { func (c *Conn) closeDB(handle ptr_t) {
r := c.call("sqlite3_close_v2", uint64(handle)) rc := res_t(c.call("sqlite3_close_v2", stk_t(handle)))
if err := c.sqlite.error(r, handle); err != nil { if err := c.sqlite.error(rc, handle); err != nil {
panic(err) panic(err)
} }
} }
@ -165,8 +165,8 @@ func (c *Conn) Close() error {
c.pending.Close() c.pending.Close()
c.pending = nil c.pending = nil
r := c.call("sqlite3_close", uint64(c.handle)) rc := res_t(c.call("sqlite3_close", stk_t(c.handle)))
if err := c.error(r); err != nil { if err := c.error(rc); err != nil {
return err return err
} }
@ -183,8 +183,8 @@ func (c *Conn) Exec(sql string) error {
sqlPtr := c.arena.string(sql) sqlPtr := c.arena.string(sql)
c.checkInterrupt(c.handle) c.checkInterrupt(c.handle)
r := c.call("sqlite3_exec", uint64(c.handle), uint64(sqlPtr), 0, 0, 0) rc := res_t(c.call("sqlite3_exec", stk_t(c.handle), stk_t(sqlPtr), 0, 0, 0))
return c.error(r, sql) return c.error(rc, sql)
} }
// Prepare calls [Conn.PrepareFlags] with no flags. // Prepare calls [Conn.PrepareFlags] with no flags.
@ -209,17 +209,17 @@ func (c *Conn) PrepareFlags(sql string, flags PrepareFlag) (stmt *Stmt, tail str
sqlPtr := c.arena.string(sql) sqlPtr := c.arena.string(sql)
c.checkInterrupt(c.handle) c.checkInterrupt(c.handle)
r := c.call("sqlite3_prepare_v3", uint64(c.handle), rc := res_t(c.call("sqlite3_prepare_v3", stk_t(c.handle),
uint64(sqlPtr), uint64(len(sql)+1), uint64(flags), stk_t(sqlPtr), stk_t(len(sql)+1), stk_t(flags),
uint64(stmtPtr), uint64(tailPtr)) stk_t(stmtPtr), stk_t(tailPtr)))
stmt = &Stmt{c: c} stmt = &Stmt{c: c}
stmt.handle = util.ReadUint32(c.mod, stmtPtr) stmt.handle = util.Read32[ptr_t](c.mod, stmtPtr)
if sql := sql[util.ReadUint32(c.mod, tailPtr)-sqlPtr:]; sql != "" { if sql := sql[util.Read32[ptr_t](c.mod, tailPtr)-sqlPtr:]; sql != "" {
tail = sql tail = sql
} }
if err := c.error(r, sql); err != nil { if err := c.error(rc, sql); err != nil {
return nil, "", err return nil, "", err
} }
if stmt.handle == 0 { if stmt.handle == 0 {
@ -233,9 +233,7 @@ func (c *Conn) PrepareFlags(sql string, flags PrepareFlag) (stmt *Stmt, tail str
// //
// https://sqlite.org/c3ref/db_name.html // https://sqlite.org/c3ref/db_name.html
func (c *Conn) DBName(n int) string { func (c *Conn) DBName(n int) string {
r := c.call("sqlite3_db_name", uint64(c.handle), uint64(n)) ptr := ptr_t(c.call("sqlite3_db_name", stk_t(c.handle), stk_t(n)))
ptr := uint32(r)
if ptr == 0 { if ptr == 0 {
return "" return ""
} }
@ -246,34 +244,34 @@ func (c *Conn) DBName(n int) string {
// //
// https://sqlite.org/c3ref/db_filename.html // https://sqlite.org/c3ref/db_filename.html
func (c *Conn) Filename(schema string) *vfs.Filename { func (c *Conn) Filename(schema string) *vfs.Filename {
var ptr uint32 var ptr ptr_t
if schema != "" { if schema != "" {
defer c.arena.mark()() defer c.arena.mark()()
ptr = c.arena.string(schema) ptr = c.arena.string(schema)
} }
r := c.call("sqlite3_db_filename", uint64(c.handle), uint64(ptr)) ptr = ptr_t(c.call("sqlite3_db_filename", stk_t(c.handle), stk_t(ptr)))
return vfs.GetFilename(c.ctx, c.mod, uint32(r), vfs.OPEN_MAIN_DB) return vfs.GetFilename(c.ctx, c.mod, ptr, vfs.OPEN_MAIN_DB)
} }
// ReadOnly determines if a database is read-only. // ReadOnly determines if a database is read-only.
// //
// https://sqlite.org/c3ref/db_readonly.html // https://sqlite.org/c3ref/db_readonly.html
func (c *Conn) ReadOnly(schema string) (ro bool, ok bool) { func (c *Conn) ReadOnly(schema string) (ro bool, ok bool) {
var ptr uint32 var ptr ptr_t
if schema != "" { if schema != "" {
defer c.arena.mark()() defer c.arena.mark()()
ptr = c.arena.string(schema) ptr = c.arena.string(schema)
} }
r := c.call("sqlite3_db_readonly", uint64(c.handle), uint64(ptr)) b := int32(c.call("sqlite3_db_readonly", stk_t(c.handle), stk_t(ptr)))
return int32(r) > 0, int32(r) < 0 return b > 0, b < 0
} }
// GetAutocommit tests the connection for auto-commit mode. // GetAutocommit tests the connection for auto-commit mode.
// //
// https://sqlite.org/c3ref/get_autocommit.html // https://sqlite.org/c3ref/get_autocommit.html
func (c *Conn) GetAutocommit() bool { func (c *Conn) GetAutocommit() bool {
r := c.call("sqlite3_get_autocommit", uint64(c.handle)) b := int32(c.call("sqlite3_get_autocommit", stk_t(c.handle)))
return r != 0 return b != 0
} }
// LastInsertRowID returns the rowid of the most recent successful INSERT // LastInsertRowID returns the rowid of the most recent successful INSERT
@ -281,8 +279,7 @@ func (c *Conn) GetAutocommit() bool {
// //
// https://sqlite.org/c3ref/last_insert_rowid.html // https://sqlite.org/c3ref/last_insert_rowid.html
func (c *Conn) LastInsertRowID() int64 { func (c *Conn) LastInsertRowID() int64 {
r := c.call("sqlite3_last_insert_rowid", uint64(c.handle)) return int64(c.call("sqlite3_last_insert_rowid", stk_t(c.handle)))
return int64(r)
} }
// SetLastInsertRowID allows the application to set the value returned by // SetLastInsertRowID allows the application to set the value returned by
@ -290,7 +287,7 @@ func (c *Conn) LastInsertRowID() int64 {
// //
// https://sqlite.org/c3ref/set_last_insert_rowid.html // https://sqlite.org/c3ref/set_last_insert_rowid.html
func (c *Conn) SetLastInsertRowID(id int64) { func (c *Conn) SetLastInsertRowID(id int64) {
c.call("sqlite3_set_last_insert_rowid", uint64(c.handle), uint64(id)) c.call("sqlite3_set_last_insert_rowid", stk_t(c.handle), stk_t(id))
} }
// Changes returns the number of rows modified, inserted or deleted // Changes returns the number of rows modified, inserted or deleted
@ -299,8 +296,7 @@ func (c *Conn) SetLastInsertRowID(id int64) {
// //
// https://sqlite.org/c3ref/changes.html // https://sqlite.org/c3ref/changes.html
func (c *Conn) Changes() int64 { func (c *Conn) Changes() int64 {
r := c.call("sqlite3_changes64", uint64(c.handle)) return int64(c.call("sqlite3_changes64", stk_t(c.handle)))
return int64(r)
} }
// TotalChanges returns the number of rows modified, inserted or deleted // TotalChanges returns the number of rows modified, inserted or deleted
@ -309,16 +305,15 @@ func (c *Conn) Changes() int64 {
// //
// https://sqlite.org/c3ref/total_changes.html // https://sqlite.org/c3ref/total_changes.html
func (c *Conn) TotalChanges() int64 { func (c *Conn) TotalChanges() int64 {
r := c.call("sqlite3_total_changes64", uint64(c.handle)) return int64(c.call("sqlite3_total_changes64", stk_t(c.handle)))
return int64(r)
} }
// ReleaseMemory frees memory used by a database connection. // ReleaseMemory frees memory used by a database connection.
// //
// https://sqlite.org/c3ref/db_release_memory.html // https://sqlite.org/c3ref/db_release_memory.html
func (c *Conn) ReleaseMemory() error { func (c *Conn) ReleaseMemory() error {
r := c.call("sqlite3_db_release_memory", uint64(c.handle)) rc := res_t(c.call("sqlite3_db_release_memory", stk_t(c.handle)))
return c.error(r) return c.error(rc)
} }
// GetInterrupt gets the context set with [Conn.SetInterrupt]. // GetInterrupt gets the context set with [Conn.SetInterrupt].
@ -354,10 +349,10 @@ func (c *Conn) SetInterrupt(ctx context.Context) (old context.Context) {
defer c.arena.mark()() defer c.arena.mark()()
stmtPtr := c.arena.new(ptrlen) 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`) loopPtr := c.arena.string(`WITH RECURSIVE c(x) AS (VALUES(0) UNION ALL SELECT x FROM c) SELECT x FROM c`)
c.call("sqlite3_prepare_v3", uint64(c.handle), uint64(loopPtr), math.MaxUint64, c.call("sqlite3_prepare_v3", stk_t(c.handle), stk_t(loopPtr), math.MaxUint64,
uint64(PREPARE_PERSISTENT), uint64(stmtPtr), 0) stk_t(PREPARE_PERSISTENT), stk_t(stmtPtr), 0)
c.pending = &Stmt{c: c} c.pending = &Stmt{c: c}
c.pending.handle = util.ReadUint32(c.mod, stmtPtr) c.pending.handle = util.Read32[ptr_t](c.mod, stmtPtr)
} }
if old.Done() != nil && ctx.Err() == nil { if old.Done() != nil && ctx.Err() == nil {
@ -369,13 +364,13 @@ func (c *Conn) SetInterrupt(ctx context.Context) (old context.Context) {
return old return old
} }
func (c *Conn) checkInterrupt(handle uint32) { func (c *Conn) checkInterrupt(handle ptr_t) {
if c.interrupt.Err() != nil { if c.interrupt.Err() != nil {
c.call("sqlite3_interrupt", uint64(handle)) c.call("sqlite3_interrupt", stk_t(handle))
} }
} }
func progressCallback(ctx context.Context, mod api.Module, _ uint32) (interrupt uint32) { func progressCallback(ctx context.Context, mod api.Module, _ ptr_t) (interrupt int32) {
if c, ok := ctx.Value(connKey{}).(*Conn); ok { if c, ok := ctx.Value(connKey{}).(*Conn); ok {
if c.interrupt.Done() != nil { if c.interrupt.Done() != nil {
runtime.Gosched() runtime.Gosched()
@ -392,11 +387,11 @@ func progressCallback(ctx context.Context, mod api.Module, _ uint32) (interrupt
// https://sqlite.org/c3ref/busy_timeout.html // https://sqlite.org/c3ref/busy_timeout.html
func (c *Conn) BusyTimeout(timeout time.Duration) error { func (c *Conn) BusyTimeout(timeout time.Duration) error {
ms := min((timeout+time.Millisecond-1)/time.Millisecond, math.MaxInt32) ms := min((timeout+time.Millisecond-1)/time.Millisecond, math.MaxInt32)
r := c.call("sqlite3_busy_timeout", uint64(c.handle), uint64(ms)) rc := res_t(c.call("sqlite3_busy_timeout", stk_t(c.handle), stk_t(ms)))
return c.error(r) return c.error(rc)
} }
func timeoutCallback(ctx context.Context, mod api.Module, count, tmout int32) (retry uint32) { 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/ // 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 { if c, ok := ctx.Value(connKey{}).(*Conn); ok && c.interrupt.Err() == nil {
switch { switch {
@ -419,19 +414,19 @@ func timeoutCallback(ctx context.Context, mod api.Module, count, tmout int32) (r
// //
// https://sqlite.org/c3ref/busy_handler.html // https://sqlite.org/c3ref/busy_handler.html
func (c *Conn) BusyHandler(cb func(ctx context.Context, count int) (retry bool)) error { func (c *Conn) BusyHandler(cb func(ctx context.Context, count int) (retry bool)) error {
var enable uint64 var enable int32
if cb != nil { if cb != nil {
enable = 1 enable = 1
} }
r := c.call("sqlite3_busy_handler_go", uint64(c.handle), enable) rc := res_t(c.call("sqlite3_busy_handler_go", stk_t(c.handle), stk_t(enable)))
if err := c.error(r); err != nil { if err := c.error(rc); err != nil {
return err return err
} }
c.busy = cb c.busy = cb
return nil return nil
} }
func busyCallback(ctx context.Context, mod api.Module, pDB uint32, count int32) (retry uint32) { 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 { if c, ok := ctx.Value(connKey{}).(*Conn); ok && c.handle == pDB && c.busy != nil {
interrupt := c.interrupt interrupt := c.interrupt
if interrupt == nil { if interrupt == nil {
@ -452,16 +447,16 @@ func (c *Conn) Status(op DBStatus, reset bool) (current, highwater int, err erro
hiPtr := c.arena.new(intlen) hiPtr := c.arena.new(intlen)
curPtr := c.arena.new(intlen) curPtr := c.arena.new(intlen)
var i uint64 var i int32
if reset { if reset {
i = 1 i = 1
} }
r := c.call("sqlite3_db_status", uint64(c.handle), rc := res_t(c.call("sqlite3_db_status", stk_t(c.handle),
uint64(op), uint64(curPtr), uint64(hiPtr), i) stk_t(op), stk_t(curPtr), stk_t(hiPtr), stk_t(i)))
if err = c.error(r); err == nil { if err = c.error(rc); err == nil {
current = int(util.ReadUint32(c.mod, curPtr)) current = int(util.Read32[int32](c.mod, curPtr))
highwater = int(util.ReadUint32(c.mod, hiPtr)) highwater = int(util.Read32[int32](c.mod, hiPtr))
} }
return return
} }
@ -472,7 +467,7 @@ func (c *Conn) Status(op DBStatus, reset bool) (current, highwater int, err erro
func (c *Conn) TableColumnMetadata(schema, table, column string) (declType, collSeq string, notNull, primaryKey, autoInc bool, err error) { func (c *Conn) TableColumnMetadata(schema, table, column string) (declType, collSeq string, notNull, primaryKey, autoInc bool, err error) {
defer c.arena.mark()() defer c.arena.mark()()
var schemaPtr, columnPtr uint32 var schemaPtr, columnPtr ptr_t
declTypePtr := c.arena.new(ptrlen) declTypePtr := c.arena.new(ptrlen)
collSeqPtr := c.arena.new(ptrlen) collSeqPtr := c.arena.new(ptrlen)
notNullPtr := c.arena.new(ptrlen) notNullPtr := c.arena.new(ptrlen)
@ -486,25 +481,25 @@ func (c *Conn) TableColumnMetadata(schema, table, column string) (declType, coll
columnPtr = c.arena.string(column) columnPtr = c.arena.string(column)
} }
r := c.call("sqlite3_table_column_metadata", uint64(c.handle), rc := res_t(c.call("sqlite3_table_column_metadata", stk_t(c.handle),
uint64(schemaPtr), uint64(tablePtr), uint64(columnPtr), stk_t(schemaPtr), stk_t(tablePtr), stk_t(columnPtr),
uint64(declTypePtr), uint64(collSeqPtr), stk_t(declTypePtr), stk_t(collSeqPtr),
uint64(notNullPtr), uint64(primaryKeyPtr), uint64(autoIncPtr)) stk_t(notNullPtr), stk_t(primaryKeyPtr), stk_t(autoIncPtr)))
if err = c.error(r); err == nil && column != "" { if err = c.error(rc); err == nil && column != "" {
if ptr := util.ReadUint32(c.mod, declTypePtr); ptr != 0 { if ptr := util.Read32[ptr_t](c.mod, declTypePtr); ptr != 0 {
declType = util.ReadString(c.mod, ptr, _MAX_NAME) declType = util.ReadString(c.mod, ptr, _MAX_NAME)
} }
if ptr := util.ReadUint32(c.mod, collSeqPtr); ptr != 0 { if ptr := util.Read32[ptr_t](c.mod, collSeqPtr); ptr != 0 {
collSeq = util.ReadString(c.mod, ptr, _MAX_NAME) collSeq = util.ReadString(c.mod, ptr, _MAX_NAME)
} }
notNull = util.ReadUint32(c.mod, notNullPtr) != 0 notNull = util.Read32[uint32](c.mod, notNullPtr) != 0
autoInc = util.ReadUint32(c.mod, autoIncPtr) != 0 autoInc = util.Read32[uint32](c.mod, autoIncPtr) != 0
primaryKey = util.ReadUint32(c.mod, primaryKeyPtr) != 0 primaryKey = util.Read32[uint32](c.mod, primaryKeyPtr) != 0
} }
return return
} }
func (c *Conn) error(rc uint64, sql ...string) error { func (c *Conn) error(rc res_t, sql ...string) error {
return c.sqlite.error(rc, c.handle, sql...) return c.sqlite.error(rc, c.handle, sql...)
} }

View file

@ -1,6 +1,10 @@
package sqlite3 package sqlite3
import "strconv" import (
"strconv"
"github.com/ncruces/go-sqlite3/internal/util"
)
const ( const (
_OK = 0 /* Successful result */ _OK = 0 /* Successful result */
@ -12,8 +16,14 @@
_MAX_SQL_LENGTH = 1e9 _MAX_SQL_LENGTH = 1e9
_MAX_FUNCTION_ARG = 100 _MAX_FUNCTION_ARG = 100
ptrlen = 4 ptrlen = util.PtrLen
intlen = 4 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. // ErrorCode is a result code that [Error.Code] might return.

View file

@ -15,7 +15,7 @@
// https://sqlite.org/c3ref/context.html // https://sqlite.org/c3ref/context.html
type Context struct { type Context struct {
c *Conn c *Conn
handle uint32 handle ptr_t
} }
// Conn returns the database connection of the // Conn returns the database connection of the
@ -32,14 +32,14 @@ func (ctx Context) Conn() *Conn {
// https://sqlite.org/c3ref/get_auxdata.html // https://sqlite.org/c3ref/get_auxdata.html
func (ctx Context) SetAuxData(n int, data any) { func (ctx Context) SetAuxData(n int, data any) {
ptr := util.AddHandle(ctx.c.ctx, data) ptr := util.AddHandle(ctx.c.ctx, data)
ctx.c.call("sqlite3_set_auxdata_go", uint64(ctx.handle), uint64(n), uint64(ptr)) 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. // GetAuxData returns metadata for argument n of the function.
// //
// https://sqlite.org/c3ref/get_auxdata.html // https://sqlite.org/c3ref/get_auxdata.html
func (ctx Context) GetAuxData(n int) any { func (ctx Context) GetAuxData(n int) any {
ptr := uint32(ctx.c.call("sqlite3_get_auxdata", uint64(ctx.handle), uint64(n))) ptr := ptr_t(ctx.c.call("sqlite3_get_auxdata", stk_t(ctx.handle), stk_t(n)))
return util.GetHandle(ctx.c.ctx, ptr) return util.GetHandle(ctx.c.ctx, ptr)
} }
@ -68,7 +68,7 @@ func (ctx Context) ResultInt(value int) {
// https://sqlite.org/c3ref/result_blob.html // https://sqlite.org/c3ref/result_blob.html
func (ctx Context) ResultInt64(value int64) { func (ctx Context) ResultInt64(value int64) {
ctx.c.call("sqlite3_result_int64", ctx.c.call("sqlite3_result_int64",
uint64(ctx.handle), uint64(value)) stk_t(ctx.handle), stk_t(value))
} }
// ResultFloat sets the result of the function to a float64. // ResultFloat sets the result of the function to a float64.
@ -76,7 +76,7 @@ func (ctx Context) ResultInt64(value int64) {
// https://sqlite.org/c3ref/result_blob.html // https://sqlite.org/c3ref/result_blob.html
func (ctx Context) ResultFloat(value float64) { func (ctx Context) ResultFloat(value float64) {
ctx.c.call("sqlite3_result_double", ctx.c.call("sqlite3_result_double",
uint64(ctx.handle), math.Float64bits(value)) stk_t(ctx.handle), stk_t(math.Float64bits(value)))
} }
// ResultText sets the result of the function to a string. // ResultText sets the result of the function to a string.
@ -85,7 +85,7 @@ func (ctx Context) ResultFloat(value float64) {
func (ctx Context) ResultText(value string) { func (ctx Context) ResultText(value string) {
ptr := ctx.c.newString(value) ptr := ctx.c.newString(value)
ctx.c.call("sqlite3_result_text_go", ctx.c.call("sqlite3_result_text_go",
uint64(ctx.handle), uint64(ptr), uint64(len(value))) stk_t(ctx.handle), stk_t(ptr), stk_t(len(value)))
} }
// ResultRawText sets the text result of the function to a []byte. // ResultRawText sets the text result of the function to a []byte.
@ -95,7 +95,7 @@ func (ctx Context) ResultText(value string) {
func (ctx Context) ResultRawText(value []byte) { func (ctx Context) ResultRawText(value []byte) {
ptr := ctx.c.newBytes(value) ptr := ctx.c.newBytes(value)
ctx.c.call("sqlite3_result_text_go", ctx.c.call("sqlite3_result_text_go",
uint64(ctx.handle), uint64(ptr), uint64(len(value))) stk_t(ctx.handle), stk_t(ptr), stk_t(len(value)))
} }
// ResultBlob sets the result of the function to a []byte. // ResultBlob sets the result of the function to a []byte.
@ -105,7 +105,7 @@ func (ctx Context) ResultRawText(value []byte) {
func (ctx Context) ResultBlob(value []byte) { func (ctx Context) ResultBlob(value []byte) {
ptr := ctx.c.newBytes(value) ptr := ctx.c.newBytes(value)
ctx.c.call("sqlite3_result_blob_go", ctx.c.call("sqlite3_result_blob_go",
uint64(ctx.handle), uint64(ptr), uint64(len(value))) 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. // ResultZeroBlob sets the result of the function to a zero-filled, length n BLOB.
@ -113,7 +113,7 @@ func (ctx Context) ResultBlob(value []byte) {
// https://sqlite.org/c3ref/result_blob.html // https://sqlite.org/c3ref/result_blob.html
func (ctx Context) ResultZeroBlob(n int64) { func (ctx Context) ResultZeroBlob(n int64) {
ctx.c.call("sqlite3_result_zeroblob64", ctx.c.call("sqlite3_result_zeroblob64",
uint64(ctx.handle), uint64(n)) stk_t(ctx.handle), stk_t(n))
} }
// ResultNull sets the result of the function to NULL. // ResultNull sets the result of the function to NULL.
@ -121,7 +121,7 @@ func (ctx Context) ResultZeroBlob(n int64) {
// https://sqlite.org/c3ref/result_blob.html // https://sqlite.org/c3ref/result_blob.html
func (ctx Context) ResultNull() { func (ctx Context) ResultNull() {
ctx.c.call("sqlite3_result_null", ctx.c.call("sqlite3_result_null",
uint64(ctx.handle)) stk_t(ctx.handle))
} }
// ResultTime sets the result of the function to a [time.Time]. // ResultTime sets the result of the function to a [time.Time].
@ -146,14 +146,14 @@ func (ctx Context) ResultTime(value time.Time, format TimeFormat) {
} }
func (ctx Context) resultRFC3339Nano(value time.Time) { func (ctx Context) resultRFC3339Nano(value time.Time) {
const maxlen = uint64(len(time.RFC3339Nano)) + 5 const maxlen = int64(len(time.RFC3339Nano)) + 5
ptr := ctx.c.new(maxlen) ptr := ctx.c.new(maxlen)
buf := util.View(ctx.c.mod, ptr, maxlen) buf := util.View(ctx.c.mod, ptr, maxlen)
buf = value.AppendFormat(buf[:0], time.RFC3339Nano) buf = value.AppendFormat(buf[:0], time.RFC3339Nano)
ctx.c.call("sqlite3_result_text_go", ctx.c.call("sqlite3_result_text_go",
uint64(ctx.handle), uint64(ptr), uint64(len(buf))) stk_t(ctx.handle), stk_t(ptr), stk_t(len(buf)))
} }
// ResultPointer sets the result of the function to NULL, just like [Context.ResultNull], // ResultPointer sets the result of the function to NULL, just like [Context.ResultNull],
@ -164,7 +164,7 @@ func (ctx Context) resultRFC3339Nano(value time.Time) {
func (ctx Context) ResultPointer(ptr any) { func (ctx Context) ResultPointer(ptr any) {
valPtr := util.AddHandle(ctx.c.ctx, ptr) valPtr := util.AddHandle(ctx.c.ctx, ptr)
ctx.c.call("sqlite3_result_pointer_go", ctx.c.call("sqlite3_result_pointer_go",
uint64(ctx.handle), uint64(valPtr)) stk_t(ctx.handle), stk_t(valPtr))
} }
// ResultJSON sets the result of the function to the JSON encoding of value. // ResultJSON sets the result of the function to the JSON encoding of value.
@ -188,7 +188,7 @@ func (ctx Context) ResultValue(value Value) {
return return
} }
ctx.c.call("sqlite3_result_value", ctx.c.call("sqlite3_result_value",
uint64(ctx.handle), uint64(value.handle)) stk_t(ctx.handle), stk_t(value.handle))
} }
// ResultError sets the result of the function an error. // ResultError sets the result of the function an error.
@ -196,12 +196,12 @@ func (ctx Context) ResultValue(value Value) {
// https://sqlite.org/c3ref/result_blob.html // https://sqlite.org/c3ref/result_blob.html
func (ctx Context) ResultError(err error) { func (ctx Context) ResultError(err error) {
if errors.Is(err, NOMEM) { if errors.Is(err, NOMEM) {
ctx.c.call("sqlite3_result_error_nomem", uint64(ctx.handle)) ctx.c.call("sqlite3_result_error_nomem", stk_t(ctx.handle))
return return
} }
if errors.Is(err, TOOBIG) { if errors.Is(err, TOOBIG) {
ctx.c.call("sqlite3_result_error_toobig", uint64(ctx.handle)) ctx.c.call("sqlite3_result_error_toobig", stk_t(ctx.handle))
return return
} }
@ -210,11 +210,11 @@ func (ctx Context) ResultError(err error) {
defer ctx.c.arena.mark()() defer ctx.c.arena.mark()()
ptr := ctx.c.arena.string(msg) ptr := ctx.c.arena.string(msg)
ctx.c.call("sqlite3_result_error", ctx.c.call("sqlite3_result_error",
uint64(ctx.handle), uint64(ptr), uint64(len(msg))) stk_t(ctx.handle), stk_t(ptr), stk_t(len(msg)))
} }
if code != _OK { if code != _OK {
ctx.c.call("sqlite3_result_error_code", ctx.c.call("sqlite3_result_error_code",
uint64(ctx.handle), uint64(code)) stk_t(ctx.handle), stk_t(code))
} }
} }
@ -223,6 +223,6 @@ func (ctx Context) ResultError(err error) {
// //
// https://sqlite.org/c3ref/vtab_nochange.html // https://sqlite.org/c3ref/vtab_nochange.html
func (ctx Context) VTabNoChange() bool { func (ctx Context) VTabNoChange() bool {
r := ctx.c.call("sqlite3_vtab_nochange", uint64(ctx.handle)) b := int32(ctx.c.call("sqlite3_vtab_nochange", stk_t(ctx.handle)))
return r != 0 return b != 0
} }

View file

@ -201,7 +201,7 @@ func (n *connector) Driver() driver.Driver {
return &SQLite{} return &SQLite{}
} }
func (n *connector) Connect(ctx context.Context) (res driver.Conn, err error) { func (n *connector) Connect(ctx context.Context) (ret driver.Conn, err error) {
c := &conn{ c := &conn{
txLock: n.txLock, txLock: n.txLock,
tmRead: n.tmRead, tmRead: n.tmRead,
@ -213,7 +213,7 @@ func (n *connector) Connect(ctx context.Context) (res driver.Conn, err error) {
return nil, err return nil, err
} }
defer func() { defer func() {
if res == nil { if ret == nil {
c.Close() c.Close()
} }
}() }()
@ -466,8 +466,9 @@ func (s *stmt) ExecContext(ctx context.Context, args []driver.NamedValue) (drive
old := s.Stmt.Conn().SetInterrupt(ctx) old := s.Stmt.Conn().SetInterrupt(ctx)
defer s.Stmt.Conn().SetInterrupt(old) defer s.Stmt.Conn().SetInterrupt(old)
err = s.Stmt.Exec() err = errors.Join(
s.Stmt.ClearBindings() s.Stmt.Exec(),
s.Stmt.ClearBindings())
if err != nil { if err != nil {
return nil, err return nil, err
} }
@ -604,8 +605,9 @@ type rows struct {
) )
func (r *rows) Close() error { func (r *rows) Close() error {
r.Stmt.ClearBindings() return errors.Join(
return r.Stmt.Reset() r.Stmt.Reset(),
r.Stmt.ClearBindings())
} }
func (r *rows) Columns() []string { func (r *rows) Columns() []string {
@ -718,19 +720,19 @@ func (r *rows) ColumnTypeScanType(index int) (typ reflect.Type) {
switch scan { switch scan {
case _INT: case _INT:
return reflect.TypeOf(int64(0)) return reflect.TypeFor[int64]()
case _REAL: case _REAL:
return reflect.TypeOf(float64(0)) return reflect.TypeFor[float64]()
case _TEXT: case _TEXT:
return reflect.TypeOf("") return reflect.TypeFor[string]()
case _BLOB: case _BLOB:
return reflect.TypeOf([]byte{}) return reflect.TypeFor[[]byte]()
case _BOOL: case _BOOL:
return reflect.TypeOf(false) return reflect.TypeFor[bool]()
case _TIME: case _TIME:
return reflect.TypeOf(time.Time{}) return reflect.TypeFor[time.Time]()
default: default:
return reflect.TypeOf((*any)(nil)).Elem() return reflect.TypeFor[any]()
} }
} }

View file

@ -1,6 +1,6 @@
# Embeddable Wasm build of SQLite # Embeddable Wasm build of SQLite
This folder includes an embeddable Wasm build of SQLite 3.48.0 for use with 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). [`github.com/ncruces/go-sqlite3`](https://pkg.go.dev/github.com/ncruces/go-sqlite3).
The following optional features are compiled in: The following optional features are compiled in:

Binary file not shown.

View file

@ -15,7 +15,7 @@ type Error struct {
str string str string
msg string msg string
sql string sql string
code uint64 code res_t
} }
// Code returns the primary error code for this error. // Code returns the primary error code for this error.
@ -146,27 +146,27 @@ func (e ExtendedErrorCode) Code() ErrorCode {
return ErrorCode(e) return ErrorCode(e)
} }
func errorCode(err error, def ErrorCode) (msg string, code uint32) { func errorCode(err error, def ErrorCode) (msg string, code res_t) {
switch code := err.(type) { switch code := err.(type) {
case nil: case nil:
return "", _OK return "", _OK
case ErrorCode: case ErrorCode:
return "", uint32(code) return "", res_t(code)
case xErrorCode: case xErrorCode:
return "", uint32(code) return "", res_t(code)
case *Error: case *Error:
return code.msg, uint32(code.code) return code.msg, res_t(code.code)
} }
var ecode ErrorCode var ecode ErrorCode
var xcode xErrorCode var xcode xErrorCode
switch { switch {
case errors.As(err, &xcode): case errors.As(err, &xcode):
code = uint32(xcode) code = res_t(xcode)
case errors.As(err, &ecode): case errors.As(err, &ecode):
code = uint32(ecode) code = res_t(ecode)
default: default:
code = uint32(def) code = res_t(def)
} }
return err.Error(), code return err.Error(), code
} }

View file

@ -14,12 +14,12 @@
// //
// https://sqlite.org/c3ref/collation_needed.html // https://sqlite.org/c3ref/collation_needed.html
func (c *Conn) CollationNeeded(cb func(db *Conn, name string)) error { func (c *Conn) CollationNeeded(cb func(db *Conn, name string)) error {
var enable uint64 var enable int32
if cb != nil { if cb != nil {
enable = 1 enable = 1
} }
r := c.call("sqlite3_collation_needed_go", uint64(c.handle), enable) rc := res_t(c.call("sqlite3_collation_needed_go", stk_t(c.handle), stk_t(enable)))
if err := c.error(r); err != nil { if err := c.error(rc); err != nil {
return err return err
} }
c.collation = cb c.collation = cb
@ -33,8 +33,8 @@ func (c *Conn) CollationNeeded(cb func(db *Conn, name string)) error {
// This can be used to load schemas that contain // This can be used to load schemas that contain
// one or more unknown collating sequences. // one or more unknown collating sequences.
func (c Conn) AnyCollationNeeded() error { func (c Conn) AnyCollationNeeded() error {
r := c.call("sqlite3_anycollseq_init", uint64(c.handle), 0, 0) rc := res_t(c.call("sqlite3_anycollseq_init", stk_t(c.handle), 0, 0))
if err := c.error(r); err != nil { if err := c.error(rc); err != nil {
return err return err
} }
c.collation = nil c.collation = nil
@ -45,31 +45,31 @@ func (c Conn) AnyCollationNeeded() error {
// //
// https://sqlite.org/c3ref/create_collation.html // https://sqlite.org/c3ref/create_collation.html
func (c *Conn) CreateCollation(name string, fn func(a, b []byte) int) error { func (c *Conn) CreateCollation(name string, fn func(a, b []byte) int) error {
var funcPtr uint32 var funcPtr ptr_t
defer c.arena.mark()() defer c.arena.mark()()
namePtr := c.arena.string(name) namePtr := c.arena.string(name)
if fn != nil { if fn != nil {
funcPtr = util.AddHandle(c.ctx, fn) funcPtr = util.AddHandle(c.ctx, fn)
} }
r := c.call("sqlite3_create_collation_go", rc := res_t(c.call("sqlite3_create_collation_go",
uint64(c.handle), uint64(namePtr), uint64(funcPtr)) stk_t(c.handle), stk_t(namePtr), stk_t(funcPtr)))
return c.error(r) return c.error(rc)
} }
// CreateFunction defines a new scalar SQL function. // CreateFunction defines a new scalar SQL function.
// //
// https://sqlite.org/c3ref/create_function.html // https://sqlite.org/c3ref/create_function.html
func (c *Conn) CreateFunction(name string, nArg int, flag FunctionFlag, fn ScalarFunction) error { func (c *Conn) CreateFunction(name string, nArg int, flag FunctionFlag, fn ScalarFunction) error {
var funcPtr uint32 var funcPtr ptr_t
defer c.arena.mark()() defer c.arena.mark()()
namePtr := c.arena.string(name) namePtr := c.arena.string(name)
if fn != nil { if fn != nil {
funcPtr = util.AddHandle(c.ctx, fn) funcPtr = util.AddHandle(c.ctx, fn)
} }
r := c.call("sqlite3_create_function_go", rc := res_t(c.call("sqlite3_create_function_go",
uint64(c.handle), uint64(namePtr), uint64(nArg), stk_t(c.handle), stk_t(namePtr), stk_t(nArg),
uint64(flag), uint64(funcPtr)) stk_t(flag), stk_t(funcPtr)))
return c.error(r) return c.error(rc)
} }
// ScalarFunction is the type of a scalar SQL function. // ScalarFunction is the type of a scalar SQL function.
@ -82,7 +82,7 @@ funcPtr = util.AddHandle(c.ctx, fn)
// //
// https://sqlite.org/c3ref/create_function.html // https://sqlite.org/c3ref/create_function.html
func (c *Conn) CreateWindowFunction(name string, nArg int, flag FunctionFlag, fn func() AggregateFunction) error { func (c *Conn) CreateWindowFunction(name string, nArg int, flag FunctionFlag, fn func() AggregateFunction) error {
var funcPtr uint32 var funcPtr ptr_t
defer c.arena.mark()() defer c.arena.mark()()
namePtr := c.arena.string(name) namePtr := c.arena.string(name)
if fn != nil { if fn != nil {
@ -92,10 +92,10 @@ funcPtr = util.AddHandle(c.ctx, fn)
if _, ok := fn().(WindowFunction); ok { if _, ok := fn().(WindowFunction); ok {
call = "sqlite3_create_window_function_go" call = "sqlite3_create_window_function_go"
} }
r := c.call(call, rc := res_t(c.call(call,
uint64(c.handle), uint64(namePtr), uint64(nArg), stk_t(c.handle), stk_t(namePtr), stk_t(nArg),
uint64(flag), uint64(funcPtr)) stk_t(flag), stk_t(funcPtr)))
return c.error(r) return c.error(rc)
} }
// AggregateFunction is the interface an aggregate function should implement. // AggregateFunction is the interface an aggregate function should implement.
@ -129,28 +129,28 @@ type WindowFunction interface {
func (c *Conn) OverloadFunction(name string, nArg int) error { func (c *Conn) OverloadFunction(name string, nArg int) error {
defer c.arena.mark()() defer c.arena.mark()()
namePtr := c.arena.string(name) namePtr := c.arena.string(name)
r := c.call("sqlite3_overload_function", rc := res_t(c.call("sqlite3_overload_function",
uint64(c.handle), uint64(namePtr), uint64(nArg)) stk_t(c.handle), stk_t(namePtr), stk_t(nArg)))
return c.error(r) return c.error(rc)
} }
func destroyCallback(ctx context.Context, mod api.Module, pApp uint32) { func destroyCallback(ctx context.Context, mod api.Module, pApp ptr_t) {
util.DelHandle(ctx, pApp) util.DelHandle(ctx, pApp)
} }
func collationCallback(ctx context.Context, mod api.Module, pArg, pDB, eTextRep, zName uint32) { 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 { if c, ok := ctx.Value(connKey{}).(*Conn); ok && c.handle == pDB && c.collation != nil {
name := util.ReadString(mod, zName, _MAX_NAME) name := util.ReadString(mod, zName, _MAX_NAME)
c.collation(c, name) c.collation(c, name)
} }
} }
func compareCallback(ctx context.Context, mod api.Module, pApp, nKey1, pKey1, nKey2, pKey2 uint32) uint32 { 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) fn := util.GetHandle(ctx, pApp).(func(a, b []byte) int)
return uint32(fn(util.View(mod, pKey1, uint64(nKey1)), util.View(mod, pKey2, uint64(nKey2)))) 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, nArg, pArg uint32) { func funcCallback(ctx context.Context, mod api.Module, pCtx, pApp ptr_t, nArg int32, pArg ptr_t) {
args := getFuncArgs() args := getFuncArgs()
defer putFuncArgs(args) defer putFuncArgs(args)
db := ctx.Value(connKey{}).(*Conn) db := ctx.Value(connKey{}).(*Conn)
@ -159,7 +159,7 @@ func funcCallback(ctx context.Context, mod api.Module, pCtx, pApp, nArg, pArg ui
fn(Context{db, pCtx}, args[:nArg]...) fn(Context{db, pCtx}, args[:nArg]...)
} }
func stepCallback(ctx context.Context, mod api.Module, pCtx, pAgg, pApp, nArg, pArg uint32) { func stepCallback(ctx context.Context, mod api.Module, pCtx, pAgg, pApp ptr_t, nArg int32, pArg ptr_t) {
args := getFuncArgs() args := getFuncArgs()
defer putFuncArgs(args) defer putFuncArgs(args)
db := ctx.Value(connKey{}).(*Conn) db := ctx.Value(connKey{}).(*Conn)
@ -168,20 +168,23 @@ func stepCallback(ctx context.Context, mod api.Module, pCtx, pAgg, pApp, nArg, p
fn.Step(Context{db, pCtx}, args[:nArg]...) fn.Step(Context{db, pCtx}, args[:nArg]...)
} }
func finalCallback(ctx context.Context, mod api.Module, pCtx, pAgg, pApp uint32) { func finalCallback(ctx context.Context, mod api.Module, pCtx, pAgg, pApp ptr_t) {
db := ctx.Value(connKey{}).(*Conn) db := ctx.Value(connKey{}).(*Conn)
fn, handle := callbackAggregate(db, pAgg, pApp) fn, handle := callbackAggregate(db, pAgg, pApp)
fn.Value(Context{db, pCtx}) fn.Value(Context{db, pCtx})
util.DelHandle(ctx, handle) 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 uint32) { func valueCallback(ctx context.Context, mod api.Module, pCtx, pAgg ptr_t) {
db := ctx.Value(connKey{}).(*Conn) db := ctx.Value(connKey{}).(*Conn)
fn := util.GetHandle(db.ctx, pAgg).(AggregateFunction) fn := util.GetHandle(db.ctx, pAgg).(AggregateFunction)
fn.Value(Context{db, pCtx}) fn.Value(Context{db, pCtx})
} }
func inverseCallback(ctx context.Context, mod api.Module, pCtx, pAgg, nArg, pArg uint32) { func inverseCallback(ctx context.Context, mod api.Module, pCtx, pAgg ptr_t, nArg int32, pArg ptr_t) {
args := getFuncArgs() args := getFuncArgs()
defer putFuncArgs(args) defer putFuncArgs(args)
db := ctx.Value(connKey{}).(*Conn) db := ctx.Value(connKey{}).(*Conn)
@ -190,9 +193,9 @@ func inverseCallback(ctx context.Context, mod api.Module, pCtx, pAgg, nArg, pArg
fn.Inverse(Context{db, pCtx}, args[:nArg]...) fn.Inverse(Context{db, pCtx}, args[:nArg]...)
} }
func callbackAggregate(db *Conn, pAgg, pApp uint32) (AggregateFunction, uint32) { func callbackAggregate(db *Conn, pAgg, pApp ptr_t) (AggregateFunction, ptr_t) {
if pApp == 0 { if pApp == 0 {
handle := util.ReadUint32(db.mod, pAgg) handle := util.Read32[ptr_t](db.mod, pAgg)
return util.GetHandle(db.ctx, handle).(AggregateFunction), handle return util.GetHandle(db.ctx, handle).(AggregateFunction), handle
} }
@ -200,17 +203,17 @@ func callbackAggregate(db *Conn, pAgg, pApp uint32) (AggregateFunction, uint32)
fn := util.GetHandle(db.ctx, pApp).(func() AggregateFunction)() fn := util.GetHandle(db.ctx, pApp).(func() AggregateFunction)()
if pAgg != 0 { if pAgg != 0 {
handle := util.AddHandle(db.ctx, fn) handle := util.AddHandle(db.ctx, fn)
util.WriteUint32(db.mod, pAgg, handle) util.Write32(db.mod, pAgg, handle)
return fn, handle return fn, handle
} }
return fn, 0 return fn, 0
} }
func callbackArgs(db *Conn, arg []Value, pArg uint32) { func callbackArgs(db *Conn, arg []Value, pArg ptr_t) {
for i := range arg { for i := range arg {
arg[i] = Value{ arg[i] = Value{
c: db, c: db,
handle: util.ReadUint32(db.mod, pArg+ptrlen*uint32(i)), handle: util.Read32[ptr_t](db.mod, pArg+ptr_t(i)*ptrlen),
} }
} }
} }

View file

@ -1,7 +0,0 @@
go 1.21
use (
.
./gormlite
./embed/bcw2
)

View file

@ -1,17 +0,0 @@
github.com/ncruces/go-sqlite3 v0.21.0/go.mod h1:zxMOaSG5kFYVFK4xQa0pdwIszqxqJ0W0BxBgwdrNjuA=
golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
golang.org/x/mod v0.17.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c=
golang.org/x/net v0.21.0/go.mod h1:bIjVDfnllIU7BJ2DNgfnXvpSvtn8VRwhlsaeUTyUS44=
golang.org/x/net v0.25.0/go.mod h1:JkAGAh7GEvH74S6FOH42FLoXpXbE/aqXSrIQjXgsiwM=
golang.org/x/telemetry v0.0.0-20240228155512-f48c80bd79b2/go.mod h1:TeRTkGYfJXctD9OcfyVLyj2J3IxLnKwHJR8f4D8a3YE=
golang.org/x/term v0.20.0/go.mod h1:8UkIAJTvZgivsXaD6/pH6U9ecQzZ45awqEOzuCvwpFY=
golang.org/x/term v0.21.0/go.mod h1:ooXLefLobQVslOqselCNF4SxFAaoS6KujMbsGzSDmX0=
golang.org/x/term v0.22.0/go.mod h1:F3qCibpT5AMpCRfhfT53vVJwhLtIVHhB9XDjfFvnMI4=
golang.org/x/term v0.23.0/go.mod h1:DgV24QBUrK6jhZXl+20l6UWznPlwAHm1Q1mGHtydmSk=
golang.org/x/term v0.24.0/go.mod h1:lOBK/LVxemqiMij05LGJ0tzNr8xlmwBRJ81PX6wVLH8=
golang.org/x/term v0.25.0/go.mod h1:RPyXicDX+6vLxogjjRxjgD2TKtmAO6NZBsBRfrOLu7M=
golang.org/x/term v0.26.0/go.mod h1:Si5m1o57C5nBNQo5z1iq+XDijt21BDBDp2bK0QI8e3E=
golang.org/x/term v0.27.0/go.mod h1:iMsnZpn0cago0GOrHO2+Y7u7JPn5AylBrcoWkElMTSM=
golang.org/x/term v0.28.0/go.mod h1:Sw/lC2IAUZ92udQNf3WodGtn4k/XoLyZoh8v/8uiwek=
golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU=
golang.org/x/tools v0.21.1-0.20240508182429-e35e4ccd0d2d/go.mod h1:aiJjzUbINMkxbQROHiO6hDPo2LHcIPhhQsa9DLh0yGk=

View file

@ -7,9 +7,6 @@
"github.com/tetratelabs/wazero/api" "github.com/tetratelabs/wazero/api"
) )
type i32 interface{ ~int32 | ~uint32 }
type i64 interface{ ~int64 | ~uint64 }
type funcVI[T0 i32] func(context.Context, api.Module, T0) type funcVI[T0 i32] func(context.Context, api.Module, T0)
func (fn funcVI[T0]) Call(ctx context.Context, mod api.Module, stack []uint64) { func (fn funcVI[T0]) Call(ctx context.Context, mod api.Module, stack []uint64) {

View file

@ -20,7 +20,7 @@ func (s *handleState) CloseNotify(ctx context.Context, exitCode uint32) {
s.holes = 0 s.holes = 0
} }
func GetHandle(ctx context.Context, id uint32) any { func GetHandle(ctx context.Context, id Ptr_t) any {
if id == 0 { if id == 0 {
return nil return nil
} }
@ -28,14 +28,14 @@ func GetHandle(ctx context.Context, id uint32) any {
return s.handles[^id] return s.handles[^id]
} }
func DelHandle(ctx context.Context, id uint32) error { func DelHandle(ctx context.Context, id Ptr_t) error {
if id == 0 { if id == 0 {
return nil return nil
} }
s := ctx.Value(moduleKey{}).(*moduleState) s := ctx.Value(moduleKey{}).(*moduleState)
a := s.handles[^id] a := s.handles[^id]
s.handles[^id] = nil s.handles[^id] = nil
if l := uint32(len(s.handles)); l == ^id { if l := Ptr_t(len(s.handles)); l == ^id {
s.handles = s.handles[:l-1] s.handles = s.handles[:l-1]
} else { } else {
s.holes++ s.holes++
@ -46,7 +46,7 @@ func DelHandle(ctx context.Context, id uint32) error {
return nil return nil
} }
func AddHandle(ctx context.Context, a any) uint32 { func AddHandle(ctx context.Context, a any) Ptr_t {
if a == nil { if a == nil {
panic(NilErr) panic(NilErr)
} }
@ -59,12 +59,12 @@ func AddHandle(ctx context.Context, a any) uint32 {
if h == nil { if h == nil {
s.holes-- s.holes--
s.handles[id] = a s.handles[id] = a
return ^uint32(id) return ^Ptr_t(id)
} }
} }
} }
// Add a new slot. // Add a new slot.
s.handles = append(s.handles, a) s.handles = append(s.handles, a)
return -uint32(len(s.handles)) return -Ptr_t(len(s.handles))
} }

View file

@ -2,6 +2,7 @@
import ( import (
"encoding/json" "encoding/json"
"math"
"strconv" "strconv"
"time" "time"
"unsafe" "unsafe"
@ -20,7 +21,7 @@ func (j JSON) Scan(value any) error {
case int64: case int64:
buf = strconv.AppendInt(nil, v, 10) buf = strconv.AppendInt(nil, v, 10)
case float64: case float64:
buf = strconv.AppendFloat(nil, v, 'g', -1, 64) buf = AppendNumber(nil, v)
case time.Time: case time.Time:
buf = append(buf, '"') buf = append(buf, '"')
buf = v.AppendFormat(buf, time.RFC3339Nano) buf = v.AppendFormat(buf, time.RFC3339Nano)
@ -33,3 +34,17 @@ func (j JSON) Scan(value any) error {
return json.Unmarshal(buf, j.Value) 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
}

View file

@ -7,110 +7,121 @@
"github.com/tetratelabs/wazero/api" "github.com/tetratelabs/wazero/api"
) )
func View(mod api.Module, ptr uint32, size uint64) []byte { 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 { if ptr == 0 {
panic(NilErr) panic(NilErr)
} }
if size > math.MaxUint32 {
panic(RangeErr)
}
if size == 0 { if size == 0 {
return nil return nil
} }
buf, ok := mod.Memory().Read(ptr, uint32(size)) if uint64(size) > math.MaxUint32 {
panic(RangeErr)
}
buf, ok := mod.Memory().Read(uint32(ptr), uint32(size))
if !ok { if !ok {
panic(RangeErr) panic(RangeErr)
} }
return buf return buf
} }
func ReadUint8(mod api.Module, ptr uint32) uint8 { func Read[T i8](mod api.Module, ptr Ptr_t) T {
if ptr == 0 { if ptr == 0 {
panic(NilErr) panic(NilErr)
} }
v, ok := mod.Memory().ReadByte(ptr) v, ok := mod.Memory().ReadByte(uint32(ptr))
if !ok { if !ok {
panic(RangeErr) panic(RangeErr)
} }
return v return T(v)
} }
func ReadUint32(mod api.Module, ptr uint32) uint32 { func Write[T i8](mod api.Module, ptr Ptr_t, v T) {
if ptr == 0 { if ptr == 0 {
panic(NilErr) panic(NilErr)
} }
v, ok := mod.Memory().ReadUint32Le(ptr) ok := mod.Memory().WriteByte(uint32(ptr), uint8(v))
if !ok {
panic(RangeErr)
}
return v
}
func WriteUint8(mod api.Module, ptr uint32, v uint8) {
if ptr == 0 {
panic(NilErr)
}
ok := mod.Memory().WriteByte(ptr, v)
if !ok { if !ok {
panic(RangeErr) panic(RangeErr)
} }
} }
func WriteUint32(mod api.Module, ptr uint32, v uint32) { func Read32[T i32](mod api.Module, ptr Ptr_t) T {
if ptr == 0 { if ptr == 0 {
panic(NilErr) panic(NilErr)
} }
ok := mod.Memory().WriteUint32Le(ptr, v) 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 { if !ok {
panic(RangeErr) panic(RangeErr)
} }
} }
func ReadUint64(mod api.Module, ptr uint32) uint64 { func Read64[T i64](mod api.Module, ptr Ptr_t) T {
if ptr == 0 { if ptr == 0 {
panic(NilErr) panic(NilErr)
} }
v, ok := mod.Memory().ReadUint64Le(ptr) v, ok := mod.Memory().ReadUint64Le(uint32(ptr))
if !ok { if !ok {
panic(RangeErr) panic(RangeErr)
} }
return v return T(v)
} }
func WriteUint64(mod api.Module, ptr uint32, v uint64) { func Write64[T i64](mod api.Module, ptr Ptr_t, v T) {
if ptr == 0 { if ptr == 0 {
panic(NilErr) panic(NilErr)
} }
ok := mod.Memory().WriteUint64Le(ptr, v) ok := mod.Memory().WriteUint64Le(uint32(ptr), uint64(v))
if !ok { if !ok {
panic(RangeErr) panic(RangeErr)
} }
} }
func ReadFloat64(mod api.Module, ptr uint32) float64 { func ReadFloat64(mod api.Module, ptr Ptr_t) float64 {
return math.Float64frombits(ReadUint64(mod, ptr)) return math.Float64frombits(Read64[uint64](mod, ptr))
} }
func WriteFloat64(mod api.Module, ptr uint32, v float64) { func WriteFloat64(mod api.Module, ptr Ptr_t, v float64) {
WriteUint64(mod, ptr, math.Float64bits(v)) Write64(mod, ptr, math.Float64bits(v))
} }
func ReadString(mod api.Module, ptr, maxlen uint32) string { func ReadString(mod api.Module, ptr Ptr_t, maxlen int64) string {
if ptr == 0 { if ptr == 0 {
panic(NilErr) panic(NilErr)
} }
switch maxlen { if maxlen <= 0 {
case 0:
return "" return ""
case math.MaxUint32:
// avoid overflow
default:
maxlen = maxlen + 1
} }
mem := mod.Memory() mem := mod.Memory()
buf, ok := mem.Read(ptr, maxlen) maxlen = min(maxlen, math.MaxInt32-1) + 1
buf, ok := mem.Read(uint32(ptr), uint32(maxlen))
if !ok { if !ok {
buf, ok = mem.Read(ptr, mem.Size()-ptr) buf, ok = mem.Read(uint32(ptr), mem.Size()-uint32(ptr))
if !ok { if !ok {
panic(RangeErr) panic(RangeErr)
} }
@ -122,13 +133,13 @@ func ReadString(mod api.Module, ptr, maxlen uint32) string {
} }
} }
func WriteBytes(mod api.Module, ptr uint32, b []byte) { func WriteBytes(mod api.Module, ptr Ptr_t, b []byte) {
buf := View(mod, ptr, uint64(len(b))) buf := View(mod, ptr, int64(len(b)))
copy(buf, b) copy(buf, b)
} }
func WriteString(mod api.Module, ptr uint32, s string) { func WriteString(mod api.Module, ptr Ptr_t, s string) {
buf := View(mod, ptr, uint64(len(s)+1)) buf := View(mod, ptr, int64(len(s))+1)
buf[len(s)] = 0 buf[len(s)] = 0
copy(buf, s) copy(buf, s)
} }

View file

@ -25,9 +25,9 @@ func (s *mmapState) new(ctx context.Context, mod api.Module, size int32) *Mapped
// Allocate page aligned memmory. // Allocate page aligned memmory.
alloc := mod.ExportedFunction("aligned_alloc") alloc := mod.ExportedFunction("aligned_alloc")
stack := [...]uint64{ stack := [...]Stk_t{
uint64(unix.Getpagesize()), Stk_t(unix.Getpagesize()),
uint64(size), Stk_t(size),
} }
if err := alloc.CallWithStack(ctx, stack[:]); err != nil { if err := alloc.CallWithStack(ctx, stack[:]); err != nil {
panic(err) panic(err)
@ -37,20 +37,20 @@ func (s *mmapState) new(ctx context.Context, mod api.Module, size int32) *Mapped
} }
// Save the newly allocated region. // Save the newly allocated region.
ptr := uint32(stack[0]) ptr := Ptr_t(stack[0])
buf := View(mod, ptr, uint64(size)) buf := View(mod, ptr, int64(size))
res := &MappedRegion{ ret := &MappedRegion{
Ptr: ptr, Ptr: ptr,
size: size, size: size,
addr: unsafe.Pointer(&buf[0]), addr: unsafe.Pointer(&buf[0]),
} }
s.regions = append(s.regions, res) s.regions = append(s.regions, ret)
return res return ret
} }
type MappedRegion struct { type MappedRegion struct {
addr unsafe.Pointer addr unsafe.Pointer
Ptr uint32 Ptr Ptr_t
size int32 size int32
used bool used bool
} }

View file

@ -29,13 +29,13 @@ func MapRegion(ctx context.Context, mod api.Module, f *os.File, offset int64, si
return nil, err return nil, err
} }
res := &MappedRegion{Handle: h, addr: a} ret := &MappedRegion{Handle: h, addr: a}
// SliceHeader, although deprecated, avoids a go vet warning. // SliceHeader, although deprecated, avoids a go vet warning.
sh := (*reflect.SliceHeader)(unsafe.Pointer(&res.Data)) sh := (*reflect.SliceHeader)(unsafe.Pointer(&ret.Data))
sh.Len = int(size) sh.Len = int(size)
sh.Cap = int(size) sh.Cap = int(size)
sh.Data = a sh.Data = a
return res, nil return ret, nil
} }
func (r *MappedRegion) Unmap() error { func (r *MappedRegion) Unmap() error {

View file

@ -3,7 +3,6 @@
import ( import (
"context" "context"
"math"
"math/bits" "math/bits"
"os" "os"
"sync" "sync"
@ -58,8 +57,8 @@ func compileSQLite() {
} else { } else {
cfg = cfg.WithMemoryLimitPages(4096) // 256MB cfg = cfg.WithMemoryLimitPages(4096) // 256MB
} }
cfg = cfg.WithCoreFeatures(api.CoreFeaturesV2)
} }
cfg = cfg.WithCoreFeatures(api.CoreFeaturesV2)
instance.runtime = wazero.NewRuntimeWithConfig(ctx, cfg) instance.runtime = wazero.NewRuntimeWithConfig(ctx, cfg)
@ -94,7 +93,7 @@ funcs struct {
id [32]*byte id [32]*byte
mask uint32 mask uint32
} }
stack [9]uint64 stack [9]stk_t
} }
func instantiateSQLite() (sqlt *sqlite, err error) { func instantiateSQLite() (sqlt *sqlite, err error) {
@ -120,7 +119,7 @@ func (sqlt *sqlite) close() error {
return sqlt.mod.Close(sqlt.ctx) return sqlt.mod.Close(sqlt.ctx)
} }
func (sqlt *sqlite) error(rc uint64, handle uint32, sql ...string) error { func (sqlt *sqlite) error(rc res_t, handle ptr_t, sql ...string) error {
if rc == _OK { if rc == _OK {
return nil return nil
} }
@ -131,18 +130,18 @@ func (sqlt *sqlite) error(rc uint64, handle uint32, sql ...string) error {
panic(util.OOMErr) panic(util.OOMErr)
} }
if r := sqlt.call("sqlite3_errstr", rc); r != 0 { if ptr := ptr_t(sqlt.call("sqlite3_errstr", stk_t(rc))); ptr != 0 {
err.str = util.ReadString(sqlt.mod, uint32(r), _MAX_NAME) err.str = util.ReadString(sqlt.mod, ptr, _MAX_NAME)
} }
if handle != 0 { if handle != 0 {
if r := sqlt.call("sqlite3_errmsg", uint64(handle)); r != 0 { if ptr := ptr_t(sqlt.call("sqlite3_errmsg", stk_t(handle))); ptr != 0 {
err.msg = util.ReadString(sqlt.mod, uint32(r), _MAX_LENGTH) err.msg = util.ReadString(sqlt.mod, ptr, _MAX_LENGTH)
} }
if len(sql) != 0 { if len(sql) != 0 {
if r := sqlt.call("sqlite3_error_offset", uint64(handle)); r != math.MaxUint32 { if i := int32(sqlt.call("sqlite3_error_offset", stk_t(handle))); i != -1 {
err.sql = sql[0][r:] err.sql = sql[0][i:]
} }
} }
} }
@ -182,7 +181,7 @@ func (sqlt *sqlite) putfn(name string, fn api.Function) {
} }
} }
func (sqlt *sqlite) call(name string, params ...uint64) uint64 { func (sqlt *sqlite) call(name string, params ...stk_t) stk_t {
copy(sqlt.stack[:], params) copy(sqlt.stack[:], params)
fn := sqlt.getfn(name) fn := sqlt.getfn(name)
err := fn.CallWithStack(sqlt.ctx, sqlt.stack[:]) err := fn.CallWithStack(sqlt.ctx, sqlt.stack[:])
@ -190,33 +189,33 @@ func (sqlt *sqlite) call(name string, params ...uint64) uint64 {
panic(err) panic(err)
} }
sqlt.putfn(name, fn) sqlt.putfn(name, fn)
return sqlt.stack[0] return stk_t(sqlt.stack[0])
} }
func (sqlt *sqlite) free(ptr uint32) { func (sqlt *sqlite) free(ptr ptr_t) {
if ptr == 0 { if ptr == 0 {
return return
} }
sqlt.call("sqlite3_free", uint64(ptr)) sqlt.call("sqlite3_free", stk_t(ptr))
} }
func (sqlt *sqlite) new(size uint64) uint32 { func (sqlt *sqlite) new(size int64) ptr_t {
ptr := uint32(sqlt.call("sqlite3_malloc64", size)) ptr := ptr_t(sqlt.call("sqlite3_malloc64", stk_t(size)))
if ptr == 0 && size != 0 { if ptr == 0 && size != 0 {
panic(util.OOMErr) panic(util.OOMErr)
} }
return ptr return ptr
} }
func (sqlt *sqlite) realloc(ptr uint32, size uint64) uint32 { func (sqlt *sqlite) realloc(ptr ptr_t, size int64) ptr_t {
ptr = uint32(sqlt.call("sqlite3_realloc64", uint64(ptr), size)) ptr = ptr_t(sqlt.call("sqlite3_realloc64", stk_t(ptr), stk_t(size)))
if ptr == 0 && size != 0 { if ptr == 0 && size != 0 {
panic(util.OOMErr) panic(util.OOMErr)
} }
return ptr return ptr
} }
func (sqlt *sqlite) newBytes(b []byte) uint32 { func (sqlt *sqlite) newBytes(b []byte) ptr_t {
if (*[0]byte)(b) == nil { if (*[0]byte)(b) == nil {
return 0 return 0
} }
@ -224,33 +223,31 @@ func (sqlt *sqlite) newBytes(b []byte) uint32 {
if size == 0 { if size == 0 {
size = 1 size = 1
} }
ptr := sqlt.new(uint64(size)) ptr := sqlt.new(int64(size))
util.WriteBytes(sqlt.mod, ptr, b) util.WriteBytes(sqlt.mod, ptr, b)
return ptr return ptr
} }
func (sqlt *sqlite) newString(s string) uint32 { func (sqlt *sqlite) newString(s string) ptr_t {
ptr := sqlt.new(uint64(len(s) + 1)) ptr := sqlt.new(int64(len(s)) + 1)
util.WriteString(sqlt.mod, ptr, s) util.WriteString(sqlt.mod, ptr, s)
return ptr return ptr
} }
func (sqlt *sqlite) newArena(size uint64) arena { const arenaSize = 4096
// Ensure the arena's size is a multiple of 8.
size = (size + 7) &^ 7 func (sqlt *sqlite) newArena() arena {
return arena{ return arena{
sqlt: sqlt, sqlt: sqlt,
size: uint32(size), base: sqlt.new(arenaSize),
base: sqlt.new(size),
} }
} }
type arena struct { type arena struct {
sqlt *sqlite sqlt *sqlite
ptrs []uint32 ptrs []ptr_t
base uint32 base ptr_t
next uint32 next int32
size uint32
} }
func (a *arena) free() { func (a *arena) free() {
@ -277,34 +274,34 @@ func (a *arena) mark() (reset func()) {
} }
} }
func (a *arena) new(size uint64) uint32 { func (a *arena) new(size int64) ptr_t {
// Align the next address, to 4 or 8 bytes. // Align the next address, to 4 or 8 bytes.
if size&7 != 0 { if size&7 != 0 {
a.next = (a.next + 3) &^ 3 a.next = (a.next + 3) &^ 3
} else { } else {
a.next = (a.next + 7) &^ 7 a.next = (a.next + 7) &^ 7
} }
if size <= uint64(a.size-a.next) { if size <= arenaSize-int64(a.next) {
ptr := a.base + a.next ptr := a.base + ptr_t(a.next)
a.next += uint32(size) a.next += int32(size)
return ptr return ptr_t(ptr)
} }
ptr := a.sqlt.new(size) ptr := a.sqlt.new(size)
a.ptrs = append(a.ptrs, ptr) a.ptrs = append(a.ptrs, ptr)
return ptr return ptr_t(ptr)
} }
func (a *arena) bytes(b []byte) uint32 { func (a *arena) bytes(b []byte) ptr_t {
if (*[0]byte)(b) == nil { if (*[0]byte)(b) == nil {
return 0 return 0
} }
ptr := a.new(uint64(len(b))) ptr := a.new(int64(len(b)))
util.WriteBytes(a.sqlt.mod, ptr, b) util.WriteBytes(a.sqlt.mod, ptr, b)
return ptr return ptr
} }
func (a *arena) string(s string) uint32 { func (a *arena) string(s string) ptr_t {
ptr := a.new(uint64(len(s) + 1)) ptr := a.new(int64(len(s)) + 1)
util.WriteString(a.sqlt.mod, ptr, s) util.WriteString(a.sqlt.mod, ptr, s)
return ptr return ptr
} }

View file

@ -16,7 +16,7 @@ type Stmt struct {
c *Conn c *Conn
err error err error
sql string sql string
handle uint32 handle ptr_t
} }
// Close destroys the prepared statement object. // Close destroys the prepared statement object.
@ -29,7 +29,7 @@ func (s *Stmt) Close() error {
return nil return nil
} }
r := s.c.call("sqlite3_finalize", uint64(s.handle)) rc := res_t(s.c.call("sqlite3_finalize", stk_t(s.handle)))
stmts := s.c.stmts stmts := s.c.stmts
for i := range stmts { for i := range stmts {
if s == stmts[i] { if s == stmts[i] {
@ -42,7 +42,7 @@ func (s *Stmt) Close() error {
} }
s.handle = 0 s.handle = 0
return s.c.error(r) return s.c.error(rc)
} }
// Conn returns the database connection to which the prepared statement belongs. // Conn returns the database connection to which the prepared statement belongs.
@ -64,9 +64,9 @@ func (s *Stmt) SQL() string {
// //
// https://sqlite.org/c3ref/expanded_sql.html // https://sqlite.org/c3ref/expanded_sql.html
func (s *Stmt) ExpandedSQL() string { func (s *Stmt) ExpandedSQL() string {
r := s.c.call("sqlite3_expanded_sql", uint64(s.handle)) ptr := ptr_t(s.c.call("sqlite3_expanded_sql", stk_t(s.handle)))
sql := util.ReadString(s.c.mod, uint32(r), _MAX_SQL_LENGTH) sql := util.ReadString(s.c.mod, ptr, _MAX_SQL_LENGTH)
s.c.free(uint32(r)) s.c.free(ptr)
return sql return sql
} }
@ -75,25 +75,25 @@ func (s *Stmt) ExpandedSQL() string {
// //
// https://sqlite.org/c3ref/stmt_readonly.html // https://sqlite.org/c3ref/stmt_readonly.html
func (s *Stmt) ReadOnly() bool { func (s *Stmt) ReadOnly() bool {
r := s.c.call("sqlite3_stmt_readonly", uint64(s.handle)) b := int32(s.c.call("sqlite3_stmt_readonly", stk_t(s.handle)))
return r != 0 return b != 0
} }
// Reset resets the prepared statement object. // Reset resets the prepared statement object.
// //
// https://sqlite.org/c3ref/reset.html // https://sqlite.org/c3ref/reset.html
func (s *Stmt) Reset() error { func (s *Stmt) Reset() error {
r := s.c.call("sqlite3_reset", uint64(s.handle)) rc := res_t(s.c.call("sqlite3_reset", stk_t(s.handle)))
s.err = nil s.err = nil
return s.c.error(r) return s.c.error(rc)
} }
// Busy determines if a prepared statement has been reset. // Busy determines if a prepared statement has been reset.
// //
// https://sqlite.org/c3ref/stmt_busy.html // https://sqlite.org/c3ref/stmt_busy.html
func (s *Stmt) Busy() bool { func (s *Stmt) Busy() bool {
r := s.c.call("sqlite3_stmt_busy", uint64(s.handle)) rc := res_t(s.c.call("sqlite3_stmt_busy", stk_t(s.handle)))
return r != 0 return rc != 0
} }
// Step evaluates the SQL statement. // Step evaluates the SQL statement.
@ -107,15 +107,15 @@ func (s *Stmt) Busy() bool {
// https://sqlite.org/c3ref/step.html // https://sqlite.org/c3ref/step.html
func (s *Stmt) Step() bool { func (s *Stmt) Step() bool {
s.c.checkInterrupt(s.c.handle) s.c.checkInterrupt(s.c.handle)
r := s.c.call("sqlite3_step", uint64(s.handle)) rc := res_t(s.c.call("sqlite3_step", stk_t(s.handle)))
switch r { switch rc {
case _ROW: case _ROW:
s.err = nil s.err = nil
return true return true
case _DONE: case _DONE:
s.err = nil s.err = nil
default: default:
s.err = s.c.error(r) s.err = s.c.error(rc)
} }
return false return false
} }
@ -143,30 +143,30 @@ func (s *Stmt) Status(op StmtStatus, reset bool) int {
if op > STMTSTATUS_FILTER_HIT && op != STMTSTATUS_MEMUSED { if op > STMTSTATUS_FILTER_HIT && op != STMTSTATUS_MEMUSED {
return 0 return 0
} }
var i uint64 var i int32
if reset { if reset {
i = 1 i = 1
} }
r := s.c.call("sqlite3_stmt_status", uint64(s.handle), n := int32(s.c.call("sqlite3_stmt_status", stk_t(s.handle),
uint64(op), i) stk_t(op), stk_t(i)))
return int(int32(r)) return int(n)
} }
// ClearBindings resets all bindings on the prepared statement. // ClearBindings resets all bindings on the prepared statement.
// //
// https://sqlite.org/c3ref/clear_bindings.html // https://sqlite.org/c3ref/clear_bindings.html
func (s *Stmt) ClearBindings() error { func (s *Stmt) ClearBindings() error {
r := s.c.call("sqlite3_clear_bindings", uint64(s.handle)) rc := res_t(s.c.call("sqlite3_clear_bindings", stk_t(s.handle)))
return s.c.error(r) return s.c.error(rc)
} }
// BindCount returns the number of SQL parameters in the prepared statement. // BindCount returns the number of SQL parameters in the prepared statement.
// //
// https://sqlite.org/c3ref/bind_parameter_count.html // https://sqlite.org/c3ref/bind_parameter_count.html
func (s *Stmt) BindCount() int { func (s *Stmt) BindCount() int {
r := s.c.call("sqlite3_bind_parameter_count", n := int32(s.c.call("sqlite3_bind_parameter_count",
uint64(s.handle)) stk_t(s.handle)))
return int(int32(r)) return int(n)
} }
// BindIndex returns the index of a parameter in the prepared statement // BindIndex returns the index of a parameter in the prepared statement
@ -176,9 +176,9 @@ func (s *Stmt) BindCount() int {
func (s *Stmt) BindIndex(name string) int { func (s *Stmt) BindIndex(name string) int {
defer s.c.arena.mark()() defer s.c.arena.mark()()
namePtr := s.c.arena.string(name) namePtr := s.c.arena.string(name)
r := s.c.call("sqlite3_bind_parameter_index", i := int32(s.c.call("sqlite3_bind_parameter_index",
uint64(s.handle), uint64(namePtr)) stk_t(s.handle), stk_t(namePtr)))
return int(int32(r)) return int(i)
} }
// BindName returns the name of a parameter in the prepared statement. // BindName returns the name of a parameter in the prepared statement.
@ -186,10 +186,8 @@ func (s *Stmt) BindIndex(name string) int {
// //
// https://sqlite.org/c3ref/bind_parameter_name.html // https://sqlite.org/c3ref/bind_parameter_name.html
func (s *Stmt) BindName(param int) string { func (s *Stmt) BindName(param int) string {
r := s.c.call("sqlite3_bind_parameter_name", ptr := ptr_t(s.c.call("sqlite3_bind_parameter_name",
uint64(s.handle), uint64(param)) stk_t(s.handle), stk_t(param)))
ptr := uint32(r)
if ptr == 0 { if ptr == 0 {
return "" return ""
} }
@ -223,9 +221,9 @@ func (s *Stmt) BindInt(param int, value int) error {
// //
// https://sqlite.org/c3ref/bind_blob.html // https://sqlite.org/c3ref/bind_blob.html
func (s *Stmt) BindInt64(param int, value int64) error { func (s *Stmt) BindInt64(param int, value int64) error {
r := s.c.call("sqlite3_bind_int64", rc := res_t(s.c.call("sqlite3_bind_int64",
uint64(s.handle), uint64(param), uint64(value)) stk_t(s.handle), stk_t(param), stk_t(value)))
return s.c.error(r) return s.c.error(rc)
} }
// BindFloat binds a float64 to the prepared statement. // BindFloat binds a float64 to the prepared statement.
@ -233,9 +231,10 @@ func (s *Stmt) BindInt64(param int, value int64) error {
// //
// https://sqlite.org/c3ref/bind_blob.html // https://sqlite.org/c3ref/bind_blob.html
func (s *Stmt) BindFloat(param int, value float64) error { func (s *Stmt) BindFloat(param int, value float64) error {
r := s.c.call("sqlite3_bind_double", rc := res_t(s.c.call("sqlite3_bind_double",
uint64(s.handle), uint64(param), math.Float64bits(value)) stk_t(s.handle), stk_t(param),
return s.c.error(r) stk_t(math.Float64bits(value))))
return s.c.error(rc)
} }
// BindText binds a string to the prepared statement. // BindText binds a string to the prepared statement.
@ -247,10 +246,10 @@ func (s *Stmt) BindText(param int, value string) error {
return TOOBIG return TOOBIG
} }
ptr := s.c.newString(value) ptr := s.c.newString(value)
r := s.c.call("sqlite3_bind_text_go", rc := res_t(s.c.call("sqlite3_bind_text_go",
uint64(s.handle), uint64(param), stk_t(s.handle), stk_t(param),
uint64(ptr), uint64(len(value))) stk_t(ptr), stk_t(len(value))))
return s.c.error(r) return s.c.error(rc)
} }
// BindRawText binds a []byte to the prepared statement as text. // BindRawText binds a []byte to the prepared statement as text.
@ -263,10 +262,10 @@ func (s *Stmt) BindRawText(param int, value []byte) error {
return TOOBIG return TOOBIG
} }
ptr := s.c.newBytes(value) ptr := s.c.newBytes(value)
r := s.c.call("sqlite3_bind_text_go", rc := res_t(s.c.call("sqlite3_bind_text_go",
uint64(s.handle), uint64(param), stk_t(s.handle), stk_t(param),
uint64(ptr), uint64(len(value))) stk_t(ptr), stk_t(len(value))))
return s.c.error(r) return s.c.error(rc)
} }
// BindBlob binds a []byte to the prepared statement. // BindBlob binds a []byte to the prepared statement.
@ -279,10 +278,10 @@ func (s *Stmt) BindBlob(param int, value []byte) error {
return TOOBIG return TOOBIG
} }
ptr := s.c.newBytes(value) ptr := s.c.newBytes(value)
r := s.c.call("sqlite3_bind_blob_go", rc := res_t(s.c.call("sqlite3_bind_blob_go",
uint64(s.handle), uint64(param), stk_t(s.handle), stk_t(param),
uint64(ptr), uint64(len(value))) stk_t(ptr), stk_t(len(value))))
return s.c.error(r) return s.c.error(rc)
} }
// BindZeroBlob binds a zero-filled, length n BLOB to the prepared statement. // BindZeroBlob binds a zero-filled, length n BLOB to the prepared statement.
@ -290,9 +289,9 @@ func (s *Stmt) BindBlob(param int, value []byte) error {
// //
// https://sqlite.org/c3ref/bind_blob.html // https://sqlite.org/c3ref/bind_blob.html
func (s *Stmt) BindZeroBlob(param int, n int64) error { func (s *Stmt) BindZeroBlob(param int, n int64) error {
r := s.c.call("sqlite3_bind_zeroblob64", rc := res_t(s.c.call("sqlite3_bind_zeroblob64",
uint64(s.handle), uint64(param), uint64(n)) stk_t(s.handle), stk_t(param), stk_t(n)))
return s.c.error(r) return s.c.error(rc)
} }
// BindNull binds a NULL to the prepared statement. // BindNull binds a NULL to the prepared statement.
@ -300,9 +299,9 @@ func (s *Stmt) BindZeroBlob(param int, n int64) error {
// //
// https://sqlite.org/c3ref/bind_blob.html // https://sqlite.org/c3ref/bind_blob.html
func (s *Stmt) BindNull(param int) error { func (s *Stmt) BindNull(param int) error {
r := s.c.call("sqlite3_bind_null", rc := res_t(s.c.call("sqlite3_bind_null",
uint64(s.handle), uint64(param)) stk_t(s.handle), stk_t(param)))
return s.c.error(r) return s.c.error(rc)
} }
// BindTime binds a [time.Time] to the prepared statement. // BindTime binds a [time.Time] to the prepared statement.
@ -316,28 +315,27 @@ func (s *Stmt) BindTime(param int, value time.Time, format TimeFormat) error {
} }
switch v := format.Encode(value).(type) { switch v := format.Encode(value).(type) {
case string: case string:
s.BindText(param, v) return s.BindText(param, v)
case int64: case int64:
s.BindInt64(param, v) return s.BindInt64(param, v)
case float64: case float64:
s.BindFloat(param, v) return s.BindFloat(param, v)
default: default:
panic(util.AssertErr()) panic(util.AssertErr())
} }
return nil
} }
func (s *Stmt) bindRFC3339Nano(param int, value time.Time) error { func (s *Stmt) bindRFC3339Nano(param int, value time.Time) error {
const maxlen = uint64(len(time.RFC3339Nano)) + 5 const maxlen = int64(len(time.RFC3339Nano)) + 5
ptr := s.c.new(maxlen) ptr := s.c.new(maxlen)
buf := util.View(s.c.mod, ptr, maxlen) buf := util.View(s.c.mod, ptr, maxlen)
buf = value.AppendFormat(buf[:0], time.RFC3339Nano) buf = value.AppendFormat(buf[:0], time.RFC3339Nano)
r := s.c.call("sqlite3_bind_text_go", rc := res_t(s.c.call("sqlite3_bind_text_go",
uint64(s.handle), uint64(param), stk_t(s.handle), stk_t(param),
uint64(ptr), uint64(len(buf))) stk_t(ptr), stk_t(len(buf))))
return s.c.error(r) return s.c.error(rc)
} }
// BindPointer binds a NULL to the prepared statement, just like [Stmt.BindNull], // BindPointer binds a NULL to the prepared statement, just like [Stmt.BindNull],
@ -348,9 +346,9 @@ func (s *Stmt) bindRFC3339Nano(param int, value time.Time) error {
// https://sqlite.org/c3ref/bind_blob.html // https://sqlite.org/c3ref/bind_blob.html
func (s *Stmt) BindPointer(param int, ptr any) error { func (s *Stmt) BindPointer(param int, ptr any) error {
valPtr := util.AddHandle(s.c.ctx, ptr) valPtr := util.AddHandle(s.c.ctx, ptr)
r := s.c.call("sqlite3_bind_pointer_go", rc := res_t(s.c.call("sqlite3_bind_pointer_go",
uint64(s.handle), uint64(param), uint64(valPtr)) stk_t(s.handle), stk_t(param), stk_t(valPtr)))
return s.c.error(r) return s.c.error(rc)
} }
// BindJSON binds the JSON encoding of value to the prepared statement. // BindJSON binds the JSON encoding of value to the prepared statement.
@ -373,27 +371,27 @@ func (s *Stmt) BindValue(param int, value Value) error {
if value.c != s.c { if value.c != s.c {
return MISUSE return MISUSE
} }
r := s.c.call("sqlite3_bind_value", rc := res_t(s.c.call("sqlite3_bind_value",
uint64(s.handle), uint64(param), uint64(value.handle)) stk_t(s.handle), stk_t(param), stk_t(value.handle)))
return s.c.error(r) return s.c.error(rc)
} }
// DataCount resets the number of columns in a result set. // DataCount resets the number of columns in a result set.
// //
// https://sqlite.org/c3ref/data_count.html // https://sqlite.org/c3ref/data_count.html
func (s *Stmt) DataCount() int { func (s *Stmt) DataCount() int {
r := s.c.call("sqlite3_data_count", n := int32(s.c.call("sqlite3_data_count",
uint64(s.handle)) stk_t(s.handle)))
return int(int32(r)) return int(n)
} }
// ColumnCount returns the number of columns in a result set. // ColumnCount returns the number of columns in a result set.
// //
// https://sqlite.org/c3ref/column_count.html // https://sqlite.org/c3ref/column_count.html
func (s *Stmt) ColumnCount() int { func (s *Stmt) ColumnCount() int {
r := s.c.call("sqlite3_column_count", n := int32(s.c.call("sqlite3_column_count",
uint64(s.handle)) stk_t(s.handle)))
return int(int32(r)) return int(n)
} }
// ColumnName returns the name of the result column. // ColumnName returns the name of the result column.
@ -401,12 +399,12 @@ func (s *Stmt) ColumnCount() int {
// //
// https://sqlite.org/c3ref/column_name.html // https://sqlite.org/c3ref/column_name.html
func (s *Stmt) ColumnName(col int) string { func (s *Stmt) ColumnName(col int) string {
r := s.c.call("sqlite3_column_name", ptr := ptr_t(s.c.call("sqlite3_column_name",
uint64(s.handle), uint64(col)) stk_t(s.handle), stk_t(col)))
if r == 0 { if ptr == 0 {
panic(util.OOMErr) panic(util.OOMErr)
} }
return util.ReadString(s.c.mod, uint32(r), _MAX_NAME) return util.ReadString(s.c.mod, ptr, _MAX_NAME)
} }
// ColumnType returns the initial [Datatype] of the result column. // ColumnType returns the initial [Datatype] of the result column.
@ -414,9 +412,8 @@ func (s *Stmt) ColumnName(col int) string {
// //
// https://sqlite.org/c3ref/column_blob.html // https://sqlite.org/c3ref/column_blob.html
func (s *Stmt) ColumnType(col int) Datatype { func (s *Stmt) ColumnType(col int) Datatype {
r := s.c.call("sqlite3_column_type", return Datatype(s.c.call("sqlite3_column_type",
uint64(s.handle), uint64(col)) stk_t(s.handle), stk_t(col)))
return Datatype(r)
} }
// ColumnDeclType returns the declared datatype of the result column. // ColumnDeclType returns the declared datatype of the result column.
@ -424,12 +421,12 @@ func (s *Stmt) ColumnType(col int) Datatype {
// //
// https://sqlite.org/c3ref/column_decltype.html // https://sqlite.org/c3ref/column_decltype.html
func (s *Stmt) ColumnDeclType(col int) string { func (s *Stmt) ColumnDeclType(col int) string {
r := s.c.call("sqlite3_column_decltype", ptr := ptr_t(s.c.call("sqlite3_column_decltype",
uint64(s.handle), uint64(col)) stk_t(s.handle), stk_t(col)))
if r == 0 { if ptr == 0 {
return "" return ""
} }
return util.ReadString(s.c.mod, uint32(r), _MAX_NAME) return util.ReadString(s.c.mod, ptr, _MAX_NAME)
} }
// ColumnDatabaseName returns the name of the database // ColumnDatabaseName returns the name of the database
@ -438,12 +435,12 @@ func (s *Stmt) ColumnDeclType(col int) string {
// //
// https://sqlite.org/c3ref/column_database_name.html // https://sqlite.org/c3ref/column_database_name.html
func (s *Stmt) ColumnDatabaseName(col int) string { func (s *Stmt) ColumnDatabaseName(col int) string {
r := s.c.call("sqlite3_column_database_name", ptr := ptr_t(s.c.call("sqlite3_column_database_name",
uint64(s.handle), uint64(col)) stk_t(s.handle), stk_t(col)))
if r == 0 { if ptr == 0 {
return "" return ""
} }
return util.ReadString(s.c.mod, uint32(r), _MAX_NAME) return util.ReadString(s.c.mod, ptr, _MAX_NAME)
} }
// ColumnTableName returns the name of the table // ColumnTableName returns the name of the table
@ -452,12 +449,12 @@ func (s *Stmt) ColumnDatabaseName(col int) string {
// //
// https://sqlite.org/c3ref/column_database_name.html // https://sqlite.org/c3ref/column_database_name.html
func (s *Stmt) ColumnTableName(col int) string { func (s *Stmt) ColumnTableName(col int) string {
r := s.c.call("sqlite3_column_table_name", ptr := ptr_t(s.c.call("sqlite3_column_table_name",
uint64(s.handle), uint64(col)) stk_t(s.handle), stk_t(col)))
if r == 0 { if ptr == 0 {
return "" return ""
} }
return util.ReadString(s.c.mod, uint32(r), _MAX_NAME) return util.ReadString(s.c.mod, ptr, _MAX_NAME)
} }
// ColumnOriginName returns the name of the table column // ColumnOriginName returns the name of the table column
@ -466,12 +463,12 @@ func (s *Stmt) ColumnTableName(col int) string {
// //
// https://sqlite.org/c3ref/column_database_name.html // https://sqlite.org/c3ref/column_database_name.html
func (s *Stmt) ColumnOriginName(col int) string { func (s *Stmt) ColumnOriginName(col int) string {
r := s.c.call("sqlite3_column_origin_name", ptr := ptr_t(s.c.call("sqlite3_column_origin_name",
uint64(s.handle), uint64(col)) stk_t(s.handle), stk_t(col)))
if r == 0 { if ptr == 0 {
return "" return ""
} }
return util.ReadString(s.c.mod, uint32(r), _MAX_NAME) return util.ReadString(s.c.mod, ptr, _MAX_NAME)
} }
// ColumnBool returns the value of the result column as a bool. // ColumnBool returns the value of the result column as a bool.
@ -498,9 +495,8 @@ func (s *Stmt) ColumnInt(col int) int {
// //
// https://sqlite.org/c3ref/column_blob.html // https://sqlite.org/c3ref/column_blob.html
func (s *Stmt) ColumnInt64(col int) int64 { func (s *Stmt) ColumnInt64(col int) int64 {
r := s.c.call("sqlite3_column_int64", return int64(s.c.call("sqlite3_column_int64",
uint64(s.handle), uint64(col)) stk_t(s.handle), stk_t(col)))
return int64(r)
} }
// ColumnFloat returns the value of the result column as a float64. // ColumnFloat returns the value of the result column as a float64.
@ -508,9 +504,9 @@ func (s *Stmt) ColumnInt64(col int) int64 {
// //
// https://sqlite.org/c3ref/column_blob.html // https://sqlite.org/c3ref/column_blob.html
func (s *Stmt) ColumnFloat(col int) float64 { func (s *Stmt) ColumnFloat(col int) float64 {
r := s.c.call("sqlite3_column_double", f := uint64(s.c.call("sqlite3_column_double",
uint64(s.handle), uint64(col)) stk_t(s.handle), stk_t(col)))
return math.Float64frombits(r) return math.Float64frombits(f)
} }
// ColumnTime returns the value of the result column as a [time.Time]. // ColumnTime returns the value of the result column as a [time.Time].
@ -562,9 +558,9 @@ func (s *Stmt) ColumnBlob(col int, buf []byte) []byte {
// //
// https://sqlite.org/c3ref/column_blob.html // https://sqlite.org/c3ref/column_blob.html
func (s *Stmt) ColumnRawText(col int) []byte { func (s *Stmt) ColumnRawText(col int) []byte {
r := s.c.call("sqlite3_column_text", ptr := ptr_t(s.c.call("sqlite3_column_text",
uint64(s.handle), uint64(col)) stk_t(s.handle), stk_t(col)))
return s.columnRawBytes(col, uint32(r)) return s.columnRawBytes(col, ptr)
} }
// ColumnRawBlob returns the value of the result column as a []byte. // ColumnRawBlob returns the value of the result column as a []byte.
@ -574,23 +570,23 @@ func (s *Stmt) ColumnRawText(col int) []byte {
// //
// https://sqlite.org/c3ref/column_blob.html // https://sqlite.org/c3ref/column_blob.html
func (s *Stmt) ColumnRawBlob(col int) []byte { func (s *Stmt) ColumnRawBlob(col int) []byte {
r := s.c.call("sqlite3_column_blob", ptr := ptr_t(s.c.call("sqlite3_column_blob",
uint64(s.handle), uint64(col)) stk_t(s.handle), stk_t(col)))
return s.columnRawBytes(col, uint32(r)) return s.columnRawBytes(col, ptr)
} }
func (s *Stmt) columnRawBytes(col int, ptr uint32) []byte { func (s *Stmt) columnRawBytes(col int, ptr ptr_t) []byte {
if ptr == 0 { if ptr == 0 {
r := s.c.call("sqlite3_errcode", uint64(s.c.handle)) rc := res_t(s.c.call("sqlite3_errcode", stk_t(s.c.handle)))
if r != _ROW && r != _DONE { if rc != _ROW && rc != _DONE {
s.err = s.c.error(r) s.err = s.c.error(rc)
} }
return nil return nil
} }
r := s.c.call("sqlite3_column_bytes", n := int32(s.c.call("sqlite3_column_bytes",
uint64(s.handle), uint64(col)) stk_t(s.handle), stk_t(col)))
return util.View(s.c.mod, ptr, r) return util.View(s.c.mod, ptr, int64(n))
} }
// ColumnJSON parses the JSON-encoded value of the result column // ColumnJSON parses the JSON-encoded value of the result column
@ -610,7 +606,7 @@ func (s *Stmt) ColumnJSON(col int, ptr any) error {
case INTEGER: case INTEGER:
data = strconv.AppendInt(nil, s.ColumnInt64(col), 10) data = strconv.AppendInt(nil, s.ColumnInt64(col), 10)
case FLOAT: case FLOAT:
data = strconv.AppendFloat(nil, s.ColumnFloat(col), 'g', -1, 64) data = util.AppendNumber(nil, s.ColumnFloat(col))
default: default:
panic(util.AssertErr()) panic(util.AssertErr())
} }
@ -622,12 +618,12 @@ func (s *Stmt) ColumnJSON(col int, ptr any) error {
// //
// https://sqlite.org/c3ref/column_blob.html // https://sqlite.org/c3ref/column_blob.html
func (s *Stmt) ColumnValue(col int) Value { func (s *Stmt) ColumnValue(col int) Value {
r := s.c.call("sqlite3_column_value", ptr := ptr_t(s.c.call("sqlite3_column_value",
uint64(s.handle), uint64(col)) stk_t(s.handle), stk_t(col)))
return Value{ return Value{
c: s.c, c: s.c,
unprot: true, unprot: true,
handle: uint32(r), handle: ptr,
} }
} }
@ -641,13 +637,13 @@ func (s *Stmt) ColumnValue(col int) Value {
// subsequent calls to [Stmt] methods. // subsequent calls to [Stmt] methods.
func (s *Stmt) Columns(dest ...any) error { func (s *Stmt) Columns(dest ...any) error {
defer s.c.arena.mark()() defer s.c.arena.mark()()
count := uint64(len(dest)) count := int64(len(dest))
typePtr := s.c.arena.new(count) typePtr := s.c.arena.new(count)
dataPtr := s.c.arena.new(count * 8) dataPtr := s.c.arena.new(count * 8)
r := s.c.call("sqlite3_columns_go", rc := res_t(s.c.call("sqlite3_columns_go",
uint64(s.handle), count, uint64(typePtr), uint64(dataPtr)) stk_t(s.handle), stk_t(count), stk_t(typePtr), stk_t(dataPtr)))
if err := s.c.error(r); err != nil { if err := s.c.error(rc); err != nil {
return err return err
} }
@ -661,19 +657,19 @@ func (s *Stmt) Columns(dest ...any) error {
for i := range dest { for i := range dest {
switch types[i] { switch types[i] {
case byte(INTEGER): case byte(INTEGER):
dest[i] = int64(util.ReadUint64(s.c.mod, dataPtr)) dest[i] = util.Read64[int64](s.c.mod, dataPtr)
case byte(FLOAT): case byte(FLOAT):
dest[i] = util.ReadFloat64(s.c.mod, dataPtr) dest[i] = util.ReadFloat64(s.c.mod, dataPtr)
case byte(NULL): case byte(NULL):
dest[i] = nil dest[i] = nil
default: default:
ptr := util.ReadUint32(s.c.mod, dataPtr+0) ptr := util.Read32[ptr_t](s.c.mod, dataPtr+0)
if ptr == 0 { if ptr == 0 {
dest[i] = []byte{} dest[i] = []byte{}
continue continue
} }
len := util.ReadUint32(s.c.mod, dataPtr+4) len := util.Read32[int32](s.c.mod, dataPtr+4)
buf := util.View(s.c.mod, ptr, uint64(len)) buf := util.View(s.c.mod, ptr, int64(len))
if types[i] == byte(TEXT) { if types[i] == byte(TEXT) {
dest[i] = string(buf) dest[i] = string(buf)
} else { } else {

View file

@ -229,13 +229,12 @@ func (c *Conn) txnExecInterrupted(sql string) error {
// //
// https://sqlite.org/c3ref/txn_state.html // https://sqlite.org/c3ref/txn_state.html
func (c *Conn) TxnState(schema string) TxnState { func (c *Conn) TxnState(schema string) TxnState {
var ptr uint32 var ptr ptr_t
if schema != "" { if schema != "" {
defer c.arena.mark()() defer c.arena.mark()()
ptr = c.arena.string(schema) ptr = c.arena.string(schema)
} }
r := c.call("sqlite3_txn_state", uint64(c.handle), uint64(ptr)) return TxnState(c.call("sqlite3_txn_state", stk_t(c.handle), stk_t(ptr)))
return TxnState(r)
} }
// CommitHook registers a callback function to be invoked // CommitHook registers a callback function to be invoked
@ -244,11 +243,11 @@ func (c *Conn) TxnState(schema string) TxnState {
// //
// https://sqlite.org/c3ref/commit_hook.html // https://sqlite.org/c3ref/commit_hook.html
func (c *Conn) CommitHook(cb func() (ok bool)) { func (c *Conn) CommitHook(cb func() (ok bool)) {
var enable uint64 var enable int32
if cb != nil { if cb != nil {
enable = 1 enable = 1
} }
c.call("sqlite3_commit_hook_go", uint64(c.handle), enable) c.call("sqlite3_commit_hook_go", stk_t(c.handle), stk_t(enable))
c.commit = cb c.commit = cb
} }
@ -257,11 +256,11 @@ func (c *Conn) CommitHook(cb func() (ok bool)) {
// //
// https://sqlite.org/c3ref/commit_hook.html // https://sqlite.org/c3ref/commit_hook.html
func (c *Conn) RollbackHook(cb func()) { func (c *Conn) RollbackHook(cb func()) {
var enable uint64 var enable int32
if cb != nil { if cb != nil {
enable = 1 enable = 1
} }
c.call("sqlite3_rollback_hook_go", uint64(c.handle), enable) c.call("sqlite3_rollback_hook_go", stk_t(c.handle), stk_t(enable))
c.rollback = cb c.rollback = cb
} }
@ -270,15 +269,15 @@ func (c *Conn) RollbackHook(cb func()) {
// //
// https://sqlite.org/c3ref/update_hook.html // https://sqlite.org/c3ref/update_hook.html
func (c *Conn) UpdateHook(cb func(action AuthorizerActionCode, schema, table string, rowid int64)) { func (c *Conn) UpdateHook(cb func(action AuthorizerActionCode, schema, table string, rowid int64)) {
var enable uint64 var enable int32
if cb != nil { if cb != nil {
enable = 1 enable = 1
} }
c.call("sqlite3_update_hook_go", uint64(c.handle), enable) c.call("sqlite3_update_hook_go", stk_t(c.handle), stk_t(enable))
c.update = cb c.update = cb
} }
func commitCallback(ctx context.Context, mod api.Module, pDB uint32) (rollback uint32) { 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, ok := ctx.Value(connKey{}).(*Conn); ok && c.handle == pDB && c.commit != nil {
if !c.commit() { if !c.commit() {
rollback = 1 rollback = 1
@ -287,17 +286,17 @@ func commitCallback(ctx context.Context, mod api.Module, pDB uint32) (rollback u
return rollback return rollback
} }
func rollbackCallback(ctx context.Context, mod api.Module, pDB uint32) { 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 { if c, ok := ctx.Value(connKey{}).(*Conn); ok && c.handle == pDB && c.rollback != nil {
c.rollback() c.rollback()
} }
} }
func updateCallback(ctx context.Context, mod api.Module, pDB uint32, action AuthorizerActionCode, zSchema, zTabName uint32, rowid uint64) { 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 { if c, ok := ctx.Value(connKey{}).(*Conn); ok && c.handle == pDB && c.update != nil {
schema := util.ReadString(mod, zSchema, _MAX_NAME) schema := util.ReadString(mod, zSchema, _MAX_NAME)
table := util.ReadString(mod, zTabName, _MAX_NAME) table := util.ReadString(mod, zTabName, _MAX_NAME)
c.update(action, schema, table, int64(rowid)) c.update(action, schema, table, rowid)
} }
} }
@ -305,6 +304,6 @@ func updateCallback(ctx context.Context, mod api.Module, pDB uint32, action Auth
// //
// https://sqlite.org/c3ref/db_cacheflush.html // https://sqlite.org/c3ref/db_cacheflush.html
func (c *Conn) CacheFlush() error { func (c *Conn) CacheFlush() error {
r := c.call("sqlite3_db_cacheflush", uint64(c.handle)) rc := res_t(c.call("sqlite3_db_cacheflush", stk_t(c.handle)))
return c.error(r) return c.error(rc)
} }

View file

@ -50,7 +50,7 @@ func ParseTable(sql string) (_ *Table, err error) {
copy(buf, sql) copy(buf, sql)
} }
stack := [...]uint64{sqlp, uint64(len(sql)), errp} stack := [...]util.Stk_t{sqlp, util.Stk_t(len(sql)), errp}
err = mod.ExportedFunction("sql3parse_table").CallWithStack(ctx, stack[:]) err = mod.ExportedFunction("sql3parse_table").CallWithStack(ctx, stack[:])
if err != nil { if err != nil {
return nil, err return nil, err
@ -96,9 +96,9 @@ func (t *Table) load(mod api.Module, ptr uint32, sql string) {
t.IsWithoutRowID = loadBool(mod, ptr+26) t.IsWithoutRowID = loadBool(mod, ptr+26)
t.IsStrict = loadBool(mod, ptr+27) t.IsStrict = loadBool(mod, ptr+27)
t.Columns = loadSlice(mod, ptr+28, func(ptr uint32, res *Column) { t.Columns = loadSlice(mod, ptr+28, func(ptr uint32, ret *Column) {
p, _ := mod.Memory().ReadUint32Le(ptr) p, _ := mod.Memory().ReadUint32Le(ptr)
res.load(mod, p, sql) ret.load(mod, p, sql)
}) })
t.Type = loadEnum[StatementType](mod, ptr+44) t.Type = loadEnum[StatementType](mod, ptr+44)
@ -166,8 +166,8 @@ type ForeignKey struct {
func (f *ForeignKey) load(mod api.Module, ptr uint32, sql string) { func (f *ForeignKey) load(mod api.Module, ptr uint32, sql string) {
f.Table = loadString(mod, ptr+0, sql) f.Table = loadString(mod, ptr+0, sql)
f.Columns = loadSlice(mod, ptr+8, func(ptr uint32, res *string) { f.Columns = loadSlice(mod, ptr+8, func(ptr uint32, ret *string) {
*res = loadString(mod, ptr, sql) *ret = loadString(mod, ptr, sql)
}) })
f.OnDelete = loadEnum[FKAction](mod, ptr+16) f.OnDelete = loadEnum[FKAction](mod, ptr+16)
@ -191,12 +191,12 @@ func loadSlice[T any](mod api.Module, ptr uint32, fn func(uint32, *T)) []T {
return nil return nil
} }
len, _ := mod.Memory().ReadUint32Le(ptr + 0) len, _ := mod.Memory().ReadUint32Le(ptr + 0)
res := make([]T, len) ret := make([]T, len)
for i := range res { for i := range ret {
fn(ref, &res[i]) fn(ref, &ret[i])
ref += 4 ref += 4
} }
return res return ret
} }
func loadEnum[T ~uint32](mod api.Module, ptr uint32) T { func loadEnum[T ~uint32](mod api.Module, ptr uint32) T {

View file

@ -14,27 +14,27 @@
// https://sqlite.org/c3ref/value.html // https://sqlite.org/c3ref/value.html
type Value struct { type Value struct {
c *Conn c *Conn
handle uint32 handle ptr_t
unprot bool unprot bool
copied bool copied bool
} }
func (v Value) protected() uint64 { func (v Value) protected() stk_t {
if v.unprot { if v.unprot {
panic(util.ValueErr) panic(util.ValueErr)
} }
return uint64(v.handle) return stk_t(v.handle)
} }
// Dup makes a copy of the SQL value and returns a pointer to that copy. // Dup makes a copy of the SQL value and returns a pointer to that copy.
// //
// https://sqlite.org/c3ref/value_dup.html // https://sqlite.org/c3ref/value_dup.html
func (v Value) Dup() *Value { func (v Value) Dup() *Value {
r := v.c.call("sqlite3_value_dup", uint64(v.handle)) ptr := ptr_t(v.c.call("sqlite3_value_dup", stk_t(v.handle)))
return &Value{ return &Value{
c: v.c, c: v.c,
copied: true, copied: true,
handle: uint32(r), handle: ptr,
} }
} }
@ -45,7 +45,7 @@ func (dup *Value) Close() error {
if !dup.copied { if !dup.copied {
panic(util.ValueErr) panic(util.ValueErr)
} }
dup.c.call("sqlite3_value_free", uint64(dup.handle)) dup.c.call("sqlite3_value_free", stk_t(dup.handle))
dup.handle = 0 dup.handle = 0
return nil return nil
} }
@ -54,16 +54,14 @@ func (dup *Value) Close() error {
// //
// https://sqlite.org/c3ref/value_blob.html // https://sqlite.org/c3ref/value_blob.html
func (v Value) Type() Datatype { func (v Value) Type() Datatype {
r := v.c.call("sqlite3_value_type", v.protected()) return Datatype(v.c.call("sqlite3_value_type", v.protected()))
return Datatype(r)
} }
// Type returns the numeric datatype of the value. // Type returns the numeric datatype of the value.
// //
// https://sqlite.org/c3ref/value_blob.html // https://sqlite.org/c3ref/value_blob.html
func (v Value) NumericType() Datatype { func (v Value) NumericType() Datatype {
r := v.c.call("sqlite3_value_numeric_type", v.protected()) return Datatype(v.c.call("sqlite3_value_numeric_type", v.protected()))
return Datatype(r)
} }
// Bool returns the value as a bool. // Bool returns the value as a bool.
@ -87,16 +85,15 @@ func (v Value) Int() int {
// //
// https://sqlite.org/c3ref/value_blob.html // https://sqlite.org/c3ref/value_blob.html
func (v Value) Int64() int64 { func (v Value) Int64() int64 {
r := v.c.call("sqlite3_value_int64", v.protected()) return int64(v.c.call("sqlite3_value_int64", v.protected()))
return int64(r)
} }
// Float returns the value as a float64. // Float returns the value as a float64.
// //
// https://sqlite.org/c3ref/value_blob.html // https://sqlite.org/c3ref/value_blob.html
func (v Value) Float() float64 { func (v Value) Float() float64 {
r := v.c.call("sqlite3_value_double", v.protected()) f := uint64(v.c.call("sqlite3_value_double", v.protected()))
return math.Float64frombits(r) return math.Float64frombits(f)
} }
// Time returns the value as a [time.Time]. // Time returns the value as a [time.Time].
@ -141,8 +138,8 @@ func (v Value) Blob(buf []byte) []byte {
// //
// https://sqlite.org/c3ref/value_blob.html // https://sqlite.org/c3ref/value_blob.html
func (v Value) RawText() []byte { func (v Value) RawText() []byte {
r := v.c.call("sqlite3_value_text", v.protected()) ptr := ptr_t(v.c.call("sqlite3_value_text", v.protected()))
return v.rawBytes(uint32(r)) return v.rawBytes(ptr)
} }
// RawBlob returns the value as a []byte. // RawBlob returns the value as a []byte.
@ -151,24 +148,24 @@ func (v Value) RawText() []byte {
// //
// https://sqlite.org/c3ref/value_blob.html // https://sqlite.org/c3ref/value_blob.html
func (v Value) RawBlob() []byte { func (v Value) RawBlob() []byte {
r := v.c.call("sqlite3_value_blob", v.protected()) ptr := ptr_t(v.c.call("sqlite3_value_blob", v.protected()))
return v.rawBytes(uint32(r)) return v.rawBytes(ptr)
} }
func (v Value) rawBytes(ptr uint32) []byte { func (v Value) rawBytes(ptr ptr_t) []byte {
if ptr == 0 { if ptr == 0 {
return nil return nil
} }
r := v.c.call("sqlite3_value_bytes", v.protected()) n := int32(v.c.call("sqlite3_value_bytes", v.protected()))
return util.View(v.c.mod, ptr, r) return util.View(v.c.mod, ptr, int64(n))
} }
// Pointer gets the pointer associated with this value, // Pointer gets the pointer associated with this value,
// or nil if it has no associated pointer. // or nil if it has no associated pointer.
func (v Value) Pointer() any { func (v Value) Pointer() any {
r := v.c.call("sqlite3_value_pointer_go", v.protected()) ptr := ptr_t(v.c.call("sqlite3_value_pointer_go", v.protected()))
return util.GetHandle(v.c.ctx, uint32(r)) return util.GetHandle(v.c.ctx, ptr)
} }
// JSON parses a JSON-encoded value // JSON parses a JSON-encoded value
@ -185,7 +182,7 @@ func (v Value) JSON(ptr any) error {
case INTEGER: case INTEGER:
data = strconv.AppendInt(nil, v.Int64(), 10) data = strconv.AppendInt(nil, v.Int64(), 10)
case FLOAT: case FLOAT:
data = strconv.AppendFloat(nil, v.Float(), 'g', -1, 64) data = util.AppendNumber(nil, v.Float())
default: default:
panic(util.AssertErr()) panic(util.AssertErr())
} }
@ -197,16 +194,16 @@ func (v Value) JSON(ptr any) error {
// //
// https://sqlite.org/c3ref/value_blob.html // https://sqlite.org/c3ref/value_blob.html
func (v Value) NoChange() bool { func (v Value) NoChange() bool {
r := v.c.call("sqlite3_value_nochange", v.protected()) b := int32(v.c.call("sqlite3_value_nochange", v.protected()))
return r != 0 return b != 0
} }
// FromBind returns true if value originated from a bound parameter. // FromBind returns true if value originated from a bound parameter.
// //
// https://sqlite.org/c3ref/value_blob.html // https://sqlite.org/c3ref/value_blob.html
func (v Value) FromBind() bool { func (v Value) FromBind() bool {
r := v.c.call("sqlite3_value_frombind", v.protected()) b := int32(v.c.call("sqlite3_value_frombind", v.protected()))
return r != 0 return b != 0
} }
// InFirst returns the first element // InFirst returns the first element
@ -216,13 +213,13 @@ func (v Value) FromBind() bool {
func (v Value) InFirst() (Value, error) { func (v Value) InFirst() (Value, error) {
defer v.c.arena.mark()() defer v.c.arena.mark()()
valPtr := v.c.arena.new(ptrlen) valPtr := v.c.arena.new(ptrlen)
r := v.c.call("sqlite3_vtab_in_first", uint64(v.handle), uint64(valPtr)) rc := res_t(v.c.call("sqlite3_vtab_in_first", stk_t(v.handle), stk_t(valPtr)))
if err := v.c.error(r); err != nil { if err := v.c.error(rc); err != nil {
return Value{}, err return Value{}, err
} }
return Value{ return Value{
c: v.c, c: v.c,
handle: util.ReadUint32(v.c.mod, valPtr), handle: util.Read32[ptr_t](v.c.mod, valPtr),
}, nil }, nil
} }
@ -233,12 +230,12 @@ func (v Value) InFirst() (Value, error) {
func (v Value) InNext() (Value, error) { func (v Value) InNext() (Value, error) {
defer v.c.arena.mark()() defer v.c.arena.mark()()
valPtr := v.c.arena.new(ptrlen) valPtr := v.c.arena.new(ptrlen)
r := v.c.call("sqlite3_vtab_in_next", uint64(v.handle), uint64(valPtr)) rc := res_t(v.c.call("sqlite3_vtab_in_next", stk_t(v.handle), stk_t(valPtr)))
if err := v.c.error(r); err != nil { if err := v.c.error(rc); err != nil {
return Value{}, err return Value{}, err
} }
return Value{ return Value{
c: v.c, c: v.c,
handle: util.ReadUint32(v.c.mod, valPtr), handle: util.Read32[ptr_t](v.c.mod, valPtr),
}, nil }, nil
} }

View file

@ -193,7 +193,7 @@ type FileSharedMemory interface {
// SharedMemory is a shared-memory WAL-index implementation. // SharedMemory is a shared-memory WAL-index implementation.
// Use [NewSharedMemory] to create a shared-memory. // Use [NewSharedMemory] to create a shared-memory.
type SharedMemory interface { type SharedMemory interface {
shmMap(context.Context, api.Module, int32, int32, bool) (uint32, _ErrorCode) shmMap(context.Context, api.Module, int32, int32, bool) (ptr_t, _ErrorCode)
shmLock(int32, int32, _ShmFlag) _ErrorCode shmLock(int32, int32, _ShmFlag) _ErrorCode
shmUnmap(bool) shmUnmap(bool)
shmBarrier() shmBarrier()
@ -207,7 +207,7 @@ type blockingSharedMemory interface {
type fileControl interface { type fileControl interface {
File File
fileControl(ctx context.Context, mod api.Module, op _FcntlOpcode, pArg uint32) _ErrorCode fileControl(ctx context.Context, mod api.Module, op _FcntlOpcode, pArg ptr_t) _ErrorCode
} }
type filePDB interface { type filePDB interface {

View file

@ -102,14 +102,14 @@ func (c cksmFile) Pragma(name string, value string) (string, error) {
} }
func (c cksmFile) DeviceCharacteristics() DeviceCharacteristic { func (c cksmFile) DeviceCharacteristics() DeviceCharacteristic {
res := c.File.DeviceCharacteristics() ret := c.File.DeviceCharacteristics()
if c.verifyCksm { if c.verifyCksm {
res &^= IOCAP_SUBPAGE_READ ret &^= IOCAP_SUBPAGE_READ
} }
return res return ret
} }
func (c cksmFile) fileControl(ctx context.Context, mod api.Module, op _FcntlOpcode, pArg uint32) _ErrorCode { func (c cksmFile) fileControl(ctx context.Context, mod api.Module, op _FcntlOpcode, pArg ptr_t) _ErrorCode {
switch op { switch op {
case _FCNTL_CKPT_START: case _FCNTL_CKPT_START:
c.inCkpt = true c.inCkpt = true

View file

@ -8,7 +8,12 @@
_MAX_PATHNAME = 1024 _MAX_PATHNAME = 1024
_DEFAULT_SECTOR_SIZE = 4096 _DEFAULT_SECTOR_SIZE = 4096
ptrlen = 4 ptrlen = util.PtrLen
)
type (
stk_t = util.Stk_t
ptr_t = util.Ptr_t
) )
// https://sqlite.org/rescode.html // https://sqlite.org/rescode.html

View file

@ -186,14 +186,14 @@ func (f *vfsFile) SectorSize() int {
} }
func (f *vfsFile) DeviceCharacteristics() DeviceCharacteristic { func (f *vfsFile) DeviceCharacteristics() DeviceCharacteristic {
res := IOCAP_SUBPAGE_READ ret := IOCAP_SUBPAGE_READ
if osBatchAtomic(f.File) { if osBatchAtomic(f.File) {
res |= IOCAP_BATCH_ATOMIC ret |= IOCAP_BATCH_ATOMIC
} }
if f.psow { if f.psow {
res |= IOCAP_POWERSAFE_OVERWRITE ret |= IOCAP_POWERSAFE_OVERWRITE
} }
return res return ret
} }
func (f *vfsFile) SizeHint(size int64) error { func (f *vfsFile) SizeHint(size int64) error {

View file

@ -16,13 +16,13 @@
type Filename struct { type Filename struct {
ctx context.Context ctx context.Context
mod api.Module mod api.Module
zPath uint32 zPath ptr_t
flags OpenFlag flags OpenFlag
stack [2]uint64 stack [2]stk_t
} }
// GetFilename is an internal API users should not call directly. // GetFilename is an internal API users should not call directly.
func GetFilename(ctx context.Context, mod api.Module, id uint32, flags OpenFlag) *Filename { func GetFilename(ctx context.Context, mod api.Module, id ptr_t, flags OpenFlag) *Filename {
if id == 0 { if id == 0 {
return nil return nil
} }
@ -71,12 +71,12 @@ func (n *Filename) path(method string) string {
return "" return ""
} }
n.stack[0] = uint64(n.zPath) n.stack[0] = stk_t(n.zPath)
fn := n.mod.ExportedFunction(method) fn := n.mod.ExportedFunction(method)
if err := fn.CallWithStack(n.ctx, n.stack[:]); err != nil { if err := fn.CallWithStack(n.ctx, n.stack[:]); err != nil {
panic(err) panic(err)
} }
return util.ReadString(n.mod, uint32(n.stack[0]), _MAX_PATHNAME) return util.ReadString(n.mod, ptr_t(n.stack[0]), _MAX_PATHNAME)
} }
// DatabaseFile returns the main database [File] corresponding to a journal. // DatabaseFile returns the main database [File] corresponding to a journal.
@ -90,12 +90,12 @@ func (n *Filename) DatabaseFile() File {
return nil return nil
} }
n.stack[0] = uint64(n.zPath) n.stack[0] = stk_t(n.zPath)
fn := n.mod.ExportedFunction("sqlite3_database_file_object") fn := n.mod.ExportedFunction("sqlite3_database_file_object")
if err := fn.CallWithStack(n.ctx, n.stack[:]); err != nil { if err := fn.CallWithStack(n.ctx, n.stack[:]); err != nil {
panic(err) panic(err)
} }
file, _ := vfsFileGet(n.ctx, n.mod, uint32(n.stack[0])).(File) file, _ := vfsFileGet(n.ctx, n.mod, ptr_t(n.stack[0])).(File)
return file return file
} }
@ -108,13 +108,13 @@ func (n *Filename) URIParameter(key string) string {
} }
uriKey := n.mod.ExportedFunction("sqlite3_uri_key") uriKey := n.mod.ExportedFunction("sqlite3_uri_key")
n.stack[0] = uint64(n.zPath) n.stack[0] = stk_t(n.zPath)
n.stack[1] = uint64(0) n.stack[1] = stk_t(0)
if err := uriKey.CallWithStack(n.ctx, n.stack[:]); err != nil { if err := uriKey.CallWithStack(n.ctx, n.stack[:]); err != nil {
panic(err) panic(err)
} }
ptr := uint32(n.stack[0]) ptr := ptr_t(n.stack[0])
if ptr == 0 { if ptr == 0 {
return "" return ""
} }
@ -127,13 +127,13 @@ func (n *Filename) URIParameter(key string) string {
if k == "" { if k == "" {
return "" return ""
} }
ptr += uint32(len(k)) + 1 ptr += ptr_t(len(k)) + 1
v := util.ReadString(n.mod, ptr, _MAX_NAME) v := util.ReadString(n.mod, ptr, _MAX_NAME)
if k == key { if k == key {
return v return v
} }
ptr += uint32(len(v)) + 1 ptr += ptr_t(len(v)) + 1
} }
} }
@ -146,13 +146,13 @@ func (n *Filename) URIParameters() url.Values {
} }
uriKey := n.mod.ExportedFunction("sqlite3_uri_key") uriKey := n.mod.ExportedFunction("sqlite3_uri_key")
n.stack[0] = uint64(n.zPath) n.stack[0] = stk_t(n.zPath)
n.stack[1] = uint64(0) n.stack[1] = stk_t(0)
if err := uriKey.CallWithStack(n.ctx, n.stack[:]); err != nil { if err := uriKey.CallWithStack(n.ctx, n.stack[:]); err != nil {
panic(err) panic(err)
} }
ptr := uint32(n.stack[0]) ptr := ptr_t(n.stack[0])
if ptr == 0 { if ptr == 0 {
return nil return nil
} }
@ -167,13 +167,13 @@ func (n *Filename) URIParameters() url.Values {
if k == "" { if k == "" {
return params return params
} }
ptr += uint32(len(k)) + 1 ptr += ptr_t(len(k)) + 1
v := util.ReadString(n.mod, ptr, _MAX_NAME) v := util.ReadString(n.mod, ptr, _MAX_NAME)
if params == nil { if params == nil {
params = url.Values{} params = url.Values{}
} }
params.Add(k, v) params.Add(k, v)
ptr += uint32(len(v)) + 1 ptr += ptr_t(len(v)) + 1
} }
} }

View file

@ -10,9 +10,11 @@
"github.com/ncruces/go-sqlite3/vfs" "github.com/ncruces/go-sqlite3/vfs"
) )
// Must be a multiple of 64K (the largest page size).
const sectorSize = 65536 const sectorSize = 65536
// Ensure sectorSize is a multiple of 64K (the largest page size).
var _ [0]struct{} = [sectorSize & 65535]struct{}{}
type memVFS struct{} type memVFS struct{}
func (memVFS) Open(name string, flags vfs.OpenFlag) (vfs.File, vfs.OpenFlag, error) { func (memVFS) Open(name string, flags vfs.OpenFlag) (vfs.File, vfs.OpenFlag, error) {

View file

@ -142,7 +142,7 @@ func (s *vfsShm) shmOpen() _ErrorCode {
return _OK return _OK
} }
func (s *vfsShm) shmMap(ctx context.Context, mod api.Module, id, size int32, extend bool) (uint32, _ErrorCode) { 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. // Ensure size is a multiple of the OS page size.
if int(size)&(unix.Getpagesize()-1) != 0 { if int(size)&(unix.Getpagesize()-1) != 0 {
return 0, _IOERR_SHMMAP return 0, _IOERR_SHMMAP

View file

@ -35,8 +35,8 @@ type vfsShm struct {
free api.Function free api.Function
path string path string
shadow [][_WALINDEX_PGSZ]byte shadow [][_WALINDEX_PGSZ]byte
ptrs []uint32 ptrs []ptr_t
stack [1]uint64 stack [1]stk_t
lock [_SHM_NLOCK]bool lock [_SHM_NLOCK]bool
} }
@ -96,7 +96,7 @@ func (s *vfsShm) shmOpen() _ErrorCode {
return _OK return _OK
} }
func (s *vfsShm) shmMap(ctx context.Context, mod api.Module, id, size int32, extend bool) (uint32, _ErrorCode) { func (s *vfsShm) shmMap(ctx context.Context, mod api.Module, id, size int32, extend bool) (ptr_t, _ErrorCode) {
if size != _WALINDEX_PGSZ { if size != _WALINDEX_PGSZ {
return 0, _IOERR_SHMMAP return 0, _IOERR_SHMMAP
} }
@ -128,15 +128,15 @@ func (s *vfsShm) shmMap(ctx context.Context, mod api.Module, id, size int32, ext
// Allocate local memory. // Allocate local memory.
for int(id) >= len(s.ptrs) { for int(id) >= len(s.ptrs) {
s.stack[0] = uint64(size) s.stack[0] = stk_t(size)
if err := s.alloc.CallWithStack(ctx, s.stack[:]); err != nil { if err := s.alloc.CallWithStack(ctx, s.stack[:]); err != nil {
panic(err) panic(err)
} }
if s.stack[0] == 0 { if s.stack[0] == 0 {
panic(util.OOMErr) panic(util.OOMErr)
} }
clear(util.View(s.mod, uint32(s.stack[0]), _WALINDEX_PGSZ)) clear(util.View(s.mod, ptr_t(s.stack[0]), _WALINDEX_PGSZ))
s.ptrs = append(s.ptrs, uint32(s.stack[0])) s.ptrs = append(s.ptrs, ptr_t(s.stack[0]))
} }
s.shadow[0][4] = 1 s.shadow[0][4] = 1
@ -168,7 +168,7 @@ func (s *vfsShm) shmUnmap(delete bool) {
defer s.Unlock() defer s.Unlock()
for _, p := range s.ptrs { for _, p := range s.ptrs {
s.stack[0] = uint64(p) s.stack[0] = stk_t(p)
if err := s.free.CallWithStack(context.Background(), s.stack[:]); err != nil { if err := s.free.CallWithStack(context.Background(), s.stack[:]); err != nil {
panic(err) panic(err)
} }

View file

@ -73,7 +73,7 @@ func (s *vfsShm) shmOpen() _ErrorCode {
return rc return rc
} }
func (s *vfsShm) shmMap(ctx context.Context, mod api.Module, id, size int32, extend bool) (uint32, _ErrorCode) { 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. // Ensure size is a multiple of the OS page size.
if int(size)&(unix.Getpagesize()-1) != 0 { if int(size)&(unix.Getpagesize()-1) != 0 {
return 0, _IOERR_SHMMAP return 0, _IOERR_SHMMAP

View file

@ -26,8 +26,8 @@ type vfsShm struct {
regions []*util.MappedRegion regions []*util.MappedRegion
shared [][]byte shared [][]byte
shadow [][_WALINDEX_PGSZ]byte shadow [][_WALINDEX_PGSZ]byte
ptrs []uint32 ptrs []ptr_t
stack [1]uint64 stack [1]stk_t
fileLock bool fileLock bool
blocking bool blocking bool
sync.Mutex sync.Mutex
@ -72,7 +72,7 @@ func (s *vfsShm) shmOpen() _ErrorCode {
return rc return rc
} }
func (s *vfsShm) shmMap(ctx context.Context, mod api.Module, id, size int32, extend bool) (_ uint32, rc _ErrorCode) { 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. // Ensure size is a multiple of the OS page size.
if size != _WALINDEX_PGSZ || (windows.Getpagesize()-1)&_WALINDEX_PGSZ != 0 { if size != _WALINDEX_PGSZ || (windows.Getpagesize()-1)&_WALINDEX_PGSZ != 0 {
return 0, _IOERR_SHMMAP return 0, _IOERR_SHMMAP
@ -119,15 +119,15 @@ func (s *vfsShm) shmMap(ctx context.Context, mod api.Module, id, size int32, ext
// Allocate local memory. // Allocate local memory.
for int(id) >= len(s.ptrs) { for int(id) >= len(s.ptrs) {
s.stack[0] = uint64(size) s.stack[0] = stk_t(size)
if err := s.alloc.CallWithStack(ctx, s.stack[:]); err != nil { if err := s.alloc.CallWithStack(ctx, s.stack[:]); err != nil {
panic(err) panic(err)
} }
if s.stack[0] == 0 { if s.stack[0] == 0 {
panic(util.OOMErr) panic(util.OOMErr)
} }
clear(util.View(s.mod, uint32(s.stack[0]), _WALINDEX_PGSZ)) clear(util.View(s.mod, ptr_t(s.stack[0]), _WALINDEX_PGSZ))
s.ptrs = append(s.ptrs, uint32(s.stack[0])) s.ptrs = append(s.ptrs, ptr_t(s.stack[0]))
} }
s.shadow[0][4] = 1 s.shadow[0][4] = 1
@ -168,7 +168,7 @@ func (s *vfsShm) shmUnmap(delete bool) {
// Free local memory. // Free local memory.
for _, p := range s.ptrs { for _, p := range s.ptrs {
s.stack[0] = uint64(p) s.stack[0] = stk_t(p)
if err := s.free.CallWithStack(context.Background(), s.stack[:]); err != nil { if err := s.free.CallWithStack(context.Background(), s.stack[:]); err != nil {
panic(err) panic(err)
} }

View file

@ -49,7 +49,7 @@ func ExportHostFunctions(env wazero.HostModuleBuilder) wazero.HostModuleBuilder
return env return env
} }
func vfsFind(ctx context.Context, mod api.Module, zVfsName uint32) uint32 { func vfsFind(ctx context.Context, mod api.Module, zVfsName ptr_t) uint32 {
name := util.ReadString(mod, zVfsName, _MAX_NAME) name := util.ReadString(mod, zVfsName, _MAX_NAME)
if vfs := Find(name); vfs != nil && vfs != (vfsOS{}) { if vfs := Find(name); vfs != nil && vfs != (vfsOS{}) {
return 1 return 1
@ -57,46 +57,46 @@ func vfsFind(ctx context.Context, mod api.Module, zVfsName uint32) uint32 {
return 0 return 0
} }
func vfsLocaltime(ctx context.Context, mod api.Module, pTm uint32, t int64) _ErrorCode { func vfsLocaltime(ctx context.Context, mod api.Module, pTm ptr_t, t int64) _ErrorCode {
tm := time.Unix(t, 0) tm := time.Unix(t, 0)
var isdst int var isdst int32
if tm.IsDST() { if tm.IsDST() {
isdst = 1 isdst = 1
} }
const size = 32 / 8 const size = 32 / 8
// https://pubs.opengroup.org/onlinepubs/7908799/xsh/time.h.html // https://pubs.opengroup.org/onlinepubs/7908799/xsh/time.h.html
util.WriteUint32(mod, pTm+0*size, uint32(tm.Second())) util.Write32(mod, pTm+0*size, int32(tm.Second()))
util.WriteUint32(mod, pTm+1*size, uint32(tm.Minute())) util.Write32(mod, pTm+1*size, int32(tm.Minute()))
util.WriteUint32(mod, pTm+2*size, uint32(tm.Hour())) util.Write32(mod, pTm+2*size, int32(tm.Hour()))
util.WriteUint32(mod, pTm+3*size, uint32(tm.Day())) util.Write32(mod, pTm+3*size, int32(tm.Day()))
util.WriteUint32(mod, pTm+4*size, uint32(tm.Month()-time.January)) util.Write32(mod, pTm+4*size, int32(tm.Month()-time.January))
util.WriteUint32(mod, pTm+5*size, uint32(tm.Year()-1900)) util.Write32(mod, pTm+5*size, int32(tm.Year()-1900))
util.WriteUint32(mod, pTm+6*size, uint32(tm.Weekday()-time.Sunday)) util.Write32(mod, pTm+6*size, int32(tm.Weekday()-time.Sunday))
util.WriteUint32(mod, pTm+7*size, uint32(tm.YearDay()-1)) util.Write32(mod, pTm+7*size, int32(tm.YearDay()-1))
util.WriteUint32(mod, pTm+8*size, uint32(isdst)) util.Write32(mod, pTm+8*size, isdst)
return _OK return _OK
} }
func vfsRandomness(ctx context.Context, mod api.Module, pVfs uint32, nByte int32, zByte uint32) uint32 { func vfsRandomness(ctx context.Context, mod api.Module, pVfs ptr_t, nByte int32, zByte ptr_t) uint32 {
mem := util.View(mod, zByte, uint64(nByte)) mem := util.View(mod, zByte, int64(nByte))
n, _ := rand.Reader.Read(mem) n, _ := rand.Reader.Read(mem)
return uint32(n) return uint32(n)
} }
func vfsSleep(ctx context.Context, mod api.Module, pVfs uint32, nMicro int32) _ErrorCode { func vfsSleep(ctx context.Context, mod api.Module, pVfs ptr_t, nMicro int32) _ErrorCode {
time.Sleep(time.Duration(nMicro) * time.Microsecond) time.Sleep(time.Duration(nMicro) * time.Microsecond)
return _OK return _OK
} }
func vfsCurrentTime64(ctx context.Context, mod api.Module, pVfs, piNow uint32) _ErrorCode { func vfsCurrentTime64(ctx context.Context, mod api.Module, pVfs, piNow ptr_t) _ErrorCode {
day, nsec := julianday.Date(time.Now()) day, nsec := julianday.Date(time.Now())
msec := day*86_400_000 + nsec/1_000_000 msec := day*86_400_000 + nsec/1_000_000
util.WriteUint64(mod, piNow, uint64(msec)) util.Write64(mod, piNow, msec)
return _OK return _OK
} }
func vfsFullPathname(ctx context.Context, mod api.Module, pVfs, zRelative uint32, nFull int32, zFull uint32) _ErrorCode { func vfsFullPathname(ctx context.Context, mod api.Module, pVfs, zRelative ptr_t, nFull int32, zFull ptr_t) _ErrorCode {
vfs := vfsGet(mod, pVfs) vfs := vfsGet(mod, pVfs)
path := util.ReadString(mod, zRelative, _MAX_PATHNAME) path := util.ReadString(mod, zRelative, _MAX_PATHNAME)
@ -110,7 +110,7 @@ func vfsFullPathname(ctx context.Context, mod api.Module, pVfs, zRelative uint32
return vfsErrorCode(err, _CANTOPEN_FULLPATH) return vfsErrorCode(err, _CANTOPEN_FULLPATH)
} }
func vfsDelete(ctx context.Context, mod api.Module, pVfs, zPath, syncDir uint32) _ErrorCode { func vfsDelete(ctx context.Context, mod api.Module, pVfs, zPath ptr_t, syncDir int32) _ErrorCode {
vfs := vfsGet(mod, pVfs) vfs := vfsGet(mod, pVfs)
path := util.ReadString(mod, zPath, _MAX_PATHNAME) path := util.ReadString(mod, zPath, _MAX_PATHNAME)
@ -118,21 +118,20 @@ func vfsDelete(ctx context.Context, mod api.Module, pVfs, zPath, syncDir uint32)
return vfsErrorCode(err, _IOERR_DELETE) return vfsErrorCode(err, _IOERR_DELETE)
} }
func vfsAccess(ctx context.Context, mod api.Module, pVfs, zPath uint32, flags AccessFlag, pResOut uint32) _ErrorCode { func vfsAccess(ctx context.Context, mod api.Module, pVfs, zPath ptr_t, flags AccessFlag, pResOut ptr_t) _ErrorCode {
vfs := vfsGet(mod, pVfs) vfs := vfsGet(mod, pVfs)
path := util.ReadString(mod, zPath, _MAX_PATHNAME) path := util.ReadString(mod, zPath, _MAX_PATHNAME)
ok, err := vfs.Access(path, flags) ok, err := vfs.Access(path, flags)
var res uint32 var res int32
if ok { if ok {
res = 1 res = 1
} }
util.Write32(mod, pResOut, res)
util.WriteUint32(mod, pResOut, res)
return vfsErrorCode(err, _IOERR_ACCESS) return vfsErrorCode(err, _IOERR_ACCESS)
} }
func vfsOpen(ctx context.Context, mod api.Module, pVfs, zPath, pFile uint32, flags OpenFlag, pOutFlags, pOutVFS uint32) _ErrorCode { func vfsOpen(ctx context.Context, mod api.Module, pVfs, zPath, pFile ptr_t, flags OpenFlag, pOutFlags, pOutVFS ptr_t) _ErrorCode {
vfs := vfsGet(mod, pVfs) vfs := vfsGet(mod, pVfs)
name := GetFilename(ctx, mod, zPath, flags) name := GetFilename(ctx, mod, zPath, flags)
@ -154,24 +153,24 @@ func vfsOpen(ctx context.Context, mod api.Module, pVfs, zPath, pFile uint32, fla
} }
if file, ok := file.(FileSharedMemory); ok && if file, ok := file.(FileSharedMemory); ok &&
pOutVFS != 0 && file.SharedMemory() != nil { pOutVFS != 0 && file.SharedMemory() != nil {
util.WriteUint32(mod, pOutVFS, 1) util.Write32(mod, pOutVFS, int32(1))
} }
if pOutFlags != 0 { if pOutFlags != 0 {
util.WriteUint32(mod, pOutFlags, uint32(flags)) util.Write32(mod, pOutFlags, flags)
} }
file = cksmWrapFile(name, flags, file) file = cksmWrapFile(name, flags, file)
vfsFileRegister(ctx, mod, pFile, file) vfsFileRegister(ctx, mod, pFile, file)
return _OK return _OK
} }
func vfsClose(ctx context.Context, mod api.Module, pFile uint32) _ErrorCode { func vfsClose(ctx context.Context, mod api.Module, pFile ptr_t) _ErrorCode {
err := vfsFileClose(ctx, mod, pFile) err := vfsFileClose(ctx, mod, pFile)
return vfsErrorCode(err, _IOERR_CLOSE) return vfsErrorCode(err, _IOERR_CLOSE)
} }
func vfsRead(ctx context.Context, mod api.Module, pFile, zBuf uint32, iAmt int32, iOfst int64) _ErrorCode { func vfsRead(ctx context.Context, mod api.Module, pFile, zBuf ptr_t, iAmt int32, iOfst int64) _ErrorCode {
file := vfsFileGet(ctx, mod, pFile).(File) file := vfsFileGet(ctx, mod, pFile).(File)
buf := util.View(mod, zBuf, uint64(iAmt)) buf := util.View(mod, zBuf, int64(iAmt))
n, err := file.ReadAt(buf, iOfst) n, err := file.ReadAt(buf, iOfst)
if n == int(iAmt) { if n == int(iAmt) {
@ -184,59 +183,58 @@ func vfsRead(ctx context.Context, mod api.Module, pFile, zBuf uint32, iAmt int32
return _IOERR_SHORT_READ return _IOERR_SHORT_READ
} }
func vfsWrite(ctx context.Context, mod api.Module, pFile, zBuf uint32, iAmt int32, iOfst int64) _ErrorCode { func vfsWrite(ctx context.Context, mod api.Module, pFile, zBuf ptr_t, iAmt int32, iOfst int64) _ErrorCode {
file := vfsFileGet(ctx, mod, pFile).(File) file := vfsFileGet(ctx, mod, pFile).(File)
buf := util.View(mod, zBuf, uint64(iAmt)) buf := util.View(mod, zBuf, int64(iAmt))
_, err := file.WriteAt(buf, iOfst) _, err := file.WriteAt(buf, iOfst)
return vfsErrorCode(err, _IOERR_WRITE) return vfsErrorCode(err, _IOERR_WRITE)
} }
func vfsTruncate(ctx context.Context, mod api.Module, pFile uint32, nByte int64) _ErrorCode { func vfsTruncate(ctx context.Context, mod api.Module, pFile ptr_t, nByte int64) _ErrorCode {
file := vfsFileGet(ctx, mod, pFile).(File) file := vfsFileGet(ctx, mod, pFile).(File)
err := file.Truncate(nByte) err := file.Truncate(nByte)
return vfsErrorCode(err, _IOERR_TRUNCATE) return vfsErrorCode(err, _IOERR_TRUNCATE)
} }
func vfsSync(ctx context.Context, mod api.Module, pFile uint32, flags SyncFlag) _ErrorCode { func vfsSync(ctx context.Context, mod api.Module, pFile ptr_t, flags SyncFlag) _ErrorCode {
file := vfsFileGet(ctx, mod, pFile).(File) file := vfsFileGet(ctx, mod, pFile).(File)
err := file.Sync(flags) err := file.Sync(flags)
return vfsErrorCode(err, _IOERR_FSYNC) return vfsErrorCode(err, _IOERR_FSYNC)
} }
func vfsFileSize(ctx context.Context, mod api.Module, pFile, pSize uint32) _ErrorCode { func vfsFileSize(ctx context.Context, mod api.Module, pFile, pSize ptr_t) _ErrorCode {
file := vfsFileGet(ctx, mod, pFile).(File) file := vfsFileGet(ctx, mod, pFile).(File)
size, err := file.Size() size, err := file.Size()
util.WriteUint64(mod, pSize, uint64(size)) util.Write64(mod, pSize, size)
return vfsErrorCode(err, _IOERR_SEEK) return vfsErrorCode(err, _IOERR_SEEK)
} }
func vfsLock(ctx context.Context, mod api.Module, pFile uint32, eLock LockLevel) _ErrorCode { func vfsLock(ctx context.Context, mod api.Module, pFile ptr_t, eLock LockLevel) _ErrorCode {
file := vfsFileGet(ctx, mod, pFile).(File) file := vfsFileGet(ctx, mod, pFile).(File)
err := file.Lock(eLock) err := file.Lock(eLock)
return vfsErrorCode(err, _IOERR_LOCK) return vfsErrorCode(err, _IOERR_LOCK)
} }
func vfsUnlock(ctx context.Context, mod api.Module, pFile uint32, eLock LockLevel) _ErrorCode { func vfsUnlock(ctx context.Context, mod api.Module, pFile ptr_t, eLock LockLevel) _ErrorCode {
file := vfsFileGet(ctx, mod, pFile).(File) file := vfsFileGet(ctx, mod, pFile).(File)
err := file.Unlock(eLock) err := file.Unlock(eLock)
return vfsErrorCode(err, _IOERR_UNLOCK) return vfsErrorCode(err, _IOERR_UNLOCK)
} }
func vfsCheckReservedLock(ctx context.Context, mod api.Module, pFile, pResOut uint32) _ErrorCode { func vfsCheckReservedLock(ctx context.Context, mod api.Module, pFile, pResOut ptr_t) _ErrorCode {
file := vfsFileGet(ctx, mod, pFile).(File) file := vfsFileGet(ctx, mod, pFile).(File)
locked, err := file.CheckReservedLock() locked, err := file.CheckReservedLock()
var res uint32 var res int32
if locked { if locked {
res = 1 res = 1
} }
util.Write32(mod, pResOut, res)
util.WriteUint32(mod, pResOut, res)
return vfsErrorCode(err, _IOERR_CHECKRESERVEDLOCK) return vfsErrorCode(err, _IOERR_CHECKRESERVEDLOCK)
} }
func vfsFileControl(ctx context.Context, mod api.Module, pFile uint32, op _FcntlOpcode, pArg uint32) _ErrorCode { func vfsFileControl(ctx context.Context, mod api.Module, pFile ptr_t, op _FcntlOpcode, pArg ptr_t) _ErrorCode {
file := vfsFileGet(ctx, mod, pFile).(File) file := vfsFileGet(ctx, mod, pFile).(File)
if file, ok := file.(fileControl); ok { if file, ok := file.(fileControl); ok {
return file.fileControl(ctx, mod, op, pArg) return file.fileControl(ctx, mod, op, pArg)
@ -244,62 +242,62 @@ func vfsFileControl(ctx context.Context, mod api.Module, pFile uint32, op _Fcntl
return vfsFileControlImpl(ctx, mod, file, op, pArg) return vfsFileControlImpl(ctx, mod, file, op, pArg)
} }
func vfsFileControlImpl(ctx context.Context, mod api.Module, file File, op _FcntlOpcode, pArg uint32) _ErrorCode { func vfsFileControlImpl(ctx context.Context, mod api.Module, file File, op _FcntlOpcode, pArg ptr_t) _ErrorCode {
switch op { switch op {
case _FCNTL_LOCKSTATE: case _FCNTL_LOCKSTATE:
if file, ok := file.(FileLockState); ok { if file, ok := file.(FileLockState); ok {
if lk := file.LockState(); lk <= LOCK_EXCLUSIVE { if lk := file.LockState(); lk <= LOCK_EXCLUSIVE {
util.WriteUint32(mod, pArg, uint32(lk)) util.Write32(mod, pArg, lk)
return _OK return _OK
} }
} }
case _FCNTL_PERSIST_WAL: case _FCNTL_PERSIST_WAL:
if file, ok := file.(FilePersistWAL); ok { if file, ok := file.(FilePersistWAL); ok {
if i := util.ReadUint32(mod, pArg); int32(i) >= 0 { if i := util.Read32[int32](mod, pArg); i >= 0 {
file.SetPersistWAL(i != 0) file.SetPersistWAL(i != 0)
} else if file.PersistWAL() { } else if file.PersistWAL() {
util.WriteUint32(mod, pArg, 1) util.Write32(mod, pArg, int32(1))
} else { } else {
util.WriteUint32(mod, pArg, 0) util.Write32(mod, pArg, int32(0))
} }
return _OK return _OK
} }
case _FCNTL_POWERSAFE_OVERWRITE: case _FCNTL_POWERSAFE_OVERWRITE:
if file, ok := file.(FilePowersafeOverwrite); ok { if file, ok := file.(FilePowersafeOverwrite); ok {
if i := util.ReadUint32(mod, pArg); int32(i) >= 0 { if i := util.Read32[int32](mod, pArg); i >= 0 {
file.SetPowersafeOverwrite(i != 0) file.SetPowersafeOverwrite(i != 0)
} else if file.PowersafeOverwrite() { } else if file.PowersafeOverwrite() {
util.WriteUint32(mod, pArg, 1) util.Write32(mod, pArg, int32(1))
} else { } else {
util.WriteUint32(mod, pArg, 0) util.Write32(mod, pArg, int32(0))
} }
return _OK return _OK
} }
case _FCNTL_CHUNK_SIZE: case _FCNTL_CHUNK_SIZE:
if file, ok := file.(FileChunkSize); ok { if file, ok := file.(FileChunkSize); ok {
size := util.ReadUint32(mod, pArg) size := util.Read32[int32](mod, pArg)
file.ChunkSize(int(size)) file.ChunkSize(int(size))
return _OK return _OK
} }
case _FCNTL_SIZE_HINT: case _FCNTL_SIZE_HINT:
if file, ok := file.(FileSizeHint); ok { if file, ok := file.(FileSizeHint); ok {
size := util.ReadUint64(mod, pArg) size := util.Read64[int64](mod, pArg)
err := file.SizeHint(int64(size)) err := file.SizeHint(size)
return vfsErrorCode(err, _IOERR_TRUNCATE) return vfsErrorCode(err, _IOERR_TRUNCATE)
} }
case _FCNTL_HAS_MOVED: case _FCNTL_HAS_MOVED:
if file, ok := file.(FileHasMoved); ok { if file, ok := file.(FileHasMoved); ok {
moved, err := file.HasMoved() moved, err := file.HasMoved()
var res uint32 var val uint32
if moved { if moved {
res = 1 val = 1
} }
util.WriteUint32(mod, pArg, res) util.Write32(mod, pArg, val)
return vfsErrorCode(err, _IOERR_FSTAT) return vfsErrorCode(err, _IOERR_FSTAT)
} }
@ -354,10 +352,10 @@ func vfsFileControlImpl(ctx context.Context, mod api.Module, file File, op _Fcnt
case _FCNTL_PRAGMA: case _FCNTL_PRAGMA:
if file, ok := file.(FilePragma); ok { if file, ok := file.(FilePragma); ok {
ptr := util.ReadUint32(mod, pArg+1*ptrlen) ptr := util.Read32[ptr_t](mod, pArg+1*ptrlen)
name := util.ReadString(mod, ptr, _MAX_SQL_LENGTH) name := util.ReadString(mod, ptr, _MAX_SQL_LENGTH)
var value string var value string
if ptr := util.ReadUint32(mod, pArg+2*ptrlen); ptr != 0 { if ptr := util.Read32[ptr_t](mod, pArg+2*ptrlen); ptr != 0 {
value = util.ReadString(mod, ptr, _MAX_SQL_LENGTH) value = util.ReadString(mod, ptr, _MAX_SQL_LENGTH)
} }
@ -369,22 +367,22 @@ func vfsFileControlImpl(ctx context.Context, mod api.Module, file File, op _Fcnt
} }
if out != "" { if out != "" {
fn := mod.ExportedFunction("sqlite3_malloc64") fn := mod.ExportedFunction("sqlite3_malloc64")
stack := [...]uint64{uint64(len(out) + 1)} stack := [...]stk_t{stk_t(len(out) + 1)}
if err := fn.CallWithStack(ctx, stack[:]); err != nil { if err := fn.CallWithStack(ctx, stack[:]); err != nil {
panic(err) panic(err)
} }
util.WriteUint32(mod, pArg, uint32(stack[0])) util.Write32(mod, pArg, ptr_t(stack[0]))
util.WriteString(mod, uint32(stack[0]), out) util.WriteString(mod, ptr_t(stack[0]), out)
} }
return ret return ret
} }
case _FCNTL_BUSYHANDLER: case _FCNTL_BUSYHANDLER:
if file, ok := file.(FileBusyHandler); ok { if file, ok := file.(FileBusyHandler); ok {
arg := util.ReadUint64(mod, pArg) arg := util.Read64[stk_t](mod, pArg)
fn := mod.ExportedFunction("sqlite3_invoke_busy_handler_go") fn := mod.ExportedFunction("sqlite3_invoke_busy_handler_go")
file.BusyHandler(func() bool { file.BusyHandler(func() bool {
stack := [...]uint64{arg} stack := [...]stk_t{arg}
if err := fn.CallWithStack(ctx, stack[:]); err != nil { if err := fn.CallWithStack(ctx, stack[:]); err != nil {
panic(err) panic(err)
} }
@ -396,7 +394,7 @@ func vfsFileControlImpl(ctx context.Context, mod api.Module, file File, op _Fcnt
case _FCNTL_LOCK_TIMEOUT: case _FCNTL_LOCK_TIMEOUT:
if file, ok := file.(FileSharedMemory); ok { if file, ok := file.(FileSharedMemory); ok {
if shm, ok := file.SharedMemory().(blockingSharedMemory); ok { if shm, ok := file.SharedMemory().(blockingSharedMemory); ok {
shm.shmEnableBlocking(util.ReadUint32(mod, pArg) != 0) shm.shmEnableBlocking(util.Read32[uint32](mod, pArg) != 0)
return _OK return _OK
} }
} }
@ -411,44 +409,45 @@ func vfsFileControlImpl(ctx context.Context, mod api.Module, file File, op _Fcnt
return _NOTFOUND return _NOTFOUND
} }
func vfsSectorSize(ctx context.Context, mod api.Module, pFile uint32) uint32 { func vfsSectorSize(ctx context.Context, mod api.Module, pFile ptr_t) uint32 {
file := vfsFileGet(ctx, mod, pFile).(File) file := vfsFileGet(ctx, mod, pFile).(File)
return uint32(file.SectorSize()) return uint32(file.SectorSize())
} }
func vfsDeviceCharacteristics(ctx context.Context, mod api.Module, pFile uint32) DeviceCharacteristic { func vfsDeviceCharacteristics(ctx context.Context, mod api.Module, pFile ptr_t) DeviceCharacteristic {
file := vfsFileGet(ctx, mod, pFile).(File) file := vfsFileGet(ctx, mod, pFile).(File)
return file.DeviceCharacteristics() return file.DeviceCharacteristics()
} }
func vfsShmBarrier(ctx context.Context, mod api.Module, pFile uint32) { func vfsShmBarrier(ctx context.Context, mod api.Module, pFile ptr_t) {
shm := vfsFileGet(ctx, mod, pFile).(FileSharedMemory).SharedMemory() shm := vfsFileGet(ctx, mod, pFile).(FileSharedMemory).SharedMemory()
shm.shmBarrier() shm.shmBarrier()
} }
func vfsShmMap(ctx context.Context, mod api.Module, pFile uint32, iRegion, szRegion int32, bExtend, pp uint32) _ErrorCode { 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() shm := vfsFileGet(ctx, mod, pFile).(FileSharedMemory).SharedMemory()
p, rc := shm.shmMap(ctx, mod, iRegion, szRegion, bExtend != 0) p, rc := shm.shmMap(ctx, mod, iRegion, szRegion, bExtend != 0)
util.WriteUint32(mod, pp, p) util.Write32(mod, pp, p)
return rc return rc
} }
func vfsShmLock(ctx context.Context, mod api.Module, pFile uint32, offset, n int32, flags _ShmFlag) _ErrorCode { func vfsShmLock(ctx context.Context, mod api.Module, pFile ptr_t, offset, n int32, flags _ShmFlag) _ErrorCode {
shm := vfsFileGet(ctx, mod, pFile).(FileSharedMemory).SharedMemory() shm := vfsFileGet(ctx, mod, pFile).(FileSharedMemory).SharedMemory()
return shm.shmLock(offset, n, flags) return shm.shmLock(offset, n, flags)
} }
func vfsShmUnmap(ctx context.Context, mod api.Module, pFile, bDelete uint32) _ErrorCode { func vfsShmUnmap(ctx context.Context, mod api.Module, pFile ptr_t, bDelete int32) _ErrorCode {
shm := vfsFileGet(ctx, mod, pFile).(FileSharedMemory).SharedMemory() shm := vfsFileGet(ctx, mod, pFile).(FileSharedMemory).SharedMemory()
shm.shmUnmap(bDelete != 0) shm.shmUnmap(bDelete != 0)
return _OK return _OK
} }
func vfsGet(mod api.Module, pVfs uint32) VFS { func vfsGet(mod api.Module, pVfs ptr_t) VFS {
var name string var name string
if pVfs != 0 { if pVfs != 0 {
const zNameOffset = 16 const zNameOffset = 16
name = util.ReadString(mod, util.ReadUint32(mod, pVfs+zNameOffset), _MAX_NAME) ptr := util.Read32[ptr_t](mod, pVfs+zNameOffset)
name = util.ReadString(mod, ptr, _MAX_NAME)
} }
if vfs := Find(name); vfs != nil { if vfs := Find(name); vfs != nil {
return vfs return vfs
@ -456,21 +455,21 @@ func vfsGet(mod api.Module, pVfs uint32) VFS {
panic(util.NoVFSErr + util.ErrorString(name)) panic(util.NoVFSErr + util.ErrorString(name))
} }
func vfsFileRegister(ctx context.Context, mod api.Module, pFile uint32, file File) { func vfsFileRegister(ctx context.Context, mod api.Module, pFile ptr_t, file File) {
const fileHandleOffset = 4 const fileHandleOffset = 4
id := util.AddHandle(ctx, file) id := util.AddHandle(ctx, file)
util.WriteUint32(mod, pFile+fileHandleOffset, id) util.Write32(mod, pFile+fileHandleOffset, id)
} }
func vfsFileGet(ctx context.Context, mod api.Module, pFile uint32) any { func vfsFileGet(ctx context.Context, mod api.Module, pFile ptr_t) any {
const fileHandleOffset = 4 const fileHandleOffset = 4
id := util.ReadUint32(mod, pFile+fileHandleOffset) id := util.Read32[ptr_t](mod, pFile+fileHandleOffset)
return util.GetHandle(ctx, id) return util.GetHandle(ctx, id)
} }
func vfsFileClose(ctx context.Context, mod api.Module, pFile uint32) error { func vfsFileClose(ctx context.Context, mod api.Module, pFile ptr_t) error {
const fileHandleOffset = 4 const fileHandleOffset = 4
id := util.ReadUint32(mod, pFile+fileHandleOffset) id := util.Read32[ptr_t](mod, pFile+fileHandleOffset)
return util.DelHandle(ctx, id) return util.DelHandle(ctx, id)
} }

View file

@ -2,6 +2,7 @@
import ( import (
"context" "context"
"errors"
"reflect" "reflect"
"github.com/tetratelabs/wazero/api" "github.com/tetratelabs/wazero/api"
@ -58,15 +59,15 @@ func CreateModule[T VTab](db *Conn, name string, create, connect VTabConstructor
flags |= VTAB_SHADOWTABS flags |= VTAB_SHADOWTABS
} }
var modulePtr uint32 var modulePtr ptr_t
defer db.arena.mark()() defer db.arena.mark()()
namePtr := db.arena.string(name) namePtr := db.arena.string(name)
if connect != nil { if connect != nil {
modulePtr = util.AddHandle(db.ctx, module[T]{create, connect}) modulePtr = util.AddHandle(db.ctx, module[T]{create, connect})
} }
r := db.call("sqlite3_create_module_go", uint64(db.handle), rc := res_t(db.call("sqlite3_create_module_go", stk_t(db.handle),
uint64(namePtr), uint64(flags), uint64(modulePtr)) stk_t(namePtr), stk_t(flags), stk_t(modulePtr)))
return db.error(r) return db.error(rc)
} }
func implements[T any](typ reflect.Type) bool { func implements[T any](typ reflect.Type) bool {
@ -80,8 +81,8 @@ func implements[T any](typ reflect.Type) bool {
func (c *Conn) DeclareVTab(sql string) error { func (c *Conn) DeclareVTab(sql string) error {
defer c.arena.mark()() defer c.arena.mark()()
sqlPtr := c.arena.string(sql) sqlPtr := c.arena.string(sql)
r := c.call("sqlite3_declare_vtab", uint64(c.handle), uint64(sqlPtr)) rc := res_t(c.call("sqlite3_declare_vtab", stk_t(c.handle), stk_t(sqlPtr)))
return c.error(r) return c.error(rc)
} }
// VTabConflictMode is a virtual table conflict resolution mode. // VTabConflictMode is a virtual table conflict resolution mode.
@ -101,8 +102,7 @@ func (c *Conn) DeclareVTab(sql string) error {
// //
// https://sqlite.org/c3ref/vtab_on_conflict.html // https://sqlite.org/c3ref/vtab_on_conflict.html
func (c *Conn) VTabOnConflict() VTabConflictMode { func (c *Conn) VTabOnConflict() VTabConflictMode {
r := c.call("sqlite3_vtab_on_conflict", uint64(c.handle)) return VTabConflictMode(c.call("sqlite3_vtab_on_conflict", stk_t(c.handle)))
return VTabConflictMode(r)
} }
// VTabConfigOption is a virtual table configuration option. // VTabConfigOption is a virtual table configuration option.
@ -121,14 +121,14 @@ func (c *Conn) VTabOnConflict() VTabConflictMode {
// //
// https://sqlite.org/c3ref/vtab_config.html // https://sqlite.org/c3ref/vtab_config.html
func (c *Conn) VTabConfig(op VTabConfigOption, args ...any) error { func (c *Conn) VTabConfig(op VTabConfigOption, args ...any) error {
var i uint64 var i int32
if op == VTAB_CONSTRAINT_SUPPORT && len(args) > 0 { if op == VTAB_CONSTRAINT_SUPPORT && len(args) > 0 {
if b, ok := args[0].(bool); ok && b { if b, ok := args[0].(bool); ok && b {
i = 1 i = 1
} }
} }
r := c.call("sqlite3_vtab_config_go", uint64(c.handle), uint64(op), i) rc := res_t(c.call("sqlite3_vtab_config_go", stk_t(c.handle), stk_t(op), stk_t(i)))
return c.error(r) return c.error(rc)
} }
// VTabConstructor is a virtual table constructor function. // VTabConstructor is a virtual table constructor function.
@ -263,7 +263,7 @@ type IndexInfo struct {
// Inputs // Inputs
Constraint []IndexConstraint Constraint []IndexConstraint
OrderBy []IndexOrderBy OrderBy []IndexOrderBy
ColumnsUsed int64 ColumnsUsed uint64
// Outputs // Outputs
ConstraintUsage []IndexConstraintUsage ConstraintUsage []IndexConstraintUsage
IdxNum int IdxNum int
@ -274,7 +274,7 @@ type IndexInfo struct {
EstimatedRows int64 EstimatedRows int64
// Internal // Internal
c *Conn c *Conn
handle uint32 handle ptr_t
} }
// An IndexConstraint describes virtual table indexing constraint information. // An IndexConstraint describes virtual table indexing constraint information.
@ -309,14 +309,14 @@ type IndexConstraintUsage struct {
func (idx *IndexInfo) RHSValue(column int) (Value, error) { func (idx *IndexInfo) RHSValue(column int) (Value, error) {
defer idx.c.arena.mark()() defer idx.c.arena.mark()()
valPtr := idx.c.arena.new(ptrlen) valPtr := idx.c.arena.new(ptrlen)
r := idx.c.call("sqlite3_vtab_rhs_value", uint64(idx.handle), rc := res_t(idx.c.call("sqlite3_vtab_rhs_value", stk_t(idx.handle),
uint64(column), uint64(valPtr)) stk_t(column), stk_t(valPtr)))
if err := idx.c.error(r); err != nil { if err := idx.c.error(rc); err != nil {
return Value{}, err return Value{}, err
} }
return Value{ return Value{
c: idx.c, c: idx.c,
handle: util.ReadUint32(idx.c.mod, valPtr), handle: util.Read32[ptr_t](idx.c.mod, valPtr),
}, nil }, nil
} }
@ -324,26 +324,26 @@ func (idx *IndexInfo) RHSValue(column int) (Value, error) {
// //
// https://sqlite.org/c3ref/vtab_collation.html // https://sqlite.org/c3ref/vtab_collation.html
func (idx *IndexInfo) Collation(column int) string { func (idx *IndexInfo) Collation(column int) string {
r := idx.c.call("sqlite3_vtab_collation", uint64(idx.handle), ptr := ptr_t(idx.c.call("sqlite3_vtab_collation", stk_t(idx.handle),
uint64(column)) stk_t(column)))
return util.ReadString(idx.c.mod, uint32(r), _MAX_NAME) return util.ReadString(idx.c.mod, ptr, _MAX_NAME)
} }
// Distinct determines if a virtual table query is DISTINCT. // Distinct determines if a virtual table query is DISTINCT.
// //
// https://sqlite.org/c3ref/vtab_distinct.html // https://sqlite.org/c3ref/vtab_distinct.html
func (idx *IndexInfo) Distinct() int { func (idx *IndexInfo) Distinct() int {
r := idx.c.call("sqlite3_vtab_distinct", uint64(idx.handle)) i := int32(idx.c.call("sqlite3_vtab_distinct", stk_t(idx.handle)))
return int(r) return int(i)
} }
// In identifies and handles IN constraints. // In identifies and handles IN constraints.
// //
// https://sqlite.org/c3ref/vtab_in.html // https://sqlite.org/c3ref/vtab_in.html
func (idx *IndexInfo) In(column, handle int) bool { func (idx *IndexInfo) In(column, handle int) bool {
r := idx.c.call("sqlite3_vtab_in", uint64(idx.handle), b := int32(idx.c.call("sqlite3_vtab_in", stk_t(idx.handle),
uint64(column), uint64(handle)) stk_t(column), stk_t(handle)))
return r != 0 return b != 0
} }
func (idx *IndexInfo) load() { func (idx *IndexInfo) load() {
@ -351,34 +351,35 @@ func (idx *IndexInfo) load() {
mod := idx.c.mod mod := idx.c.mod
ptr := idx.handle ptr := idx.handle
idx.Constraint = make([]IndexConstraint, util.ReadUint32(mod, ptr+0)) nConstraint := util.Read32[int32](mod, ptr+0)
idx.ConstraintUsage = make([]IndexConstraintUsage, util.ReadUint32(mod, ptr+0)) idx.Constraint = make([]IndexConstraint, nConstraint)
idx.OrderBy = make([]IndexOrderBy, util.ReadUint32(mod, ptr+8)) idx.ConstraintUsage = make([]IndexConstraintUsage, nConstraint)
idx.OrderBy = make([]IndexOrderBy, util.Read32[int32](mod, ptr+8))
constraintPtr := util.ReadUint32(mod, ptr+4) constraintPtr := util.Read32[ptr_t](mod, ptr+4)
constraint := idx.Constraint constraint := idx.Constraint
for i := range idx.Constraint { for i := range idx.Constraint {
constraint[i] = IndexConstraint{ constraint[i] = IndexConstraint{
Column: int(int32(util.ReadUint32(mod, constraintPtr+0))), Column: int(util.Read32[int32](mod, constraintPtr+0)),
Op: IndexConstraintOp(util.ReadUint8(mod, constraintPtr+4)), Op: util.Read[IndexConstraintOp](mod, constraintPtr+4),
Usable: util.ReadUint8(mod, constraintPtr+5) != 0, Usable: util.Read[byte](mod, constraintPtr+5) != 0,
} }
constraintPtr += 12 constraintPtr += 12
} }
orderByPtr := util.ReadUint32(mod, ptr+12) orderByPtr := util.Read32[ptr_t](mod, ptr+12)
orderBy := idx.OrderBy orderBy := idx.OrderBy
for i := range orderBy { for i := range orderBy {
orderBy[i] = IndexOrderBy{ orderBy[i] = IndexOrderBy{
Column: int(int32(util.ReadUint32(mod, orderByPtr+0))), Column: int(util.Read32[int32](mod, orderByPtr+0)),
Desc: util.ReadUint8(mod, orderByPtr+4) != 0, Desc: util.Read[byte](mod, orderByPtr+4) != 0,
} }
orderByPtr += 8 orderByPtr += 8
} }
idx.EstimatedCost = util.ReadFloat64(mod, ptr+40) idx.EstimatedCost = util.ReadFloat64(mod, ptr+40)
idx.EstimatedRows = int64(util.ReadUint64(mod, ptr+48)) idx.EstimatedRows = util.Read64[int64](mod, ptr+48)
idx.ColumnsUsed = int64(util.ReadUint64(mod, ptr+64)) idx.ColumnsUsed = util.Read64[uint64](mod, ptr+64)
} }
func (idx *IndexInfo) save() { func (idx *IndexInfo) save() {
@ -386,26 +387,26 @@ func (idx *IndexInfo) save() {
mod := idx.c.mod mod := idx.c.mod
ptr := idx.handle ptr := idx.handle
usagePtr := util.ReadUint32(mod, ptr+16) usagePtr := util.Read32[ptr_t](mod, ptr+16)
for _, usage := range idx.ConstraintUsage { for _, usage := range idx.ConstraintUsage {
util.WriteUint32(mod, usagePtr+0, uint32(usage.ArgvIndex)) util.Write32(mod, usagePtr+0, int32(usage.ArgvIndex))
if usage.Omit { if usage.Omit {
util.WriteUint8(mod, usagePtr+4, 1) util.Write(mod, usagePtr+4, int8(1))
} }
usagePtr += 8 usagePtr += 8
} }
util.WriteUint32(mod, ptr+20, uint32(idx.IdxNum)) util.Write32(mod, ptr+20, int32(idx.IdxNum))
if idx.IdxStr != "" { if idx.IdxStr != "" {
util.WriteUint32(mod, ptr+24, idx.c.newString(idx.IdxStr)) util.Write32(mod, ptr+24, idx.c.newString(idx.IdxStr))
util.WriteUint32(mod, ptr+28, 1) // needToFreeIdxStr util.Write32(mod, ptr+28, int32(1)) // needToFreeIdxStr
} }
if idx.OrderByConsumed { if idx.OrderByConsumed {
util.WriteUint32(mod, ptr+32, 1) util.Write32(mod, ptr+32, int32(1))
} }
util.WriteFloat64(mod, ptr+40, idx.EstimatedCost) util.WriteFloat64(mod, ptr+40, idx.EstimatedCost)
util.WriteUint64(mod, ptr+48, uint64(idx.EstimatedRows)) util.Write64(mod, ptr+48, idx.EstimatedRows)
util.WriteUint32(mod, ptr+56, uint32(idx.IdxFlags)) util.Write32(mod, ptr+56, idx.IdxFlags)
} }
// IndexConstraintOp is a virtual table constraint operator code. // IndexConstraintOp is a virtual table constraint operator code.
@ -442,42 +443,39 @@ func (idx *IndexInfo) save() {
INDEX_SCAN_UNIQUE IndexScanFlag = 1 INDEX_SCAN_UNIQUE IndexScanFlag = 1
) )
func vtabModuleCallback(i vtabConstructor) func(_ context.Context, _ api.Module, _, _, _, _, _ uint32) uint32 { 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, nArg, pArg, ppVTab, pzErr uint32) uint32 { 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 := make([]reflect.Value, 1+nArg)
arg[0] = reflect.ValueOf(ctx.Value(connKey{})) arg[0] = reflect.ValueOf(ctx.Value(connKey{}))
for i := uint32(0); i < nArg; i++ { for i := range nArg {
ptr := util.ReadUint32(mod, pArg+i*ptrlen) ptr := util.Read32[ptr_t](mod, pArg+ptr_t(i)*ptrlen)
arg[i+1] = reflect.ValueOf(util.ReadString(mod, ptr, _MAX_SQL_LENGTH)) arg[i+1] = reflect.ValueOf(util.ReadString(mod, ptr, _MAX_SQL_LENGTH))
} }
module := vtabGetHandle(ctx, mod, pMod) module := vtabGetHandle(ctx, mod, pMod)
res := reflect.ValueOf(module).Index(int(i)).Call(arg) val := reflect.ValueOf(module).Index(int(i)).Call(arg)
err, _ := res[1].Interface().(error) err, _ := val[1].Interface().(error)
if err == nil { if err == nil {
vtabPutHandle(ctx, mod, ppVTab, res[0].Interface()) vtabPutHandle(ctx, mod, ppVTab, val[0].Interface())
} }
return vtabError(ctx, mod, pzErr, _PTR_ERROR, err) return vtabError(ctx, mod, pzErr, _PTR_ERROR, err)
} }
} }
func vtabDisconnectCallback(ctx context.Context, mod api.Module, pVTab uint32) uint32 { func vtabDisconnectCallback(ctx context.Context, mod api.Module, pVTab ptr_t) res_t {
err := vtabDelHandle(ctx, mod, pVTab) err := vtabDelHandle(ctx, mod, pVTab)
return vtabError(ctx, mod, 0, _PTR_ERROR, err) return vtabError(ctx, mod, 0, _PTR_ERROR, err)
} }
func vtabDestroyCallback(ctx context.Context, mod api.Module, pVTab uint32) uint32 { func vtabDestroyCallback(ctx context.Context, mod api.Module, pVTab ptr_t) res_t {
vtab := vtabGetHandle(ctx, mod, pVTab).(VTabDestroyer) vtab := vtabGetHandle(ctx, mod, pVTab).(VTabDestroyer)
err := vtab.Destroy() err := errors.Join(vtab.Destroy(), vtabDelHandle(ctx, mod, pVTab))
if cerr := vtabDelHandle(ctx, mod, pVTab); err == nil {
err = cerr
}
return vtabError(ctx, mod, 0, _PTR_ERROR, err) return vtabError(ctx, mod, 0, _PTR_ERROR, err)
} }
func vtabBestIndexCallback(ctx context.Context, mod api.Module, pVTab, pIdxInfo uint32) uint32 { func vtabBestIndexCallback(ctx context.Context, mod api.Module, pVTab, pIdxInfo ptr_t) res_t {
var info IndexInfo var info IndexInfo
info.handle = pIdxInfo info.handle = pIdxInfo
info.c = ctx.Value(connKey{}).(*Conn) info.c = ctx.Value(connKey{}).(*Conn)
@ -490,7 +488,7 @@ func vtabBestIndexCallback(ctx context.Context, mod api.Module, pVTab, pIdxInfo
return vtabError(ctx, mod, pVTab, _VTAB_ERROR, err) return vtabError(ctx, mod, pVTab, _VTAB_ERROR, err)
} }
func vtabUpdateCallback(ctx context.Context, mod api.Module, pVTab, nArg, pArg, pRowID uint32) uint32 { 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) vtab := vtabGetHandle(ctx, mod, pVTab).(VTabUpdater)
db := ctx.Value(connKey{}).(*Conn) db := ctx.Value(connKey{}).(*Conn)
@ -498,33 +496,33 @@ func vtabUpdateCallback(ctx context.Context, mod api.Module, pVTab, nArg, pArg,
callbackArgs(db, args, pArg) callbackArgs(db, args, pArg)
rowID, err := vtab.Update(args...) rowID, err := vtab.Update(args...)
if err == nil { if err == nil {
util.WriteUint64(mod, pRowID, uint64(rowID)) util.Write64(mod, pRowID, rowID)
} }
return vtabError(ctx, mod, pVTab, _VTAB_ERROR, err) return vtabError(ctx, mod, pVTab, _VTAB_ERROR, err)
} }
func vtabRenameCallback(ctx context.Context, mod api.Module, pVTab, zNew uint32) uint32 { func vtabRenameCallback(ctx context.Context, mod api.Module, pVTab, zNew ptr_t) res_t {
vtab := vtabGetHandle(ctx, mod, pVTab).(VTabRenamer) vtab := vtabGetHandle(ctx, mod, pVTab).(VTabRenamer)
err := vtab.Rename(util.ReadString(mod, zNew, _MAX_NAME)) err := vtab.Rename(util.ReadString(mod, zNew, _MAX_NAME))
return vtabError(ctx, mod, pVTab, _VTAB_ERROR, err) return vtabError(ctx, mod, pVTab, _VTAB_ERROR, err)
} }
func vtabFindFuncCallback(ctx context.Context, mod api.Module, pVTab uint32, nArg int32, zName, pxFunc uint32) uint32 { func vtabFindFuncCallback(ctx context.Context, mod api.Module, pVTab ptr_t, nArg int32, zName, pxFunc ptr_t) int32 {
vtab := vtabGetHandle(ctx, mod, pVTab).(VTabOverloader) vtab := vtabGetHandle(ctx, mod, pVTab).(VTabOverloader)
f, op := vtab.FindFunction(int(nArg), util.ReadString(mod, zName, _MAX_NAME)) f, op := vtab.FindFunction(int(nArg), util.ReadString(mod, zName, _MAX_NAME))
if op != 0 { if op != 0 {
var wrapper uint32 var wrapper ptr_t
wrapper = util.AddHandle(ctx, func(c Context, arg ...Value) { wrapper = util.AddHandle(ctx, func(c Context, arg ...Value) {
defer util.DelHandle(ctx, wrapper) defer util.DelHandle(ctx, wrapper)
f(c, arg...) f(c, arg...)
}) })
util.WriteUint32(mod, pxFunc, wrapper) util.Write32(mod, pxFunc, wrapper)
} }
return uint32(op) return int32(op)
} }
func vtabIntegrityCallback(ctx context.Context, mod api.Module, pVTab, zSchema, zTabName, mFlags, pzErr uint32) uint32 { 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) vtab := vtabGetHandle(ctx, mod, pVTab).(VTabChecker)
schema := util.ReadString(mod, zSchema, _MAX_NAME) schema := util.ReadString(mod, zSchema, _MAX_NAME)
table := util.ReadString(mod, zTabName, _MAX_NAME) table := util.ReadString(mod, zTabName, _MAX_NAME)
@ -536,49 +534,49 @@ func vtabIntegrityCallback(ctx context.Context, mod api.Module, pVTab, zSchema,
return code return code
} }
func vtabBeginCallback(ctx context.Context, mod api.Module, pVTab uint32) uint32 { func vtabBeginCallback(ctx context.Context, mod api.Module, pVTab ptr_t) res_t {
vtab := vtabGetHandle(ctx, mod, pVTab).(VTabTxn) vtab := vtabGetHandle(ctx, mod, pVTab).(VTabTxn)
err := vtab.Begin() err := vtab.Begin()
return vtabError(ctx, mod, pVTab, _VTAB_ERROR, err) return vtabError(ctx, mod, pVTab, _VTAB_ERROR, err)
} }
func vtabSyncCallback(ctx context.Context, mod api.Module, pVTab uint32) uint32 { func vtabSyncCallback(ctx context.Context, mod api.Module, pVTab ptr_t) res_t {
vtab := vtabGetHandle(ctx, mod, pVTab).(VTabTxn) vtab := vtabGetHandle(ctx, mod, pVTab).(VTabTxn)
err := vtab.Sync() err := vtab.Sync()
return vtabError(ctx, mod, pVTab, _VTAB_ERROR, err) return vtabError(ctx, mod, pVTab, _VTAB_ERROR, err)
} }
func vtabCommitCallback(ctx context.Context, mod api.Module, pVTab uint32) uint32 { func vtabCommitCallback(ctx context.Context, mod api.Module, pVTab ptr_t) res_t {
vtab := vtabGetHandle(ctx, mod, pVTab).(VTabTxn) vtab := vtabGetHandle(ctx, mod, pVTab).(VTabTxn)
err := vtab.Commit() err := vtab.Commit()
return vtabError(ctx, mod, pVTab, _VTAB_ERROR, err) return vtabError(ctx, mod, pVTab, _VTAB_ERROR, err)
} }
func vtabRollbackCallback(ctx context.Context, mod api.Module, pVTab uint32) uint32 { func vtabRollbackCallback(ctx context.Context, mod api.Module, pVTab ptr_t) res_t {
vtab := vtabGetHandle(ctx, mod, pVTab).(VTabTxn) vtab := vtabGetHandle(ctx, mod, pVTab).(VTabTxn)
err := vtab.Rollback() err := vtab.Rollback()
return vtabError(ctx, mod, pVTab, _VTAB_ERROR, err) return vtabError(ctx, mod, pVTab, _VTAB_ERROR, err)
} }
func vtabSavepointCallback(ctx context.Context, mod api.Module, pVTab uint32, id int32) uint32 { func vtabSavepointCallback(ctx context.Context, mod api.Module, pVTab ptr_t, id int32) res_t {
vtab := vtabGetHandle(ctx, mod, pVTab).(VTabSavepointer) vtab := vtabGetHandle(ctx, mod, pVTab).(VTabSavepointer)
err := vtab.Savepoint(int(id)) err := vtab.Savepoint(int(id))
return vtabError(ctx, mod, pVTab, _VTAB_ERROR, err) return vtabError(ctx, mod, pVTab, _VTAB_ERROR, err)
} }
func vtabReleaseCallback(ctx context.Context, mod api.Module, pVTab uint32, id int32) uint32 { func vtabReleaseCallback(ctx context.Context, mod api.Module, pVTab ptr_t, id int32) res_t {
vtab := vtabGetHandle(ctx, mod, pVTab).(VTabSavepointer) vtab := vtabGetHandle(ctx, mod, pVTab).(VTabSavepointer)
err := vtab.Release(int(id)) err := vtab.Release(int(id))
return vtabError(ctx, mod, pVTab, _VTAB_ERROR, err) return vtabError(ctx, mod, pVTab, _VTAB_ERROR, err)
} }
func vtabRollbackToCallback(ctx context.Context, mod api.Module, pVTab uint32, id int32) uint32 { func vtabRollbackToCallback(ctx context.Context, mod api.Module, pVTab ptr_t, id int32) res_t {
vtab := vtabGetHandle(ctx, mod, pVTab).(VTabSavepointer) vtab := vtabGetHandle(ctx, mod, pVTab).(VTabSavepointer)
err := vtab.RollbackTo(int(id)) err := vtab.RollbackTo(int(id))
return vtabError(ctx, mod, pVTab, _VTAB_ERROR, err) return vtabError(ctx, mod, pVTab, _VTAB_ERROR, err)
} }
func cursorOpenCallback(ctx context.Context, mod api.Module, pVTab, ppCur uint32) uint32 { func cursorOpenCallback(ctx context.Context, mod api.Module, pVTab, ppCur ptr_t) res_t {
vtab := vtabGetHandle(ctx, mod, pVTab).(VTab) vtab := vtabGetHandle(ctx, mod, pVTab).(VTab)
cursor, err := vtab.Open() cursor, err := vtab.Open()
@ -589,12 +587,12 @@ func cursorOpenCallback(ctx context.Context, mod api.Module, pVTab, ppCur uint32
return vtabError(ctx, mod, pVTab, _VTAB_ERROR, err) return vtabError(ctx, mod, pVTab, _VTAB_ERROR, err)
} }
func cursorCloseCallback(ctx context.Context, mod api.Module, pCur uint32) uint32 { func cursorCloseCallback(ctx context.Context, mod api.Module, pCur ptr_t) res_t {
err := vtabDelHandle(ctx, mod, pCur) err := vtabDelHandle(ctx, mod, pCur)
return vtabError(ctx, mod, 0, _VTAB_ERROR, err) return vtabError(ctx, mod, 0, _VTAB_ERROR, err)
} }
func cursorFilterCallback(ctx context.Context, mod api.Module, pCur uint32, idxNum int32, idxStr, nArg, pArg uint32) uint32 { 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) cursor := vtabGetHandle(ctx, mod, pCur).(VTabCursor)
db := ctx.Value(connKey{}).(*Conn) db := ctx.Value(connKey{}).(*Conn)
args := make([]Value, nArg) args := make([]Value, nArg)
@ -607,7 +605,7 @@ func cursorFilterCallback(ctx context.Context, mod api.Module, pCur uint32, idxN
return vtabError(ctx, mod, pCur, _CURSOR_ERROR, err) return vtabError(ctx, mod, pCur, _CURSOR_ERROR, err)
} }
func cursorEOFCallback(ctx context.Context, mod api.Module, pCur uint32) uint32 { func cursorEOFCallback(ctx context.Context, mod api.Module, pCur ptr_t) int32 {
cursor := vtabGetHandle(ctx, mod, pCur).(VTabCursor) cursor := vtabGetHandle(ctx, mod, pCur).(VTabCursor)
if cursor.EOF() { if cursor.EOF() {
return 1 return 1
@ -615,25 +613,25 @@ func cursorEOFCallback(ctx context.Context, mod api.Module, pCur uint32) uint32
return 0 return 0
} }
func cursorNextCallback(ctx context.Context, mod api.Module, pCur uint32) uint32 { func cursorNextCallback(ctx context.Context, mod api.Module, pCur ptr_t) res_t {
cursor := vtabGetHandle(ctx, mod, pCur).(VTabCursor) cursor := vtabGetHandle(ctx, mod, pCur).(VTabCursor)
err := cursor.Next() err := cursor.Next()
return vtabError(ctx, mod, pCur, _CURSOR_ERROR, err) return vtabError(ctx, mod, pCur, _CURSOR_ERROR, err)
} }
func cursorColumnCallback(ctx context.Context, mod api.Module, pCur, pCtx uint32, n int32) uint32 { func cursorColumnCallback(ctx context.Context, mod api.Module, pCur, pCtx ptr_t, n int32) res_t {
cursor := vtabGetHandle(ctx, mod, pCur).(VTabCursor) cursor := vtabGetHandle(ctx, mod, pCur).(VTabCursor)
db := ctx.Value(connKey{}).(*Conn) db := ctx.Value(connKey{}).(*Conn)
err := cursor.Column(Context{db, pCtx}, int(n)) err := cursor.Column(Context{db, pCtx}, int(n))
return vtabError(ctx, mod, pCur, _CURSOR_ERROR, err) return vtabError(ctx, mod, pCur, _CURSOR_ERROR, err)
} }
func cursorRowIDCallback(ctx context.Context, mod api.Module, pCur, pRowID uint32) uint32 { func cursorRowIDCallback(ctx context.Context, mod api.Module, pCur, pRowID ptr_t) res_t {
cursor := vtabGetHandle(ctx, mod, pCur).(VTabCursor) cursor := vtabGetHandle(ctx, mod, pCur).(VTabCursor)
rowID, err := cursor.RowID() rowID, err := cursor.RowID()
if err == nil { if err == nil {
util.WriteUint64(mod, pRowID, uint64(rowID)) util.Write64(mod, pRowID, rowID)
} }
return vtabError(ctx, mod, pCur, _CURSOR_ERROR, err) return vtabError(ctx, mod, pCur, _CURSOR_ERROR, err)
@ -645,7 +643,7 @@ func cursorRowIDCallback(ctx context.Context, mod api.Module, pCur, pRowID uint3
_CURSOR_ERROR _CURSOR_ERROR
) )
func vtabError(ctx context.Context, mod api.Module, ptr, kind uint32, err error) uint32 { func vtabError(ctx context.Context, mod api.Module, ptr ptr_t, kind uint32, err error) res_t {
const zErrMsgOffset = 8 const zErrMsgOffset = 8
msg, code := errorCode(err, ERROR) msg, code := errorCode(err, ERROR)
if msg != "" && ptr != 0 { if msg != "" && ptr != 0 {
@ -653,32 +651,32 @@ func vtabError(ctx context.Context, mod api.Module, ptr, kind uint32, err error)
case _VTAB_ERROR: case _VTAB_ERROR:
ptr = ptr + zErrMsgOffset // zErrMsg ptr = ptr + zErrMsgOffset // zErrMsg
case _CURSOR_ERROR: case _CURSOR_ERROR:
ptr = util.ReadUint32(mod, ptr) + zErrMsgOffset // pVTab->zErrMsg ptr = util.Read32[ptr_t](mod, ptr) + zErrMsgOffset // pVTab->zErrMsg
} }
db := ctx.Value(connKey{}).(*Conn) db := ctx.Value(connKey{}).(*Conn)
if ptr := util.ReadUint32(mod, ptr); ptr != 0 { if ptr := util.Read32[ptr_t](mod, ptr); ptr != 0 {
db.free(ptr) db.free(ptr)
} }
util.WriteUint32(mod, ptr, db.newString(msg)) util.Write32(mod, ptr, db.newString(msg))
} }
return code return code
} }
func vtabGetHandle(ctx context.Context, mod api.Module, ptr uint32) any { func vtabGetHandle(ctx context.Context, mod api.Module, ptr ptr_t) any {
const handleOffset = 4 const handleOffset = 4
handle := util.ReadUint32(mod, ptr-handleOffset) handle := util.Read32[ptr_t](mod, ptr-handleOffset)
return util.GetHandle(ctx, handle) return util.GetHandle(ctx, handle)
} }
func vtabDelHandle(ctx context.Context, mod api.Module, ptr uint32) error { func vtabDelHandle(ctx context.Context, mod api.Module, ptr ptr_t) error {
const handleOffset = 4 const handleOffset = 4
handle := util.ReadUint32(mod, ptr-handleOffset) handle := util.Read32[ptr_t](mod, ptr-handleOffset)
return util.DelHandle(ctx, handle) return util.DelHandle(ctx, handle)
} }
func vtabPutHandle(ctx context.Context, mod api.Module, pptr uint32, val any) { func vtabPutHandle(ctx context.Context, mod api.Module, pptr ptr_t, val any) {
const handleOffset = 4 const handleOffset = 4
handle := util.AddHandle(ctx, val) handle := util.AddHandle(ctx, val)
ptr := util.ReadUint32(mod, pptr) ptr := util.Read32[ptr_t](mod, pptr)
util.WriteUint32(mod, ptr-handleOffset, handle) util.Write32(mod, ptr-handleOffset, handle)
} }

6
vendor/modules.txt vendored
View file

@ -412,8 +412,6 @@ github.com/jackc/puddle/v2/internal/genstack
# github.com/jessevdk/go-flags v1.5.0 # github.com/jessevdk/go-flags v1.5.0
## explicit; go 1.15 ## explicit; go 1.15
github.com/jessevdk/go-flags github.com/jessevdk/go-flags
# github.com/jimsmart/grobotstxt v1.0.3
## explicit; go 1.14
# github.com/jinzhu/inflection v1.0.0 # github.com/jinzhu/inflection v1.0.0
## explicit ## explicit
github.com/jinzhu/inflection github.com/jinzhu/inflection
@ -503,8 +501,8 @@ github.com/modern-go/reflect2
# github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 # github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822
## explicit ## explicit
github.com/munnerz/goautoneg github.com/munnerz/goautoneg
# github.com/ncruces/go-sqlite3 v0.22.0 # github.com/ncruces/go-sqlite3 v0.23.0
## explicit; go 1.21 ## explicit; go 1.22
github.com/ncruces/go-sqlite3 github.com/ncruces/go-sqlite3
github.com/ncruces/go-sqlite3/driver github.com/ncruces/go-sqlite3/driver
github.com/ncruces/go-sqlite3/embed github.com/ncruces/go-sqlite3/embed