Skip to content

Commit

Permalink
Delete functions, modules, hooks.
Browse files Browse the repository at this point in the history
  • Loading branch information
ncruces committed Sep 30, 2024
1 parent 8b6c2b2 commit 25fc5a6
Show file tree
Hide file tree
Showing 12 changed files with 93 additions and 13 deletions.
5 changes: 4 additions & 1 deletion config.go
Original file line number Diff line number Diff line change
Expand Up @@ -284,7 +284,10 @@ func walCallback(ctx context.Context, mod api.Module, _, pDB, zSchema uint32, pa
//
// https://sqlite.org/c3ref/autovacuum_pages.html
func (c *Conn) AutoVacuumPages(cb func(schema string, dbPages, freePages, bytesPerPage uint) uint) error {
funcPtr := util.AddHandle(c.ctx, cb)
var funcPtr uint32
if cb != nil {
funcPtr = util.AddHandle(c.ctx, cb)
}
r := c.call("sqlite3_autovacuum_pages_go", uint64(c.handle), uint64(funcPtr))
return c.error(r)
}
Expand Down
Binary file modified embed/bcw2/bcw2.wasm
Binary file not shown.
Binary file modified embed/sqlite3.wasm
Binary file not shown.
22 changes: 16 additions & 6 deletions func.go
Original file line number Diff line number Diff line change
Expand Up @@ -44,9 +44,12 @@ func (c Conn) AnyCollationNeeded() error {
//
// https://sqlite.org/c3ref/create_collation.html
func (c *Conn) CreateCollation(name string, fn func(a, b []byte) int) error {
var funcPtr uint32
defer c.arena.mark()()
namePtr := c.arena.string(name)
funcPtr := util.AddHandle(c.ctx, fn)
if fn != nil {
funcPtr = util.AddHandle(c.ctx, fn)
}
r := c.call("sqlite3_create_collation_go",
uint64(c.handle), uint64(namePtr), uint64(funcPtr))
return c.error(r)
Expand All @@ -56,9 +59,12 @@ func (c *Conn) CreateCollation(name string, fn func(a, b []byte) int) error {
//
// https://sqlite.org/c3ref/create_function.html
func (c *Conn) CreateFunction(name string, nArg int, flag FunctionFlag, fn ScalarFunction) error {
var funcPtr uint32
defer c.arena.mark()()
namePtr := c.arena.string(name)
funcPtr := util.AddHandle(c.ctx, fn)
if fn != nil {
funcPtr = util.AddHandle(c.ctx, fn)
}
r := c.call("sqlite3_create_function_go",
uint64(c.handle), uint64(namePtr), uint64(nArg),
uint64(flag), uint64(funcPtr))
Expand All @@ -75,10 +81,13 @@ type ScalarFunction func(ctx Context, arg ...Value)
//
// https://sqlite.org/c3ref/create_function.html
func (c *Conn) CreateWindowFunction(name string, nArg int, flag FunctionFlag, fn func() AggregateFunction) error {
var funcPtr uint32
defer c.arena.mark()()
call := "sqlite3_create_aggregate_function_go"
namePtr := c.arena.string(name)
funcPtr := util.AddHandle(c.ctx, fn)
if fn != nil {
funcPtr = util.AddHandle(c.ctx, fn)
}
call := "sqlite3_create_aggregate_function_go"
if _, ok := fn().(WindowFunction); ok {
call = "sqlite3_create_window_function_go"
}
Expand Down Expand Up @@ -188,11 +197,12 @@ func callbackAggregate(db *Conn, pAgg, pApp uint32) (AggregateFunction, uint32)

// We need to create the aggregate.
fn := util.GetHandle(db.ctx, pApp).(func() AggregateFunction)()
handle := util.AddHandle(db.ctx, fn)
if pAgg != 0 {
handle := util.AddHandle(db.ctx, fn)
util.WriteUint32(db.mod, pAgg, handle)
return fn, handle
}
return fn, handle
return fn, 0
}

func callbackArgs(db *Conn, arg []Value, pArg uint32) {
Expand Down
9 changes: 7 additions & 2 deletions internal/util/handle.go
Original file line number Diff line number Diff line change
Expand Up @@ -35,17 +35,22 @@ func DelHandle(ctx context.Context, id uint32) error {
s := ctx.Value(moduleKey{}).(*moduleState)
a := s.handles[^id]
s.handles[^id] = nil
s.holes++
if l := uint32(len(s.handles)); l == ^id {
s.handles = s.handles[:l-1]
} else {
s.holes++
}
if c, ok := a.(io.Closer); ok {
return c.Close()
}
return nil
}

func AddHandle(ctx context.Context, a any) (id uint32) {
func AddHandle(ctx context.Context, a any) uint32 {
if a == nil {
panic(NilErr)
}

s := ctx.Value(moduleKey{}).(*moduleState)

// Find an empty slot.
Expand Down
1 change: 1 addition & 0 deletions sqlite3/column.c
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ int sqlite3_columns_go(sqlite3_stmt *stmt, int nCol, char *aType,
switch (aType[i] = sqlite3_column_type(stmt, i)) {
default: // SQLITE_NULL
aData[i] = (union sqlite3_data){};
continue;
case SQLITE_INTEGER:
aData[i].i = sqlite3_column_int64(stmt, i);
continue;
Expand Down
15 changes: 15 additions & 0 deletions sqlite3/func.c
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,9 @@ int sqlite3_collation_needed_go(sqlite3 *db, bool enable) {
}

int sqlite3_create_collation_go(sqlite3 *db, const char *name, go_handle app) {
if (app == NULL) {
return sqlite3_create_collation_v2(db, name, SQLITE_UTF8, NULL, NULL, NULL);
}
int rc = sqlite3_create_collation_v2(db, name, SQLITE_UTF8, app, go_compare,
go_destroy);
if (rc) go_destroy(app);
Expand All @@ -61,20 +64,32 @@ int sqlite3_create_collation_go(sqlite3 *db, const char *name, go_handle app) {

int sqlite3_create_function_go(sqlite3 *db, const char *name, int argc,
int flags, go_handle app) {
if (app == NULL) {
return sqlite3_create_function_v2(db, name, argc, SQLITE_UTF8 | flags, NULL,
NULL, NULL, NULL, NULL);
}
return sqlite3_create_function_v2(db, name, argc, SQLITE_UTF8 | flags, app,
go_func_wrapper, /*step=*/NULL,
/*final=*/NULL, go_destroy);
}

int sqlite3_create_aggregate_function_go(sqlite3 *db, const char *name,
int argc, int flags, go_handle app) {
if (app == NULL) {
return sqlite3_create_function_v2(db, name, argc, SQLITE_UTF8 | flags, NULL,
NULL, NULL, NULL, NULL);
}
return sqlite3_create_function_v2(db, name, argc, SQLITE_UTF8 | flags, app,
/*func=*/NULL, go_step_wrapper,
go_final_wrapper, go_destroy);
}

int sqlite3_create_window_function_go(sqlite3 *db, const char *name, int argc,
int flags, go_handle app) {
if (app == NULL) {
return sqlite3_create_window_function(db, name, argc, SQLITE_UTF8 | flags,
NULL, NULL, NULL, NULL, NULL, NULL);
}
return sqlite3_create_window_function(
db, name, argc, SQLITE_UTF8 | flags, app, go_step_wrapper,
go_final_wrapper, go_value_wrapper, go_inverse_wrapper, go_destroy);
Expand Down
7 changes: 4 additions & 3 deletions sqlite3/hooks.c
Original file line number Diff line number Diff line change
Expand Up @@ -57,9 +57,10 @@ int sqlite3_config_log_go(bool enable) {
}

int sqlite3_autovacuum_pages_go(sqlite3 *db, go_handle app) {
int rc = sqlite3_autovacuum_pages(db, go_autovacuum_pages, app, go_destroy);
if (rc) go_destroy(app);
return rc;
if (app == NULL) {
return sqlite3_autovacuum_pages(db, NULL, NULL, NULL);
}
return sqlite3_autovacuum_pages(db, go_autovacuum_pages, app, go_destroy);
}

#ifndef sqliteBusyCallback
Expand Down
4 changes: 4 additions & 0 deletions sqlite3/vtab.c
Original file line number Diff line number Diff line change
Expand Up @@ -163,6 +163,10 @@ static int go_vtab_shadown_name_wrapper(const char *zName) { return true; }

int sqlite3_create_module_go(sqlite3 *db, const char *zName, int flags,
go_handle handle) {
if (handle == NULL) {
return sqlite3_create_module_v2(db, zName, NULL, NULL, NULL);
}

struct go_module *mod = malloc(sizeof(struct go_module));
if (mod == NULL) {
go_destroy(handle);
Expand Down
18 changes: 18 additions & 0 deletions tests/func_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -209,6 +209,24 @@ func TestCreateFunction_error(t *testing.T) {
stmt.Step()
}

func TestCreateFunction_delete(t *testing.T) {
db, err := sqlite3.Open(":memory:")
if err != nil {
t.Fatal(err)
}
defer db.Close()

err = db.CreateFunction("regexp", 2, 0, nil)
if err != nil {
t.Fatal(err)
}

err = db.Exec(`SELECT 'a' REGEXP 'a|b'`)
if err == nil {
t.Error("want error")
}
}

func TestOverloadFunction(t *testing.T) {
t.Parallel()

Expand Down
20 changes: 20 additions & 0 deletions tests/vtab_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
package tests

import (
"testing"

"github.com/ncruces/go-sqlite3"
)

func TestCreateModule_delete(t *testing.T) {
db, err := sqlite3.Open(":memory:")
if err != nil {
t.Fatal(err)
}
defer db.Close()

err = sqlite3.CreateModule[sqlite3.VTab](db, "generate_series", nil, nil)
if err != nil {
t.Fatal(err)
}
}
5 changes: 4 additions & 1 deletion vtab.go
Original file line number Diff line number Diff line change
Expand Up @@ -57,9 +57,12 @@ func CreateModule[T VTab](db *Conn, name string, create, connect VTabConstructor
flags |= VTAB_SHADOWTABS
}

var modulePtr uint32
defer db.arena.mark()()
namePtr := db.arena.string(name)
modulePtr := util.AddHandle(db.ctx, module[T]{create, connect})
if connect != nil {
modulePtr = util.AddHandle(db.ctx, module[T]{create, connect})
}
r := db.call("sqlite3_create_module_go", uint64(db.handle),
uint64(namePtr), uint64(flags), uint64(modulePtr))
return db.error(r)
Expand Down

0 comments on commit 25fc5a6

Please sign in to comment.