diff --git a/conn.go b/conn.go index 8c8ed3b..b1e11c5 100644 --- a/conn.go +++ b/conn.go @@ -105,7 +105,6 @@ func (c *Conn) openDB(filename string, flags OpenFlag) (uint32, error) { } } - c.call(c.api.timeCollation, uint64(handle)) return handle, nil } diff --git a/embed/README.md b/embed/README.md index ea88feb..2d94da3 100644 --- a/embed/README.md +++ b/embed/README.md @@ -4,11 +4,18 @@ This folder includes an embeddable WASM build of SQLite 3.41.1 for use with [`github.com/ncruces/go-sqlite3`](https://pkg.go.dev/github.com/ncruces/go-sqlite3). The following optional features are compiled in: -- math functions -- FTS3/4/5 -- JSON -- R*Tree -- GeoPoly +- [math functions](https://www.sqlite.org/lang_mathfunc.html) +- [FTS3/4](https://www.sqlite.org/fts3.html)/[5](https://www.sqlite.org/fts5.html) +- [JSON](https://www.sqlite.org/json1.html) +- [R*Tree](https://www.sqlite.org/rtree.html) +- [GeoPoly](https://www.sqlite.org/geopoly.html) +- [base64](https://github.com/sqlite/sqlite/blob/master/ext/misc/base64.c) +- [decimal](https://github.com/sqlite/sqlite/blob/master/ext/misc/decimal.c) +- [regexp](https://github.com/sqlite/sqlite/blob/master/ext/misc/regexp.c) +- [series](https://github.com/sqlite/sqlite/blob/master/ext/misc/series.c) +- [uint](https://github.com/sqlite/sqlite/blob/master/ext/misc/uint.c) +- [uuid](https://github.com/sqlite/sqlite/blob/master/ext/misc/uuid.c) +- [time](../sqlite3/time.c) See the [configuration options](../sqlite3/sqlite_cfg.h). diff --git a/embed/build.sh b/embed/build.sh index f864f58..59a2c70 100755 --- a/embed/build.sh +++ b/embed/build.sh @@ -6,6 +6,7 @@ cd -P -- "$(dirname -- "$0")" # build SQLite zig cc --target=wasm32-wasi -flto -g0 -Os \ -o sqlite3.wasm ../sqlite3/main.c \ + -I../sqlite3/ \ -mmutable-globals \ -mbulk-memory -mreference-types \ -mnontrapping-fptoint -msign-ext \ diff --git a/embed/exports.txt b/embed/exports.txt index f9d5d40..ae07974 100644 --- a/embed/exports.txt +++ b/embed/exports.txt @@ -45,5 +45,4 @@ sqlite3_backup_step sqlite3_backup_finish sqlite3_backup_remaining sqlite3_backup_pagecount -sqlite3_time_collation sqlite3_interrupt_offset \ No newline at end of file diff --git a/embed/sqlite3.wasm b/embed/sqlite3.wasm index ca2fc43..3f2ed8e 100644 Binary files a/embed/sqlite3.wasm and b/embed/sqlite3.wasm differ diff --git a/module.go b/module.go index d601e70..a742e2d 100644 --- a/module.go +++ b/module.go @@ -155,7 +155,6 @@ func newModule(mod api.Module) (m *module, err error) { backupFinish: getFun("sqlite3_backup_finish"), backupRemaining: getFun("sqlite3_backup_remaining"), backupPageCount: getFun("sqlite3_backup_pagecount"), - timeCollation: getFun("sqlite3_time_collation"), interrupt: getVal("sqlite3_interrupt_offset"), } if err != nil { @@ -349,6 +348,5 @@ type sqliteAPI struct { backupFinish api.Function backupRemaining api.Function backupPageCount api.Function - timeCollation api.Function interrupt uint32 } diff --git a/sqlite3/download.sh b/sqlite3/download.sh index 0c191c5..c032ec8 100755 --- a/sqlite3/download.sh +++ b/sqlite3/download.sh @@ -8,6 +8,15 @@ unzip -d . sqlite-amalgamation-*.zip mv sqlite-amalgamation-*/sqlite3* . rm -rf sqlite-amalgamation-* +cd ext/ +curl -#OL "https://github.com/sqlite/sqlite/raw/version-3.41.1/ext/misc/decimal.c" +curl -#OL "https://github.com/sqlite/sqlite/raw/version-3.41.1/ext/misc/uint.c" +curl -#OL "https://github.com/sqlite/sqlite/raw/version-3.41.1/ext/misc/uuid.c" +curl -#OL "https://github.com/sqlite/sqlite/raw/version-3.41.1/ext/misc/base64.c" +curl -#OL "https://github.com/sqlite/sqlite/raw/version-3.41.1/ext/misc/regexp.c" +curl -#OL "https://github.com/sqlite/sqlite/raw/version-3.41.1/ext/misc/series.c" +cd ~- + cd ../tests/mptest/testdata/ curl -#OL "https://github.com/sqlite/sqlite/raw/version-3.41.1/mptest/mptest.c" curl -#OL "https://github.com/sqlite/sqlite/raw/version-3.41.1/mptest/config01.test" diff --git a/sqlite3/ext/.gitignore b/sqlite3/ext/.gitignore new file mode 100644 index 0000000..09b2ac1 --- /dev/null +++ b/sqlite3/ext/.gitignore @@ -0,0 +1 @@ +*.c \ No newline at end of file diff --git a/sqlite3/main.c b/sqlite3/main.c index fe7311d..813d8e0 100644 --- a/sqlite3/main.c +++ b/sqlite3/main.c @@ -5,6 +5,13 @@ // #include "os.c" #include "qsort.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 "time.c" sqlite3_destructor_type malloc_destructor = &free; @@ -17,4 +24,25 @@ int sqlite3_os_init() { int main() { int rc = sqlite3_initialize(); if (rc != SQLITE_OK) return 1; + + rc = sqlite3_auto_extension((void (*)(void))sqlite3_base_init); + if (rc != SQLITE_OK) return 1; + + rc = sqlite3_auto_extension((void (*)(void))sqlite3_decimal_init); + if (rc != SQLITE_OK) return 1; + + rc = sqlite3_auto_extension((void (*)(void))sqlite3_regexp_init); + if (rc != SQLITE_OK) return 1; + + rc = sqlite3_auto_extension((void (*)(void))sqlite3_series_init); + if (rc != SQLITE_OK) return 1; + + rc = sqlite3_auto_extension((void (*)(void))sqlite3_uint_init); + if (rc != SQLITE_OK) return 1; + + rc = sqlite3_auto_extension((void (*)(void))sqlite3_uuid_init); + if (rc != SQLITE_OK) return 1; + + rc = sqlite3_auto_extension((void (*)(void))sqlite3_time_init); + if (rc != SQLITE_OK) return 1; } diff --git a/sqlite3/time.c b/sqlite3/time.c index 374047d..75b8744 100644 --- a/sqlite3/time.c +++ b/sqlite3/time.c @@ -26,6 +26,7 @@ static int time_collation(void *pArg, int nKey1, const void *pKey1, int nKey2, return rc; } -int sqlite3_time_collation(sqlite3 *db) { - return sqlite3_create_collation(db, "TIME", SQLITE_UTF8, 0, time_collation); +int sqlite3_time_init(sqlite3 *db, char **pzErrMsg, + const sqlite3_api_routines *pApi) { + return sqlite3_create_collation(db, "time", SQLITE_UTF8, 0, time_collation); } \ No newline at end of file diff --git a/tests/bradfitz/sql_test.go b/tests/bradfitz/sql_test.go index a4ae19f..7b4c278 100644 --- a/tests/bradfitz/sql_test.go +++ b/tests/bradfitz/sql_test.go @@ -126,7 +126,7 @@ func testTxQuery(t params) { if r.Err() != nil { t.Fatal(err) } - t.Fatal("expected one rows") + t.Fatal("expected one row") } var name string diff --git a/tests/ext_test.go b/tests/ext_test.go new file mode 100644 index 0000000..9a3baec --- /dev/null +++ b/tests/ext_test.go @@ -0,0 +1,77 @@ +package tests + +import ( + "testing" + + "github.com/ncruces/go-sqlite3" +) + +func Test_base64(t *testing.T) { + t.Parallel() + + db, err := sqlite3.Open(":memory:") + if err != nil { + t.Fatal(err) + } + defer db.Close() + + // base64 + stmt, _, err := db.Prepare(`SELECT base64('TWFueSBoYW5kcyBtYWtlIGxpZ2h0IHdvcmsu')`) + if err != nil { + t.Error(err) + } + defer stmt.Close() + + if !stmt.Step() { + t.Fatal("expected one row") + } + if got := stmt.ColumnText(0); got != "Many hands make light work." { + t.Errorf("got %q", got) + } +} + +func Test_decimal(t *testing.T) { + t.Parallel() + + db, err := sqlite3.Open(":memory:") + if err != nil { + t.Fatal(err) + } + defer db.Close() + + stmt, _, err := db.Prepare(`SELECT decimal_add(decimal('0.1'), decimal('0.2')) = decimal('0.3')`) + if err != nil { + t.Error(err) + } + defer stmt.Close() + + if !stmt.Step() { + t.Fatal("expected one row") + } + if !stmt.ColumnBool(0) { + t.Error("want true") + } +} + +func Test_uint(t *testing.T) { + t.Parallel() + + db, err := sqlite3.Open(":memory:") + if err != nil { + t.Fatal(err) + } + defer db.Close() + + stmt, _, err := db.Prepare(`SELECT 'z2' < 'z11' COLLATE UINT`) + if err != nil { + t.Error(err) + } + defer stmt.Close() + + if !stmt.Step() { + t.Fatal("expected one row") + } + if !stmt.ColumnBool(0) { + t.Error("want true") + } +} diff --git a/tests/mptest/testdata/build.sh b/tests/mptest/testdata/build.sh index 25c8495..ae6e9d1 100755 --- a/tests/mptest/testdata/build.sh +++ b/tests/mptest/testdata/build.sh @@ -5,7 +5,7 @@ cd -P -- "$(dirname -- "$0")" zig cc --target=wasm32-wasi -flto -g0 -Os \ -o mptest.wasm main.c \ - -I../../../sqlite3 \ + -I../../../sqlite3/ \ -mmutable-globals \ -mbulk-memory -mreference-types \ -mnontrapping-fptoint -msign-ext \ diff --git a/tests/mptest/testdata/main.c b/tests/mptest/testdata/main.c index 8e1287f..27239ab 100644 --- a/tests/mptest/testdata/main.c +++ b/tests/mptest/testdata/main.c @@ -5,7 +5,6 @@ // #include "os.c" #include "qsort.c" -#include "time.c" sqlite3_destructor_type malloc_destructor = &free; size_t sqlite3_interrupt_offset = offsetof(sqlite3, u1.isInterrupted); diff --git a/tests/speedtest1/testdata/build.sh b/tests/speedtest1/testdata/build.sh index 6f8c60e..5daa5fc 100755 --- a/tests/speedtest1/testdata/build.sh +++ b/tests/speedtest1/testdata/build.sh @@ -5,7 +5,7 @@ cd -P -- "$(dirname -- "$0")" zig cc --target=wasm32-wasi -flto -g0 -Os \ -o speedtest1.wasm main.c \ - -I../../../sqlite3 \ + -I../../../sqlite3/ \ -mmutable-globals \ -mbulk-memory -mreference-types \ -mnontrapping-fptoint -msign-ext \ diff --git a/tests/speedtest1/testdata/main.c b/tests/speedtest1/testdata/main.c index c56e200..833dd82 100644 --- a/tests/speedtest1/testdata/main.c +++ b/tests/speedtest1/testdata/main.c @@ -5,7 +5,6 @@ // #include "os.c" #include "qsort.c" -#include "time.c" sqlite3_destructor_type malloc_destructor = &free; size_t sqlite3_interrupt_offset = offsetof(sqlite3, u1.isInterrupted);