Skip to main content

Crate sqlx_cloudflare_do

Crate sqlx_cloudflare_do 

Source
Expand description

A Cloudflare Durable Objects driver for sqlx.

Do is an sqlx::Database over a Durable Object’s SQL storage, so code written against sqlx’s runtime API – sqlx::query, sqlx::query_as, #[derive(sqlx::FromRow)], Executor – runs inside a SQLite-backed Durable Object with the database type swapped.

use sqlx_cloudflare_do::{Do, DoConnection};
use worker::{durable_object, DurableObject, Env, Request, Response, State};

#[derive(sqlx::FromRow)]
struct User {
    id: i64,
    name: String,
}

#[durable_object]
pub struct Users {
    conn: DoConnection,
}

impl DurableObject for Users {
    fn new(state: State, _env: Env) -> Self {
        // One connection for the object's lifetime: it is only a handle to
        // storage the object already owns.
        Self { conn: DoConnection::new(state.storage()) }
    }

    async fn fetch(&self, _req: Request) -> worker::Result<Response> {
        let user = sqlx::query_as::<Do, User>("SELECT id, name FROM users WHERE id = ?")
            .bind(1_i64)
            .fetch_one(&self.conn)
            .await
            .map_err(|e| worker::Error::RustError(e.to_string()))?;

        Response::ok(user.name)
    }
}

The database lives in the Durable Object: queries never leave the process, and each one runs to completion before its future first returns. The class must be declared with new_sqlite_classes in wrangler.toml – the key-value-backed kind has no SQL storage.

§What Durable Object storage cannot do

Each of these fails loudly rather than pretending:

  • begin(). It returns an error: sql.exec rejects BEGIN and SAVEPOINT. Transactions take a callback instead – DoConnection::transaction – and DoConnection::execute_batch runs several statements atomically without one.
  • Integers beyond ±(2^53 − 1). Values cross as JavaScript numbers, so binding a wider i64 is an encode error rather than a rounded value. See types.
  • query! and describe. sqlx’s macros only know its built-in drivers, and sql.exec cannot describe a statement without running it.

There is no sqlx::Pool either – a Durable Object’s storage has nothing to pool – and no sqlx::migrate!.

This crate only runs on wasm32-unknown-unknown, inside a Worker. It compiles on other targets so that docs, unit tests and cargo check work, but its Send impls lean on Durable Objects being single-threaded: do not call it from a threaded host.

Modules§

types
Encode, Decode and Type for the Rust types Durable Object storage can store.

Structs§

Do
The Cloudflare Durable Object storage driver: the type sqlx code names in Executor<'_, Database = Do>, sqlx::query_as::<Do, _> and so on.
DoArguments
The parameters bound to one query, in placeholder order.
DoColumn
A column of a Durable Object storage result.
DoConnectOptions
The options type sqlx requires of every connection.
DoConnection
A connection to a Durable Object’s SQL storage.
DoDatabaseError
An error the database returned for a statement.
DoQueryResult
What a statement did.
DoRow
A row of a Durable Object storage result.
DoStatement
A “prepared” Durable Object storage statement: the SQL and nothing else.
DoTransaction
An open transaction: the executor DoConnection::transaction hands its callback.
DoTransactionManager
Refuses begin().
DoValue
A value read out of a Durable Object storage result, already converted from JavaScript.
DoValueRef
A borrowed DoValue, which is what Decode implementations read.

Enums§

DoArgumentValue
One SQLite value on the Rust side of the JavaScript boundary, in either direction: a parameter a query binds, or a value a result row holds.
DoTypeInfo
The storage class of a single value, which is all these backends report.

Traits§

DoExecutor
An executor for Durable Object storage: &DoConnection or &mut DoConnection.

Type Aliases§

DoBatchResult
What one statement of a DoConnection::fetch_batch did, and the rows it returned.