Skip to main content

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