drizzle_core/builder.rs
1pub mod conflict;
2pub mod insert_select;
3pub mod states;
4
5pub use conflict::*;
6pub use insert_select::*;
7pub use states::*;
8
9/// Builder states whose query is complete and can be executed.
10///
11/// Dialect crates implement this for their builder state markers to allow
12/// execution, set operations, or prepared statements in those states.
13#[diagnostic::on_unimplemented(
14 message = "this query is not complete yet: `{Self}` cannot run",
15 label = "the query is still missing a clause",
16 note = "a DELETE or UPDATE must say which rows it changes with `.r#where(...)`; write \
17 `.r#where(true)` to change every row on purpose",
18 note = "a SELECT needs `.from(...)`, an INSERT needs `.values(...)`, and an UPDATE \
19 needs `.set(...)`"
20)]
21pub trait ExecutableState {
22 /// The row count of a query in this state whose selection alone has
23 /// [`RowCount`](crate::row::RowCount) `R`: `R` when the clauses so far
24 /// keep every row of the selection (FROM, JOIN, WHERE, ORDER BY), else
25 /// [`ZeroOrMore`](crate::row::ZeroOrMore) (LIMIT, OFFSET, a set
26 /// operation, or a statement other than SELECT).
27 type Rows<R: crate::row::RowCount>: crate::row::RowCount;
28}
29
30/// The state of a query builder before any statement has been started.
31#[derive(Debug, Clone)]
32pub struct BuilderInit;
33
34impl ExecutableState for BuilderInit {
35 type Rows<R: crate::row::RowCount> = crate::row::ZeroOrMore;
36}
37
38// =============================================================================
39// Capability marker traits for typestate method gating
40// =============================================================================
41// These allow a single generic impl block per method instead of duplicating
42// across every state that supports it.
43//
44// Used directly by the inner `SelectBuilder` impls in driver crates.
45// Wrapper builders (`DrizzleBuilder`, `TransactionBuilder`) use a declarative
46// macro to stamp out per-state impls instead, because Rust's inherent impl
47// overlap rules prevent trait-gated generics when other builder types
48// (insert/update/delete) define methods with the same name.
49
50/// Clause markers for [`ClauseAllowed`].
51///
52/// Each marker names a builder method (or a use of a whole query). A builder
53/// state implements `ClauseAllowed<clause::X>` when that method may be called
54/// next.
55pub mod clause {
56 /// `.r#where()`.
57 #[derive(Debug, Clone, Copy, Default)]
58 pub struct Where;
59 /// `.group_by()`.
60 #[derive(Debug, Clone, Copy, Default)]
61 pub struct GroupBy;
62 /// `.having()` (requires GROUP BY).
63 #[derive(Debug, Clone, Copy, Default)]
64 pub struct Having;
65 /// `.order_by()`.
66 #[derive(Debug, Clone, Copy, Default)]
67 pub struct OrderBy;
68 /// `.limit()`.
69 #[derive(Debug, Clone, Copy, Default)]
70 pub struct Limit;
71 /// `.offset()`.
72 #[derive(Debug, Clone, Copy, Default)]
73 pub struct Offset;
74 /// `.join()` and its variants.
75 #[derive(Debug, Clone, Copy, Default)]
76 pub struct Join;
77 /// Use as a CTE or with a locking clause: a single SELECT that is not a
78 /// `UNION`/`INTERSECT`/`EXCEPT`.
79 #[derive(Debug, Clone, Copy, Default)]
80 pub struct Simple;
81 /// Operand of `UNION`/`INTERSECT`/`EXCEPT`: a SELECT, possibly compound,
82 /// without a locking clause.
83 #[derive(Debug, Clone, Copy, Default)]
84 pub struct Compound;
85 /// Row source for a derived table or `INSERT ... SELECT`: any completed
86 /// SELECT. Never an INSERT/UPDATE/DELETE, even with `RETURNING`.
87 #[derive(Debug, Clone, Copy, Default)]
88 pub struct Source;
89}
90
91/// The builder state `Self` allows the clause `Clause` next.
92///
93/// SELECT builders track their progress in a state type parameter. Clause
94/// methods require `State: ClauseAllowed<clause::X>`, so calling a clause
95/// out of order (`.group_by(...)` after `.limit(...)`, `.having(...)`
96/// without `.group_by(...)`) is a compile error:
97///
98/// ```text
99/// error[E0277]: builder state `SelectLimitSet` does not allow `drizzle_core::builder::clause::GroupBy`
100/// = note: SELECT clauses go in order: FROM, JOIN, WHERE, GROUP BY, HAVING, ORDER BY, LIMIT, OFFSET
101/// ```
102///
103/// The same check stops a statement that is not a SELECT (a
104/// `DELETE ... RETURNING`, say) from being used as a subquery, set operand,
105/// derived table, or `INSERT ... SELECT` source. Dialect crates implement
106/// this for their states and may add their own clause markers for
107/// dialect-only clauses. A few methods whose names clash with INSERT /
108/// UPDATE / DELETE methods (`.r#where`, `.order_by`) use a dialect-local
109/// trait with the same error message instead.
110///
111/// # Examples
112///
113/// ```
114/// use drizzle_core::{ClauseAllowed, clause};
115///
116/// struct AfterFrom;
117/// impl ClauseAllowed<clause::Where> for AfterFrom {}
118///
119/// fn where_<S: ClauseAllowed<clause::Where>>(_state: S) {}
120///
121/// where_(AfterFrom);
122/// ```
123///
124/// ```compile_fail
125/// # use drizzle_core::{ClauseAllowed, clause};
126/// # struct AfterLimit;
127/// fn where_<S: ClauseAllowed<clause::Where>>(_state: S) {}
128///
129/// // error: builder state `AfterLimit` does not allow `Where`
130/// where_(AfterLimit);
131/// ```
132#[diagnostic::on_unimplemented(
133 message = "builder state `{Self}` does not allow `{Clause}`",
134 label = "not available at this point of the query",
135 note = "SELECT clauses go in order: FROM, JOIN, WHERE, GROUP BY, HAVING, ORDER BY, LIMIT, OFFSET",
136 note = "only a SELECT can be a set operand, a subquery, a derived table, or an INSERT source"
137)]
138pub trait ClauseAllowed<Clause> {}