1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
//! A Cloudflare Durable Objects driver for sqlx.
//!
//! [`Do`] is an [`sqlx::Database`](sqlx_core::database::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.
//!
//! ```no_run
//! 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.
pub use DoArguments;
pub use DoColumn;
pub use ;
pub use Do;
pub use DoRow;
pub use DoStatement;
pub use ;
pub use ;
// The types Durable Object storage shares with D1, under this crate's names:
// both are SQLite behind a JavaScript API, so they are the same types
// underneath.
pub use ;
/// What one statement of a [`DoConnection::fetch_batch`] did, and the rows it
/// returned.
pub type DoBatchResult = BatchResult;
/// An executor for Durable Object storage: `&DoConnection` or
/// `&mut DoConnection`.
// NOTE: required due to the lack of lazy normalization
impl_into_arguments_for_arguments!;
impl_column_index_for_row!;
impl_column_index_for_statement!;
impl_acquire!;
impl_encode_for_option!;