diff --git a/embed/build.sh b/embed/build.sh index 105c216..a80a94a 100755 --- a/embed/build.sh +++ b/embed/build.sh @@ -4,7 +4,7 @@ set -euo pipefail cd -P -- "$(dirname -- "$0")" ROOT=../ -BINARYEN="$ROOT/tools/binaryen-version_113/bin" +BINARYEN="$ROOT/tools/binaryen-version_114/bin" WASI_SDK="$ROOT/tools/wasi-sdk-20.0/bin" "$WASI_SDK/clang" --target=wasm32-wasi -flto -g0 -O2 \ diff --git a/embed/exports.txt b/embed/exports.txt index 2a07fc0..d14ae18 100644 --- a/embed/exports.txt +++ b/embed/exports.txt @@ -46,4 +46,27 @@ sqlite3_uri_parameter sqlite3_uri_key sqlite3_changes64 sqlite3_last_insert_rowid -sqlite3_get_autocommit \ No newline at end of file +sqlite3_get_autocommit +sqlite3_anycollseq_init +sqlite3_create_go_collation +sqlite3_create_go_function +sqlite3_create_go_window_function +sqlite3_create_go_aggregate_function +sqlite3_aggregate_context +sqlite3_user_data +sqlite3_value_type +sqlite3_value_int64 +sqlite3_value_double +sqlite3_value_text +sqlite3_value_blob +sqlite3_value_bytes +sqlite3_result_null +sqlite3_result_int64 +sqlite3_result_double +sqlite3_result_text64 +sqlite3_result_blob64 +sqlite3_result_zeroblob64 +sqlite3_result_error +sqlite3_result_error_code +sqlite3_result_error_nomem +sqlite3_result_error_toobig \ No newline at end of file diff --git a/embed/sqlite3.wasm b/embed/sqlite3.wasm index 6a7c852..3b8be54 100755 Binary files a/embed/sqlite3.wasm and b/embed/sqlite3.wasm differ diff --git a/func.go b/func.go new file mode 100644 index 0000000..e795323 --- /dev/null +++ b/func.go @@ -0,0 +1,36 @@ +package sqlite3 + +import ( + "context" + + "github.com/ncruces/go-sqlite3/internal/util" + "github.com/tetratelabs/wazero" + "github.com/tetratelabs/wazero/api" +) + +func exportHostFunctions(env wazero.HostModuleBuilder) wazero.HostModuleBuilder { + util.ExportFuncVI(env, "go_destroy", cbDestroy) + util.ExportFuncIIIIII(env, "go_compare", cbCompare) + util.ExportFuncVIII(env, "go_func", cbFunc) + util.ExportFuncVIII(env, "go_step", cbStep) + util.ExportFuncVI(env, "go_final", cbFinal) + util.ExportFuncVI(env, "go_value", cbValue) + util.ExportFuncVIII(env, "go_inverse", cbInverse) + return env +} + +func cbDestroy(ctx context.Context, mod api.Module, pArg uint32) {} + +func cbCompare(ctx context.Context, mod api.Module, pArg, nKey1, pKey1, nKey2, pKey2 uint32) uint32 { + return 0 +} + +func cbFunc(ctx context.Context, mod api.Module, pCtx, nArg, pArg uint32) {} + +func cbStep(ctx context.Context, mod api.Module, pCtx, nArg, pArg uint32) {} + +func cbFinal(ctx context.Context, mod api.Module, pCtx uint32) {} + +func cbValue(ctx context.Context, mod api.Module, pCtx uint32) {} + +func cbInverse(ctx context.Context, mod api.Module, pCtx, nArg, pArg uint32) {} diff --git a/internal/util/func.go b/internal/util/func.go index 65efe3b..9ff7757 100644 --- a/internal/util/func.go +++ b/internal/util/func.go @@ -10,6 +10,32 @@ import ( type i32 interface{ ~int32 | ~uint32 } type i64 interface{ ~int64 | ~uint64 } +type funcVI[T0 i32] func(context.Context, api.Module, T0) + +func (fn funcVI[T0]) Call(ctx context.Context, mod api.Module, stack []uint64) { + fn(ctx, mod, T0(stack[0])) +} + +func ExportFuncVI[T0 i32](mod wazero.HostModuleBuilder, name string, fn func(context.Context, api.Module, T0)) { + mod.NewFunctionBuilder(). + WithGoModuleFunction(funcVI[T0](fn), + []api.ValueType{api.ValueTypeI32}, nil). + Export(name) +} + +type funcVIII[T0, T1, T2 i32] func(context.Context, api.Module, T0, T1, T2) + +func (fn funcVIII[T0, T1, T2]) Call(ctx context.Context, mod api.Module, stack []uint64) { + fn(ctx, mod, T0(stack[0]), T1(stack[1]), T2(stack[2])) +} + +func ExportFuncVIII[T0, T1, T2 i32](mod wazero.HostModuleBuilder, name string, fn func(context.Context, api.Module, T0, T1, T2)) { + mod.NewFunctionBuilder(). + WithGoModuleFunction(funcVIII[T0, T1, T2](fn), + []api.ValueType{api.ValueTypeI32, api.ValueTypeI32, api.ValueTypeI32}, nil). + Export(name) +} + type funcII[TR, T0 i32] func(context.Context, api.Module, T0) TR func (fn funcII[TR, T0]) Call(ctx context.Context, mod api.Module, stack []uint64) { diff --git a/module.go b/module.go index e279601..fc6d027 100644 --- a/module.go +++ b/module.go @@ -53,7 +53,9 @@ func compileModule() { ctx := context.Background() sqlite3.runtime = wazero.NewRuntime(ctx) - env := vfs.ExportHostFunctions(sqlite3.runtime.NewHostModuleBuilder("env")) + env := sqlite3.runtime.NewHostModuleBuilder("env") + env = vfs.ExportHostFunctions(env) + env = exportHostFunctions(env) _, sqlite3.err = env.Instantiate(ctx) if sqlite3.err != nil { return diff --git a/sqlite3/.gitignore b/sqlite3/.gitignore index 2ebf02e..4e3d5d2 100644 --- a/sqlite3/.gitignore +++ b/sqlite3/.gitignore @@ -1,3 +1,4 @@ +ext/ sqlite3.c sqlite3.h sqlite3ext.h \ No newline at end of file diff --git a/sqlite3/download.sh b/sqlite3/download.sh index 9850ffb..01435c7 100755 --- a/sqlite3/download.sh +++ b/sqlite3/download.sh @@ -8,10 +8,9 @@ unzip -d . sqlite-amalgamation-*.zip mv sqlite-amalgamation-*/sqlite3* . rm -rf sqlite-amalgamation-* -patch < vfs_find.patch -patch < open_memory.patch -patch < locking_mode.patch +cat *.patch | patch +mkdir -p ext/ cd ext/ curl -#OL "https://github.com/sqlite/sqlite/raw/version-3.42.0/ext/misc/decimal.c" curl -#OL "https://github.com/sqlite/sqlite/raw/version-3.42.0/ext/misc/uint.c" @@ -19,6 +18,7 @@ curl -#OL "https://github.com/sqlite/sqlite/raw/version-3.42.0/ext/misc/uuid.c" curl -#OL "https://github.com/sqlite/sqlite/raw/version-3.42.0/ext/misc/base64.c" curl -#OL "https://github.com/sqlite/sqlite/raw/version-3.42.0/ext/misc/regexp.c" curl -#OL "https://github.com/sqlite/sqlite/raw/version-3.42.0/ext/misc/series.c" +curl -#OL "https://github.com/sqlite/sqlite/raw/version-3.42.0/ext/misc/anycollseq.c" cd ~- cd ../vfs/tests/mptest/testdata/ diff --git a/sqlite3/ext/.gitignore b/sqlite3/ext/.gitignore deleted file mode 100644 index 09b2ac1..0000000 --- a/sqlite3/ext/.gitignore +++ /dev/null @@ -1 +0,0 @@ -*.c \ No newline at end of file diff --git a/sqlite3/func.c b/sqlite3/func.c new file mode 100644 index 0000000..1be22de --- /dev/null +++ b/sqlite3/func.c @@ -0,0 +1,36 @@ +#include + +#include "sqlite3.h" + +int go_compare(void *, int, const void *, int, const void *); +void go_func(sqlite3_context *, int, sqlite3_value **); +void go_step(sqlite3_context *, int, sqlite3_value **); +void go_final(sqlite3_context *); +void go_value(sqlite3_context *); +void go_inverse(sqlite3_context *, int, sqlite3_value **); +void go_destroy(void *); + +int sqlite3_create_go_collation(sqlite3 *db, const char *zName, void *pApp) { + return sqlite3_create_collation_v2(db, zName, SQLITE_UTF8, pApp, go_compare, + go_destroy); +} + +int sqlite3_create_go_function(sqlite3 *db, const char *zName, int nArg, + int flags, void *pApp) { + return sqlite3_create_function_v2(db, zName, nArg, SQLITE_UTF8 | flags, pApp, + go_func, NULL, NULL, go_destroy); +} + +int sqlite3_create_go_window_function(sqlite3 *db, const char *zName, int nArg, + int flags, void *pApp) { + return sqlite3_create_window_function(db, zName, nArg, SQLITE_UTF8 | flags, + pApp, go_step, go_final, NULL, NULL, + go_destroy); +} + +int sqlite3_create_go_aggregate_function(sqlite3 *db, const char *zName, + int nArg, int flags, void *pApp) { + return sqlite3_create_window_function(db, zName, nArg, SQLITE_UTF8 | flags, + pApp, go_step, go_final, go_value, + go_inverse, go_destroy); +} diff --git a/sqlite3/main.c b/sqlite3/main.c index d4b6c2d..e4ec00d 100644 --- a/sqlite3/main.c +++ b/sqlite3/main.c @@ -6,12 +6,14 @@ // VFS #include "vfs.c" // Extensions +#include "ext/anycollseq.c" #include "ext/base64.c" #include "ext/decimal.c" #include "ext/regexp.c" #include "ext/series.c" #include "ext/uint.c" #include "ext/uuid.c" +#include "func.c" #include "time.c" __attribute__((constructor)) void init() { diff --git a/vfs/tests/mptest/testdata/build.sh b/vfs/tests/mptest/testdata/build.sh index fc2f31f..8d4247b 100755 --- a/vfs/tests/mptest/testdata/build.sh +++ b/vfs/tests/mptest/testdata/build.sh @@ -4,7 +4,7 @@ set -euo pipefail cd -P -- "$(dirname -- "$0")" ROOT=../../../../ -BINARYEN="$ROOT/tools/binaryen-version_113/bin" +BINARYEN="$ROOT/tools/binaryen-version_114/bin" WASI_SDK="$ROOT/tools/wasi-sdk-20.0/bin" "$WASI_SDK/clang" --target=wasm32-wasi -flto -g0 -O2 \ diff --git a/vfs/tests/speedtest1/testdata/build.sh b/vfs/tests/speedtest1/testdata/build.sh index 0ef94e6..174e067 100755 --- a/vfs/tests/speedtest1/testdata/build.sh +++ b/vfs/tests/speedtest1/testdata/build.sh @@ -4,7 +4,7 @@ set -euo pipefail cd -P -- "$(dirname -- "$0")" ROOT=../../../../ -BINARYEN="$ROOT/tools/binaryen-version_113/bin" +BINARYEN="$ROOT/tools/binaryen-version_114/bin" WASI_SDK="$ROOT/tools/wasi-sdk-20.0/bin" "$WASI_SDK/clang" --target=wasm32-wasi -flto -g0 -O2 \