Skip to main content

sqlx_cloudflare_d1/
transaction.rs

1use std::future::{self, Future};
2
3use sqlx_core::error::Error;
4use sqlx_core::sql_str::SqlStr;
5use sqlx_core::transaction::TransactionManager;
6
7use crate::error::unsupported;
8use crate::{D1Connection, D1};
9
10const NO_TRANSACTIONS: &str = "D1 has no interactive transactions; \
11     send the statements together with `D1Connection::execute_batch`, \
12     which D1 runs atomically";
13
14/// Refuses every transaction.
15///
16/// D1 does not hold a transaction open across calls, so `BEGIN` cannot be
17/// followed by anything but its own statement. Buffering writes until
18/// `commit` would look like a transaction and not be one -- reads inside it
19/// would see the database as it was before -- which is worse than an error.
20/// So `conn.begin()` compiles and fails at runtime, and the atomic
21/// multi-statement case goes through `D1Connection::execute_batch`.
22#[derive(Debug)]
23pub struct D1TransactionManager;
24
25impl TransactionManager for D1TransactionManager {
26    type Database = D1;
27
28    fn begin(
29        _conn: &mut D1Connection,
30        _statement: Option<SqlStr>,
31    ) -> impl Future<Output = Result<(), Error>> + Send + '_ {
32        future::ready(Err(unsupported(NO_TRANSACTIONS)))
33    }
34
35    // Unreachable in practice: `begin` never succeeds, so there is never a
36    // transaction to end. They still answer rather than panic.
37    fn commit(_conn: &mut D1Connection) -> impl Future<Output = Result<(), Error>> + Send + '_ {
38        future::ready(Err(unsupported(NO_TRANSACTIONS)))
39    }
40
41    fn rollback(_conn: &mut D1Connection) -> impl Future<Output = Result<(), Error>> + Send + '_ {
42        future::ready(Err(unsupported(NO_TRANSACTIONS)))
43    }
44
45    // `Transaction` calls this from `Drop` when `begin` failed -- it cannot
46    // tell a failed begin from an abandoned transaction -- so it must be a
47    // quiet no-op, not an error.
48    fn start_rollback(_conn: &mut D1Connection) {}
49
50    fn get_transaction_depth(_conn: &D1Connection) -> usize {
51        0
52    }
53}