1use drizzle_core::Token;
2pub use drizzle_core::{
4 OrderBy, SQL, ToSQL,
5 traits::{SQLSchema, SQLTable},
6};
7
8use crate::{
10 ToPostgresSQL, common::PostgresSchemaType, traits::PostgresTable, values::PostgresValue,
11};
12use std::{fmt::Debug, marker::PhantomData};
13
14pub mod cte;
16pub mod delete;
17pub mod insert;
18pub mod prepared;
19pub mod select;
20pub mod update;
21
22pub use cte::{CTEDefinition, CTEView};
24
25pub use delete::{DeleteInitial, DeleteReturningSet, DeleteWhereSet};
27pub use insert::{
28 Conflict, InsertInitial, InsertOnConflictSet, InsertReturningSet, InsertValuesSet,
29};
30pub use select::{
31 SelectFromSet, SelectGroupSet, SelectInitial, SelectJoinSet, SelectLimitSet, SelectOffsetSet,
32 SelectOrderSet, SelectWhereSet,
33};
34pub use update::{UpdateInitial, UpdateReturningSet, UpdateSetClauseSet, UpdateWhereSet};
35
36#[derive(Debug, Clone)]
42pub struct OrderByClause<'a> {
43 pub expr: SQL<'a, PostgresValue<'a>>,
45 pub direction: OrderBy,
47}
48
49impl<'a> OrderByClause<'a> {
50 pub const fn new(expr: SQL<'a, PostgresValue<'a>>, direction: OrderBy) -> Self {
52 Self { expr, direction }
53 }
54}
55
56pub trait BuilderState {}
57
58#[derive(Debug, Clone)]
59pub struct BuilderInit;
60
61#[derive(Debug, Clone)]
62pub struct CTEInit;
63
64impl BuilderState for BuilderInit {}
65impl ExecutableState for BuilderInit {}
66
67impl ExecutableState for CTEInit {}
68
69#[derive(Debug, Clone, Default)]
74pub struct QueryBuilder<'a, Schema = (), State = (), Table = ()> {
75 pub sql: SQL<'a, PostgresValue<'a>>,
76 schema: PhantomData<Schema>,
77 state: PhantomData<State>,
78 table: PhantomData<Table>,
79}
80
81impl<'a, Schema, State, Table> ToSQL<'a, PostgresValue<'a>>
86 for QueryBuilder<'a, Schema, State, Table>
87{
88 fn to_sql(&self) -> SQL<'a, PostgresValue<'a>> {
89 self.sql.clone()
90 }
91}
92
93impl<'a> QueryBuilder<'a> {
94 pub const fn new<S>() -> QueryBuilder<'a, S, BuilderInit> {
96 QueryBuilder {
97 sql: SQL::empty(),
98 schema: PhantomData,
99 state: PhantomData,
100 table: PhantomData,
101 }
102 }
103}
104
105impl<'a, Schema, State> QueryBuilder<'a, Schema, State>
106where
107 State: BuilderState,
108{
109 pub fn select<T>(&self, columns: T) -> select::SelectBuilder<'a, Schema, select::SelectInitial>
110 where
111 T: ToPostgresSQL<'a>,
112 {
113 let sql = crate::helpers::select(columns);
114 select::SelectBuilder {
115 sql,
116 schema: PhantomData,
117 state: PhantomData,
118 table: PhantomData,
119 }
120 }
121}
122
123impl<'a, Schema> QueryBuilder<'a, Schema, CTEInit> {
124 pub fn select<T>(&self, columns: T) -> select::SelectBuilder<'a, Schema, select::SelectInitial>
125 where
126 T: ToPostgresSQL<'a>,
127 {
128 let sql = self.sql.clone().append(crate::helpers::select(columns));
129 select::SelectBuilder {
130 sql,
131 schema: PhantomData,
132 state: PhantomData,
133 table: PhantomData,
134 }
135 }
136
137 pub fn with<C>(&self, cte: C) -> QueryBuilder<'a, Schema, CTEInit>
138 where
139 C: CTEDefinition<'a>,
140 {
141 let sql = self
142 .sql
143 .clone()
144 .push(Token::COMMA)
145 .append(cte.cte_definition());
146 QueryBuilder {
147 sql,
148 schema: PhantomData,
149 state: PhantomData,
150 table: PhantomData,
151 }
152 }
153}
154
155impl<'a, Schema, State> QueryBuilder<'a, Schema, State>
156where
157 State: BuilderState,
158{
159 pub fn insert<Table>(
160 &self,
161 table: Table,
162 ) -> insert::InsertBuilder<'a, Schema, insert::InsertInitial, Table>
163 where
164 Table: PostgresTable<'a>,
165 {
166 let sql = crate::helpers::insert(table);
167
168 insert::InsertBuilder {
169 sql,
170 schema: PhantomData,
171 state: PhantomData,
172 table: PhantomData,
173 }
174 }
175
176 pub fn update<Table>(
177 &self,
178 table: Table,
179 ) -> update::UpdateBuilder<'a, Schema, update::UpdateInitial, Table>
180 where
181 Table: PostgresTable<'a>,
182 {
183 let sql = crate::helpers::update::<'a, Table, PostgresSchemaType, PostgresValue<'a>>(table);
184
185 update::UpdateBuilder {
186 sql,
187 schema: PhantomData,
188 state: PhantomData,
189 table: PhantomData,
190 }
191 }
192
193 pub fn delete<Table>(
194 &self,
195 table: Table,
196 ) -> delete::DeleteBuilder<'a, Schema, delete::DeleteInitial, Table>
197 where
198 Table: PostgresTable<'a>,
199 {
200 let sql = crate::helpers::delete::<'a, Table, PostgresSchemaType, PostgresValue<'a>>(table);
201
202 delete::DeleteBuilder {
203 sql,
204 schema: PhantomData,
205 state: PhantomData,
206 table: PhantomData,
207 }
208 }
209
210 pub fn with<C>(&self, cte: C) -> QueryBuilder<'a, Schema, CTEInit>
211 where
212 C: CTEDefinition<'a>,
213 {
214 let sql = SQL::from(Token::WITH).append(cte.cte_definition());
215 QueryBuilder {
216 sql,
217 schema: PhantomData,
218 state: PhantomData,
219 table: PhantomData,
220 }
221 }
222}
223
224pub trait ExecutableState {}
226
227#[cfg(test)]
228mod tests {
229 use super::*;
230
231 #[test]
232 fn test_query_builder_new() {
233 let qb = QueryBuilder::new::<()>();
234 let sql = qb.to_sql();
235 assert_eq!(sql.sql(), "");
236 assert_eq!(sql.params().len(), 0);
237 }
238
239 #[test]
240 fn test_builder_state_trait() {
241 fn assert_builder_state<T: BuilderState>() {}
243
244 assert_builder_state::<BuilderInit>();
245 }
246}