diff --git a/embed/README.md b/embed/README.md index 0f79f7a..0adf617 100644 --- a/embed/README.md +++ b/embed/README.md @@ -1,6 +1,6 @@ # Embeddable Wasm build of SQLite -This folder includes an embeddable Wasm build of SQLite 3.50.1 for use with +This folder includes an embeddable Wasm build of SQLite 3.50.2 for use with [`github.com/ncruces/go-sqlite3`](https://pkg.go.dev/github.com/ncruces/go-sqlite3). The following optional features are compiled in: diff --git a/embed/bcw2/bcw2.wasm b/embed/bcw2/bcw2.wasm index 8cbc72c..2af374b 100755 Binary files a/embed/bcw2/bcw2.wasm and b/embed/bcw2/bcw2.wasm differ diff --git a/embed/bcw2/build.sh b/embed/bcw2/build.sh index 7b5a56e..02a7d90 100755 --- a/embed/bcw2/build.sh +++ b/embed/bcw2/build.sh @@ -13,8 +13,8 @@ mkdir -p build/ext/ cp "$ROOT"/sqlite3/*.[ch] build/ cp "$ROOT"/sqlite3/*.patch build/ -# https://sqlite.org/src/info/93740658c8c6f531 -curl -# https://sqlite.org/src/tarball/sqlite.tar.gz?r=93740658c8 | tar xz +# https://sqlite.org/src/info/a6f6fbe6173de8a2 +curl -# https://sqlite.org/src/tarball/sqlite.tar.gz?r=a6f6fbe617 | tar xz cd sqlite if [[ "$OSTYPE" == "msys" || "$OSTYPE" == "cygwin" ]]; then diff --git a/embed/bcw2/go.mod b/embed/bcw2/go.mod index 17221dc..2a995e0 100644 --- a/embed/bcw2/go.mod +++ b/embed/bcw2/go.mod @@ -4,7 +4,7 @@ go 1.23.0 toolchain go1.24.0 -require github.com/ncruces/go-sqlite3 v0.26.0 +require github.com/ncruces/go-sqlite3 v0.26.2 require ( github.com/ncruces/julianday v1.0.0 // indirect diff --git a/embed/bcw2/go.sum b/embed/bcw2/go.sum index 4cd73fa..60820d2 100644 --- a/embed/bcw2/go.sum +++ b/embed/bcw2/go.sum @@ -1,5 +1,5 @@ -github.com/ncruces/go-sqlite3 v0.26.0 h1:dY6ASfuhSEbtSge6kJwjyJVC7bXCpgEVOycmdboKJek= -github.com/ncruces/go-sqlite3 v0.26.0/go.mod h1:46HIzeCQQ+aNleAxCli+vpA2tfh7ttSnw24kQahBc1o= +github.com/ncruces/go-sqlite3 v0.26.2 h1:5UkIBwdfMN2irpVI1dgi9TjTUlxNI06Rti1C8O7ZKVg= +github.com/ncruces/go-sqlite3 v0.26.2/go.mod h1:XFTPtFIo1DmGCh+XVP8KGn9b/o2f+z0WZuT09x2N6eo= github.com/ncruces/julianday v1.0.0 h1:fH0OKwa7NWvniGQtxdJRxAgkBMolni2BjDHaWTxqt7M= github.com/ncruces/julianday v1.0.0/go.mod h1:Dusn2KvZrrovOMJuOt0TNXL6tB7U2E8kvza5fFc9G7g= github.com/ncruces/sort v0.1.5 h1:fiFWXXAqKI8QckPf/6hu/bGFwcEPrirIOFaJqWujs4k= @@ -8,5 +8,5 @@ github.com/tetratelabs/wazero v1.9.0 h1:IcZ56OuxrtaEz8UYNRHBrUa9bYeX9oVY93KspZZB github.com/tetratelabs/wazero v1.9.0/go.mod h1:TSbcXCfFP0L2FGkRPxHphadXPjo1T6W+CseNNY7EkjM= golang.org/x/sys v0.33.0 h1:q3i8TbbEz+JRD9ywIRlyRAQbM0qF7hu24q3teo2hbuw= golang.org/x/sys v0.33.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k= -golang.org/x/text v0.25.0 h1:qVyWApTSYLk/drJRO5mDlNYskwQznZmkpV2c8q9zls4= -golang.org/x/text v0.25.0/go.mod h1:WEdwpYrmk1qmdHvhkSTNPm3app7v4rsT8F2UD6+VHIA= +golang.org/x/text v0.26.0 h1:P42AVeLghgTYr4+xUnTRKDMqpar+PtX7KWuNQL21L8M= +golang.org/x/text v0.26.0/go.mod h1:QK15LZJUUQVJxhz7wXgxSy/CJaTFjd0G+YLonydOVQA= diff --git a/embed/init_test.go b/embed/init_test.go index ba64846..7fc489c 100644 --- a/embed/init_test.go +++ b/embed/init_test.go @@ -19,7 +19,7 @@ func Test_init(t *testing.T) { if err != nil { t.Fatal(err) } - if version != "3.50.1" { + if version != "3.50.2" { t.Error(version) } } diff --git a/embed/sqlite3.wasm b/embed/sqlite3.wasm index 60e4387..7ad7f74 100755 Binary files a/embed/sqlite3.wasm and b/embed/sqlite3.wasm differ diff --git a/gormlite/go.mod b/gormlite/go.mod index 26a52b8..2fea8b0 100644 --- a/gormlite/go.mod +++ b/gormlite/go.mod @@ -5,7 +5,7 @@ go 1.23.0 toolchain go1.24.0 require ( - github.com/ncruces/go-sqlite3 v0.26.0 + github.com/ncruces/go-sqlite3 v0.26.2 gorm.io/gorm v1.30.0 ) diff --git a/gormlite/go.sum b/gormlite/go.sum index aa30ed1..362f67e 100644 --- a/gormlite/go.sum +++ b/gormlite/go.sum @@ -2,8 +2,8 @@ github.com/jinzhu/inflection v1.0.0 h1:K317FqzuhWc8YvSVlFMCCUb36O/S9MCKRDI7QkRKD github.com/jinzhu/inflection v1.0.0/go.mod h1:h+uFLlag+Qp1Va5pdKtLDYj+kHp5pxUVkryuEj+Srlc= github.com/jinzhu/now v1.1.5 h1:/o9tlHleP7gOFmsnYNz3RGnqzefHA47wQpKrrdTIwXQ= github.com/jinzhu/now v1.1.5/go.mod h1:d3SSVoowX0Lcu0IBviAWJpolVfI5UJVZZ7cO71lE/z8= -github.com/ncruces/go-sqlite3 v0.26.0 h1:dY6ASfuhSEbtSge6kJwjyJVC7bXCpgEVOycmdboKJek= -github.com/ncruces/go-sqlite3 v0.26.0/go.mod h1:46HIzeCQQ+aNleAxCli+vpA2tfh7ttSnw24kQahBc1o= +github.com/ncruces/go-sqlite3 v0.26.2 h1:5UkIBwdfMN2irpVI1dgi9TjTUlxNI06Rti1C8O7ZKVg= +github.com/ncruces/go-sqlite3 v0.26.2/go.mod h1:XFTPtFIo1DmGCh+XVP8KGn9b/o2f+z0WZuT09x2N6eo= github.com/ncruces/julianday v1.0.0 h1:fH0OKwa7NWvniGQtxdJRxAgkBMolni2BjDHaWTxqt7M= github.com/ncruces/julianday v1.0.0/go.mod h1:Dusn2KvZrrovOMJuOt0TNXL6tB7U2E8kvza5fFc9G7g= github.com/tetratelabs/wazero v1.9.0 h1:IcZ56OuxrtaEz8UYNRHBrUa9bYeX9oVY93KspZZBf/I= diff --git a/sqlite3/busy_timeout.patch b/sqlite3/busy_timeout.patch index 4df8346..a0b24d2 100644 --- a/sqlite3/busy_timeout.patch +++ b/sqlite3/busy_timeout.patch @@ -2,7 +2,7 @@ # handle, and interrupt, sqlite3_busy_timeout. --- sqlite3.c.orig +++ sqlite3.c -@@ -183364,7 +183364,7 @@ +@@ -184433,7 +184433,7 @@ if( !sqlite3SafetyCheckOk(db) ) return SQLITE_MISUSE_BKPT; #endif if( ms>0 ){ @@ -10,4 +10,4 @@ + sqlite3_busy_handler(db, (int(*)(void*,int))sqliteBusyCallback, (void*)db); db->busyTimeout = ms; - }else{ + #ifdef SQLITE_ENABLE_SETLK_TIMEOUT diff --git a/sqlite3/download.sh b/sqlite3/download.sh index 582e9dc..a8d8bf2 100755 --- a/sqlite3/download.sh +++ b/sqlite3/download.sh @@ -3,7 +3,7 @@ set -euo pipefail cd -P -- "$(dirname -- "$0")" -curl -#OL "https://sqlite.org/2025/sqlite-amalgamation-3500100.zip" +curl -#OL "https://sqlite.org/2025/sqlite-amalgamation-3500200.zip" unzip -d . sqlite-amalgamation-*.zip mv sqlite-amalgamation-*/sqlite3.c . mv sqlite-amalgamation-*/sqlite3.h . @@ -19,30 +19,30 @@ rm -rf sqlite-amalgamation-* mkdir -p ext/ cd ext/ -curl -#OL "https://github.com/sqlite/sqlite/raw/version-3.50.1/ext/misc/anycollseq.c" -curl -#OL "https://github.com/sqlite/sqlite/raw/version-3.50.1/ext/misc/base64.c" -curl -#OL "https://github.com/sqlite/sqlite/raw/version-3.50.1/ext/misc/decimal.c" -curl -#OL "https://github.com/sqlite/sqlite/raw/version-3.50.1/ext/misc/ieee754.c" -curl -#OL "https://github.com/sqlite/sqlite/raw/version-3.50.1/ext/misc/regexp.c" -curl -#OL "https://github.com/sqlite/sqlite/raw/version-3.50.1/ext/misc/series.c" -curl -#OL "https://github.com/sqlite/sqlite/raw/version-3.50.1/ext/misc/spellfix.c" -curl -#OL "https://github.com/sqlite/sqlite/raw/version-3.50.1/ext/misc/uint.c" +curl -#OL "https://github.com/sqlite/sqlite/raw/version-3.50.2/ext/misc/anycollseq.c" +curl -#OL "https://github.com/sqlite/sqlite/raw/version-3.50.2/ext/misc/base64.c" +curl -#OL "https://github.com/sqlite/sqlite/raw/version-3.50.2/ext/misc/decimal.c" +curl -#OL "https://github.com/sqlite/sqlite/raw/version-3.50.2/ext/misc/ieee754.c" +curl -#OL "https://github.com/sqlite/sqlite/raw/version-3.50.2/ext/misc/regexp.c" +curl -#OL "https://github.com/sqlite/sqlite/raw/version-3.50.2/ext/misc/series.c" +curl -#OL "https://github.com/sqlite/sqlite/raw/version-3.50.2/ext/misc/spellfix.c" +curl -#OL "https://github.com/sqlite/sqlite/raw/version-3.50.2/ext/misc/uint.c" cd ~- cd ../vfs/tests/mptest/testdata/ -curl -#OL "https://github.com/sqlite/sqlite/raw/version-3.50.1/mptest/config01.test" -curl -#OL "https://github.com/sqlite/sqlite/raw/version-3.50.1/mptest/config02.test" -curl -#OL "https://github.com/sqlite/sqlite/raw/version-3.50.1/mptest/crash01.test" -curl -#OL "https://github.com/sqlite/sqlite/raw/version-3.50.1/mptest/crash02.subtest" -curl -#OL "https://github.com/sqlite/sqlite/raw/version-3.50.1/mptest/multiwrite01.test" +curl -#OL "https://github.com/sqlite/sqlite/raw/version-3.50.2/mptest/config01.test" +curl -#OL "https://github.com/sqlite/sqlite/raw/version-3.50.2/mptest/config02.test" +curl -#OL "https://github.com/sqlite/sqlite/raw/version-3.50.2/mptest/crash01.test" +curl -#OL "https://github.com/sqlite/sqlite/raw/version-3.50.2/mptest/crash02.subtest" +curl -#OL "https://github.com/sqlite/sqlite/raw/version-3.50.2/mptest/multiwrite01.test" cd ~- cd ../vfs/tests/mptest/wasm/ -curl -#OL "https://github.com/sqlite/sqlite/raw/version-3.50.1/mptest/mptest.c" +curl -#OL "https://github.com/sqlite/sqlite/raw/version-3.50.2/mptest/mptest.c" cd ~- cd ../vfs/tests/speedtest1/wasm/ -curl -#OL "https://github.com/sqlite/sqlite/raw/version-3.50.1/test/speedtest1.c" +curl -#OL "https://github.com/sqlite/sqlite/raw/version-3.50.2/test/speedtest1.c" cd ~- cat *.patch | patch -p0 --no-backup-if-mismatch \ No newline at end of file diff --git a/sqlite3/libc/libc_test.go b/sqlite3/libc/libc_test.go index c44190c..4a1bb5b 100644 --- a/sqlite3/libc/libc_test.go +++ b/sqlite3/libc/libc_test.go @@ -4,6 +4,7 @@ import ( "bytes" "context" _ "embed" + "math" "os" "strings" "testing" @@ -230,6 +231,10 @@ func Test_memchr(t *testing.T) { fill(memory[ptr:ptr+max(pos, length)], 5) memory[ptr+pos] = 7 + if pos >= 0 { + memory[ptr+pos+2] = 7 + } + got := call(memchr, uint64(ptr), 7, uint64(length)) if uint32(got) != uint32(want) { t.Errorf("memchr(%d, %d, %d) = %d, want %d", @@ -243,9 +248,14 @@ func Test_memchr(t *testing.T) { fill(memory[ptr:ptr+length], 5) memory[len(memory)-1] = 7 - want := len(memory) - 1 - if length == 0 { - want = 0 + var want int + if length != 0 { + want = len(memory) - 1 + got := call(memchr, uint64(ptr), 7, math.MaxUint32) + if uint32(got) != uint32(want) { + t.Errorf("memchr(%d, %d, %d) = %d, want %d", + ptr, 7, uint32(math.MaxUint32), uint32(got), uint32(want)) + } } got := call(memchr, uint64(ptr), 7, uint64(length)) diff --git a/sqlite3/libc/string.h b/sqlite3/libc/string.h index 86e2197..91a395e 100644 --- a/sqlite3/libc/string.h +++ b/sqlite3/libc/string.h @@ -101,13 +101,13 @@ void *memchr(const void *s, int c, size_t n) { const v128_t cmp = wasm_i8x16_eq(*v, vc); // Bitmask is slow on AArch64, any_true is much faster. if (wasm_v128_any_true(cmp)) { - // Clear the bits corresponding to alignment (little-endian) + // Clear the bits corresponding to align (little-endian) // so we can count trailing zeros. int mask = wasm_i8x16_bitmask(cmp) >> align << align; - // At least one bit will be set, unless we cleared them. - // Knowing this helps the compiler. + // At least one bit will be set, unless align cleared them. + // Knowing this helps the compiler if it unrolls the loop. __builtin_assume(mask || align); - // If the mask is zero because of alignment, + // If the mask became zero because of align, // it's as if we didn't find anything. if (mask) { // Find the offset of the first one bit (little-endian). @@ -137,8 +137,10 @@ void *memrchr(const void *s, int c, size_t n) { // Bitmask is slow on AArch64, any_true is much faster. if (wasm_v128_any_true(cmp)) { // Find the offset of the last one bit (little-endian). - size_t clz = __builtin_clz(wasm_i8x16_bitmask(cmp)) - 15; - return (char *)(v + 1) - clz; + // The leading 16 bits of the bitmask are always zero, + // and to be ignored. + size_t clz = __builtin_clz(wasm_i8x16_bitmask(cmp)) - 16; + return (char *)(v + 1) - (clz + 1); } } @@ -163,13 +165,13 @@ size_t strlen(const char *s) { // Bitmask is slow on AArch64, all_true is much faster. if (!wasm_i8x16_all_true(*v)) { const v128_t cmp = wasm_i8x16_eq(*v, (v128_t){}); - // Clear the bits corresponding to alignment (little-endian) + // Clear the bits corresponding to align (little-endian) // so we can count trailing zeros. int mask = wasm_i8x16_bitmask(cmp) >> align << align; - // At least one bit will be set, unless we cleared them. - // Knowing this helps the compiler. + // At least one bit will be set, unless align cleared them. + // Knowing this helps the compiler if it unrolls the loop. __builtin_assume(mask || align); - // If the mask is zero because of alignment, + // If the mask became zero because of align, // it's as if we didn't find anything. if (mask) { // Find the offset of the first one bit (little-endian). @@ -194,13 +196,13 @@ static char *__strchrnul(const char *s, int c) { const v128_t cmp = wasm_i8x16_eq(*v, (v128_t){}) | wasm_i8x16_eq(*v, vc); // Bitmask is slow on AArch64, any_true is much faster. if (wasm_v128_any_true(cmp)) { - // Clear the bits corresponding to alignment (little-endian) + // Clear the bits corresponding to align (little-endian) // so we can count trailing zeros. int mask = wasm_i8x16_bitmask(cmp) >> align << align; - // At least one bit will be set, unless we cleared them. - // Knowing this helps the compiler. + // At least one bit will be set, unless align cleared them. + // Knowing this helps the compiler if it unrolls the loop. __builtin_assume(mask || align); - // If the mask is zero because of alignment, + // If the mask became zero because of align, // it's as if we didn't find anything. if (mask) { // Find the offset of the first one bit (little-endian). @@ -301,13 +303,13 @@ size_t strspn(const char *s, const char *c) { const v128_t cmp = wasm_i8x16_eq(*v, vc); // Bitmask is slow on AArch64, all_true is much faster. if (!wasm_i8x16_all_true(cmp)) { - // Clear the bits corresponding to alignment (little-endian) + // Clear the bits corresponding to align (little-endian) // so we can count trailing zeros. int mask = (uint16_t)~wasm_i8x16_bitmask(cmp) >> align << align; - // At least one bit will be set, unless we cleared them. - // Knowing this helps the compiler. + // At least one bit will be set, unless align cleared them. + // Knowing this helps the compiler if it unrolls the loop. __builtin_assume(mask || align); - // If the mask is zero because of alignment, + // If the mask became zero because of align, // it's as if we didn't find anything. if (mask) { // Find the offset of the first one bit (little-endian). @@ -330,13 +332,13 @@ size_t strspn(const char *s, const char *c) { const v128_t cmp = __wasm_v128_chkbits(bitmap, *v); // Bitmask is slow on AArch64, all_true is much faster. if (!wasm_i8x16_all_true(cmp)) { - // Clear the bits corresponding to alignment (little-endian) + // Clear the bits corresponding to align (little-endian) // so we can count trailing zeros. int mask = (uint16_t)~wasm_i8x16_bitmask(cmp) >> align << align; - // At least one bit will be set, unless we cleared them. - // Knowing this helps the compiler. + // At least one bit will be set, unless align cleared them. + // Knowing this helps the compiler if it unrolls the loop. __builtin_assume(mask || align); - // If the mask is zero because of alignment, + // If the mask became zero because of align, // it's as if we didn't find anything. if (mask) { // Find the offset of the first one bit (little-endian). @@ -370,13 +372,13 @@ size_t strcspn(const char *s, const char *c) { const v128_t cmp = __wasm_v128_chkbits(bitmap, *v); // Bitmask is slow on AArch64, any_true is much faster. if (wasm_v128_any_true(cmp)) { - // Clear the bits corresponding to alignment (little-endian) + // Clear the bits corresponding to align (little-endian) // so we can count trailing zeros. int mask = wasm_i8x16_bitmask(cmp) >> align << align; - // At least one bit will be set, unless we cleared them. - // Knowing this helps the compiler. + // At least one bit will be set, unless align cleared them. + // Knowing this helps the compiler if it unrolls the loop. __builtin_assume(mask || align); - // If the mask is zero because of alignment, + // If the mask became zero because of align, // it's as if we didn't find anything. if (mask) { // Find the offset of the first one bit (little-endian). diff --git a/sqlite3/vfs_find.patch b/sqlite3/vfs_find.patch index 1e2cefa..53fde65 100644 --- a/sqlite3/vfs_find.patch +++ b/sqlite3/vfs_find.patch @@ -1,7 +1,7 @@ # Remove VFS registration. Go handles it. --- sqlite3.c.orig +++ sqlite3.c -@@ -26726,7 +26726,7 @@ +@@ -26883,7 +26883,7 @@ sqlite3_free(p); return sqlite3_os_init(); } @@ -10,7 +10,7 @@ /* ** The list of all registered VFS implementations. */ -@@ -26823,7 +26823,7 @@ +@@ -26980,7 +26980,7 @@ sqlite3_mutex_leave(mutex); return SQLITE_OK; } diff --git a/vfs/tests/mptest/wasm/mptest.wasm b/vfs/tests/mptest/wasm/mptest.wasm index 8918876..431d0a6 100644 Binary files a/vfs/tests/mptest/wasm/mptest.wasm and b/vfs/tests/mptest/wasm/mptest.wasm differ diff --git a/vfs/tests/speedtest1/wasm/speedtest1.wasm b/vfs/tests/speedtest1/wasm/speedtest1.wasm index ff840a4..5856b10 100644 Binary files a/vfs/tests/speedtest1/wasm/speedtest1.wasm and b/vfs/tests/speedtest1/wasm/speedtest1.wasm differ