Skip to content

Commit

Permalink
Better implementation using sqlite-wasm-rs
Browse files Browse the repository at this point in the history
  • Loading branch information
wuhesheng committed Feb 8, 2025
1 parent f10e2da commit f5703c9
Show file tree
Hide file tree
Showing 11 changed files with 20 additions and 77 deletions.
2 changes: 1 addition & 1 deletion diesel/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ path = "../diesel_derives"
libsqlite3-sys = { version = ">=0.17.2, <0.32.0", optional = true, features = ["bundled_bindings"] }

[target.'cfg(all(target_family = "wasm", target_os = "unknown"))'.dependencies]
sqlite-wasm-rs = { version = ">=0.1.3, <0.2.0", optional = true }
sqlite-wasm-rs = { version = ">=0.2.1, <0.3.0", optional = true }

[target.'cfg(all(target_family = "wasm", target_os = "unknown"))'.dev-dependencies]
# Something is dependent on it, so we use feature to override it.
Expand Down
6 changes: 0 additions & 6 deletions diesel/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -778,12 +778,6 @@ pub mod prelude {
#[cfg(feature = "sqlite")]
#[doc(inline)]
pub use crate::sqlite::SqliteConnection;

// These exported API from `sqlite-wasm-rs` are stable:
#[cfg(feature = "sqlite")]
#[cfg(all(target_family = "wasm", target_os = "unknown"))]
#[doc(inline)]
pub use sqlite_wasm_rs::export::init_sqlite;
}

