sqlite-wasm-rs 0.2.1

Provide sqlite solution for wasm32-unknown-unknown target.
Documentation

SQLite Wasm Rust

Crates.io

Provide sqlite solution for wasm32-unknown-unknown target.

Shim Usage

[dependencies]
sqlite-wasm-rs = "0.2"
use sqlite_wasm_rs::export::{self as ffi, install_opfs_sahpool};

async fn open_db() -> anyhow::Result<()> {
    // open with memory vfs
    let mut db = std::ptr::null_mut();
    let ret = unsafe {
        ffi::sqlite3_open_v2(
            c"mem.db".as_ptr().cast(),
            &mut db as *mut _,
            ffi::SQLITE_OPEN_READWRITE | ffi::SQLITE_OPEN_CREATE,
            std::ptr::null()
        )
    };
    assert_eq!(ffi::SQLITE_OK, ret);

    // install opfs-sahpool persistent vfs and set as default vfs
    install_opfs_sahpool(None, true).await?;

    // open with opfs-sahpool vfs
    let mut db = std::ptr::null_mut();
    let ret = unsafe {
        ffi::sqlite3_open_v2(
            c"opfs-sahpool.db".as_ptr().cast(),
            &mut db as *mut _,
            ffi::SQLITE_OPEN_READWRITE | ffi::SQLITE_OPEN_CREATE,
            std::ptr::null()
        )
    };
    assert_eq!(ffi::SQLITE_OK, ret);
}

Wrapper Usage

[dependencies]
sqlite-wasm-rs = { version = "0.2", default-features = false, features = ["wrapper"] }

Then see Wrapper Usage

Use external libc (shim only)

As mentioned below, sqlite is now directly linked to emscripten's libc. But we provide the ability to customize libc.

Cargo provides a links field that can be used to specify which library to link to.

We created a new sqlite-wasm-libc library with no implementation and only a links = "libc" configuration.

Then with the help of Overriding Build Scripts, you can overriding its configuration in your crate and link sqlite to your custom libc.

More see custom-libc example.

Multithreading

When target-feature=+atomics is enabled, sqlite-wasm-rs support multithreading, see multithread example.

Shim VS Wrapper

Shim

Compile sqlite with -DSQLITE_OS_OTHER, linking and implement the external functions required by sqlite (malloc, realloc, sqlite3_os_init etc..). And because the wasm32-unknown-unknown target does not have libc, string functions such as strcmp need to be implemented. Finally, some web platform-specific functions need to be implemented, such as time-related functions.

Given that sqlite mainly supports emscripten, linking emscripten to wasm32-unknown-unknown is the best approach (otherwise you need to implement some methods of libc yourself). But here is a question, is wasm32-unknown-unknown now C-ABI compatible?

The rustwasm team has done a lot of work and is now compatible with the -Zwasm-c-abi compiler flag, see https://github.com/rustwasm/wasm-bindgen/issues/3454. But it doesn't mean that there will be problems if you don't use the -Zwasm-c-abi flags, see https://github.com/rustwasm/wasm-bindgen/pull/2209. At least after testing, it works without -Zwasm-c-abi.

Advantages

  • No additional wrapper, providing the highest performance.
  • The C interface does not require manual maintenance, just bindgen.
  • No need to init_sqlite() before use.

Disadvantages

The only disvantage is that VFS needs to be implemented manually, but I have implemented two pure rust version of vfs:

  • memory-vfs: as the default vfs, no additional conditions are required, just use.
  • opfs-sahpool: ported from sqlite-wasm, it provides the best performance persistent storage method.

Wrapper

Wrap the official sqlite-wasm, and expect to provide a usable C-like API.

Advantages

  • There are a variety of official persistent VFS implementations to choose from. (memvfs, opfs, opfs-sahpool, kvvfs).

Disadvantages

  • Asynchronous initialization is required before using sqlite (because sqlite.wasm needs to be initialized), which is inconvenient to use.
  • The C interface needs to be added manually, which is prone to errors.
  • Interaction with sqlite.wasm requires memory copying and memory management, which affects performance in some scenarios.

Why vendor sqlite-wasm

  • sqlite-wasm wrap some codes that are very convenient for JS, but difficult to use for rust.
  • Some sqlite C-API are not exported.

Change history: https://github.com/Spxg/sqlite

Related Project

  • sqlite-wasm: SQLite Wasm conveniently wrapped as an ES Module.
  • sqlite-web-rs: A SQLite WebAssembly backend for Diesel.
  • rusqlite: Ergonomic bindings to SQLite for Rust.