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