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
//! The execution layer's traits, owned by no driver.
//!
//! Layer 1 builds a statement — `Query::build()` hands back `(String,
//! Vec<Value>)`, synchronously, with no driver in the loop. This crate is
//! everything between that pair and a mapped Rust value coming back out of a
//! real database, expressed as traits a backend crate implements:
//!
//! - [`Executor`] — object-safe, three methods, `&self`. A pool, a connection
//! and a [`Transaction`] all implement it, so `&dyn Executor` is the type
//! application code, generated models and hooks pass around.
//! - [`Execute`] — the ergonomic verbs, blanket-implemented on every
//! [`Query`](keelson_core::Query): `q.fetch_all(&db)`, `q.fetch_one(&db)`,
//! `q.execute(&db)`. Tracing (feature `tracing`) lives here, in the one
//! funnel every backend flows through.
//! - [`Transaction`] and [`Begin`] — an owned, lifetime-free transaction that
//! consumes itself on commit/rollback; savepoints are closures.
//! [`BeginWith`] adds isolation levels and access modes ([`TxOptions`]),
//! refusing per engine anything that engine would only appear to honour.
//! [`Atomic`] is the one a *reusable* unit of work takes: a transaction at
//! the top, a savepoint inside one, and the same call site either way.
//! - [`Row`] and [`FromRow`] — rows decoded once, at the driver seam, into
//! [`Value`](keelson_core::Value)s; every decode error names its column.
//! - [`RawConnection`] — the seam a backend implements per driver; this crate
//! owns the transaction SQL (`BEGIN`/`COMMIT`/`SAVEPOINT …`) so its
//! semantics cannot drift between backends.
//!
//! # Which one does my function take?
//!
//! The question every signature in an application asks, and the answer is a
//! **capability**, not a style. Each row may do everything above it:
//!
//! | parameter | what the function may do |
//! |---|---|
//! | `db: &dyn Executor` | run statements |
//! | `db: impl Atomic` | …and carve one all-or-nothing block out of wherever it turns out to be |
//! | `db: impl Begin` (a pool) | …and start a transaction, with an isolation level |
//! | `db: &Transaction` | …and commit or roll it back — and, on purpose, *not* `begin`: nesting is spelled [`savepoint`](Transaction::savepoint) |
//!
//! **Take the weakest row that does the job.** A repository method that runs
//! one statement takes `&dyn Executor`; a unit of work that must not
//! half-apply takes [`impl Atomic`](Atomic); a usecase saying "a transaction
//! begins here" takes a pool and calls [`within`](BeginExt::within).
//!
//! The ladder only goes downward. An `impl Atomic` can be handed on as
//! `&dyn Executor`, and so can a [`Transaction`] — but nothing recovers a
//! scope from `&dyn Executor`, because erasing it threw away whether a
//! transaction is open. That one-way street is a safety property rather than
//! a limitation: a hook receives `&dyn Executor` not because hooks are
//! trusted, but because the type it is given has no method that could end the
//! caller's transaction.
//!
//! It is also why the spellings differ. [`Executor`]'s three methods are
//! object-safe, so it is erased and compiles once; [`Atomic::atomic`] takes
//! the caller's closure, whose type differs at every call site, so it can
//! only be generic — and being generic is exactly what lets it open a scope.
//! `impl Atomic` still accepts everything: `&pool`, `pool`, `Arc<pool>`,
//! `&dyn Begin`, and the `&Transaction` a scope closure hands you.
//!
//! The full design, with every rejected alternative, is `docs/execution.md`.
//! The type-by-type binding contract backends implement against is
//! `docs/type-mappings.md`.
//!
//! No public type here carries a lifetime parameter (the house rule); the only
//! lifetimes are the transient `'_` on futures borrowed from `&self` for one
//! call. Nothing here names a driver: Layer 2's generated models depend on
//! this crate and pick up a backend only in the application's own `Cargo.toml`.
//!
//! # Where this sits
//!
//! Layer 2 of keelson, and the half of it that names no driver. Below:
//! [keelson-core](https://docs.rs/keelson-core) and the dialect crates, which build the
//! `(String, Vec<Value>)` these traits carry. Beside: [keelson-sqlx](https://docs.rs/keelson-sqlx),
//! the backend that implements them over sqlx's PostgreSQL, MySQL and SQLite
//! drivers. Above: [keelson-models](https://docs.rs/keelson-models), whose generated models
//! execute through `&dyn Executor` and therefore through whatever backend the
//! application picked. The whole map is the [keelson](https://docs.rs/keelson) facade crate.
pub use ;
pub use ExecError;
pub use Execute;
pub use ;
pub use ;
pub use ;
// For `bind_newtype!` expansion only.
pub use keelson_core as __core;