#[doc(inline)]
Expand Down
26 changes: 7 additions & 19 deletions diesel/src/sqlite/connection/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -174,12 +174,8 @@ impl Connection for SqliteConnection {
/// If you plan to use this connection type on the `wasm32-unknown-unknown` target please
/// make sure to read the following notes:
///
/// * You must initialize sqlite using `diesel::init_sqlite` before calling `SqliteConnection::establish`.
/// * The database is stored in memory by default. sqlite-wasm
/// provides different persistent VFS (Virtual File Systems), but they all have different limitations.
/// See <https://sqlite.org/wasm/doc/trunk/persistence.md> for details. Make sure to chose
/// an appropriated VFS implementation for your usecase.
/// * VFS can be selected through the `database_url` via an URL option, such as `file:data.db?vfs=opfs`.
/// * The database is stored in memory by default.
/// * Persistent VFS (Virtual File Systems) is optional, see <https://github.com/Spxg/sqlite-wasm-rs/blob/master/VFS.md>
fn establish(database_url: &str) -> ConnectionResult<Self> {
let mut instrumentation = DynInstrumentation::default_instrumentation();
instrumentation.on_connection_event(InstrumentationEvent::StartEstablishConnection {
Expand Down Expand Up @@ -989,26 +985,18 @@ mod tests {

#[cfg(all(target_family = "wasm", target_os = "unknown"))]
#[wasm_bindgen_test::wasm_bindgen_test]
async fn test_sqlite_wasm_vfs_default() {
crate::init_sqlite().await.unwrap();
fn test_sqlite_wasm_vfs_default() {
SqliteConnection::establish("test_sqlite_wasm_vfs_default.db").unwrap();
}

#[cfg(all(target_family = "wasm", target_os = "unknown"))]
#[wasm_bindgen_test::wasm_bindgen_test]
async fn test_sqlite_wasm_vfs_opfs() {
crate::init_sqlite().await.unwrap();
SqliteConnection::establish("file:test_sqlite_wasm_vfs_opfs.db?vfs=opfs").unwrap();
}

#[cfg(all(target_family = "wasm", target_os = "unknown"))]
#[wasm_bindgen_test::wasm_bindgen_test]
async fn test_sqlite_wasm_vfs_opfs_sahpool() {
let sqlite = crate::init_sqlite().await.unwrap();
let util = sqlite.install_opfs_sahpool(None).await.unwrap();
let util = sqlite_wasm_rs::export::install_opfs_sahpool(None, true)
.await
.unwrap();
SqliteConnection::establish("file:test_sqlite_wasm_vfs_opfs_sahpool.db?vfs=opfs-sahpool")
.unwrap();
assert_eq!(1, util.get_file_count());
util.remove_vfs().await;
assert!(util.get_file_count() > 0);
}
}
30 changes: 1 addition & 29 deletions diesel_test_helper/src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
extern crate proc_macro2;
use proc_macro::TokenStream;
use quote::quote;
use syn::{parse_macro_input, token::Async, ItemFn};
use syn::{parse_macro_input, ItemFn};

/// Since sqlite wasm support has been added, #[wasm_bindgen_test] needs
/// to be used in the wasm environment. This macro is designed to solve platform test differences.
Expand All @@ -15,7 +15,6 @@ pub fn test(_: TokenStream, item: TokenStream) -> TokenStream {
} = parse_macro_input!(item as ItemFn);

let cfgs = quote! {
#[cfg_attr(all(target_family = "wasm", target_os = "unknown", feature = "sqlite"), diesel_test_helper::sqlite_wasm)]
#[cfg_attr(all(target_family = "wasm", target_os = "unknown"), wasm_bindgen_test::wasm_bindgen_test)]
#[cfg_attr(not(all(target_family = "wasm", target_os = "unknown")), test)]
};
Expand All @@ -28,30 +27,3 @@ pub fn test(_: TokenStream, item: TokenStream) -> TokenStream {
)
.into()
}

/// Sqlite wasm requires asynchronous initialization, so this macro
/// turns the function into asynchronous and provides an initialization method
#[proc_macro_attribute]
pub fn sqlite_wasm(_: TokenStream, item: TokenStream) -> TokenStream {
let ItemFn {
mut sig,
vis,
block,
attrs,
} = parse_macro_input!(item as ItemFn);

let prepare = quote! {
crate::init_sqlite().await.unwrap();
};

sig.asyncness = Some(Async::default());

quote!(
#(#attrs)*
#vis #sig {
#prepare
#block
}
)
.into()
}
2 changes: 0 additions & 2 deletions diesel_tests/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -32,8 +32,6 @@ diesel_test_helper = { path = "../diesel_test_helper" }
# Something is dependent on it, so we use feature to override it.
getrandom = { version = "0.2", features = ["js"] }
wasm-bindgen-test = "0.3.49"
# Wasm can use thread::sleep when atomic target_feature is enabled, but that requires nightly
wasmtimer = "0.4.1"

[features]
default = []
Expand Down
6 changes: 1 addition & 5 deletions diesel_tests/tests/connection.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ use diesel::*;

#[diesel_test_helper::test]
#[cfg(any(feature = "postgres", feature = "sqlite"))]
#[cfg(not(all(target_family = "wasm", target_os = "unknown")))]
fn managing_updated_at_for_table() {
use crate::schema_dsl::*;
use chrono::NaiveDateTime;
Expand Down Expand Up @@ -65,12 +66,7 @@ fn managing_updated_at_for_table() {
assert_eq!(Ok(0), result);

if cfg!(feature = "sqlite") {
// wasm can use thread::sleep when atomic target_feature
// is enabled, but that requires nightly
#[cfg(not(all(target_family = "wasm", target_os = "unknown")))]
std::thread::sleep(Duration::from_millis(1000));
#[cfg(all(target_family = "wasm", target_os = "unknown"))]
wasmtimer::tokio::sleep(Duration::from_secs(1)).await;
}

let query = auto_time.find(2).select(updated_at);
Expand Down
4 changes: 0 additions & 4 deletions diesel_tests/tests/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,3 @@ mod transactions;
mod types;
mod types_roundtrip;
mod update;

/// Re-export it, because the `td::test` macro use `crate::init_sqlite`
#[cfg(all(target_family = "wasm", target_os = "unknown", feature = "sqlite"))]
pub use diesel::init_sqlite;
1 change: 1 addition & 0 deletions examples/sqlite/wasm/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ serde = { version = "1.0.217", features = ["derive"] }
serde-wasm-bindgen = "0.6.5"
wasm-bindgen = "0.2.99"
wasm-bindgen-futures = "0.4.49"
sqlite-wasm-rs = "0.2"

[lib]
crate-type = ["cdylib"]
3 changes: 1 addition & 2 deletions examples/sqlite/wasm/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,7 @@
<label for="vfs">choose vfs:</label>
<select id="vfs">
<option value="0">memory</option>
<option value="1">opfs</option>
<option value="2">opfs-sahpool</option>
<option value="1">opfs-sahpool</option>
</select>
<button id="SwitchVFS">Switch VFS</button>
<p></p>
Expand Down
11 changes: 5 additions & 6 deletions examples/sqlite/wasm/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -37,8 +37,7 @@ pub fn establish_connection() -> SqliteConnection {
let (vfs, once) = &*VFS.lock().unwrap();
let url = match vfs {
0 => "post.db",
1 => "file:post.db?vfs=opfs",
2 => "file:post.db?vfs=opfs-sahpool",
1 => "file:post.db?vfs=opfs-sahpool",
_ => unreachable!(),
};
let mut conn =
Expand All @@ -49,11 +48,11 @@ pub fn establish_connection() -> SqliteConnection {
conn
}

#[cfg(all(target_family = "wasm", target_os = "unknown"))]
#[wasm_bindgen]
pub async fn init_sqlite() {
let sqlite = diesel::init_sqlite().await.unwrap();
sqlite.install_opfs_sahpool(None).await.unwrap();
pub async fn install_opfs_sahpool() {
sqlite_wasm_rs::export::install_opfs_sahpool(None, false)
.await
.unwrap();
}

#[wasm_bindgen]
Expand Down
6 changes: 3 additions & 3 deletions examples/sqlite/wasm/worker.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import init, {
init_sqlite,
install_opfs_sahpool,
switch_vfs,
create_post,
get_post,
Expand All @@ -9,7 +9,7 @@ import init, {
} from "./pkg/sqlite_wasm_example.js";

await init();
await init_sqlite();
await install_opfs_sahpool();

async function run_in_worker(event) {
const payload = event.data;
Expand Down Expand Up @@ -65,7 +65,7 @@ async function run_in_worker(event) {
};
}

self.onmessage = function (event) {
self.onmessage = function(event) {
run_in_worker(event);
}

Expand Down

0 comments on commit f5703c9

Please sign in to comment.