1use drizzle_core::Token;
2pub use drizzle_core::builder::{BuilderInit, ExecutableState, OrderByClause};
4pub use drizzle_core::{
5 OrderBy, SQL, ToSQL,
6 traits::{SQLSchema, SQLTable},
7};
8
9use crate::{common::PostgresSchemaType, traits::PostgresTable, values::PostgresValue};
11use std::{fmt::Debug, marker::PhantomData};
12
13pub mod cte;
15pub mod delete;
16pub mod insert;
17pub mod prepared;
18pub mod refresh;
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 refresh::{
31 RefreshConcurrently, RefreshInitial, RefreshMaterializedView, RefreshWithNoData,
32 refresh_materialized_view,
33};
34pub use select::{
35 SelectForSet, SelectFromSet, SelectGroupSet, SelectInitial, SelectJoinSet, SelectLimitSet,
36 SelectOffsetSet, SelectOrderSet, SelectWhereSet,
37};
38pub use update::{
39 UpdateFromSet, UpdateInitial, UpdateReturningSet, UpdateSetClauseSet, UpdateWhereSet,
40};
41
42pub use drizzle_core::traits::SQLViewInfo;
44
45#[derive(Debug, Clone)]
46pub struct CTEInit;
47
48impl ExecutableState for CTEInit {}
49
50#[derive(Debug, Clone, Default)]
55pub struct QueryBuilder<'a, Schema = (), State = (), Table = ()> {
56 pub sql: SQL<'a, PostgresValue<'a>>,
57 schema: PhantomData<Schema>,
58 state: PhantomData<State>,
59 table: PhantomData<Table>,
60}
61
62impl<'a, Schema, State, Table> ToSQL<'a, PostgresValue<'a>>
67 for QueryBuilder<'a, Schema, State, Table>
68{
69 fn to_sql(&self) -> SQL<'a, PostgresValue<'a>> {
70 self.sql.clone()
71 }
72}
73
74impl<'a> QueryBuilder<'a> {
75 pub const fn new<S>() -> QueryBuilder<'a, S, BuilderInit> {
77 QueryBuilder {
78 sql: SQL::empty(),
79 schema: PhantomData,
80 state: PhantomData,
81 table: PhantomData,
82 }
83 }
84}
85
86impl<'a, Schema> QueryBuilder<'a, Schema, BuilderInit> {
87 pub fn select<T>(&self, columns: T) -> select::SelectBuilder<'a, Schema, select::SelectInitial>
88 where
89 T: ToSQL<'a, PostgresValue<'a>>,
90 {
91 let sql = crate::helpers::select(columns);
92 select::SelectBuilder {
93 sql,
94 schema: PhantomData,
95 state: PhantomData,
96 table: PhantomData,
97 }
98 }
99
100 pub fn select_distinct<T>(
104 &self,
105 columns: T,
106 ) -> select::SelectBuilder<'a, Schema, select::SelectInitial>
107 where
108 T: ToSQL<'a, PostgresValue<'a>>,
109 {
110 let sql = crate::helpers::select_distinct(columns);
111 select::SelectBuilder {
112 sql,
113 schema: PhantomData,
114 state: PhantomData,
115 table: PhantomData,
116 }
117 }
118
119 pub fn select_distinct_on<On, Columns>(
121 &self,
122 on: On,
123 columns: Columns,
124 ) -> select::SelectBuilder<'a, Schema, select::SelectInitial>
125 where
126 On: ToSQL<'a, PostgresValue<'a>>,
127 Columns: ToSQL<'a, PostgresValue<'a>>,
128 {
129 let sql = crate::helpers::select_distinct_on(on, columns);
130 select::SelectBuilder {
131 sql,
132 schema: PhantomData,
133 state: PhantomData,
134 table: PhantomData,
135 }
136 }
137}
138
139impl<'a, Schema> QueryBuilder<'a, Schema, CTEInit> {
140 pub fn select<T>(&self, columns: T) -> select::SelectBuilder<'a, Schema, select::SelectInitial>
141 where
142 T: ToSQL<'a, PostgresValue<'a>>,
143 {
144 let sql = self.sql.clone().append(crate::helpers::select(columns));
145 select::SelectBuilder {
146 sql,
147 schema: PhantomData,
148 state: PhantomData,
149 table: PhantomData,
150 }
151 }
152
153 pub fn select_distinct<T>(
155 &self,
156 columns: T,
157 ) -> select::SelectBuilder<'a, Schema, select::SelectInitial>
158 where
159 T: ToSQL<'a, PostgresValue<'a>>,
160 {
161 let sql = self
162 .sql
163 .clone()
164 .append(crate::helpers::select_distinct(columns));
165 select::SelectBuilder {
166 sql,
167 schema: PhantomData,
168 state: PhantomData,
169 table: PhantomData,
170 }
171 }
172
173 pub fn select_distinct_on<On, Columns>(
175 &self,
176 on: On,
177 columns: Columns,
178 ) -> select::SelectBuilder<'a, Schema, select::SelectInitial>
179 where
180 On: ToSQL<'a, PostgresValue<'a>>,
181 Columns: ToSQL<'a, PostgresValue<'a>>,
182 {
183 let sql = self
184 .sql
185 .clone()
186 .append(crate::helpers::select_distinct_on(on, columns));
187 select::SelectBuilder {
188 sql,
189 schema: PhantomData,
190 state: PhantomData,
191 table: PhantomData,
192 }
193 }
194
195 pub fn insert<Table>(
197 &self,
198 table: Table,
199 ) -> insert::InsertBuilder<'a, Schema, insert::InsertInitial, Table>
200 where
201 Table: PostgresTable<'a>,
202 {
203 let sql = self.sql.clone().append(crate::helpers::insert(table));
204
205 insert::InsertBuilder {
206 sql,
207 schema: PhantomData,
208 state: PhantomData,
209 table: PhantomData,
210 }
211 }
212
213 pub fn update<Table>(
215 &self,
216 table: Table,
217 ) -> update::UpdateBuilder<'a, Schema, update::UpdateInitial, Table>
218 where
219 Table: PostgresTable<'a>,
220 {
221 let sql = self.sql.clone().append(crate::helpers::update::<
222 'a,
223 Table,
224 PostgresSchemaType,
225 PostgresValue<'a>,
226 >(table));
227
228 update::UpdateBuilder {
229 sql,
230 schema: PhantomData,
231 state: PhantomData,
232 table: PhantomData,
233 }
234 }
235
236 pub fn delete<Table>(
238 &self,
239 table: Table,
240 ) -> delete::DeleteBuilder<'a, Schema, delete::DeleteInitial, Table>
241 where
242 Table: PostgresTable<'a>,
243 {
244 let sql = self.sql.clone().append(crate::helpers::delete::<
245 'a,
246 Table,
247 PostgresSchemaType,
248 PostgresValue<'a>,
249 >(table));
250
251 delete::DeleteBuilder {
252 sql,
253 schema: PhantomData,
254 state: PhantomData,
255 table: PhantomData,
256 }
257 }
258
259 pub fn with<C>(&self, cte: C) -> QueryBuilder<'a, Schema, CTEInit>
260 where
261 C: CTEDefinition<'a>,
262 {
263 let sql = self
264 .sql
265 .clone()
266 .push(Token::COMMA)
267 .append(cte.cte_definition());
268 QueryBuilder {
269 sql,
270 schema: PhantomData,
271 state: PhantomData,
272 table: PhantomData,
273 }
274 }
275}
276
277impl<'a, Schema> QueryBuilder<'a, Schema, BuilderInit> {
278 pub fn insert<Table>(
279 &self,
280 table: Table,
281 ) -> insert::InsertBuilder<'a, Schema, insert::InsertInitial, Table>
282 where
283 Table: PostgresTable<'a>,
284 {
285 let sql = crate::helpers::insert(table);
286
287 insert::InsertBuilder {
288 sql,
289 schema: PhantomData,
290 state: PhantomData,
291 table: PhantomData,
292 }
293 }
294
295 pub fn update<Table>(
296 &self,
297 table: Table,
298 ) -> update::UpdateBuilder<'a, Schema, update::UpdateInitial, Table>
299 where
300 Table: PostgresTable<'a>,
301 {
302 let sql = crate::helpers::update::<'a, Table, PostgresSchemaType, PostgresValue<'a>>(table);
303
304 update::UpdateBuilder {
305 sql,
306 schema: PhantomData,
307 state: PhantomData,
308 table: PhantomData,
309 }
310 }
311
312 pub fn delete<Table>(
313 &self,
314 table: Table,
315 ) -> delete::DeleteBuilder<'a, Schema, delete::DeleteInitial, Table>
316 where
317 Table: PostgresTable<'a>,
318 {
319 let sql = crate::helpers::delete::<'a, Table, PostgresSchemaType, PostgresValue<'a>>(table);
320
321 delete::DeleteBuilder {
322 sql,
323 schema: PhantomData,
324 state: PhantomData,
325 table: PhantomData,
326 }
327 }
328
329 pub fn with<C>(&self, cte: C) -> QueryBuilder<'a, Schema, CTEInit>
330 where
331 C: CTEDefinition<'a>,
332 {
333 let sql = SQL::from(Token::WITH).append(cte.cte_definition());
334 QueryBuilder {
335 sql,
336 schema: PhantomData,
337 state: PhantomData,
338 table: PhantomData,
339 }
340 }
341}
342
343#[cfg(test)]
345mod tests {
346 use super::*;
347
348 #[test]
349 fn test_query_builder_new() {
350 let qb = QueryBuilder::new::<()>();
351 let sql = qb.to_sql();
352 assert_eq!(sql.sql(), "");
353 assert_eq!(sql.params().count(), 0);
354 }
355
356 #[test]
357 fn test_builder_init_type() {
358 let _state = BuilderInit;
359 }
360}