From 4e4ac798f92240f851b1a02383ba2f2f68ec87f4 Mon Sep 17 00:00:00 2001 From: Spxg Date: Sun, 29 Dec 2024 20:43:33 +0800 Subject: [PATCH] Add wasm32-unknown-unknown target support --- diesel/Cargo.toml | 9 ++++++-- diesel/src/lib.rs | 7 +++++++ .../src/sqlite/connection/bind_collector.rs | 7 +++++-- diesel/src/sqlite/connection/functions.rs | 4 ++++ diesel/src/sqlite/connection/mod.rs | 4 ++++ diesel/src/sqlite/connection/raw.rs | 21 ++++++++++++++++++- .../sqlite/connection/serialized_database.rs | 4 ++++ diesel/src/sqlite/connection/sqlite_value.rs | 4 ++++ diesel/src/sqlite/connection/stmt.rs | 3 +++ 9 files changed, 58 insertions(+), 5 deletions(-) diff --git a/diesel/Cargo.toml b/diesel/Cargo.toml index fc69b80ac609..cc2c44078e62 100644 --- a/diesel/Cargo.toml +++ b/diesel/Cargo.toml @@ -24,7 +24,6 @@ include = [ byteorder = { version = "1.0", optional = true } chrono = { version = "0.4.20", optional = true, default-features = false, features = ["clock", "std"] } libc = { version = "0.2.0", optional = true } -libsqlite3-sys = { version = ">=0.17.2, <0.31.0", optional = true, features = ["bundled_bindings"] } mysqlclient-sys = { version = ">=0.2.5, <0.5.0", optional = true } mysqlclient-src = { version = "0.1.0", optional = true } pq-sys = { version = ">=0.4.0, <0.7.0", optional = true } @@ -50,6 +49,12 @@ downcast-rs = "1.2.1" version = "~2.2.0" path = "../diesel_derives" +[target.'cfg(not(all(target_family = "wasm", not(target_os = "wasi"))))'.dependencies] +libsqlite3-sys = { version = ">=0.17.2, <0.31.0", optional = true, features = ["bundled_bindings"] } + +[target.'cfg(all(target_family = "wasm", not(target_os = "wasi")))'.dependencies] +sqlite-wasm-rs = { version = "0.1.0", optional = true } + [dev-dependencies] cfg-if = "1" dotenvy = "0.15" @@ -67,7 +72,7 @@ huge-tables = ["64-column-tables"] 64-column-tables = ["32-column-tables", "diesel_derives/64-column-tables"] 128-column-tables = ["64-column-tables", "diesel_derives/128-column-tables"] postgres = ["dep:pq-sys", "postgres_backend"] -sqlite = ["dep:libsqlite3-sys", "diesel_derives/sqlite", "time?/formatting", "time?/parsing"] +sqlite = ["dep:libsqlite3-sys", "dep:sqlite-wasm-rs", "diesel_derives/sqlite", "time?/formatting", "time?/parsing"] mysql = ["dep:mysqlclient-sys", "dep:url", "dep:percent-encoding", "dep:bitflags", "mysql_backend"] without-deprecated = ["diesel_derives/without-deprecated"] with-deprecated = ["diesel_derives/with-deprecated"] diff --git a/diesel/src/lib.rs b/diesel/src/lib.rs index 3b558054da77..94c498f47220 100644 --- a/diesel/src/lib.rs +++ b/diesel/src/lib.rs @@ -768,6 +768,13 @@ pub mod prelude { #[cfg(feature = "sqlite")] #[doc(inline)] pub use crate::sqlite::SqliteConnection; + // Before using C-API, you must initialize sqlite. + // + // Initializing the database is a one-time operation during + // the life of the program. + #[cfg(feature = "sqlite")] + #[cfg(all(target_family = "wasm", not(target_os = "wasi")))] + pub use sqlite_wasm_rs::init_sqlite; } #[doc(inline)] diff --git a/diesel/src/sqlite/connection/bind_collector.rs b/diesel/src/sqlite/connection/bind_collector.rs index e1ce91e434ec..5ca4afa65263 100644 --- a/diesel/src/sqlite/connection/bind_collector.rs +++ b/diesel/src/sqlite/connection/bind_collector.rs @@ -3,6 +3,10 @@ use crate::serialize::{IsNull, Output}; use crate::sql_types::HasSqlType; use crate::sqlite::{Sqlite, SqliteType}; use crate::QueryResult; +#[cfg(not(all(target_family = "wasm", not(target_os = "wasi"))))] +use libsqlite3_sys as ffi; +#[cfg(all(target_family = "wasm", not(target_os = "wasi")))] +use sqlite_wasm_rs::c as ffi; #[derive(Debug, Default)] pub struct SqliteBindCollector<'a> { @@ -127,9 +131,8 @@ impl InternalSqliteBindValue<'_> { #[allow(unsafe_code)] // ffi function calls pub(in crate::sqlite) fn result_of( self, - ctx: &mut libsqlite3_sys::sqlite3_context, + ctx: &mut ffi::sqlite3_context, ) -> Result<(), std::num::TryFromIntError> { - use libsqlite3_sys as ffi; use std::os::raw as libc; // This unsafe block assumes the following invariants: // diff --git a/diesel/src/sqlite/connection/functions.rs b/diesel/src/sqlite/connection/functions.rs index 68891f339f0f..d75245dc0ccc 100644 --- a/diesel/src/sqlite/connection/functions.rs +++ b/diesel/src/sqlite/connection/functions.rs @@ -1,5 +1,9 @@ +#[cfg(not(all(target_family = "wasm", not(target_os = "wasi"))))] extern crate libsqlite3_sys as ffi; +#[cfg(all(target_family = "wasm", not(target_os = "wasi")))] +use sqlite_wasm_rs::c as ffi; + use super::raw::RawConnection; use super::row::PrivateSqliteRow; use super::{Sqlite, SqliteAggregateFunction, SqliteBindValue}; diff --git a/diesel/src/sqlite/connection/mod.rs b/diesel/src/sqlite/connection/mod.rs index 454f00f7b4a3..56b9fba18481 100644 --- a/diesel/src/sqlite/connection/mod.rs +++ b/diesel/src/sqlite/connection/mod.rs @@ -1,5 +1,9 @@ +#[cfg(not(all(target_family = "wasm", not(target_os = "wasi"))))] extern crate libsqlite3_sys as ffi; +#[cfg(all(target_family = "wasm", not(target_os = "wasi")))] +use sqlite_wasm_rs::c as ffi; + mod bind_collector; mod functions; mod owned_row; diff --git a/diesel/src/sqlite/connection/raw.rs b/diesel/src/sqlite/connection/raw.rs index 57d6a5fbcf40..eb626e7f4f6f 100644 --- a/diesel/src/sqlite/connection/raw.rs +++ b/diesel/src/sqlite/connection/raw.rs @@ -1,6 +1,10 @@ #![allow(unsafe_code)] // ffi calls +#[cfg(not(all(target_family = "wasm", not(target_os = "wasi"))))] extern crate libsqlite3_sys as ffi; +#[cfg(all(target_family = "wasm", not(target_os = "wasi")))] +use sqlite_wasm_rs::c as ffi; + use std::ffi::{CString, NulError}; use std::io::{stderr, Write}; use std::os::raw as libc; @@ -45,8 +49,23 @@ impl RawConnection { CString::new(database_url)? }; let flags = ffi::SQLITE_OPEN_READWRITE | ffi::SQLITE_OPEN_CREATE | ffi::SQLITE_OPEN_URI; + // Persistent Storage is supported, use opfs vfs. + // This support is only available when sqlite is loaded from a + // Worker thread, whether it's loaded in its own dedicated worker + // or in a worker together with client code. + #[cfg(all(target_family = "wasm", not(target_os = "wasi")))] + let vfs = CString::new("opfs")?; + let connection_status = unsafe { - ffi::sqlite3_open_v2(database_url.as_ptr(), &mut conn_pointer, flags, ptr::null()) + ffi::sqlite3_open_v2( + database_url.as_ptr(), + &mut conn_pointer, + flags, + #[cfg(not(all(target_family = "wasm", not(target_os = "wasi"))))] + ptr::null(), + #[cfg(all(target_family = "wasm", not(target_os = "wasi")))] + vfs.as_ptr(), + ) }; match connection_status { diff --git a/diesel/src/sqlite/connection/serialized_database.rs b/diesel/src/sqlite/connection/serialized_database.rs index 28a98a286131..675e82fd0373 100644 --- a/diesel/src/sqlite/connection/serialized_database.rs +++ b/diesel/src/sqlite/connection/serialized_database.rs @@ -1,6 +1,10 @@ #![allow(unsafe_code)] +#[cfg(not(all(target_family = "wasm", not(target_os = "wasi"))))] extern crate libsqlite3_sys as ffi; +#[cfg(all(target_family = "wasm", not(target_os = "wasi")))] +use sqlite_wasm_rs::c as ffi; + use std::ops::Deref; /// `SerializedDatabase` is a wrapper for a serialized database that is dynamically allocated by calling `sqlite3_serialize`. diff --git a/diesel/src/sqlite/connection/sqlite_value.rs b/diesel/src/sqlite/connection/sqlite_value.rs index f0d1a4afbda7..d7eb5044e652 100644 --- a/diesel/src/sqlite/connection/sqlite_value.rs +++ b/diesel/src/sqlite/connection/sqlite_value.rs @@ -1,6 +1,10 @@ #![allow(unsafe_code)] // ffi calls +#[cfg(not(all(target_family = "wasm", not(target_os = "wasi"))))] extern crate libsqlite3_sys as ffi; +#[cfg(all(target_family = "wasm", not(target_os = "wasi")))] +use sqlite_wasm_rs::c as ffi; + use std::cell::Ref; use std::ptr::NonNull; use std::{slice, str}; diff --git a/diesel/src/sqlite/connection/stmt.rs b/diesel/src/sqlite/connection/stmt.rs index a02354c46bd4..cccd9c843364 100644 --- a/diesel/src/sqlite/connection/stmt.rs +++ b/diesel/src/sqlite/connection/stmt.rs @@ -8,7 +8,10 @@ use crate::query_builder::{QueryFragment, QueryId}; use crate::result::Error::DatabaseError; use crate::result::*; use crate::sqlite::{Sqlite, SqliteType}; +#[cfg(not(all(target_family = "wasm", not(target_os = "wasi"))))] use libsqlite3_sys as ffi; +#[cfg(all(target_family = "wasm", not(target_os = "wasi")))] +use sqlite_wasm_rs::c as ffi; use std::cell::OnceCell; use std::ffi::{CStr, CString}; use std::io::{stderr, Write};