Deoptimize.

This commit is contained in:
Nuno Cruces
2023-11-30 17:52:35 +00:00
parent a9e32fd3f0
commit d862f47d95
12 changed files with 115 additions and 297 deletions

View File

@@ -71,12 +71,12 @@ func (c *Conn) backupInit(dst uint32, dstName string, src uint32, srcName string
other = src
}
r := c.call(c.api.backupInit,
r := c.call("sqlite3_backup_init",
uint64(dst), uint64(dstPtr),
uint64(src), uint64(srcPtr))
if r == 0 {
defer c.closeDB(other)
r = c.call(c.api.errcode, uint64(dst))
r = c.call("sqlite3_errcode", uint64(dst))
return nil, c.sqlite.error(r, dst)
}
@@ -97,7 +97,7 @@ func (b *Backup) Close() error {
return nil
}
r := b.c.call(b.c.api.backupFinish, uint64(b.handle))
r := b.c.call("sqlite3_backup_finish", uint64(b.handle))
b.c.closeDB(b.otherc)
b.handle = 0
return b.c.error(r)
@@ -108,7 +108,7 @@ func (b *Backup) Close() error {
//
// https://sqlite.org/c3ref/backup_finish.html#sqlite3backupstep
func (b *Backup) Step(nPage int) (done bool, err error) {
r := b.c.call(b.c.api.backupStep, uint64(b.handle), uint64(nPage))
r := b.c.call("sqlite3_backup_step", uint64(b.handle), uint64(nPage))
if r == _DONE {
return true, nil
}
@@ -120,7 +120,7 @@ func (b *Backup) Step(nPage int) (done bool, err error) {
//
// https://sqlite.org/c3ref/backup_finish.html#sqlite3backupremaining
func (b *Backup) Remaining() int {
r := b.c.call(b.c.api.backupRemaining, uint64(b.handle))
r := b.c.call("sqlite3_backup_remaining", uint64(b.handle))
return int(r)
}
@@ -129,6 +129,6 @@ func (b *Backup) Remaining() int {
//
// https://sqlite.org/c3ref/backup_finish.html#sqlite3backuppagecount
func (b *Backup) PageCount() int {
r := b.c.call(b.c.api.backupPageCount, uint64(b.handle))
r := b.c.call("sqlite3_backup_pagecount", uint64(b.handle))
return int(r)
}

18
blob.go
View File

@@ -41,7 +41,7 @@ func (c *Conn) OpenBlob(db, table, column string, row int64, write bool) (*Blob,
flags = 1
}
r := c.call(c.api.blobOpen, uint64(c.handle),
r := c.call("sqlite3_blob_open", uint64(c.handle),
uint64(dbPtr), uint64(tablePtr), uint64(columnPtr),
uint64(row), flags, uint64(blobPtr))
@@ -51,7 +51,7 @@ func (c *Conn) OpenBlob(db, table, column string, row int64, write bool) (*Blob,
blob := Blob{c: c}
blob.handle = util.ReadUint32(c.mod, blobPtr)
blob.bytes = int64(c.call(c.api.blobBytes, uint64(blob.handle)))
blob.bytes = int64(c.call("sqlite3_blob_bytes", uint64(blob.handle)))
return &blob, nil
}
@@ -65,7 +65,7 @@ func (b *Blob) Close() error {
return nil
}
r := b.c.call(b.c.api.blobClose, uint64(b.handle))
r := b.c.call("sqlite3_blob_close", uint64(b.handle))
b.handle = 0
return b.c.error(r)
@@ -95,7 +95,7 @@ func (b *Blob) Read(p []byte) (n int, err error) {
defer b.c.arena.mark()()
ptr := b.c.arena.new(uint64(want))
r := b.c.call(b.c.api.blobRead, uint64(b.handle),
r := b.c.call("sqlite3_blob_read", uint64(b.handle),
uint64(ptr), uint64(want), uint64(b.offset))
err = b.c.error(r)
if err != nil {
@@ -128,7 +128,7 @@ func (b *Blob) WriteTo(w io.Writer) (n int64, err error) {
ptr := b.c.arena.new(uint64(want))
for want > 0 {
r := b.c.call(b.c.api.blobRead, uint64(b.handle),
r := b.c.call("sqlite3_blob_read", uint64(b.handle),
uint64(ptr), uint64(want), uint64(b.offset))
err = b.c.error(r)
if err != nil {
@@ -161,7 +161,7 @@ func (b *Blob) Write(p []byte) (n int, err error) {
defer b.c.arena.mark()()
ptr := b.c.arena.bytes(p)
r := b.c.call(b.c.api.blobWrite, uint64(b.handle),
r := b.c.call("sqlite3_blob_write", uint64(b.handle),
uint64(ptr), uint64(len(p)), uint64(b.offset))
err = b.c.error(r)
if err != nil {
@@ -194,7 +194,7 @@ func (b *Blob) ReadFrom(r io.Reader) (n int64, err error) {
mem := util.View(b.c.mod, ptr, uint64(want))
m, err := r.Read(mem[:want])
if m > 0 {
r := b.c.call(b.c.api.blobWrite, uint64(b.handle),
r := b.c.call("sqlite3_blob_write", uint64(b.handle),
uint64(ptr), uint64(m), uint64(b.offset))
err := b.c.error(r)
if err != nil {
@@ -243,8 +243,8 @@ func (b *Blob) Seek(offset int64, whence int) (int64, error) {
//
// https://sqlite.org/c3ref/blob_reopen.html
func (b *Blob) Reopen(row int64) error {
err := b.c.error(b.c.call(b.c.api.blobReopen, uint64(b.handle), uint64(row)))
b.bytes = int64(b.c.call(b.c.api.blobBytes, uint64(b.handle)))
err := b.c.error(b.c.call("sqlite3_blob_reopen", uint64(b.handle), uint64(row)))
b.bytes = int64(b.c.call("sqlite3_blob_bytes", uint64(b.handle)))
b.offset = 0
return err
}

24
conn.go
View File

@@ -77,7 +77,7 @@ func (c *Conn) openDB(filename string, flags OpenFlag) (uint32, error) {
namePtr := c.arena.string(filename)
flags |= OPEN_EXRESCODE
r := c.call(c.api.open, uint64(namePtr), uint64(connPtr), uint64(flags), 0)
r := c.call("sqlite3_open_v2", uint64(namePtr), uint64(connPtr), uint64(flags), 0)
handle := util.ReadUint32(c.mod, connPtr)
if err := c.sqlite.error(r, handle); err != nil {
@@ -97,7 +97,7 @@ func (c *Conn) openDB(filename string, flags OpenFlag) (uint32, error) {
}
pragmaPtr := c.arena.string(pragmas.String())
r := c.call(c.api.exec, uint64(handle), uint64(pragmaPtr), 0, 0, 0)
r := c.call("sqlite3_exec", uint64(handle), uint64(pragmaPtr), 0, 0, 0)
if err := c.sqlite.error(r, handle, pragmas.String()); err != nil {
if errors.Is(err, ERROR) {
err = fmt.Errorf("sqlite3: invalid _pragma: %w", err)
@@ -111,7 +111,7 @@ func (c *Conn) openDB(filename string, flags OpenFlag) (uint32, error) {
}
func (c *Conn) closeDB(handle uint32) {
r := c.call(c.api.closeZombie, uint64(handle))
r := c.call("sqlite3_close_v2", uint64(handle))
if err := c.sqlite.error(r, handle); err != nil {
panic(err)
}
@@ -134,7 +134,7 @@ func (c *Conn) Close() error {
c.pending.Close()
c.pending = nil
r := c.call(c.api.close, uint64(c.handle))
r := c.call("sqlite3_close", uint64(c.handle))
if err := c.error(r); err != nil {
return err
}
@@ -153,7 +153,7 @@ func (c *Conn) Exec(sql string) error {
defer c.arena.mark()()
sqlPtr := c.arena.string(sql)
r := c.call(c.api.exec, uint64(c.handle), uint64(sqlPtr), 0, 0, 0)
r := c.call("sqlite3_exec", uint64(c.handle), uint64(sqlPtr), 0, 0, 0)
return c.error(r, sql)
}
@@ -178,7 +178,7 @@ func (c *Conn) PrepareFlags(sql string, flags PrepareFlag) (stmt *Stmt, tail str
tailPtr := c.arena.new(ptrlen)
sqlPtr := c.arena.string(sql)
r := c.call(c.api.prepare, uint64(c.handle),
r := c.call("sqlite3_prepare_v3", uint64(c.handle),
uint64(sqlPtr), uint64(len(sql)+1), uint64(flags),
uint64(stmtPtr), uint64(tailPtr))
@@ -201,7 +201,7 @@ func (c *Conn) PrepareFlags(sql string, flags PrepareFlag) (stmt *Stmt, tail str
//
// https://sqlite.org/c3ref/get_autocommit.html
func (c *Conn) GetAutocommit() bool {
r := c.call(c.api.autocommit, uint64(c.handle))
r := c.call("sqlite3_get_autocommit", uint64(c.handle))
return r != 0
}
@@ -210,7 +210,7 @@ func (c *Conn) GetAutocommit() bool {
//
// https://sqlite.org/c3ref/last_insert_rowid.html
func (c *Conn) LastInsertRowID() int64 {
r := c.call(c.api.lastRowid, uint64(c.handle))
r := c.call("sqlite3_last_insert_rowid", uint64(c.handle))
return int64(r)
}
@@ -220,7 +220,7 @@ func (c *Conn) LastInsertRowID() int64 {
//
// https://sqlite.org/c3ref/changes.html
func (c *Conn) Changes() int64 {
r := c.call(c.api.changes, uint64(c.handle))
r := c.call("sqlite3_changes64", uint64(c.handle))
return int64(r)
}
@@ -256,12 +256,12 @@ func (c *Conn) SetInterrupt(ctx context.Context) (old context.Context) {
c.interrupt = ctx
// Remove the handler if the context can't be canceled.
if ctx == nil || ctx.Done() == nil {
c.call(c.api.progressHandler, uint64(c.handle), 0)
c.call("sqlite3_progress_handler_go", uint64(c.handle), 0)
return old
}
c.pending.Step()
c.call(c.api.progressHandler, uint64(c.handle), 100)
c.call("sqlite3_progress_handler_go", uint64(c.handle), 100)
return old
}
@@ -276,7 +276,7 @@ func progressCallback(ctx context.Context, mod api.Module, _ uint32) uint32 {
func (c *Conn) checkInterrupt() {
if c.interrupt != nil && c.interrupt.Err() != nil {
c.call(c.api.interrupt, uint64(c.handle))
c.call("sqlite3_interrupt", uint64(c.handle))
}
}

View File

@@ -32,14 +32,14 @@ func (ctx Context) Conn() *Conn {
// https://sqlite.org/c3ref/get_auxdata.html
func (ctx Context) SetAuxData(n int, data any) {
ptr := util.AddHandle(ctx.c.ctx, data)
ctx.c.call(ctx.c.api.setAuxData, uint64(ctx.handle), uint64(n), uint64(ptr))
ctx.c.call("sqlite3_set_auxdata_go", uint64(ctx.handle), uint64(n), uint64(ptr))
}
// GetAuxData returns metadata for argument n of the function.
//
// https://sqlite.org/c3ref/get_auxdata.html
func (ctx Context) GetAuxData(n int) any {
ptr := uint32(ctx.c.call(ctx.c.api.getAuxData, uint64(ctx.handle), uint64(n)))
ptr := uint32(ctx.c.call("sqlite3_get_auxdata", uint64(ctx.handle), uint64(n)))
return util.GetHandle(ctx.c.ctx, ptr)
}
@@ -67,7 +67,7 @@ func (ctx Context) ResultInt(value int) {
//
// https://sqlite.org/c3ref/result_blob.html
func (ctx Context) ResultInt64(value int64) {
ctx.c.call(ctx.c.api.resultInteger,
ctx.c.call("sqlite3_result_int64",
uint64(ctx.handle), uint64(value))
}
@@ -75,7 +75,7 @@ func (ctx Context) ResultInt64(value int64) {
//
// https://sqlite.org/c3ref/result_blob.html
func (ctx Context) ResultFloat(value float64) {
ctx.c.call(ctx.c.api.resultFloat,
ctx.c.call("sqlite3_result_double",
uint64(ctx.handle), math.Float64bits(value))
}
@@ -84,9 +84,9 @@ func (ctx Context) ResultFloat(value float64) {
// https://sqlite.org/c3ref/result_blob.html
func (ctx Context) ResultText(value string) {
ptr := ctx.c.newString(value)
ctx.c.call(ctx.c.api.resultText,
ctx.c.call("sqlite3_result_text64",
uint64(ctx.handle), uint64(ptr), uint64(len(value)),
uint64(ctx.c.api.destructor), _UTF8)
uint64(ctx.c.freer), _UTF8)
}
// ResultRawText sets the text result of the function to a []byte.
@@ -94,9 +94,9 @@ func (ctx Context) ResultText(value string) {
// https://sqlite.org/c3ref/result_blob.html
func (ctx Context) ResultRawText(value []byte) {
ptr := ctx.c.newBytes(value)
ctx.c.call(ctx.c.api.resultText,
ctx.c.call("sqlite3_result_text64",
uint64(ctx.handle), uint64(ptr), uint64(len(value)),
uint64(ctx.c.api.destructor), _UTF8)
uint64(ctx.c.freer), _UTF8)
}
// ResultBlob sets the result of the function to a []byte.
@@ -105,16 +105,16 @@ func (ctx Context) ResultRawText(value []byte) {
// https://sqlite.org/c3ref/result_blob.html
func (ctx Context) ResultBlob(value []byte) {
ptr := ctx.c.newBytes(value)
ctx.c.call(ctx.c.api.resultBlob,
ctx.c.call("sqlite3_result_blob64",
uint64(ctx.handle), uint64(ptr), uint64(len(value)),
uint64(ctx.c.api.destructor))
uint64(ctx.c.freer))
}
// ResultZeroBlob sets the result of the function to a zero-filled, length n BLOB.
//
// https://sqlite.org/c3ref/result_blob.html
func (ctx Context) ResultZeroBlob(n int64) {
ctx.c.call(ctx.c.api.resultZeroBlob,
ctx.c.call("sqlite3_result_zeroblob64",
uint64(ctx.handle), uint64(n))
}
@@ -122,7 +122,7 @@ func (ctx Context) ResultZeroBlob(n int64) {
//
// https://sqlite.org/c3ref/result_blob.html
func (ctx Context) ResultNull() {
ctx.c.call(ctx.c.api.resultNull,
ctx.c.call("sqlite3_result_null",
uint64(ctx.handle))
}
@@ -153,9 +153,9 @@ func (ctx Context) resultRFC3339Nano(value time.Time) {
buf := util.View(ctx.c.mod, ptr, maxlen)
buf = value.AppendFormat(buf[:0], time.RFC3339Nano)
ctx.c.call(ctx.c.api.resultText,
ctx.c.call("sqlite3_result_text64",
uint64(ctx.handle), uint64(ptr), uint64(len(buf)),
uint64(ctx.c.api.destructor), _UTF8)
uint64(ctx.c.freer), _UTF8)
}
// ResultPointer sets the result of the function to NULL, just like [Context.ResultNull],
@@ -165,7 +165,7 @@ func (ctx Context) resultRFC3339Nano(value time.Time) {
// https://sqlite.org/c3ref/result_blob.html
func (ctx Context) ResultPointer(ptr any) {
valPtr := util.AddHandle(ctx.c.ctx, ptr)
ctx.c.call(ctx.c.api.resultPointer, uint64(valPtr))
ctx.c.call("sqlite3_result_pointer_go", uint64(valPtr))
}
// ResultJSON sets the result of the function to the JSON encoding of value.
@@ -188,7 +188,7 @@ func (ctx Context) ResultValue(value Value) {
ctx.ResultError(MISUSE)
return
}
ctx.c.call(ctx.c.api.resultValue,
ctx.c.call("sqlite3_result_value",
uint64(ctx.handle), uint64(value.handle))
}
@@ -197,12 +197,12 @@ func (ctx Context) ResultValue(value Value) {
// https://sqlite.org/c3ref/result_blob.html
func (ctx Context) ResultError(err error) {
if errors.Is(err, NOMEM) {
ctx.c.call(ctx.c.api.resultErrorMem, uint64(ctx.handle))
ctx.c.call("sqlite3_result_error_nomem", uint64(ctx.handle))
return
}
if errors.Is(err, TOOBIG) {
ctx.c.call(ctx.c.api.resultErrorBig, uint64(ctx.handle))
ctx.c.call("sqlite3_result_error_toobig", uint64(ctx.handle))
return
}
@@ -210,11 +210,11 @@ func (ctx Context) ResultError(err error) {
if msg != "" {
defer ctx.c.arena.mark()()
ptr := ctx.c.arena.string(msg)
ctx.c.call(ctx.c.api.resultError,
ctx.c.call("sqlite3_result_error",
uint64(ctx.handle), uint64(ptr), uint64(len(msg)))
}
if code != _OK {
ctx.c.call(ctx.c.api.resultErrorCode,
ctx.c.call("sqlite3_result_error_code",
uint64(ctx.handle), uint64(code))
}
}

View File

@@ -135,7 +135,7 @@ func Test_ErrorCode_Error(t *testing.T) {
// Test all error codes.
for i := 0; i == int(ErrorCode(i)); i++ {
want := "sqlite3: "
r := db.call(db.api.errstr, uint64(i))
r := db.call("sqlite3_errstr", uint64(i))
want += util.ReadString(db.mod, uint32(r), _MAX_NAME)
got := ErrorCode(i).Error()
@@ -157,7 +157,7 @@ func Test_ExtendedErrorCode_Error(t *testing.T) {
// Test all extended error codes.
for i := 0; i == int(ExtendedErrorCode(i)); i++ {
want := "sqlite3: "
r := db.call(db.api.errstr, uint64(i))
r := db.call("sqlite3_errstr", uint64(i))
want += util.ReadString(db.mod, uint32(r), _MAX_NAME)
got := ExtendedErrorCode(i).Error()

14
func.go
View File

@@ -14,7 +14,7 @@ import (
// This can be used to load schemas that contain
// one or more unknown collating sequences.
func (c *Conn) AnyCollationNeeded() {
c.call(c.api.anyCollation, uint64(c.handle), 0, 0)
c.call("sqlite3_anycollseq_init", uint64(c.handle), 0, 0)
}
// CreateCollation defines a new collating sequence.
@@ -24,7 +24,7 @@ func (c *Conn) CreateCollation(name string, fn func(a, b []byte) int) error {
defer c.arena.mark()()
namePtr := c.arena.string(name)
funcPtr := util.AddHandle(c.ctx, fn)
r := c.call(c.api.createCollation,
r := c.call("sqlite3_create_collation_go",
uint64(c.handle), uint64(namePtr), uint64(funcPtr))
return c.error(r)
}
@@ -36,7 +36,7 @@ func (c *Conn) CreateFunction(name string, nArg int, flag FunctionFlag, fn func(
defer c.arena.mark()()
namePtr := c.arena.string(name)
funcPtr := util.AddHandle(c.ctx, fn)
r := c.call(c.api.createFunction,
r := c.call("sqlite3_create_function_go",
uint64(c.handle), uint64(namePtr), uint64(nArg),
uint64(flag), uint64(funcPtr))
return c.error(r)
@@ -49,11 +49,11 @@ func (c *Conn) CreateFunction(name string, nArg int, flag FunctionFlag, fn func(
// https://sqlite.org/c3ref/create_function.html
func (c *Conn) CreateWindowFunction(name string, nArg int, flag FunctionFlag, fn func() AggregateFunction) error {
defer c.arena.mark()()
call := c.api.createAggregate
call := "sqlite3_create_aggregate_function_go"
namePtr := c.arena.string(name)
funcPtr := util.AddHandle(c.ctx, fn)
if _, ok := fn().(WindowFunction); ok {
call = c.api.createWindow
call = "sqlite3_create_window_function_go"
}
r := c.call(call,
uint64(c.handle), uint64(namePtr), uint64(nArg),
@@ -128,7 +128,7 @@ func inverseCallback(ctx context.Context, mod api.Module, pCtx, nArg, pArg uint3
}
func userDataHandle(db *Conn, pCtx uint32) any {
pApp := uint32(db.call(db.api.userData, uint64(pCtx)))
pApp := uint32(db.call("sqlite3_user_data", uint64(pCtx)))
return util.GetHandle(db.ctx, pApp)
}
@@ -139,7 +139,7 @@ func aggregateCtxHandle(db *Conn, pCtx uint32, close *uint32) AggregateFunction
if close == nil {
size = ptrlen
}
ptr := uint32(db.call(db.api.aggregateCtx, uint64(pCtx), size))
ptr := uint32(db.call("sqlite3_aggregate_context", uint64(pCtx), size))
// If we already have an aggregate, return it.
if ptr != 0 {

View File

@@ -15,9 +15,8 @@ const (
OOMErr = ErrorString("sqlite3: out of memory")
RangeErr = ErrorString("sqlite3: index out of range")
NoNulErr = ErrorString("sqlite3: missing NUL terminator")
NoGlobalErr = ErrorString("sqlite3: could not find global: ")
NoFuncErr = ErrorString("sqlite3: could not find function: ")
BinaryErr = ErrorString("sqlite3: no SQLite binary embed/set/loaded")
NoBinaryErr = ErrorString("sqlite3: no SQLite binary embed/set/loaded")
BadBinaryErr = ErrorString("sqlite3: invalid SQLite binary embed/set/loaded")
TimeErr = ErrorString("sqlite3: invalid time value")
WhenceErr = ErrorString("sqlite3: invalid whence")
OffsetErr = ErrorString("sqlite3: invalid offset")

208
sqlite.go
View File

@@ -57,7 +57,7 @@ func compileSQLite() {
}
}
if bin == nil {
instance.err = util.BinaryErr
instance.err = util.NoBinaryErr
return
}
@@ -67,7 +67,7 @@ func compileSQLite() {
type sqlite struct {
ctx context.Context
mod api.Module
api sqliteAPI
freer uint32
stack [8]uint64
}
@@ -86,110 +86,12 @@ func instantiateSQLite() (sqlt *sqlite, err error) {
return nil, err
}
getFun := func(name string) api.Function {
f := sqlt.mod.ExportedFunction(name)
if f == nil {
err = util.NoFuncErr + util.ErrorString(name)
return nil
}
return f
global := sqlt.mod.ExportedGlobal("malloc_destructor")
if global == nil {
return nil, util.BadBinaryErr
}
getVal := func(name string) uint32 {
g := sqlt.mod.ExportedGlobal(name)
if g == nil {
err = util.NoGlobalErr + util.ErrorString(name)
return 0
}
return util.ReadUint32(sqlt.mod, uint32(g.Get()))
}
sqlt.api = sqliteAPI{
free: getFun("free"),
malloc: getFun("malloc"),
destructor: getVal("malloc_destructor"),
errcode: getFun("sqlite3_errcode"),
errstr: getFun("sqlite3_errstr"),
errmsg: getFun("sqlite3_errmsg"),
erroff: getFun("sqlite3_error_offset"),
open: getFun("sqlite3_open_v2"),
close: getFun("sqlite3_close"),
closeZombie: getFun("sqlite3_close_v2"),
prepare: getFun("sqlite3_prepare_v3"),
finalize: getFun("sqlite3_finalize"),
reset: getFun("sqlite3_reset"),
step: getFun("sqlite3_step"),
exec: getFun("sqlite3_exec"),
interrupt: getFun("sqlite3_interrupt"),
progressHandler: getFun("sqlite3_progress_handler_go"),
clearBindings: getFun("sqlite3_clear_bindings"),
bindCount: getFun("sqlite3_bind_parameter_count"),
bindIndex: getFun("sqlite3_bind_parameter_index"),
bindName: getFun("sqlite3_bind_parameter_name"),
bindNull: getFun("sqlite3_bind_null"),
bindInteger: getFun("sqlite3_bind_int64"),
bindFloat: getFun("sqlite3_bind_double"),
bindText: getFun("sqlite3_bind_text64"),
bindBlob: getFun("sqlite3_bind_blob64"),
bindZeroBlob: getFun("sqlite3_bind_zeroblob64"),
bindPointer: getFun("sqlite3_bind_pointer_go"),
bindValue: getFun("sqlite3_bind_value"),
columnCount: getFun("sqlite3_column_count"),
columnName: getFun("sqlite3_column_name"),
columnType: getFun("sqlite3_column_type"),
columnInteger: getFun("sqlite3_column_int64"),
columnFloat: getFun("sqlite3_column_double"),
columnText: getFun("sqlite3_column_text"),
columnBlob: getFun("sqlite3_column_blob"),
columnBytes: getFun("sqlite3_column_bytes"),
columnValue: getFun("sqlite3_column_value"),
blobOpen: getFun("sqlite3_blob_open"),
blobClose: getFun("sqlite3_blob_close"),
blobReopen: getFun("sqlite3_blob_reopen"),
blobBytes: getFun("sqlite3_blob_bytes"),
blobRead: getFun("sqlite3_blob_read"),
blobWrite: getFun("sqlite3_blob_write"),
backupInit: getFun("sqlite3_backup_init"),
backupStep: getFun("sqlite3_backup_step"),
backupFinish: getFun("sqlite3_backup_finish"),
backupRemaining: getFun("sqlite3_backup_remaining"),
backupPageCount: getFun("sqlite3_backup_pagecount"),
changes: getFun("sqlite3_changes64"),
lastRowid: getFun("sqlite3_last_insert_rowid"),
autocommit: getFun("sqlite3_get_autocommit"),
anyCollation: getFun("sqlite3_anycollseq_init"),
createCollation: getFun("sqlite3_create_collation_go"),
createFunction: getFun("sqlite3_create_function_go"),
createAggregate: getFun("sqlite3_create_aggregate_function_go"),
createWindow: getFun("sqlite3_create_window_function_go"),
aggregateCtx: getFun("sqlite3_aggregate_context"),
userData: getFun("sqlite3_user_data"),
setAuxData: getFun("sqlite3_set_auxdata_go"),
getAuxData: getFun("sqlite3_get_auxdata"),
valueType: getFun("sqlite3_value_type"),
valueInteger: getFun("sqlite3_value_int64"),
valueFloat: getFun("sqlite3_value_double"),
valueText: getFun("sqlite3_value_text"),
valueBlob: getFun("sqlite3_value_blob"),
valueBytes: getFun("sqlite3_value_bytes"),
valuePointer: getFun("sqlite3_value_pointer_go"),
resultNull: getFun("sqlite3_result_null"),
resultInteger: getFun("sqlite3_result_int64"),
resultFloat: getFun("sqlite3_result_double"),
resultText: getFun("sqlite3_result_text64"),
resultBlob: getFun("sqlite3_result_blob64"),
resultZeroBlob: getFun("sqlite3_result_zeroblob64"),
resultPointer: getFun("sqlite3_result_pointer_go"),
resultValue: getFun("sqlite3_result_value"),
resultError: getFun("sqlite3_result_error"),
resultErrorCode: getFun("sqlite3_result_error_code"),
resultErrorMem: getFun("sqlite3_result_error_nomem"),
resultErrorBig: getFun("sqlite3_result_error_toobig"),
createModule: getFun("sqlite3_create_module_go"),
declareVTab: getFun("sqlite3_declare_vtab"),
vtabConfig: getFun("sqlite3_vtab_config_go"),
vtabRHSValue: getFun("sqlite3_vtab_rhs_value"),
}
sqlt.freer = util.ReadUint32(sqlt.mod, uint32(global.Get()))
if err != nil {
return nil, err
}
@@ -211,17 +113,17 @@ func (sqlt *sqlite) error(rc uint64, handle uint32, sql ...string) error {
panic(util.OOMErr)
}
if r := sqlt.call(sqlt.api.errstr, rc); r != 0 {
if r := sqlt.call("sqlite3_errstr", rc); r != 0 {
err.str = util.ReadString(sqlt.mod, uint32(r), _MAX_NAME)
}
if handle != 0 {
if r := sqlt.call(sqlt.api.errmsg, uint64(handle)); r != 0 {
if r := sqlt.call("sqlite3_errmsg", uint64(handle)); r != 0 {
err.msg = util.ReadString(sqlt.mod, uint32(r), _MAX_NAME)
}
if sql != nil {
if r := sqlt.call(sqlt.api.erroff, uint64(handle)); r != math.MaxUint32 {
if r := sqlt.call("sqlite3_error_offset", uint64(handle)); r != math.MaxUint32 {
err.sql = sql[0][r:]
}
}
@@ -234,8 +136,9 @@ func (sqlt *sqlite) error(rc uint64, handle uint32, sql ...string) error {
return &err
}
func (sqlt *sqlite) call(fn api.Function, params ...uint64) uint64 {
func (sqlt *sqlite) call(name string, params ...uint64) uint64 {
copy(sqlt.stack[:], params)
fn := sqlt.mod.ExportedFunction(name)
err := fn.CallWithStack(sqlt.ctx, sqlt.stack[:])
if err != nil {
panic(err)
@@ -247,14 +150,14 @@ func (sqlt *sqlite) free(ptr uint32) {
if ptr == 0 {
return
}
sqlt.call(sqlt.api.free, uint64(ptr))
sqlt.call("free", uint64(ptr))
}
func (sqlt *sqlite) new(size uint64) uint32 {
if size > _MAX_ALLOCATION_SIZE {
panic(util.OOMErr)
}
ptr := uint32(sqlt.call(sqlt.api.malloc, size))
ptr := uint32(sqlt.call("malloc", size))
if ptr == 0 && size != 0 {
panic(util.OOMErr)
}
@@ -342,90 +245,7 @@ func (a *arena) string(s string) uint32 {
}
type sqliteAPI struct {
free api.Function
malloc api.Function
errcode api.Function
errstr api.Function
errmsg api.Function
erroff api.Function
open api.Function
close api.Function
closeZombie api.Function
prepare api.Function
finalize api.Function
reset api.Function
step api.Function
exec api.Function
interrupt api.Function
progressHandler api.Function
clearBindings api.Function
bindCount api.Function
bindIndex api.Function
bindName api.Function
bindNull api.Function
bindInteger api.Function
bindFloat api.Function
bindText api.Function
bindBlob api.Function
bindZeroBlob api.Function
bindPointer api.Function
bindValue api.Function
columnCount api.Function
columnName api.Function
columnType api.Function
columnInteger api.Function
columnFloat api.Function
columnText api.Function
columnBlob api.Function
columnBytes api.Function
columnValue api.Function
blobOpen api.Function
blobClose api.Function
blobReopen api.Function
blobBytes api.Function
blobRead api.Function
blobWrite api.Function
backupInit api.Function
backupStep api.Function
backupFinish api.Function
backupRemaining api.Function
backupPageCount api.Function
changes api.Function
lastRowid api.Function
autocommit api.Function
anyCollation api.Function
createCollation api.Function
createFunction api.Function
createAggregate api.Function
createWindow api.Function
aggregateCtx api.Function
userData api.Function
setAuxData api.Function
getAuxData api.Function
valueType api.Function
valueInteger api.Function
valueFloat api.Function
valueText api.Function
valueBlob api.Function
valueBytes api.Function
valuePointer api.Function
resultNull api.Function
resultInteger api.Function
resultFloat api.Function
resultText api.Function
resultBlob api.Function
resultZeroBlob api.Function
resultPointer api.Function
resultValue api.Function
resultError api.Function
resultErrorCode api.Function
resultErrorMem api.Function
resultErrorBig api.Function
createModule api.Function
declareVTab api.Function
vtabConfig api.Function
vtabRHSValue api.Function
destructor uint32
destructor uint32
}
func exportCallbacks(env wazero.HostModuleBuilder) wazero.HostModuleBuilder {

View File

@@ -37,7 +37,7 @@ func Test_sqlite_call_closed(t *testing.T) {
sqlite.close()
defer func() { _ = recover() }()
sqlite.call(sqlite.api.free)
sqlite.call("free")
t.Error("want panic")
}

63
stmt.go
View File

@@ -28,7 +28,7 @@ func (s *Stmt) Close() error {
return nil
}
r := s.c.call(s.c.api.finalize, uint64(s.handle))
r := s.c.call("sqlite3_finalize", uint64(s.handle))
s.handle = 0
return s.c.error(r)
@@ -38,7 +38,7 @@ func (s *Stmt) Close() error {
//
// https://sqlite.org/c3ref/reset.html
func (s *Stmt) Reset() error {
r := s.c.call(s.c.api.reset, uint64(s.handle))
r := s.c.call("sqlite3_reset", uint64(s.handle))
s.err = nil
return s.c.error(r)
}
@@ -47,7 +47,7 @@ func (s *Stmt) Reset() error {
//
// https://sqlite.org/c3ref/clear_bindings.html
func (s *Stmt) ClearBindings() error {
r := s.c.call(s.c.api.clearBindings, uint64(s.handle))
r := s.c.call("sqlite3_clear_bindings", uint64(s.handle))
return s.c.error(r)
}
@@ -62,8 +62,7 @@ func (s *Stmt) ClearBindings() error {
// https://sqlite.org/c3ref/step.html
func (s *Stmt) Step() bool {
s.c.checkInterrupt()
step := s.c.mod.ExportedFunction("sqlite3_step")
r := s.c.call(step, uint64(s.handle))
r := s.c.call("sqlite3_step", uint64(s.handle))
switch r {
case _ROW:
return true
@@ -95,7 +94,7 @@ func (s *Stmt) Exec() error {
//
// https://sqlite.org/c3ref/bind_parameter_count.html
func (s *Stmt) BindCount() int {
r := s.c.call(s.c.api.bindCount,
r := s.c.call("sqlite3_bind_parameter_count",
uint64(s.handle))
return int(r)
}
@@ -107,7 +106,7 @@ func (s *Stmt) BindCount() int {
func (s *Stmt) BindIndex(name string) int {
defer s.c.arena.mark()()
namePtr := s.c.arena.string(name)
r := s.c.call(s.c.api.bindIndex,
r := s.c.call("sqlite3_bind_parameter_index",
uint64(s.handle), uint64(namePtr))
return int(r)
}
@@ -117,7 +116,7 @@ func (s *Stmt) BindIndex(name string) int {
//
// https://sqlite.org/c3ref/bind_parameter_name.html
func (s *Stmt) BindName(param int) string {
r := s.c.call(s.c.api.bindName,
r := s.c.call("sqlite3_bind_parameter_name",
uint64(s.handle), uint64(param))
ptr := uint32(r)
@@ -154,7 +153,7 @@ func (s *Stmt) BindInt(param int, value int) error {
//
// https://sqlite.org/c3ref/bind_blob.html
func (s *Stmt) BindInt64(param int, value int64) error {
r := s.c.call(s.c.api.bindInteger,
r := s.c.call("sqlite3_bind_int64",
uint64(s.handle), uint64(param), uint64(value))
return s.c.error(r)
}
@@ -164,7 +163,7 @@ func (s *Stmt) BindInt64(param int, value int64) error {
//
// https://sqlite.org/c3ref/bind_blob.html
func (s *Stmt) BindFloat(param int, value float64) error {
r := s.c.call(s.c.api.bindFloat,
r := s.c.call("sqlite3_bind_double",
uint64(s.handle), uint64(param), math.Float64bits(value))
return s.c.error(r)
}
@@ -178,10 +177,10 @@ func (s *Stmt) BindText(param int, value string) error {
return TOOBIG
}
ptr := s.c.newString(value)
r := s.c.call(s.c.api.bindText,
r := s.c.call("sqlite3_bind_text64",
uint64(s.handle), uint64(param),
uint64(ptr), uint64(len(value)),
uint64(s.c.api.destructor), _UTF8)
uint64(s.c.freer), _UTF8)
return s.c.error(r)
}
@@ -194,10 +193,10 @@ func (s *Stmt) BindRawText(param int, value []byte) error {
return TOOBIG
}
ptr := s.c.newBytes(value)
r := s.c.call(s.c.api.bindText,
r := s.c.call("sqlite3_bind_text64",
uint64(s.handle), uint64(param),
uint64(ptr), uint64(len(value)),
uint64(s.c.api.destructor), _UTF8)
uint64(s.c.freer), _UTF8)
return s.c.error(r)
}
@@ -211,10 +210,10 @@ func (s *Stmt) BindBlob(param int, value []byte) error {
return TOOBIG
}
ptr := s.c.newBytes(value)
r := s.c.call(s.c.api.bindBlob,
r := s.c.call("sqlite3_bind_blob64",
uint64(s.handle), uint64(param),
uint64(ptr), uint64(len(value)),
uint64(s.c.api.destructor))
uint64(s.c.freer))
return s.c.error(r)
}
@@ -223,7 +222,7 @@ func (s *Stmt) BindBlob(param int, value []byte) error {
//
// https://sqlite.org/c3ref/bind_blob.html
func (s *Stmt) BindZeroBlob(param int, n int64) error {
r := s.c.call(s.c.api.bindZeroBlob,
r := s.c.call("sqlite3_bind_zeroblob64",
uint64(s.handle), uint64(param), uint64(n))
return s.c.error(r)
}
@@ -233,7 +232,7 @@ func (s *Stmt) BindZeroBlob(param int, n int64) error {
//
// https://sqlite.org/c3ref/bind_blob.html
func (s *Stmt) BindNull(param int) error {
r := s.c.call(s.c.api.bindNull,
r := s.c.call("sqlite3_bind_null",
uint64(s.handle), uint64(param))
return s.c.error(r)
}
@@ -266,10 +265,10 @@ func (s *Stmt) bindRFC3339Nano(param int, value time.Time) error {
buf := util.View(s.c.mod, ptr, maxlen)
buf = value.AppendFormat(buf[:0], time.RFC3339Nano)
r := s.c.call(s.c.api.bindText,
r := s.c.call("sqlite3_bind_text64",
uint64(s.handle), uint64(param),
uint64(ptr), uint64(len(buf)),
uint64(s.c.api.destructor), _UTF8)
uint64(s.c.freer), _UTF8)
return s.c.error(r)
}
@@ -281,7 +280,7 @@ func (s *Stmt) bindRFC3339Nano(param int, value time.Time) error {
// https://sqlite.org/c3ref/bind_blob.html
func (s *Stmt) BindPointer(param int, ptr any) error {
valPtr := util.AddHandle(s.c.ctx, ptr)
r := s.c.call(s.c.api.bindPointer,
r := s.c.call("sqlite3_bind_pointer_go",
uint64(s.handle), uint64(param), uint64(valPtr))
return s.c.error(r)
}
@@ -306,7 +305,7 @@ func (s *Stmt) BindValue(param int, value Value) error {
if value.sqlite != s.c.sqlite {
return MISUSE
}
r := s.c.call(s.c.api.bindValue,
r := s.c.call("sqlite3_bind_value",
uint64(s.handle), uint64(param), uint64(value.handle))
return s.c.error(r)
}
@@ -315,7 +314,7 @@ func (s *Stmt) BindValue(param int, value Value) error {
//
// https://sqlite.org/c3ref/column_count.html
func (s *Stmt) ColumnCount() int {
r := s.c.call(s.c.api.columnCount,
r := s.c.call("sqlite3_column_count",
uint64(s.handle))
return int(r)
}
@@ -325,7 +324,7 @@ func (s *Stmt) ColumnCount() int {
//
// https://sqlite.org/c3ref/column_name.html
func (s *Stmt) ColumnName(col int) string {
r := s.c.call(s.c.api.columnName,
r := s.c.call("sqlite3_column_name",
uint64(s.handle), uint64(col))
ptr := uint32(r)
@@ -340,7 +339,7 @@ func (s *Stmt) ColumnName(col int) string {
//
// https://sqlite.org/c3ref/column_blob.html
func (s *Stmt) ColumnType(col int) Datatype {
r := s.c.call(s.c.api.columnType,
r := s.c.call("sqlite3_column_type",
uint64(s.handle), uint64(col))
return Datatype(r)
}
@@ -372,7 +371,7 @@ func (s *Stmt) ColumnInt(col int) int {
//
// https://sqlite.org/c3ref/column_blob.html
func (s *Stmt) ColumnInt64(col int) int64 {
r := s.c.call(s.c.api.columnInteger,
r := s.c.call("sqlite3_column_int64",
uint64(s.handle), uint64(col))
return int64(r)
}
@@ -382,7 +381,7 @@ func (s *Stmt) ColumnInt64(col int) int64 {
//
// https://sqlite.org/c3ref/column_blob.html
func (s *Stmt) ColumnFloat(col int) float64 {
r := s.c.call(s.c.api.columnFloat,
r := s.c.call("sqlite3_column_double",
uint64(s.handle), uint64(col))
return math.Float64frombits(r)
}
@@ -436,7 +435,7 @@ func (s *Stmt) ColumnBlob(col int, buf []byte) []byte {
//
// https://sqlite.org/c3ref/column_blob.html
func (s *Stmt) ColumnRawText(col int) []byte {
r := s.c.call(s.c.api.columnText,
r := s.c.call("sqlite3_column_text",
uint64(s.handle), uint64(col))
return s.columnRawBytes(col, uint32(r))
}
@@ -448,19 +447,19 @@ func (s *Stmt) ColumnRawText(col int) []byte {
//
// https://sqlite.org/c3ref/column_blob.html
func (s *Stmt) ColumnRawBlob(col int) []byte {
r := s.c.call(s.c.api.columnBlob,
r := s.c.call("sqlite3_column_blob",
uint64(s.handle), uint64(col))
return s.columnRawBytes(col, uint32(r))
}
func (s *Stmt) columnRawBytes(col int, ptr uint32) []byte {
if ptr == 0 {
r := s.c.call(s.c.api.errcode, uint64(s.c.handle))
r := s.c.call("sqlite3_errcode", uint64(s.c.handle))
s.err = s.c.error(r)
return nil
}
r := s.c.call(s.c.api.columnBytes,
r := s.c.call("sqlite3_column_bytes",
uint64(s.handle), uint64(col))
return util.View(s.c.mod, ptr, r)
}
@@ -494,7 +493,7 @@ func (s *Stmt) ColumnJSON(col int, ptr any) error {
//
// https://sqlite.org/c3ref/column_blob.html
func (s *Stmt) ColumnValue(col int) Value {
r := s.c.call(s.c.api.columnValue,
r := s.c.call("sqlite3_column_value",
uint64(s.handle), uint64(col))
return Value{
unprot: true,

View File

@@ -29,7 +29,7 @@ func (v Value) protected() uint64 {
//
// https://sqlite.org/c3ref/value_blob.html
func (v Value) Type() Datatype {
r := v.call(v.api.valueType, v.protected())
r := v.call("sqlite3_value_type", v.protected())
return Datatype(r)
}
@@ -57,7 +57,7 @@ func (v Value) Int() int {
//
// https://sqlite.org/c3ref/value_blob.html
func (v Value) Int64() int64 {
r := v.call(v.api.valueInteger, v.protected())
r := v.call("sqlite3_value_int64", v.protected())
return int64(r)
}
@@ -65,7 +65,7 @@ func (v Value) Int64() int64 {
//
// https://sqlite.org/c3ref/value_blob.html
func (v Value) Float() float64 {
r := v.call(v.api.valueFloat, v.protected())
r := v.call("sqlite3_value_double", v.protected())
return math.Float64frombits(r)
}
@@ -111,7 +111,7 @@ func (v Value) Blob(buf []byte) []byte {
//
// https://sqlite.org/c3ref/value_blob.html
func (v Value) RawText() []byte {
r := v.call(v.api.valueText, v.protected())
r := v.call("sqlite3_value_text", v.protected())
return v.rawBytes(uint32(r))
}
@@ -121,7 +121,7 @@ func (v Value) RawText() []byte {
//
// https://sqlite.org/c3ref/value_blob.html
func (v Value) RawBlob() []byte {
r := v.call(v.api.valueBlob, v.protected())
r := v.call("sqlite3_value_blob", v.protected())
return v.rawBytes(uint32(r))
}
@@ -130,14 +130,14 @@ func (v Value) rawBytes(ptr uint32) []byte {
return nil
}
r := v.call(v.api.valueBytes, v.protected())
r := v.call("sqlite3_value_bytes", v.protected())
return util.View(v.mod, ptr, r)
}
// Pointer gets the pointer associated with this value,
// or nil if it has no associated pointer.
func (v Value) Pointer() any {
r := v.call(v.api.valuePointer, v.protected())
r := v.call("sqlite3_value_pointer_go", v.protected())
return util.GetHandle(v.ctx, uint32(r))
}

View File

@@ -56,7 +56,7 @@ func CreateModule[T VTab](db *Conn, name string, create, connect VTabConstructor
defer db.arena.mark()()
namePtr := db.arena.string(name)
modulePtr := util.AddHandle(db.ctx, module[T]{create, connect})
r := db.call(db.api.createModule, uint64(db.handle),
r := db.call("sqlite3_create_module_go", uint64(db.handle),
uint64(namePtr), uint64(flags), uint64(modulePtr))
return db.error(r)
}
@@ -72,7 +72,7 @@ func implements[T any](typ reflect.Type) bool {
func (c *Conn) DeclareVtab(sql string) error {
defer c.arena.mark()()
sqlPtr := c.arena.string(sql)
r := c.call(c.api.declareVTab, uint64(c.handle), uint64(sqlPtr))
r := c.call("sqlite3_declare_vtab", uint64(c.handle), uint64(sqlPtr))
return c.error(r)
}
@@ -98,7 +98,7 @@ func (c *Conn) VtabConfig(op VtabConfigOption, args ...any) error {
i = 1
}
}
r := c.call(c.api.vtabConfig, uint64(c.handle), uint64(op), i)
r := c.call("sqlite3_vtab_config_go", uint64(c.handle), uint64(op), i)
return c.error(r)
}
@@ -257,7 +257,7 @@ type IndexConstraintUsage struct {
func (idx *IndexInfo) RHSValue(column int) (Value, error) {
defer idx.c.arena.mark()()
valPtr := idx.c.arena.new(ptrlen)
r := idx.c.call(idx.c.api.vtabRHSValue,
r := idx.c.call("sqlite3_vtab_rhs_value",
uint64(idx.handle), uint64(column), uint64(valPtr))
if err := idx.c.error(r); err != nil {
return Value{}, err