persistant_relational/backend.rs
1// SPDX-License-Identifier: MIT OR Apache-2.0
2use crate::{Dialect, RelError, Row, Value};
3use std::future::Future;
4
5/// The isolation level a transaction asks for. A backend gives the level asked for or a stronger one;
6/// which it can actually show is what the `rel.isolation.*` leaves certify.
7#[derive(Debug, Clone, Copy, Default, PartialEq, Eq, Hash)]
8#[non_exhaustive]
9pub enum Isolation {
10 /// No dirty reads: the backend's usual level for a transaction here.
11 #[default]
12 ReadCommitted,
13 /// A row or count read twice in the transaction reads the same.
14 RepeatableRead,
15 /// Concurrent transactions behave as if they ran one at a time (a conflicting one fails with
16 /// [`RelError::Serialization`], or waits).
17 Serializable,
18}
19
20/// A relational database, as small as it can be.
21///
22/// Statements are written in the backend's own [`Dialect`]; parameters are positional and written
23/// as that dialect writes them (`$1` for PostgreSQL). Nothing here translates SQL.
24pub trait RelationalBackend: Send + Sync {
25 /// A transaction on this backend. Dropping it without `commit` rolls it back.
26 type Tx<'a>: RelationalTx + 'a
27 where
28 Self: 'a;
29
30 /// The backend's name as it appears in matrix rows (`postgres`).
31 fn backend(&self) -> &str;
32
33 /// The server version string as it appears in matrix rows (`16.15`).
34 fn version(&self) -> &str;
35
36 /// The dialect statements must be written in.
37 fn dialect(&self) -> Dialect;
38
39 /// Run a statement that returns no rows; the result is the number of rows affected.
40 fn execute(
41 &self,
42 sql: &str,
43 params: &[Value],
44 ) -> impl Future<Output = Result<u64, RelError>> + Send;
45
46 /// Run a statement and return its rows.
47 fn query(
48 &self,
49 sql: &str,
50 params: &[Value],
51 ) -> impl Future<Output = Result<Vec<Row>, RelError>> + Send;
52
53 /// Begin a transaction at (at least) `isolation`.
54 fn begin(
55 &self,
56 isolation: Isolation,
57 ) -> impl Future<Output = Result<Self::Tx<'_>, RelError>> + Send;
58}
59
60/// A transaction. Statements run inside it are committed or rolled back together.
61pub trait RelationalTx: Send {
62 /// As [`RelationalBackend::execute`], inside the transaction.
63 fn execute(
64 &mut self,
65 sql: &str,
66 params: &[Value],
67 ) -> impl Future<Output = Result<u64, RelError>> + Send;
68
69 /// As [`RelationalBackend::query`], inside the transaction.
70 fn query(
71 &mut self,
72 sql: &str,
73 params: &[Value],
74 ) -> impl Future<Output = Result<Vec<Row>, RelError>> + Send;
75
76 /// Commit.
77 fn commit(self) -> impl Future<Output = Result<(), RelError>> + Send;
78
79 /// Roll back.
80 fn rollback(self) -> impl Future<Output = Result<(), RelError>> + Send;
81}