From 8b9f533b896756bdf41933992a444e4cc4065e47 Mon Sep 17 00:00:00 2001 From: Andrew Plaza Date: Mon, 5 Aug 2024 17:47:26 -0400 Subject: [PATCH] porting stmt, then sqlite_value --- Cargo.lock | 96 +-- Cargo.toml | 3 +- diesel-wasm-sqlite/.vscode/settings.json | 32 + diesel-wasm-sqlite/Cargo.lock | 697 ++++++++++++++++ diesel-wasm-sqlite/Cargo.toml | 5 + diesel-wasm-sqlite/README.md | 6 + diesel-wasm-sqlite/package-lock.json | 756 ++++++++++++++++++ diesel-wasm-sqlite/package.js | 110 +++ diesel-wasm-sqlite/src/backend.rs | 6 +- .../src/connection/bind_collector.rs | 24 +- diesel-wasm-sqlite/src/connection/mod.rs | 8 +- .../src/connection/owned_row.rs | 14 +- diesel-wasm-sqlite/src/connection/raw.rs | 379 +-------- diesel-wasm-sqlite/src/connection/row.rs | 26 +- .../src/connection/sqlite_value.rs | 42 +- diesel-wasm-sqlite/src/connection/stmt.rs | 158 ++-- diesel-wasm-sqlite/src/ffi.rs | 67 ++ diesel-wasm-sqlite/src/lib.rs | 6 +- diesel-wasm-sqlite/src/package.js | 39 + diesel-wasm-sqlite/src/sqlite_types.rs | 19 +- 20 files changed, 1865 insertions(+), 628 deletions(-) create mode 100644 diesel-wasm-sqlite/.vscode/settings.json create mode 100644 diesel-wasm-sqlite/Cargo.lock create mode 100644 diesel-wasm-sqlite/package-lock.json diff --git a/Cargo.lock b/Cargo.lock index c29df6d2e..6f5b50da0 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1066,72 +1066,19 @@ name = "diesel" version = "2.2.0" source = "git+https://github.com/xmtp/diesel?branch=insipx/wasm-backend#a3fa32d4291bbae566cf544ca63a1aa2543da943" dependencies = [ - "diesel_derives 2.2.0", + "diesel_derives", "libsqlite3-sys", "r2d2", "time", ] -[[package]] -name = "diesel" -version = "2.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bf97ee7261bb708fa3402fa9c17a54b70e90e3cb98afb3dc8999d5512cb03f94" -dependencies = [ - "diesel_derives 2.2.2", -] - -[[package]] -name = "diesel-async" -version = "0.5.0" -source = "git+https://github.com/insipx/diesel_async?branch=insipx/wasm-async#c255cddfecec3597fb102cfa85494f6e23cb6b9b" -dependencies = [ - "async-trait", - "diesel 2.2.2", - "futures-util", - "scoped-futures", -] - -[[package]] -name = "diesel-wasm-sqlite" -version = "0.1.1" -dependencies = [ - "async-trait", - "bitflags 2.6.0", - "console_error_panic_hook", - "diesel 2.2.2", - "diesel-async", - "futures", - "getrandom", - "log", - "rand", - "tokio", - "wasm-bindgen", - "wasm-bindgen-futures", - "wasm-bindgen-test", - "web-sys", -] - [[package]] name = "diesel_derives" version = "2.2.0" source = "git+https://github.com/xmtp/diesel?branch=insipx/wasm-backend#a3fa32d4291bbae566cf544ca63a1aa2543da943" dependencies = [ - "diesel_table_macro_syntax 0.2.0 (git+https://github.com/xmtp/diesel?branch=insipx/wasm-backend)", - "dsl_auto_type 0.1.0", - "proc-macro2", - "quote", - "syn 2.0.71", -] - -[[package]] -name = "diesel_derives" -version = "2.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d6ff2be1e7312c858b2ef974f5c7089833ae57b5311b334b30923af58e5718d8" -dependencies = [ - "diesel_table_macro_syntax 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", - "dsl_auto_type 0.1.2", + "diesel_table_macro_syntax", + "dsl_auto_type", "proc-macro2", "quote", "syn 2.0.71", @@ -1142,20 +1089,11 @@ name = "diesel_migrations" version = "2.2.0" source = "git+https://github.com/xmtp/diesel?branch=insipx/wasm-backend#a3fa32d4291bbae566cf544ca63a1aa2543da943" dependencies = [ - "diesel 2.2.0", + "diesel", "migrations_internals", "migrations_macros", ] -[[package]] -name = "diesel_table_macro_syntax" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "209c735641a413bc68c4923a9d6ad4bcb3ca306b794edaa7eb0b3228a99ffb25" -dependencies = [ - "syn 2.0.71", -] - [[package]] name = "diesel_table_macro_syntax" version = "0.2.0" @@ -1252,20 +1190,6 @@ dependencies = [ "syn 2.0.71", ] -[[package]] -name = "dsl_auto_type" -version = "0.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c5d9abe6314103864cc2d8901b7ae224e0ab1a103a0a416661b4097b0779b607" -dependencies = [ - "darling", - "either", - "heck 0.5.0", - "proc-macro2", - "quote", - "syn 2.0.71", -] - [[package]] name = "dunce" version = "1.0.4" @@ -4735,16 +4659,6 @@ dependencies = [ "parking_lot 0.12.3", ] -[[package]] -name = "scoped-futures" -version = "0.1.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b1473e24c637950c9bd38763220bea91ec3e095a89f672bbd7a10d03e77ba467" -dependencies = [ - "cfg-if", - "pin-utils", -] - [[package]] name = "scoped-tls" version = "1.0.1" @@ -6653,7 +6567,7 @@ dependencies = [ "chrono", "criterion", "ctor", - "diesel 2.2.0", + "diesel", "diesel_migrations", "ed25519-dalek", "ethers", diff --git a/Cargo.toml b/Cargo.toml index 78f19303c..892323ebf 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -9,7 +9,7 @@ members = [ "xmtp_user_preferences", "xmtp_v2", "xmtp_mls", - "xmtp_id", "diesel-wasm-sqlite" + "xmtp_id" ] exclude = [ @@ -17,6 +17,7 @@ exclude = [ "bindings_wasm", "xmtp_api_grpc_gateway", "bindings_node", + "diesel-wasm-sqlite" ] # Make the feature resolver explicit. diff --git a/diesel-wasm-sqlite/.vscode/settings.json b/diesel-wasm-sqlite/.vscode/settings.json new file mode 100644 index 000000000..cb6099b62 --- /dev/null +++ b/diesel-wasm-sqlite/.vscode/settings.json @@ -0,0 +1,32 @@ +{ + "rust-analyzer": { + "cargo": { + "sysroot": "discover", + "allTargets": false, + "target": "wasm32-unknown-unknown" + }, + "procMacro": { + "enable": true, + "attributes.enable": true, + "ignored": { + "async-trait": ["async_trait"], + "napi-derive": ["napi"], + "async-recursion": ["async_recursion"], + "ctor": ["ctor"], + "tokio": ["test"] + } + } + }, + "[toml]": { + "editor.defaultFormatter": "tamasfe.even-better-toml" + }, + "[typescript]": { + "editor.defaultFormatter": "esbenp.prettier-vscode" + }, + "[javascript]": { + "editor.defaultFormatter": "esbenp.prettier-vscode" + }, + "[json]": { + "editor.defaultFormatter": "esbenp.prettier-vscode" + } +} diff --git a/diesel-wasm-sqlite/Cargo.lock b/diesel-wasm-sqlite/Cargo.lock new file mode 100644 index 000000000..171c620d6 --- /dev/null +++ b/diesel-wasm-sqlite/Cargo.lock @@ -0,0 +1,697 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 3 + +[[package]] +name = "addr2line" +version = "0.22.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6e4503c46a5c0c7844e948c9a4d6acd9f50cccb4de1c48eb9e291ea17470c678" +dependencies = [ + "gimli", +] + +[[package]] +name = "adler" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe" + +[[package]] +name = "async-trait" +version = "0.1.81" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6e0c28dcc82d7c8ead5cb13beb15405b57b8546e93215673ff8ca0349a028107" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "autocfg" +version = "1.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0c4b4d0bd25bd0b74681c0ad21497610ce1b7c91b1022cd21c80c6fbdd9476b0" + +[[package]] +name = "backtrace" +version = "0.3.73" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5cc23269a4f8976d0a4d2e7109211a419fe30e8d88d677cd60b6bc79c5732e0a" +dependencies = [ + "addr2line", + "cc", + "cfg-if", + "libc", + "miniz_oxide", + "object", + "rustc-demangle", +] + +[[package]] +name = "bitflags" +version = "2.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b048fb63fd8b5923fc5aa7b340d8e156aec7ec02f0c78fa8a6ddc2613f6f71de" + +[[package]] +name = "bumpalo" +version = "3.16.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "79296716171880943b8470b5f8d03aa55eb2e645a4874bdbb28adb49162e012c" + +[[package]] +name = "byteorder" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b" + +[[package]] +name = "bytes" +version = "1.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8318a53db07bb3f8dca91a600466bdb3f2eaadeedfdbcf02e1accbad9271ba50" + +[[package]] +name = "cc" +version = "1.1.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "26a5c3fd7bfa1ce3897a3a3501d362b2d87b7f2583ebcb4a949ec25911025cbc" + +[[package]] +name = "cfg-if" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" + +[[package]] +name = "console_error_panic_hook" +version = "0.1.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a06aeb73f470f66dcdbf7223caeebb85984942f22f1adb2a088cf9668146bbbc" +dependencies = [ + "cfg-if", + "wasm-bindgen", +] + +[[package]] +name = "darling" +version = "0.20.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6f63b86c8a8826a49b8c21f08a2d07338eec8d900540f8630dc76284be802989" +dependencies = [ + "darling_core", + "darling_macro", +] + +[[package]] +name = "darling_core" +version = "0.20.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "95133861a8032aaea082871032f5815eb9e98cef03fa916ab4500513994df9e5" +dependencies = [ + "fnv", + "ident_case", + "proc-macro2", + "quote", + "strsim", + "syn", +] + +[[package]] +name = "darling_macro" +version = "0.20.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d336a2a514f6ccccaa3e09b02d41d35330c07ddf03a62165fcec10bb561c7806" +dependencies = [ + "darling_core", + "quote", + "syn", +] + +[[package]] +name = "diesel" +version = "2.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bf97ee7261bb708fa3402fa9c17a54b70e90e3cb98afb3dc8999d5512cb03f94" +dependencies = [ + "diesel_derives", +] + +[[package]] +name = "diesel-async" +version = "0.5.0" +source = "git+https://github.com/insipx/diesel_async?branch=insipx/wasm-async#c255cddfecec3597fb102cfa85494f6e23cb6b9b" +dependencies = [ + "async-trait", + "diesel", + "futures-util", + "scoped-futures", +] + +[[package]] +name = "diesel-wasm-sqlite" +version = "0.1.1" +dependencies = [ + "async-trait", + "bitflags", + "console_error_panic_hook", + "diesel", + "diesel-async", + "futures", + "getrandom", + "log", + "rand", + "serde", + "serde-wasm-bindgen", + "tokio", + "wasm-bindgen", + "wasm-bindgen-futures", + "wasm-bindgen-test", + "web-sys", +] + +[[package]] +name = "diesel_derives" +version = "2.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d6ff2be1e7312c858b2ef974f5c7089833ae57b5311b334b30923af58e5718d8" +dependencies = [ + "diesel_table_macro_syntax", + "dsl_auto_type", + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "diesel_table_macro_syntax" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "209c735641a413bc68c4923a9d6ad4bcb3ca306b794edaa7eb0b3228a99ffb25" +dependencies = [ + "syn", +] + +[[package]] +name = "dsl_auto_type" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c5d9abe6314103864cc2d8901b7ae224e0ab1a103a0a416661b4097b0779b607" +dependencies = [ + "darling", + "either", + "heck", + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "either" +version = "1.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "60b1af1c220855b6ceac025d3f6ecdd2b7c4894bfe9cd9bda4fbb4bc7c0d4cf0" + +[[package]] +name = "fnv" +version = "1.0.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" + +[[package]] +name = "futures" +version = "0.3.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "645c6916888f6cb6350d2550b80fb63e734897a8498abe35cfb732b6487804b0" +dependencies = [ + "futures-channel", + "futures-core", + "futures-executor", + "futures-io", + "futures-sink", + "futures-task", + "futures-util", +] + +[[package]] +name = "futures-channel" +version = "0.3.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "eac8f7d7865dcb88bd4373ab671c8cf4508703796caa2b1985a9ca867b3fcb78" +dependencies = [ + "futures-core", + "futures-sink", +] + +[[package]] +name = "futures-core" +version = "0.3.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dfc6580bb841c5a68e9ef15c77ccc837b40a7504914d52e47b8b0e9bbda25a1d" + +[[package]] +name = "futures-executor" +version = "0.3.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a576fc72ae164fca6b9db127eaa9a9dda0d61316034f33a0a0d4eda41f02b01d" +dependencies = [ + "futures-core", + "futures-task", + "futures-util", +] + +[[package]] +name = "futures-io" +version = "0.3.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a44623e20b9681a318efdd71c299b6b222ed6f231972bfe2f224ebad6311f0c1" + +[[package]] +name = "futures-macro" +version = "0.3.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "87750cf4b7a4c0625b1529e4c543c2182106e4dedc60a2a6455e00d212c489ac" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "futures-sink" +version = "0.3.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9fb8e00e87438d937621c1c6269e53f536c14d3fbd6a042bb24879e57d474fb5" + +[[package]] +name = "futures-task" +version = "0.3.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "38d84fa142264698cdce1a9f9172cf383a0c82de1bddcf3092901442c4097004" + +[[package]] +name = "futures-util" +version = "0.3.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3d6401deb83407ab3da39eba7e33987a73c3df0c82b4bb5813ee871c19c41d48" +dependencies = [ + "futures-channel", + "futures-core", + "futures-io", + "futures-macro", + "futures-sink", + "futures-task", + "memchr", + "pin-project-lite", + "pin-utils", + "slab", +] + +[[package]] +name = "getrandom" +version = "0.2.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c4567c8db10ae91089c99af84c68c38da3ec2f087c3f82960bcdbf3656b6f4d7" +dependencies = [ + "cfg-if", + "js-sys", + "libc", + "wasi", + "wasm-bindgen", +] + +[[package]] +name = "gimli" +version = "0.29.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "40ecd4077b5ae9fd2e9e169b102c6c330d0605168eb0e8bf79952b256dbefffd" + +[[package]] +name = "heck" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea" + +[[package]] +name = "ident_case" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b9e0384b61958566e926dc50660321d12159025e767c18e043daf26b70104c39" + +[[package]] +name = "js-sys" +version = "0.3.69" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "29c15563dc2726973df627357ce0c9ddddbea194836909d655df6a75d2cf296d" +dependencies = [ + "wasm-bindgen", +] + +[[package]] +name = "libc" +version = "0.2.155" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "97b3888a4aecf77e811145cadf6eef5901f4782c53886191b2f693f24761847c" + +[[package]] +name = "log" +version = "0.4.22" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a7a70ba024b9dc04c27ea2f0c0548feb474ec5c54bba33a7f72f873a39d07b24" + +[[package]] +name = "memchr" +version = "2.7.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "78ca9ab1a0babb1e7d5695e3530886289c18cf2f87ec19a575a0abdce112e3a3" + +[[package]] +name = "miniz_oxide" +version = "0.7.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b8a240ddb74feaf34a79a7add65a741f3167852fba007066dcac1ca548d89c08" +dependencies = [ + "adler", +] + +[[package]] +name = "object" +version = "0.36.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3f203fa8daa7bb185f760ae12bd8e097f63d17041dcdcaf675ac54cdf863170e" +dependencies = [ + "memchr", +] + +[[package]] +name = "once_cell" +version = "1.19.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3fdb12b2476b595f9358c5161aa467c2438859caa136dec86c26fdd2efe17b92" + +[[package]] +name = "pin-project-lite" +version = "0.2.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bda66fc9667c18cb2758a2ac84d1167245054bcf85d5d1aaa6923f45801bdd02" + +[[package]] +name = "pin-utils" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" + +[[package]] +name = "ppv-lite86" +version = "0.2.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "77957b295656769bb8ad2b6a6b09d897d94f05c41b069aede1fcdaa675eaea04" +dependencies = [ + "zerocopy", +] + +[[package]] +name = "proc-macro2" +version = "1.0.86" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5e719e8df665df0d1c8fbfd238015744736151d4445ec0836b8e628aae103b77" +dependencies = [ + "unicode-ident", +] + +[[package]] +name = "quote" +version = "1.0.36" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0fa76aaf39101c457836aec0ce2316dbdc3ab723cdda1c6bd4e6ad4208acaca7" +dependencies = [ + "proc-macro2", +] + +[[package]] +name = "rand" +version = "0.8.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404" +dependencies = [ + "libc", + "rand_chacha", + "rand_core", +] + +[[package]] +name = "rand_chacha" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88" +dependencies = [ + "ppv-lite86", + "rand_core", +] + +[[package]] +name = "rand_core" +version = "0.6.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c" +dependencies = [ + "getrandom", +] + +[[package]] +name = "rustc-demangle" +version = "0.1.24" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "719b953e2095829ee67db738b3bfa9fa368c94900df327b3f07fe6e794d2fe1f" + +[[package]] +name = "scoped-futures" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b1473e24c637950c9bd38763220bea91ec3e095a89f672bbd7a10d03e77ba467" +dependencies = [ + "cfg-if", + "pin-utils", +] + +[[package]] +name = "scoped-tls" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e1cf6437eb19a8f4a6cc0f7dca544973b0b78843adbfeb3683d1a94a0024a294" + +[[package]] +name = "serde" +version = "1.0.204" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bc76f558e0cbb2a839d37354c575f1dc3fdc6546b5be373ba43d95f231bf7c12" +dependencies = [ + "serde_derive", +] + +[[package]] +name = "serde-wasm-bindgen" +version = "0.6.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8302e169f0eddcc139c70f139d19d6467353af16f9fce27e8c30158036a1e16b" +dependencies = [ + "js-sys", + "serde", + "wasm-bindgen", +] + +[[package]] +name = "serde_derive" +version = "1.0.204" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e0cd7e117be63d3c3678776753929474f3b04a43a080c744d6b0ae2a8c28e222" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "slab" +version = "0.4.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8f92a496fb766b417c996b9c5e57daf2f7ad3b0bebe1ccfca4856390e3d3bb67" +dependencies = [ + "autocfg", +] + +[[package]] +name = "strsim" +version = "0.11.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7da8b5736845d9f2fcb837ea5d9e2628564b3b043a70948a3f0b778838c5fb4f" + +[[package]] +name = "syn" +version = "2.0.72" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dc4b9b9bf2add8093d3f2c0204471e951b2285580335de42f9d2534f3ae7a8af" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + +[[package]] +name = "tokio" +version = "1.39.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "daa4fb1bc778bd6f04cbfc4bb2d06a7396a8f299dc33ea1900cedaa316f467b1" +dependencies = [ + "backtrace", + "bytes", + "pin-project-lite", + "tokio-macros", +] + +[[package]] +name = "tokio-macros" +version = "2.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "693d596312e88961bc67d7f1f97af8a70227d9f90c31bba5806eec004978d752" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "unicode-ident" +version = "1.0.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b" + +[[package]] +name = "wasi" +version = "0.11.0+wasi-snapshot-preview1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" + +[[package]] +name = "wasm-bindgen" +version = "0.2.92" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4be2531df63900aeb2bca0daaaddec08491ee64ceecbee5076636a3b026795a8" +dependencies = [ + "cfg-if", + "wasm-bindgen-macro", +] + +[[package]] +name = "wasm-bindgen-backend" +version = "0.2.92" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "614d787b966d3989fa7bb98a654e369c762374fd3213d212cfc0251257e747da" +dependencies = [ + "bumpalo", + "log", + "once_cell", + "proc-macro2", + "quote", + "syn", + "wasm-bindgen-shared", +] + +[[package]] +name = "wasm-bindgen-futures" +version = "0.4.42" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "76bc14366121efc8dbb487ab05bcc9d346b3b5ec0eaa76e46594cabbe51762c0" +dependencies = [ + "cfg-if", + "js-sys", + "wasm-bindgen", + "web-sys", +] + +[[package]] +name = "wasm-bindgen-macro" +version = "0.2.92" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a1f8823de937b71b9460c0c34e25f3da88250760bec0ebac694b49997550d726" +dependencies = [ + "quote", + "wasm-bindgen-macro-support", +] + +[[package]] +name = "wasm-bindgen-macro-support" +version = "0.2.92" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e94f17b526d0a461a191c78ea52bbce64071ed5c04c9ffe424dcb38f74171bb7" +dependencies = [ + "proc-macro2", + "quote", + "syn", + "wasm-bindgen-backend", + "wasm-bindgen-shared", +] + +[[package]] +name = "wasm-bindgen-shared" +version = "0.2.92" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "af190c94f2773fdb3729c55b007a722abb5384da03bc0986df4c289bf5567e96" + +[[package]] +name = "wasm-bindgen-test" +version = "0.3.42" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d9bf62a58e0780af3e852044583deee40983e5886da43a271dd772379987667b" +dependencies = [ + "console_error_panic_hook", + "js-sys", + "scoped-tls", + "wasm-bindgen", + "wasm-bindgen-futures", + "wasm-bindgen-test-macro", +] + +[[package]] +name = "wasm-bindgen-test-macro" +version = "0.3.42" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b7f89739351a2e03cb94beb799d47fb2cac01759b40ec441f7de39b00cbf7ef0" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "web-sys" +version = "0.3.69" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "77afa9a11836342370f4817622a2f0f418b134426d91a82dfb48f532d2ec13ef" +dependencies = [ + "js-sys", + "wasm-bindgen", +] + +[[package]] +name = "zerocopy" +version = "0.7.35" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1b9b4fd18abc82b8136838da5d50bae7bdea537c574d8dc1a34ed098d6c166f0" +dependencies = [ + "byteorder", + "zerocopy-derive", +] + +[[package]] +name = "zerocopy-derive" +version = "0.7.35" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fa4f8080344d4671fb4e831a13ad1e68092748387dfc4f55e356242fae12ce3e" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] diff --git a/diesel-wasm-sqlite/Cargo.toml b/diesel-wasm-sqlite/Cargo.toml index ae566a745..555aee523 100644 --- a/diesel-wasm-sqlite/Cargo.toml +++ b/diesel-wasm-sqlite/Cargo.toml @@ -19,6 +19,8 @@ tokio = { version = "1.38", default-features = false, features = ["rt", "macros" futures = "0.3" async-trait = "0.1" bitflags = "2.6" +serde = { version = "1.0", features = ["derive"] } +serde-wasm-bindgen = "0.6" [dev-dependencies] rand = "0.8" @@ -33,3 +35,6 @@ crate-type = ["cdylib", "rlib"] [features] default = ["console_error_panic_hook"] +[build] +target = "wasm32-unknown-unknown" + diff --git a/diesel-wasm-sqlite/README.md b/diesel-wasm-sqlite/README.md index 608cdda29..77b146779 100644 --- a/diesel-wasm-sqlite/README.md +++ b/diesel-wasm-sqlite/README.md @@ -17,3 +17,9 @@ wasm-pack test --chrome --headless - [ ] wa-sqlite should be included in `pkg` build w/o manual copy (wasm-pack issue?) - [ ] OPFS + +# Notes + +- rust-analyzer doesn't like crates with different targets in the same + workspace. If you want this to work well with your LSP, open + `diesel-wasm-sqlite` as it's own project. diff --git a/diesel-wasm-sqlite/package-lock.json b/diesel-wasm-sqlite/package-lock.json new file mode 100644 index 000000000..e92a88e09 --- /dev/null +++ b/diesel-wasm-sqlite/package-lock.json @@ -0,0 +1,756 @@ +{ + "name": "diesel-wasm-sqlite", + "version": "1.0.0", + "lockfileVersion": 3, + "requires": true, + "packages": { + "": { + "name": "diesel-wasm-sqlite", + "version": "1.0.0", + "dependencies": { + "@xmtp/wa-sqlite": "^1.0.1" + }, + "devDependencies": { + "@rollup/plugin-node-resolve": "^15.2.3", + "rollup": "^4.19.0", + "rollup-plugin-base64": "^1.0.1", + "rollup-plugin-copy": "^3.5.0" + }, + "engines": { + "node": ">=20" + } + }, + "node_modules/@nodelib/fs.scandir": { + "version": "2.1.5", + "dev": true, + "license": "MIT", + "dependencies": { + "@nodelib/fs.stat": "2.0.5", + "run-parallel": "^1.1.9" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/@nodelib/fs.stat": { + "version": "2.0.5", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 8" + } + }, + "node_modules/@nodelib/fs.walk": { + "version": "1.2.8", + "dev": true, + "license": "MIT", + "dependencies": { + "@nodelib/fs.scandir": "2.1.5", + "fastq": "^1.6.0" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/@rollup/plugin-node-resolve": { + "version": "15.2.3", + "dev": true, + "license": "MIT", + "dependencies": { + "@rollup/pluginutils": "^5.0.1", + "@types/resolve": "1.20.2", + "deepmerge": "^4.2.2", + "is-builtin-module": "^3.2.1", + "is-module": "^1.0.0", + "resolve": "^1.22.1" + }, + "engines": { + "node": ">=14.0.0" + }, + "peerDependencies": { + "rollup": "^2.78.0||^3.0.0||^4.0.0" + }, + "peerDependenciesMeta": { + "rollup": { + "optional": true + } + } + }, + "node_modules/@rollup/pluginutils": { + "version": "5.1.0", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/estree": "^1.0.0", + "estree-walker": "^2.0.2", + "picomatch": "^2.3.1" + }, + "engines": { + "node": ">=14.0.0" + }, + "peerDependencies": { + "rollup": "^1.20.0||^2.0.0||^3.0.0||^4.0.0" + }, + "peerDependenciesMeta": { + "rollup": { + "optional": true + } + } + }, + "node_modules/@rollup/rollup-darwin-arm64": { + "version": "4.19.0", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ] + }, + "node_modules/@types/estree": { + "version": "1.0.5", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/fs-extra": { + "version": "8.1.5", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/@types/glob": { + "version": "7.2.0", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/minimatch": "*", + "@types/node": "*" + } + }, + "node_modules/@types/minimatch": { + "version": "5.1.2", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/node": { + "version": "20.14.11", + "dev": true, + "license": "MIT", + "dependencies": { + "undici-types": "~5.26.4" + } + }, + "node_modules/@types/resolve": { + "version": "1.20.2", + "dev": true, + "license": "MIT" + }, + "node_modules/@xmtp/wa-sqlite": { + "version": "1.0.1" + }, + "node_modules/array-union": { + "version": "2.1.0", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/balanced-match": { + "version": "1.0.2", + "dev": true, + "license": "MIT" + }, + "node_modules/brace-expansion": { + "version": "1.1.11", + "dev": true, + "license": "MIT", + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/braces": { + "version": "3.0.3", + "dev": true, + "license": "MIT", + "dependencies": { + "fill-range": "^7.1.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/builtin-modules": { + "version": "3.3.0", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/colorette": { + "version": "1.4.0", + "dev": true, + "license": "MIT" + }, + "node_modules/concat-map": { + "version": "0.0.1", + "dev": true, + "license": "MIT" + }, + "node_modules/deepmerge": { + "version": "4.3.1", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/dir-glob": { + "version": "3.0.1", + "dev": true, + "license": "MIT", + "dependencies": { + "path-type": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/estree-walker": { + "version": "2.0.2", + "dev": true, + "license": "MIT" + }, + "node_modules/fast-glob": { + "version": "3.3.2", + "dev": true, + "license": "MIT", + "dependencies": { + "@nodelib/fs.stat": "^2.0.2", + "@nodelib/fs.walk": "^1.2.3", + "glob-parent": "^5.1.2", + "merge2": "^1.3.0", + "micromatch": "^4.0.4" + }, + "engines": { + "node": ">=8.6.0" + } + }, + "node_modules/fastq": { + "version": "1.17.1", + "dev": true, + "license": "ISC", + "dependencies": { + "reusify": "^1.0.4" + } + }, + "node_modules/fill-range": { + "version": "7.1.1", + "dev": true, + "license": "MIT", + "dependencies": { + "to-regex-range": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/fs-extra": { + "version": "8.1.0", + "dev": true, + "license": "MIT", + "dependencies": { + "graceful-fs": "^4.2.0", + "jsonfile": "^4.0.0", + "universalify": "^0.1.0" + }, + "engines": { + "node": ">=6 <7 || >=8" + } + }, + "node_modules/fs.realpath": { + "version": "1.0.0", + "dev": true, + "license": "ISC" + }, + "node_modules/fsevents": { + "version": "2.3.3", + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": "^8.16.0 || ^10.6.0 || >=11.0.0" + } + }, + "node_modules/function-bind": { + "version": "1.1.2", + "dev": true, + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/glob-parent": { + "version": "5.1.2", + "dev": true, + "license": "ISC", + "dependencies": { + "is-glob": "^4.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/globby": { + "version": "10.0.1", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/glob": "^7.1.1", + "array-union": "^2.1.0", + "dir-glob": "^3.0.1", + "fast-glob": "^3.0.3", + "glob": "^7.1.3", + "ignore": "^5.1.1", + "merge2": "^1.2.3", + "slash": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/globby/node_modules/glob": { + "version": "7.2.3", + "dev": true, + "license": "ISC", + "dependencies": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.1.1", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + }, + "engines": { + "node": "*" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/graceful-fs": { + "version": "4.2.11", + "dev": true, + "license": "ISC" + }, + "node_modules/hasown": { + "version": "2.0.2", + "dev": true, + "license": "MIT", + "dependencies": { + "function-bind": "^1.1.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/ignore": { + "version": "5.3.1", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 4" + } + }, + "node_modules/inflight": { + "version": "1.0.6", + "dev": true, + "license": "ISC", + "dependencies": { + "once": "^1.3.0", + "wrappy": "1" + } + }, + "node_modules/inherits": { + "version": "2.0.4", + "dev": true, + "license": "ISC" + }, + "node_modules/is-builtin-module": { + "version": "3.2.1", + "dev": true, + "license": "MIT", + "dependencies": { + "builtin-modules": "^3.3.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/is-core-module": { + "version": "2.15.0", + "dev": true, + "license": "MIT", + "dependencies": { + "hasown": "^2.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-extglob": { + "version": "2.1.1", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-glob": { + "version": "4.0.3", + "dev": true, + "license": "MIT", + "dependencies": { + "is-extglob": "^2.1.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-module": { + "version": "1.0.0", + "dev": true, + "license": "MIT" + }, + "node_modules/is-number": { + "version": "7.0.0", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.12.0" + } + }, + "node_modules/is-plain-object": { + "version": "3.0.1", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/jsonfile": { + "version": "4.0.0", + "dev": true, + "license": "MIT", + "optionalDependencies": { + "graceful-fs": "^4.1.6" + } + }, + "node_modules/merge2": { + "version": "1.4.1", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 8" + } + }, + "node_modules/micromatch": { + "version": "4.0.7", + "dev": true, + "license": "MIT", + "dependencies": { + "braces": "^3.0.3", + "picomatch": "^2.3.1" + }, + "engines": { + "node": ">=8.6" + } + }, + "node_modules/minimatch": { + "version": "3.1.2", + "dev": true, + "license": "ISC", + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "node_modules/once": { + "version": "1.4.0", + "dev": true, + "license": "ISC", + "dependencies": { + "wrappy": "1" + } + }, + "node_modules/path-is-absolute": { + "version": "1.0.1", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/path-parse": { + "version": "1.0.7", + "dev": true, + "license": "MIT" + }, + "node_modules/path-type": { + "version": "4.0.0", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/picomatch": { + "version": "2.3.1", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8.6" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, + "node_modules/queue-microtask": { + "version": "1.2.3", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "MIT" + }, + "node_modules/resolve": { + "version": "1.22.8", + "dev": true, + "license": "MIT", + "dependencies": { + "is-core-module": "^2.13.0", + "path-parse": "^1.0.7", + "supports-preserve-symlinks-flag": "^1.0.0" + }, + "bin": { + "resolve": "bin/resolve" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/reusify": { + "version": "1.0.4", + "dev": true, + "license": "MIT", + "engines": { + "iojs": ">=1.0.0", + "node": ">=0.10.0" + } + }, + "node_modules/rollup": { + "version": "4.19.0", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/estree": "1.0.5" + }, + "bin": { + "rollup": "dist/bin/rollup" + }, + "engines": { + "node": ">=18.0.0", + "npm": ">=8.0.0" + }, + "optionalDependencies": { + "@rollup/rollup-android-arm-eabi": "4.19.0", + "@rollup/rollup-android-arm64": "4.19.0", + "@rollup/rollup-darwin-arm64": "4.19.0", + "@rollup/rollup-darwin-x64": "4.19.0", + "@rollup/rollup-linux-arm-gnueabihf": "4.19.0", + "@rollup/rollup-linux-arm-musleabihf": "4.19.0", + "@rollup/rollup-linux-arm64-gnu": "4.19.0", + "@rollup/rollup-linux-arm64-musl": "4.19.0", + "@rollup/rollup-linux-powerpc64le-gnu": "4.19.0", + "@rollup/rollup-linux-riscv64-gnu": "4.19.0", + "@rollup/rollup-linux-s390x-gnu": "4.19.0", + "@rollup/rollup-linux-x64-gnu": "4.19.0", + "@rollup/rollup-linux-x64-musl": "4.19.0", + "@rollup/rollup-win32-arm64-msvc": "4.19.0", + "@rollup/rollup-win32-ia32-msvc": "4.19.0", + "@rollup/rollup-win32-x64-msvc": "4.19.0", + "fsevents": "~2.3.2" + } + }, + "node_modules/rollup-plugin-base64": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/rollup-plugin-base64/-/rollup-plugin-base64-1.0.1.tgz", + "integrity": "sha512-IbdX8fjuXO/Op3hYmRPjVo0VwcSenwsQDaDTFdoe+70B5ZGoLMtr96L2yhHXCfxv7HwZVvxZqLsuWj6VwzRt3g==", + "dev": true, + "dependencies": { + "@rollup/pluginutils": "^3.1.0" + } + }, + "node_modules/rollup-plugin-base64/node_modules/@rollup/pluginutils": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/@rollup/pluginutils/-/pluginutils-3.1.0.tgz", + "integrity": "sha512-GksZ6pr6TpIjHm8h9lSQ8pi8BE9VeubNT0OMJ3B5uZJ8pz73NPiqOtCog/x2/QzM1ENChPKxMDhiQuRHsqc+lg==", + "dev": true, + "dependencies": { + "@types/estree": "0.0.39", + "estree-walker": "^1.0.1", + "picomatch": "^2.2.2" + }, + "engines": { + "node": ">= 8.0.0" + }, + "peerDependencies": { + "rollup": "^1.20.0||^2.0.0" + } + }, + "node_modules/rollup-plugin-base64/node_modules/@types/estree": { + "version": "0.0.39", + "resolved": "https://registry.npmjs.org/@types/estree/-/estree-0.0.39.tgz", + "integrity": "sha512-EYNwp3bU+98cpU4lAWYYL7Zz+2gryWH1qbdDTidVd6hkiR6weksdbMadyXKXNPEkQFhXM+hVO9ZygomHXp+AIw==", + "dev": true + }, + "node_modules/rollup-plugin-base64/node_modules/estree-walker": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-1.0.1.tgz", + "integrity": "sha512-1fMXF3YP4pZZVozF8j/ZLfvnR8NSIljt56UhbZ5PeeDmmGHpgpdwQt7ITlGvYaQukCvuBRMLEiKiYC+oeIg4cg==", + "dev": true + }, + "node_modules/rollup-plugin-base64/node_modules/rollup": { + "version": "2.79.1", + "resolved": "https://registry.npmjs.org/rollup/-/rollup-2.79.1.tgz", + "integrity": "sha512-uKxbd0IhMZOhjAiD5oAFp7BqvkA4Dv47qpOCtaNvng4HBwdbWtdOh8f5nZNuk2rp51PMGk3bzfWu5oayNEuYnw==", + "dev": true, + "peer": true, + "bin": { + "rollup": "dist/bin/rollup" + }, + "engines": { + "node": ">=10.0.0" + }, + "optionalDependencies": { + "fsevents": "~2.3.2" + } + }, + "node_modules/rollup-plugin-copy": { + "version": "3.5.0", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/fs-extra": "^8.0.1", + "colorette": "^1.1.0", + "fs-extra": "^8.1.0", + "globby": "10.0.1", + "is-plain-object": "^3.0.0" + }, + "engines": { + "node": ">=8.3" + } + }, + "node_modules/run-parallel": { + "version": "1.2.0", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "MIT", + "dependencies": { + "queue-microtask": "^1.2.2" + } + }, + "node_modules/slash": { + "version": "3.0.0", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/supports-preserve-symlinks-flag": { + "version": "1.0.0", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/to-regex-range": { + "version": "5.0.1", + "dev": true, + "license": "MIT", + "dependencies": { + "is-number": "^7.0.0" + }, + "engines": { + "node": ">=8.0" + } + }, + "node_modules/undici-types": { + "version": "5.26.5", + "dev": true, + "license": "MIT" + }, + "node_modules/universalify": { + "version": "0.1.2", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 4.0.0" + } + }, + "node_modules/wrappy": { + "version": "1.0.2", + "dev": true, + "license": "ISC" + } + } +} diff --git a/diesel-wasm-sqlite/package.js b/diesel-wasm-sqlite/package.js index 225640279..a3a89aaba 100644 --- a/diesel-wasm-sqlite/package.js +++ b/diesel-wasm-sqlite/package.js @@ -63,6 +63,99 @@ export class SQLite { this.sqlite3.result_null(context); } + bind(stmt, i, value) { + try { + return this.sqlite3.bind(stmt, i, value); + } catch (error) { + console.log("bind err"); + throw error; + } + } + + bind_blob(stmt, i, value) { + try { + return this.sqlite3.bind_blob(stmt, i, value); + } catch (error) { + console.log("bind blob error"); + throw error; + } + } + + bind_collection(stmt, bindings) { + try { + return this.sqlite3.bind_collection(stmt, bindings); + } catch (error) { + console.log("bind collection error"); + throw error; + } + } + + bind_double(stmt, i, value) { + try { + return this.sqlite3.bind_double(stmt, i, value); + } catch (error) { + console.log("bind double error"); + throw error; + } + } + + bind_int(stmt, i, value) { + try { + return this.sqlite3.bind_int(stmt, i, value); + } catch (error) { + console.log("bind int error"); + throw error; + } + } + + bind_int64(stmt, i, value) { + try { + return this.sqlite3.bind_int64(stmt, i, value); + } catch (error) { + console.log("bind int644 error"); + throw error; + } + } + + bind_null(stmt, i) { + try { + return this.sqlite3.bind_null(stmt, i); + } catch (error) { + console.log("bind null error"); + throw error; + } + } + + bind_parameter_count(stmt) -> i32 { + return this.sqlite3.bind_parameter_count(stmt); + } + + bind_parameter_name(stmt, i) -> string { + return this.sqlite3.bind_paramater_name(stmt, it); + } + + bind_text(stmt, i, value) { + try { + this.sqlite3.bind_text(stmt, i, value); + } catch (error) { + console.log("bind text error"); + throw error; + } + } + + async reset(stmt) { + try { + return await this.sqlite3.reset(stmt); + } catch (error) { + console.log("reset err"); + throw error; + } + } + + value(pValue) { + this.sqlite3.value(pValue); + } + async open_v2(database_url, iflags) { try { console.log("Opening database!", database_url); @@ -84,10 +177,27 @@ export class SQLite { } } + finalize(stmt) { + try { + return this.sqlite3.finalize(stmt); + } catch (error) { + console.log("stmt error"); + } + } + changes(db) { return this.sqlite3.changes(db); } + async prepare(database, sql, options) { + try { + await this.sqlite3.statements(database, sql, options); + } catch (error) { + console.log("sqlite prepare error"); + throw error; + } + } + batch_execute(database, query) { try { sqlite3.exec(database, query); diff --git a/diesel-wasm-sqlite/src/backend.rs b/diesel-wasm-sqlite/src/backend.rs index 9e251eff6..d3e5465a7 100644 --- a/diesel-wasm-sqlite/src/backend.rs +++ b/diesel-wasm-sqlite/src/backend.rs @@ -38,9 +38,9 @@ pub enum SqliteType { impl Backend for WasmSqlite { type QueryBuilder = SqliteQueryBuilder; - type RawValue<'a> = (); - // type RawValue<'a> = SqliteValue<'a, 'a, 'a>; - type BindCollector<'a> = SqliteBindCollector<'a>; + // type RawValue<'a> = (); + type RawValue<'a> = SqliteValue<'a, 'a, 'a>; + type BindCollector<'a> = SqliteBindCollector; } impl TypeMetadata for WasmSqlite { diff --git a/diesel-wasm-sqlite/src/connection/bind_collector.rs b/diesel-wasm-sqlite/src/connection/bind_collector.rs index 3258aef9e..7f9322407 100644 --- a/diesel-wasm-sqlite/src/connection/bind_collector.rs +++ b/diesel-wasm-sqlite/src/connection/bind_collector.rs @@ -1,15 +1,20 @@ use crate::{SqliteType, WasmSqlite}; -use diesel::query_builder::{BindCollector, MoveableBindCollector}; -use diesel::result::QueryResult; -use diesel::serialize::{IsNull, Output}; -use diesel::sql_types::HasSqlType; +use diesel::{ + query_builder::{BindCollector, MoveableBindCollector}, + result::QueryResult, + serialize::{IsNull, Output}, + sql_types::HasSqlType, +}; +use wasm_bindgen::JsValue; + +pub type BindValue = JsValue; #[derive(Debug, Default)] -pub struct SqliteBindCollector<'a> { - pub(crate) binds: Vec<(InternalSqliteBindValue<'a>, SqliteType)>, +pub struct SqliteBindCollector { + pub(crate) binds: Vec<(JsValue, SqliteType)>, } -impl SqliteBindCollector<'_> { +impl SqliteBindCollector { pub(crate) fn new() -> Self { Self { binds: Vec::new() } } @@ -140,7 +145,7 @@ impl InternalSqliteBindValue<'_> { } } -impl<'a> BindCollector<'a, WasmSqlite> for SqliteBindCollector<'a> { +impl<'a> BindCollector<'a, WasmSqlite> for SqliteBindCollector { type Buffer = SqliteBindValue<'a>; fn push_bound_value(&mut self, bind: &'a U, metadata_lookup: &mut ()) -> QueryResult<()> @@ -157,6 +162,7 @@ impl<'a> BindCollector<'a, WasmSqlite> for SqliteBindCollector<'a> { .map_err(diesel::result::Error::SerializationError)?; let bind = to_sql_output.into_inner(); let metadata = WasmSqlite::metadata(metadata_lookup); + self.binds.push(( match is_null { IsNull::No => bind.inner, @@ -221,7 +227,7 @@ pub struct SqliteBindCollectorData { binds: Vec<(OwnedSqliteBindValue, SqliteType)>, } -impl MoveableBindCollector for SqliteBindCollector<'_> { +impl MoveableBindCollector for SqliteBindCollector { type BindData = SqliteBindCollectorData; fn moveable(&self) -> Self::BindData { diff --git a/diesel-wasm-sqlite/src/connection/mod.rs b/diesel-wasm-sqlite/src/connection/mod.rs index 8061d32c2..46097c0e8 100644 --- a/diesel-wasm-sqlite/src/connection/mod.rs +++ b/diesel-wasm-sqlite/src/connection/mod.rs @@ -1,12 +1,12 @@ mod bind_collector; // mod functions; -// mod owned_row; +mod owned_row; mod raw; -// mod row; +mod row; // mod serialized_database; -// mod sqlite_value; +mod sqlite_value; // mod statement_iterator; -// mod stmt; +mod stmt; pub(crate) use self::bind_collector::SqliteBindCollector; pub use self::bind_collector::SqliteBindValue; diff --git a/diesel-wasm-sqlite/src/connection/owned_row.rs b/diesel-wasm-sqlite/src/connection/owned_row.rs index 43e225d0e..f29dd8370 100644 --- a/diesel-wasm-sqlite/src/connection/owned_row.rs +++ b/diesel-wasm-sqlite/src/connection/owned_row.rs @@ -1,9 +1,11 @@ use std::sync::Arc; use super::sqlite_value::{OwnedSqliteValue, SqliteValue}; -use crate::backend::Backend; -use crate::row::{Field, PartialRow, Row, RowIndex, RowSealed}; -use crate::sqlite::Sqlite; +use crate::WasmSqlite; +use diesel::{ + backend::Backend, + row::{Field, PartialRow, Row, RowIndex, RowSealed}, +}; #[derive(Debug)] pub struct OwnedSqliteRow { @@ -25,7 +27,7 @@ impl OwnedSqliteRow { impl RowSealed for OwnedSqliteRow {} -impl<'a> Row<'a, Sqlite> for OwnedSqliteRow { +impl<'a> Row<'a, WasmSqlite> for OwnedSqliteRow { type Field<'field> = OwnedSqliteField<'field> where 'a: 'field, Self: 'field; type InnerPartialRow = Self; @@ -74,7 +76,7 @@ pub struct OwnedSqliteField<'row> { pub(super) col_idx: i32, } -impl<'row> Field<'row, Sqlite> for OwnedSqliteField<'row> { +impl<'row> Field<'row, WasmSqlite> for OwnedSqliteField<'row> { fn field_name(&self) -> Option<&str> { self.row .column_names @@ -86,7 +88,7 @@ impl<'row> Field<'row, Sqlite> for OwnedSqliteField<'row> { self.value().is_none() } - fn value(&self) -> Option<::RawValue<'row>> { + fn value(&self) -> Option<::RawValue<'row>> { SqliteValue::from_owned_row(self.row, self.col_idx) } } diff --git a/diesel-wasm-sqlite/src/connection/raw.rs b/diesel-wasm-sqlite/src/connection/raw.rs index 0ea58dc13..8a1d2beb4 100644 --- a/diesel-wasm-sqlite/src/connection/raw.rs +++ b/diesel-wasm-sqlite/src/connection/raw.rs @@ -1,10 +1,6 @@ #![allow(unsafe_code)] // ffi calls -// use std::ffi::{CString, NulError}; // use std::io::{stderr, Write}; -// use std::os::raw as libc; -// use std::ptr::NonNull; -// use std::{mem, ptr, slice, str}; // use super::functions::{build_sql_function_args, process_sql_function_result}; // use super::serialized_database::SerializedDatabase; @@ -105,101 +101,6 @@ impl RawConnection { Ok(()) } - /* - pub(super) fn register_aggregate_function( - &self, - fn_name: &str, - num_args: usize, - ) -> QueryResult<()> - where - A: SqliteAggregateFunction + 'static + Send + std::panic::UnwindSafe, - Args: FromSqlRow, - Ret: ToSql, - Sqlite: HasSqlType, - { - let fn_name = Self::get_fn_name(fn_name)?; - let flags = Self::get_flags(false); - - let result = unsafe { - ffi::sqlite3_create_function_v2( - self.internal_connection.as_ptr(), - fn_name.as_ptr(), - num_args as _, - flags, - ptr::null_mut(), - None, - Some(run_aggregator_step_function::<_, _, _, _, A>), - Some(run_aggregator_final_function::<_, _, _, _, A>), - None, - ) - }; - - Self::process_sql_function_result(result) - } - - pub(super) fn register_collation_function( - &self, - collation_name: &str, - collation: F, - ) -> QueryResult<()> - where - F: Fn(&str, &str) -> std::cmp::Ordering + std::panic::UnwindSafe + Send + 'static, - { - let callback_fn = Box::into_raw(Box::new(CollationUserPtr { - callback: collation, - collation_name: collation_name.to_owned(), - })); - let collation_name = Self::get_fn_name(collation_name)?; - - let result = unsafe { - ffi::sqlite3_create_collation_v2( - self.internal_connection.as_ptr(), - collation_name.as_ptr(), - ffi::SQLITE_UTF8, - callback_fn as *mut _, - Some(run_collation_function::), - Some(destroy_boxed::>), - ) - }; - - let result = Self::process_sql_function_result(result); - if result.is_err() { - destroy_boxed::>(callback_fn as *mut _); - } - result - } - - pub(super) fn serialize(&mut self) -> SerializedDatabase { - unsafe { - let mut size: ffi::sqlite3_int64 = 0; - let data_ptr = ffi::sqlite3_serialize( - self.internal_connection.as_ptr(), - std::ptr::null(), - &mut size as *mut _, - 0, - ); - SerializedDatabase::new(data_ptr, size as usize) - } - } - - pub(super) fn deserialize(&mut self, data: &[u8]) -> QueryResult<()> { - // the cast for `ffi::SQLITE_DESERIALIZE_READONLY` is required for old libsqlite3-sys versions - #[allow(clippy::unnecessary_cast)] - unsafe { - let result = ffi::sqlite3_deserialize( - self.internal_connection.as_ptr(), - std::ptr::null(), - data.as_ptr() as *mut u8, - data.len() as i64, - data.len() as i64, - ffi::SQLITE_DESERIALIZE_READONLY as u32, - ); - - ensure_sqlite_ok(result, self.internal_connection.as_ptr()) - } - } - */ - fn get_flags(deterministic: bool) -> i32 { let mut flags = SqliteFlags::SQLITE_UTF8; if deterministic { @@ -207,29 +108,16 @@ impl RawConnection { } flags.bits() as i32 } - - /* - fn process_sql_function_result(result: i32) -> Result<(), Error> { - if result == ffi::SQLITE_OK { - Ok(()) - } else { - let error_message = super::error_message(result); - Err(DatabaseError( - DatabaseErrorKind::Unknown, - Box::new(error_message.to_string()), - )) - } - } - */ } -/* + +/* TODO: AsyncDrop impl Drop for RawConnection { fn drop(&mut self) { use std::thread::panicking; let sqlite3 = crate::get_sqlite_unchecked(); - let close_result = sqlite3.close(self.internal_connection); + let close_result = sqlite3.close(self.internal_connection).unwrap(); if close_result != ffi::SQLITE_OK { let error_message = super::error_message(close_result); @@ -273,267 +161,6 @@ impl From for SqliteCallbackError { Self::DieselError(e) } } - -struct CustomFunctionUserPtr { - callback: F, - function_name: String, -} -*/ - -/* -// Need a custom option type here, because the std lib one does not have guarantees about the discriminate values -// See: https://github.com/rust-lang/rfcs/blob/master/text/2195-really-tagged-unions.md#opaque-tags -#[repr(u8)] -enum OptionalAggregator { - // Discriminant is 0 - None, - Some(A), -} - -#[allow(warnings)] -extern "C" fn run_aggregator_step_function( - ctx: *mut ffi::sqlite3_context, - num_args: libc::c_int, - value_ptr: *mut *mut ffi::sqlite3_value, -) where - A: SqliteAggregateFunction + 'static + Send + std::panic::UnwindSafe, - Args: FromSqlRow, - Ret: ToSql, - Sqlite: HasSqlType, -{ - let result = std::panic::catch_unwind(move || { - let args = unsafe { slice::from_raw_parts_mut(value_ptr, num_args as _) }; - run_aggregator_step::(ctx, args) - }) - .unwrap_or_else(|e| { - Err(SqliteCallbackError::Panic(format!( - "{}::step() panicked", - std::any::type_name::() - ))) - }); - - match result { - Ok(()) => {} - Err(e) => e.emit(ctx), - } -} - -fn run_aggregator_step( - ctx: *mut ffi::sqlite3_context, - args: &mut [*mut ffi::sqlite3_value], -) -> Result<(), SqliteCallbackError> -where - A: SqliteAggregateFunction, - Args: FromSqlRow, -{ - static NULL_AG_CTX_ERR: &str = "An unknown error occurred. sqlite3_aggregate_context returned a null pointer. This should never happen."; - static NULL_CTX_ERR: &str = - "We've written the aggregator to the aggregate context, but it could not be retrieved."; - - let aggregate_context = unsafe { - // This block of unsafe code makes the following assumptions: - // - // * sqlite3_aggregate_context allocates sizeof::> - // bytes of zeroed memory as documented here: - // https://www.sqlite.org/c3ref/aggregate_context.html - // A null pointer is returned for negative or zero sized types, - // which should be impossible in theory. We check that nevertheless - // - // * OptionalAggregator::None has a discriminant of 0 as specified by - // #[repr(u8)] + RFC 2195 - // - // * If all bytes are zero, the discriminant is also zero, so we can - // assume that we get OptionalAggregator::None in this case. This is - // not UB as we only access the discriminant here, so we do not try - // to read any other zeroed memory. After that we initialize our enum - // by writing a correct value at this location via ptr::write_unaligned - // - // * We use ptr::write_unaligned as we did not found any guarantees that - // the memory will have a correct alignment. - // (Note I(weiznich): would assume that it is aligned correctly, but we - // we cannot guarantee it, so better be safe than sorry) - ffi::sqlite3_aggregate_context(ctx, std::mem::size_of::>() as i32) - }; - let aggregate_context = NonNull::new(aggregate_context as *mut OptionalAggregator); - let aggregator = unsafe { - match aggregate_context.map(|a| &mut *a.as_ptr()) { - Some(&mut OptionalAggregator::Some(ref mut agg)) => agg, - Some(a_ptr @ &mut OptionalAggregator::None) => { - ptr::write_unaligned(a_ptr as *mut _, OptionalAggregator::Some(A::default())); - if let OptionalAggregator::Some(ref mut agg) = a_ptr { - agg - } else { - return Err(SqliteCallbackError::Abort(NULL_CTX_ERR)); - } - } - None => { - return Err(SqliteCallbackError::Abort(NULL_AG_CTX_ERR)); - } - } - }; - let args = build_sql_function_args::(args)?; - - aggregator.step(args); - Ok(()) -} - -extern "C" fn run_aggregator_final_function( - ctx: *mut ffi::sqlite3_context, -) where - A: SqliteAggregateFunction + 'static + Send, - Args: FromSqlRow, - Ret: ToSql, - Sqlite: HasSqlType, -{ - static NO_AGGREGATOR_FOUND: &str = "We've written to the aggregator in the xStep callback. If xStep was never called, then ffi::sqlite_aggregate_context() would have returned a NULL pointer."; - let aggregate_context = unsafe { - // Within the xFinal callback, it is customary to set nBytes to 0 so no pointless memory - // allocations occur, a null pointer is returned in this case - // See: https://www.sqlite.org/c3ref/aggregate_context.html - // - // For the reasoning about the safety of the OptionalAggregator handling - // see the comment in run_aggregator_step_function. - ffi::sqlite3_aggregate_context(ctx, 0) - }; - - let result = std::panic::catch_unwind(|| { - let mut aggregate_context = NonNull::new(aggregate_context as *mut OptionalAggregator); - - let aggregator = if let Some(a) = aggregate_context.as_mut() { - let a = unsafe { a.as_mut() }; - match std::mem::replace(a, OptionalAggregator::None) { - OptionalAggregator::None => { - return Err(SqliteCallbackError::Abort(NO_AGGREGATOR_FOUND)); - } - OptionalAggregator::Some(a) => Some(a), - } - } else { - None - }; - - let res = A::finalize(aggregator); - let value = process_sql_function_result(&res)?; - // We've checked already that ctx is not null - unsafe { - value.result_of(&mut *ctx); - } - Ok(()) - }) - .unwrap_or_else(|_e| { - Err(SqliteCallbackError::Panic(format!( - "{}::finalize() panicked", - std::any::type_name::() - ))) - }); - if let Err(e) = result { - e.emit(ctx); - } -} - -unsafe fn context_error_str(ctx: *mut ffi::sqlite3_context, error: &str) { - ffi::sqlite3_result_error(ctx, error.as_ptr() as *const _, error.len() as _); -} - -struct CollationUserPtr { - callback: F, - collation_name: String, -} - -#[allow(warnings)] -extern "C" fn run_collation_function( - user_ptr: *mut libc::c_void, - lhs_len: libc::c_int, - lhs_ptr: *const libc::c_void, - rhs_len: libc::c_int, - rhs_ptr: *const libc::c_void, -) -> libc::c_int -where - F: Fn(&str, &str) -> std::cmp::Ordering + Send + std::panic::UnwindSafe + 'static, -{ - let user_ptr = user_ptr as *const CollationUserPtr; - let user_ptr = std::panic::AssertUnwindSafe(unsafe { user_ptr.as_ref() }); - - let result = std::panic::catch_unwind(|| { - let user_ptr = user_ptr.ok_or_else(|| { - SqliteCallbackError::Abort( - "Got a null pointer as data pointer. This should never happen", - ) - })?; - for (ptr, len, side) in &[(rhs_ptr, rhs_len, "rhs"), (lhs_ptr, lhs_len, "lhs")] { - if *len < 0 { - assert_fail!( - "An unknown error occurred. {}_len is negative. This should never happen.", - side - ); - } - if ptr.is_null() { - assert_fail!( - "An unknown error occurred. {}_ptr is a null pointer. This should never happen.", - side - ); - } - } - - let (rhs, lhs) = unsafe { - // Depending on the eTextRep-parameter to sqlite3_create_collation_v2() the strings can - // have various encodings. register_collation_function() always selects SQLITE_UTF8, so the - // pointers point to valid UTF-8 strings (assuming correct behavior of libsqlite3). - ( - str::from_utf8(slice::from_raw_parts(rhs_ptr as *const u8, rhs_len as _)), - str::from_utf8(slice::from_raw_parts(lhs_ptr as *const u8, lhs_len as _)), - ) - }; - - let rhs = - rhs.map_err(|_| SqliteCallbackError::Abort("Got an invalid UTF-8 string for rhs"))?; - let lhs = - lhs.map_err(|_| SqliteCallbackError::Abort("Got an invalid UTF-8 string for lhs"))?; - - Ok((user_ptr.callback)(rhs, lhs)) - }) - .unwrap_or_else(|p| { - Err(SqliteCallbackError::Panic( - user_ptr - .map(|u| u.collation_name.clone()) - .unwrap_or_default(), - )) - }); - - match result { - Ok(std::cmp::Ordering::Less) => -1, - Ok(std::cmp::Ordering::Equal) => 0, - Ok(std::cmp::Ordering::Greater) => 1, - Err(SqliteCallbackError::Abort(a)) => { - eprintln!( - "Collation function {} failed with: {}", - user_ptr - .map(|c| &c.collation_name as &str) - .unwrap_or_default(), - a - ); - std::process::abort() - } - Err(SqliteCallbackError::DieselError(e)) => { - eprintln!( - "Collation function {} failed with: {}", - user_ptr - .map(|c| &c.collation_name as &str) - .unwrap_or_default(), - e - ); - std::process::abort() - } - Err(SqliteCallbackError::Panic(msg)) => { - eprintln!("Collation function {} panicked", msg); - std::process::abort() - } - } -} - -extern "C" fn destroy_boxed(data: *mut libc::c_void) { - let ptr = data as *mut F; - unsafe { std::mem::drop(Box::from_raw(ptr)) }; -} */ #[cfg(test)] diff --git a/diesel-wasm-sqlite/src/connection/row.rs b/diesel-wasm-sqlite/src/connection/row.rs index 75cc27369..3d9f1d94f 100644 --- a/diesel-wasm-sqlite/src/connection/row.rs +++ b/diesel-wasm-sqlite/src/connection/row.rs @@ -5,9 +5,11 @@ use std::sync::Arc; use super::owned_row::OwnedSqliteRow; use super::sqlite_value::{OwnedSqliteValue, SqliteValue}; use super::stmt::StatementUse; -use crate::backend::Backend; -use crate::row::{Field, IntoOwnedRow, PartialRow, Row, RowIndex, RowSealed}; -use crate::sqlite::Sqlite; +use crate::WasmSqlite; +use diesel::{ + backend::Backend, + row::{Field, IntoOwnedRow, PartialRow, Row, RowIndex, RowSealed}, +}; #[allow(missing_debug_implementations)] pub struct SqliteRow<'stmt, 'query> { @@ -23,7 +25,7 @@ pub(super) enum PrivateSqliteRow<'stmt, 'query> { }, } -impl<'stmt> IntoOwnedRow<'stmt, Sqlite> for SqliteRow<'stmt, '_> { +impl<'stmt> IntoOwnedRow<'stmt, WasmSqlite> for SqliteRow<'stmt, '_> { type OwnedRow = OwnedSqliteRow; type Cache = Option]>>; @@ -129,7 +131,7 @@ impl<'stmt, 'query> PrivateSqliteRow<'stmt, 'query> { impl<'stmt, 'query> RowSealed for SqliteRow<'stmt, 'query> {} -impl<'stmt, 'query> Row<'stmt, Sqlite> for SqliteRow<'stmt, 'query> { +impl<'stmt, 'query> Row<'stmt, WasmSqlite> for SqliteRow<'stmt, 'query> { type Field<'field> = SqliteField<'field, 'field> where 'stmt: 'field, Self: 'field; type InnerPartialRow = Self; @@ -181,7 +183,7 @@ pub struct SqliteField<'stmt, 'query> { pub(super) col_idx: i32, } -impl<'stmt, 'query> Field<'stmt, Sqlite> for SqliteField<'stmt, 'query> { +impl<'stmt, 'query> Field<'stmt, WasmSqlite> for SqliteField<'stmt, 'query> { fn field_name(&self) -> Option<&str> { match &*self.row { PrivateSqliteRow::Direct(stmt) => stmt.field_name(self.col_idx), @@ -195,7 +197,7 @@ impl<'stmt, 'query> Field<'stmt, Sqlite> for SqliteField<'stmt, 'query> { self.value().is_none() } - fn value(&self) -> Option<::RawValue<'_>> { + fn value(&self) -> Option<::RawValue<'_>> { SqliteValue::new(Ref::clone(&self.row), self.col_idx) } } @@ -298,23 +300,23 @@ mod tests { let second_values = (second_fields.0.value(), second_fields.1.value()); assert_eq!( - >::from_nullable_sql(first_values.0) + >::from_nullable_sql(first_values.0) .unwrap(), expected[0].0 ); assert_eq!( - >::from_nullable_sql(first_values.1) + >::from_nullable_sql(first_values.1) .unwrap(), expected[0].1 ); assert_eq!( - >::from_nullable_sql(second_values.0) + >::from_nullable_sql(second_values.0) .unwrap(), expected[1].0 ); assert_eq!( - >::from_nullable_sql(second_values.1) + >::from_nullable_sql(second_values.1) .unwrap(), expected[1].1 ); @@ -323,7 +325,7 @@ mod tests { let first_values = (first_fields.0.value(), first_fields.1.value()); assert_eq!( - >::from_nullable_sql(first_values.0) + >::from_nullable_sql(first_values.0) .unwrap(), expected[0].0 ); diff --git a/diesel-wasm-sqlite/src/connection/sqlite_value.rs b/diesel-wasm-sqlite/src/connection/sqlite_value.rs index 7210d104b..d59febf59 100644 --- a/diesel-wasm-sqlite/src/connection/sqlite_value.rs +++ b/diesel-wasm-sqlite/src/connection/sqlite_value.rs @@ -1,11 +1,10 @@ #![allow(unsafe_code)] // ffi calls -extern crate libsqlite3_sys as ffi; use std::cell::Ref; -use std::ptr::NonNull; use std::{slice, str}; -use crate::sqlite::SqliteType; +use crate::{backend::SqliteType, sqlite_types}; +use wasm_bindgen::JsValue; use super::owned_row::OwnedSqliteRow; use super::row::PrivateSqliteRow; @@ -24,22 +23,16 @@ pub struct SqliteValue<'row, 'stmt, 'query> { // to safe the match statements for each method // According to benchmarks this leads to a ~20-30% speedup // + // // This is sound as long as nobody calls `stmt.step()` // while holding this value. We ensure this by including // a reference to the row above. - value: NonNull, + value: JsValue, } -#[derive(Debug)] -#[repr(transparent)] +#[derive(Debug, Clone)] pub(super) struct OwnedSqliteValue { - pub(super) value: NonNull, -} - -impl Drop for OwnedSqliteValue { - fn drop(&mut self) { - unsafe { ffi::sqlite3_value_free(self.value.as_ptr()) } - } + pub(super) value: JsValue, } // Unsafe Send impl safe since sqlite3_value is built with sqlite3_value_dup @@ -148,25 +141,14 @@ impl<'row, 'stmt, 'query> SqliteValue<'row, 'stmt, 'query> { } impl OwnedSqliteValue { - pub(super) fn copy_from_ptr(ptr: NonNull) -> Option { - let tpe = unsafe { ffi::sqlite3_value_type(ptr.as_ptr()) }; - if ffi::SQLITE_NULL == tpe { + pub(super) fn new_from_ptr(ptr: &JsValue) -> Option { + let sqlite3 = crate::get_sqlite_unchecked(); + let value = sqlite3.value(ptr); + + if value.is_null() { return None; } - let value = unsafe { ffi::sqlite3_value_dup(ptr.as_ptr()) }; - Some(Self { - value: NonNull::new(value)?, - }) - } - pub(super) fn duplicate(&self) -> OwnedSqliteValue { - // self.value is a `NonNull` ptr so this cannot be null - let value = unsafe { ffi::sqlite3_value_dup(self.value.as_ptr()) }; - let value = NonNull::new(value).expect( - "Sqlite documentation states this returns only null if value is null \ - or OOM. If you ever see this panic message please open an issue at \ - https://github.com/diesel-rs/diesel.", - ); - OwnedSqliteValue { value } + Some(Self { value }) } } diff --git a/diesel-wasm-sqlite/src/connection/stmt.rs b/diesel-wasm-sqlite/src/connection/stmt.rs index 92b12465d..b8659ab86 100644 --- a/diesel-wasm-sqlite/src/connection/stmt.rs +++ b/diesel-wasm-sqlite/src/connection/stmt.rs @@ -1,53 +1,57 @@ -#![allow(unsafe_code)] // fii code +#![allow(unsafe_code)] //TODO: can probably remove for wa-sqlite use super::bind_collector::{InternalSqliteBindValue, SqliteBindCollector}; use super::raw::RawConnection; use super::sqlite_value::OwnedSqliteValue; -use crate::connection::statement_cache::{MaybeCached, PrepareForCache}; -use crate::connection::Instrumentation; -use crate::query_builder::{QueryFragment, QueryId}; -use crate::result::Error::DatabaseError; -use crate::result::*; -use crate::sqlite::{Sqlite, SqliteType}; -use libsqlite3_sys as ffi; +use crate::{ + sqlite_types::{PrepareOptions, SqlitePrepareFlags}, + SqliteType, WasmSqlite, +}; +use diesel::{ + connection::{ + statement_cache::{MaybeCached, PrepareForCache}, + Instrumentation, + }, + query_builder::{QueryFragment, QueryId}, + result::{Error::DatabaseError, *}, +}; use std::cell::OnceCell; -use std::ffi::{CStr, CString}; use std::io::{stderr, Write}; -use std::os::raw as libc; -use std::ptr::{self, NonNull}; + +use wasm_bindgen::JsValue; pub(super) struct Statement { - inner_statement: NonNull, + inner_statement: JsValue, } impl Statement { - pub(super) fn prepare( + pub(super) async fn prepare( raw_connection: &RawConnection, sql: &str, is_cached: PrepareForCache, ) -> QueryResult { - let mut stmt = ptr::null_mut(); - let mut unused_portion = ptr::null(); - // the cast for `ffi::SQLITE_PREPARE_PERSISTENT` is required for old libsqlite3-sys versions - #[allow(clippy::unnecessary_cast)] - let prepare_result = unsafe { - ffi::sqlite3_prepare_v3( - raw_connection.internal_connection.as_ptr(), - CString::new(sql)?.as_ptr(), - sql.len() as libc::c_int, - if matches!(is_cached, PrepareForCache::Yes) { - ffi::SQLITE_PREPARE_PERSISTENT as u32 - } else { - 0 - }, - &mut stmt, - &mut unused_portion, - ) + let sqlite3 = crate::get_sqlite_unchecked(); + let flags = if matches!(is_cached, PrepareForCache::Yes) { + Some(SqlitePrepareFlags::SQLITE_PREPARE_PERSISTENT.bits()) + } else { + None }; - ensure_sqlite_ok(prepare_result, raw_connection.internal_connection.as_ptr()).map(|_| { - Statement { - inner_statement: unsafe { NonNull::new_unchecked(stmt) }, - } + let options = PrepareOptions { + flags, + unscoped: None, + }; + + let stmt = sqlite3 + .prepare( + &raw_connection.internal_connection, + sql, + Some(serde_wasm_bindgen::to_value(&options).unwrap()), + ) + .await + .unwrap(); + + Ok(Statement { + inner_statement: stmt, }) } @@ -56,13 +60,16 @@ impl Statement { // `SqliteBindValue::String` or `SqliteBindValue::BorrowedString` is valid // till either a new value is bound to the same parameter or the underlying // prepared statement is dropped. - unsafe fn bind( - &mut self, - tpe: SqliteType, - value: InternalSqliteBindValue<'_>, - bind_index: i32, - ) -> QueryResult>> { - let mut ret_ptr = None; + fn bind(&self, _tpe: SqliteType, value: JsValue, bind_index: i32) -> QueryResult { + let sqlite3 = crate::get_sqlite_unchecked(); + let result = sqlite3 + .bind(&self.inner_statement, bind_index, value.into()) + .unwrap(); + + // TODO:insipx Pretty sure we can have a simpler implementation here + // making use of `wa-sqlite` `bind` which abstracts over the individual bind functions in + // sqlite3. However, not sure how this will work further up the stack. + /* let result = match (tpe, value) { (_, InternalSqliteBindValue::Null) => { ffi::sqlite3_bind_null(self.inner_statement.as_ptr(), bind_index) @@ -136,41 +143,24 @@ impl Statement { format!("Type mismatch: Expected {t:?}, got {b}").into(), )) } - }; - match ensure_sqlite_ok(result, self.raw_connection()) { - Ok(()) => Ok(ret_ptr), - Err(e) => { - if let Some(ptr) = ret_ptr { - // This is a `NonNul` ptr so it cannot be null - // It points to a slice internally as we did not apply - // any cast above. - std::mem::drop(Box::from_raw(ptr.as_ptr())) - } - Err(e) - } } + */ + Ok(result) } - fn reset(&mut self) { - unsafe { ffi::sqlite3_reset(self.inner_statement.as_ptr()) }; + async fn reset(&self) { + let sqlite3 = crate::get_sqlite_unchecked(); + let _ = sqlite3.reset(&self.inner_statement).await.unwrap(); } + /* not sure if there is equivalent method or just cloning the stmt is enough fn raw_connection(&self) -> *mut ffi::sqlite3 { unsafe { ffi::sqlite3_db_handle(self.inner_statement.as_ptr()) } } + */ } -pub(super) fn ensure_sqlite_ok( - code: libc::c_int, - raw_connection: *mut ffi::sqlite3, -) -> QueryResult<()> { - if code == ffi::SQLITE_OK { - Ok(()) - } else { - Err(last_error(raw_connection)) - } -} - +/* TODO: Useful for converting JS Error messages to Rust fn last_error(raw_connection: *mut ffi::sqlite3) -> Error { let error_message = last_error_message(raw_connection); let error_information = Box::new(error_message); @@ -191,27 +181,18 @@ fn last_error_message(conn: *mut ffi::sqlite3) -> String { c_str.to_string_lossy().into_owned() } + fn last_error_code(conn: *mut ffi::sqlite3) -> libc::c_int { unsafe { ffi::sqlite3_extended_errcode(conn) } } +*/ impl Drop for Statement { fn drop(&mut self) { - use std::thread::panicking; - - let raw_connection = self.raw_connection(); - let finalize_result = unsafe { ffi::sqlite3_finalize(self.inner_statement.as_ptr()) }; - if let Err(e) = ensure_sqlite_ok(finalize_result, raw_connection) { - if panicking() { - write!( - stderr(), - "Error finalizing SQLite prepared statement: {e:?}" - ) - .expect("Error writing to `stderr`"); - } else { - panic!("Error finalizing SQLite prepared statement: {:?}", e); - } - } + let sqlite3 = crate::get_sqlite_unchecked(); + let _ = sqlite3 + .finalize(&self.inner_statement) + .expect("Error finalized SQLite prepared statement"); } } @@ -231,7 +212,7 @@ struct BoundStatement<'stmt, 'query> { // We use a boxed queryfragment here just to erase the // generic type, we use NonNull to communicate // that this is a shared buffer - query: Option + 'query>>, + query: Option + 'query>>, // we need to store any owned bind values separately, as they are not // contained in the query itself. We use NonNull to // communicate that this is a shared buffer @@ -247,7 +228,7 @@ impl<'stmt, 'query> BoundStatement<'stmt, 'query> { instrumentation: &'stmt mut dyn Instrumentation, ) -> QueryResult> where - T: QueryFragment + QueryId + 'query, + T: QueryFragment + QueryId + 'query, { // Don't use a trait object here to prevent using a virtual function call // For sqlite this can introduce a measurable overhead @@ -256,7 +237,7 @@ impl<'stmt, 'query> BoundStatement<'stmt, 'query> { let query = Box::new(query); let mut bind_collector = SqliteBindCollector::new(); - query.collect_binds(&mut bind_collector, &mut (), &Sqlite)?; + query.collect_binds(&mut bind_collector, &mut (), &WasmSqlite)?; let SqliteBindCollector { binds } = bind_collector; let mut ret = BoundStatement { @@ -269,7 +250,7 @@ impl<'stmt, 'query> BoundStatement<'stmt, 'query> { ret.bind_buffers(binds)?; - let query = query as Box + 'query>; + let query = query as Box + 'query>; ret.query = NonNull::new(Box::into_raw(query)); Ok(ret) @@ -278,10 +259,7 @@ impl<'stmt, 'query> BoundStatement<'stmt, 'query> { // This is a separated function so that // not the whole constructor is generic over the query type T. // This hopefully prevents binary bloat. - fn bind_buffers( - &mut self, - binds: Vec<(InternalSqliteBindValue<'_>, SqliteType)>, - ) -> QueryResult<()> { + fn bind_buffers(&mut self, binds: Vec<(JsValue, SqliteType)>) -> QueryResult<()> { // It is useful to preallocate `binds_to_free` because it // - Guarantees that pushing inside it cannot panic, which guarantees the `Drop` // impl of `BoundStatement` will always re-`bind` as needed @@ -405,7 +383,7 @@ impl<'stmt, 'query> StatementUse<'stmt, 'query> { instrumentation: &'stmt mut dyn Instrumentation, ) -> QueryResult> where - T: QueryFragment + QueryId + 'query, + T: QueryFragment + QueryId + 'query, { Ok(Self { statement: BoundStatement::bind(statement, query, instrumentation)?, diff --git a/diesel-wasm-sqlite/src/ffi.rs b/diesel-wasm-sqlite/src/ffi.rs index 05765afad..e38d05461 100644 --- a/diesel-wasm-sqlite/src/ffi.rs +++ b/diesel-wasm-sqlite/src/ffi.rs @@ -23,6 +23,8 @@ unsafe impl Sync for SQLite {} #[wasm_bindgen(module = "/src/package.js")] extern "C" { pub type SQLite; + pub type SQLiteCompatibleType; + // pub type SqlitePrepareOptions; #[wasm_bindgen(constructor)] pub fn new(module: JsValue) -> SQLite; @@ -48,6 +50,60 @@ extern "C" { #[wasm_bindgen(method)] pub fn result_null(this: &SQLite, context: i32); + #[wasm_bindgen(method, catch)] + pub fn bind( + this: &SQLite, + stmt: &JsValue, + idx: i32, + value: SQLiteCompatibleType, + ) -> Result; + /* + #[wasm_bindgen(method, catch)] + pub fn bind_blob( + this: &SQLite, + stmt: &JsValue, + idx: i32, + value: Vec, + ) -> Result; + + // JsValue here is an interesting type that needs to be ported in order to make use of this + // but not currently using it. + + #[wasm_bindgen(method, catch)] + pub fn bind_collection( + this: &SQLite, + stmt: &JsValue, + bindings: JsValue, + ) -> Result; + + #[wasm_bindgen(method, catch)] + pub fn bind_double(this: &SQLite, stmt: &JsValue, idx: i32, value: f64) + -> Result; + + #[wasm_bindgen(method, catch)] + pub fn bind_int(this: &SQLite, stmt: &JsValue, idx: i32, value: i32) -> Result; + + #[wasm_bindgen(method, catch)] + pub fn bind_int64(this: &SQLite, stmt: &JsValue, idx: i32, value: i64) -> Result; + + #[wasm_bindgen(method, catch)] + pub fn bind_null(this: &SQLite, stmt: &JsValue, idx: i32) -> Result; + */ + #[wasm_bindgen(method)] + pub fn bind_parameter_count(this: &SQLite, stmt: &JsValue) -> i32; + + #[wasm_bindgen(method)] + pub fn bind_parameter_name(this: &SQLite, stmt: &JsValue, idx: i32) -> String; + + #[wasm_bindgen(method, catch)] + pub fn bind_text(this: &SQLite, stmt: &JsValue, idx: i32, value: &str) -> Result; + + #[wasm_bindgen(method, catch)] + pub async fn reset(this: &SQLite, stmt: &JsValue) -> Result; + + #[wasm_bindgen(method)] + pub fn value(this: &SQLite, pValue: &JsValue); + #[wasm_bindgen(method, catch)] pub async fn open_v2( this: &SQLite, @@ -58,9 +114,20 @@ extern "C" { #[wasm_bindgen(method, catch)] pub async fn exec(this: &SQLite, database: &JsValue, query: &str) -> Result<(), JsValue>; + #[wasm_bindgen(method, catch)] + pub fn finalize(this: &SQLite, stmt: &JsValue) -> Result<(), JsValue>; + #[wasm_bindgen(method)] pub fn changes(this: &SQLite, database: &JsValue) -> usize; + #[wasm_bindgen(method, catch)] + pub async fn prepare( + db: &SQLite, + database: &JsValue, + sql: &str, + options: Option, + ) -> Result; + #[wasm_bindgen(method, catch)] pub fn batch_execute(this: &SQLite, database: &JsValue, query: &str) -> Result<(), JsValue>; diff --git a/diesel-wasm-sqlite/src/lib.rs b/diesel-wasm-sqlite/src/lib.rs index d97cbb813..ffd6ad0f1 100644 --- a/diesel-wasm-sqlite/src/lib.rs +++ b/diesel-wasm-sqlite/src/lib.rs @@ -10,12 +10,8 @@ pub mod utils; compile_error!("This crate only suports the `wasm32-unknown-unknown` target"); use self::ffi::SQLite; -use diesel::{ - query_builder::{AsQuery, QueryFragment, QueryId}, - result::QueryResult, -}; use tokio::sync::OnceCell; -use wasm_bindgen::{prelude::wasm_bindgen, JsValue}; +use wasm_bindgen::JsValue; pub use backend::{SqliteType, WasmSqlite}; diff --git a/diesel-wasm-sqlite/src/package.js b/diesel-wasm-sqlite/src/package.js index 4a11058de..a1552fc96 100644 --- a/diesel-wasm-sqlite/src/package.js +++ b/diesel-wasm-sqlite/src/package.js @@ -2762,6 +2762,28 @@ class SQLite { this.sqlite3.result_null(context); } + bind(stmt, i, value) { + try { + return this.sqlite3.bind(stmt, i, value); + } catch (error) { + console.log("bind err"); + throw error; + } + } + + async reset(stmt) { + try { + return await this.sqlite3.reset(stmt); + } catch (error) { + console.log("reset err"); + throw error; + } + } + + value(pValue) { + this.sqlite3.value(pValue); + } + async open_v2(database_url, iflags) { try { console.log("Opening database!", database_url); @@ -2783,10 +2805,27 @@ class SQLite { } } + finalize(stmt) { + try { + return this.sqlite3.finalize(stmt); + } catch (error) { + console.log("stmt error"); + } + } + changes(db) { return this.sqlite3.changes(db); } + async prepare(database, sql, options) { + try { + await this.sqlite3.statements(database, sql, options); + } catch (error) { + console.log("sqlite prepare error"); + throw error; + } + } + batch_execute(database, query) { try { sqlite3.exec(database, query); diff --git a/diesel-wasm-sqlite/src/sqlite_types.rs b/diesel-wasm-sqlite/src/sqlite_types.rs index c9ede3420..20723a052 100644 --- a/diesel-wasm-sqlite/src/sqlite_types.rs +++ b/diesel-wasm-sqlite/src/sqlite_types.rs @@ -1,6 +1,14 @@ use super::backend::{SqliteType, WasmSqlite}; use bitflags::bitflags; use diesel::sql_types::*; +use serde::{Deserialize, Serialize}; + +/// `SqlitePrepareOptions` imported type +#[derive(Serialize, Deserialize, Default, Clone, Debug, Copy)] +pub struct PrepareOptions { + pub flags: Option, + pub unscoped: Option, +} macro_rules! impl_has_sql_type { ($type:ty, $sql_type:expr) => { @@ -52,7 +60,7 @@ bitflags! { } } -/// SQLite Text Encodings https://www.sqlite.org/capi3ref.html#SQLITE_ANY +// SQLite Text Encodings https://www.sqlite.org/capi3ref.html#SQLITE_ANY bitflags! { pub struct SqliteFlags: u32 { const SQLITE_UTF8 = 1; /* IMP: R-37514-35566 */ @@ -70,3 +78,12 @@ bitflags! { const SQLITE_RESULT_SUBTYPE = 0x001000000; } } + +// SQLite Prepare Flags https://www.sqlite.org/c3ref/c_prepare_normalize.html#sqlitepreparepersistent +bitflags! { + pub struct SqlitePrepareFlags: i32 { + const SQLITE_PREPARE_PERSISTENT = 0x01; + const SQLITE_PREPARE_NORMALIZE = 0x02; + const SQLITE_PREPARE_NO_VTAB = 0x04; + } +}