1use drizzle_core::Token;
2pub use drizzle_core::builder::{BuilderInit, ExecutableState};
4pub use drizzle_core::{
5 OrderBy, SQL, ToSQL,
6 traits::{SQLSchema, SQLTable},
7};
8
9use crate::{common::PostgresSchemaType, traits::PostgresTable, values::PostgresValue};
11use core::{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 InsertDoUpdateSet, InsertInitial, InsertOnConflictSet, InsertReturningSet, InsertValuesSet,
29 OnConflictBuilder,
30};
31pub use refresh::{
32 RefreshConcurrently, RefreshInitial, RefreshMaterializedView, RefreshWithNoData,
33 refresh_materialized_view,
34};
35pub use select::{
36 SelectForSet, SelectFromSet, SelectGroupSet, SelectInitial, SelectJoinSet, SelectLimitSet,
37 SelectOffsetSet, SelectOrderSet, SelectSetOpSet, SelectWhereSet,
38};
39pub use update::{
40 UpdateFromSet, UpdateInitial, UpdateReturningSet, UpdateSetClauseSet, UpdateWhereSet,
41};
42
43pub use drizzle_core::traits::SQLViewInfo;
45
46#[derive(Debug, Clone)]
47pub struct CTEInit;
48
49impl ExecutableState for CTEInit {}
50
51#[derive(Debug, Clone, Default)]
56pub struct QueryBuilder<
57 'a,
58 Schema = (),
59 State = (),
60 Table = (),
61 Marker = (),
62 Row = (),
63 Grouped = (),
64> {
65 pub sql: SQL<'a, PostgresValue<'a>>,
66 schema: PhantomData<Schema>,
67 state: PhantomData<State>,
68 table: PhantomData<Table>,
69 marker: PhantomData<Marker>,
70 row: PhantomData<Row>,
71 grouped: PhantomData<Grouped>,
72}
73
74impl<'a, Schema, State, Table, Marker, Row, Grouped> ToSQL<'a, PostgresValue<'a>>
79 for QueryBuilder<'a, Schema, State, Table, Marker, Row, Grouped>
80{
81 fn to_sql(&self) -> SQL<'a, PostgresValue<'a>> {
82 self.sql.clone()
83 }
84}
85
86impl<'a, Schema, State, Table, Marker, Row, Grouped>
87 QueryBuilder<'a, Schema, State, Table, Marker, Row, Grouped>
88where
89 State: ExecutableState,
90{
91 #[must_use]
98 pub fn comment(mut self, text: impl AsRef<str>) -> Self {
99 let fragment = drizzle_core::sql::comment::<PostgresValue<'a>>(text);
100 if fragment.chunks.is_empty() {
101 return self;
102 }
103 let existing = core::mem::replace(&mut self.sql, fragment);
104 self.sql.append_mut(existing);
105 self
106 }
107
108 #[must_use]
115 pub fn comment_tags<I, K, V>(mut self, pairs: I) -> Self
116 where
117 I: IntoIterator<Item = (K, V)>,
118 K: AsRef<str>,
119 V: AsRef<str>,
120 {
121 let fragment = drizzle_core::sql::comment_tags::<PostgresValue<'a>, _, _, _>(pairs);
122 if fragment.chunks.is_empty() {
123 return self;
124 }
125 let existing = core::mem::replace(&mut self.sql, fragment);
126 self.sql.append_mut(existing);
127 self
128 }
129}
130
131impl<'a> QueryBuilder<'a> {
132 #[must_use]
134 pub const fn new<S>() -> QueryBuilder<'a, S, BuilderInit> {
135 QueryBuilder {
136 sql: SQL::empty(),
137 schema: PhantomData,
138 state: PhantomData,
139 table: PhantomData,
140 marker: PhantomData,
141 row: PhantomData,
142 grouped: PhantomData,
143 }
144 }
145}
146
147impl<'a, Schema> QueryBuilder<'a, Schema, BuilderInit> {
148 pub fn select<T>(
152 &self,
153 columns: T,
154 ) -> select::SelectBuilder<'a, Schema, select::SelectInitial, (), T::Marker>
155 where
156 T: ToSQL<'a, PostgresValue<'a>> + drizzle_core::IntoSelectTarget,
157 {
158 let sql = crate::helpers::select(columns);
159 select::SelectBuilder {
160 sql,
161 schema: PhantomData,
162 state: PhantomData,
163 table: PhantomData,
164 marker: PhantomData,
165 row: PhantomData,
166 grouped: PhantomData,
167 }
168 }
169
170 pub fn select_distinct<T>(
174 &self,
175 columns: T,
176 ) -> select::SelectBuilder<'a, Schema, select::SelectInitial, (), T::Marker>
177 where
178 T: ToSQL<'a, PostgresValue<'a>> + drizzle_core::IntoSelectTarget,
179 {
180 let sql = crate::helpers::select_distinct(columns);
181 select::SelectBuilder {
182 sql,
183 schema: PhantomData,
184 state: PhantomData,
185 table: PhantomData,
186 marker: PhantomData,
187 row: PhantomData,
188 grouped: PhantomData,
189 }
190 }
191
192 pub fn select_distinct_on<On, Columns>(
197 &self,
198 on: On,
199 columns: Columns,
200 ) -> select::SelectBuilder<'a, Schema, select::SelectInitial, (), Columns::Marker>
201 where
202 On: ToSQL<'a, PostgresValue<'a>>,
203 Columns: ToSQL<'a, PostgresValue<'a>> + drizzle_core::IntoSelectTarget,
204 {
205 let sql = crate::helpers::select_distinct_on(on, columns);
206 select::SelectBuilder {
207 sql,
208 schema: PhantomData,
209 state: PhantomData,
210 table: PhantomData,
211 marker: PhantomData,
212 row: PhantomData,
213 grouped: PhantomData,
214 }
215 }
216}
217
218impl<'a, Schema> QueryBuilder<'a, Schema, CTEInit> {
219 pub fn select<T>(
221 &self,
222 columns: T,
223 ) -> select::SelectBuilder<'a, Schema, select::SelectInitial, (), T::Marker>
224 where
225 T: ToSQL<'a, PostgresValue<'a>> + drizzle_core::IntoSelectTarget,
226 {
227 let sql = self.sql.clone().append(crate::helpers::select(columns));
228 select::SelectBuilder {
229 sql,
230 schema: PhantomData,
231 state: PhantomData,
232 table: PhantomData,
233 marker: PhantomData,
234 row: PhantomData,
235 grouped: PhantomData,
236 }
237 }
238
239 pub fn select_distinct<T>(
241 &self,
242 columns: T,
243 ) -> select::SelectBuilder<'a, Schema, select::SelectInitial, (), T::Marker>
244 where
245 T: ToSQL<'a, PostgresValue<'a>> + drizzle_core::IntoSelectTarget,
246 {
247 let sql = self
248 .sql
249 .clone()
250 .append(crate::helpers::select_distinct(columns));
251 select::SelectBuilder {
252 sql,
253 schema: PhantomData,
254 state: PhantomData,
255 table: PhantomData,
256 marker: PhantomData,
257 row: PhantomData,
258 grouped: PhantomData,
259 }
260 }
261
262 pub fn select_distinct_on<On, Columns>(
264 &self,
265 on: On,
266 columns: Columns,
267 ) -> select::SelectBuilder<'a, Schema, select::SelectInitial, (), Columns::Marker>
268 where
269 On: ToSQL<'a, PostgresValue<'a>>,
270 Columns: ToSQL<'a, PostgresValue<'a>> + drizzle_core::IntoSelectTarget,
271 {
272 let sql = self
273 .sql
274 .clone()
275 .append(crate::helpers::select_distinct_on(on, columns));
276 select::SelectBuilder {
277 sql,
278 schema: PhantomData,
279 state: PhantomData,
280 table: PhantomData,
281 marker: PhantomData,
282 row: PhantomData,
283 grouped: PhantomData,
284 }
285 }
286
287 pub fn insert<Table>(
289 &self,
290 table: Table,
291 ) -> insert::InsertBuilder<'a, Schema, insert::InsertInitial, Table>
292 where
293 Table: PostgresTable<'a>,
294 {
295 let sql = self
296 .sql
297 .clone()
298 .append(crate::helpers::insert::<Table>(&table));
299
300 insert::InsertBuilder {
301 sql,
302 schema: PhantomData,
303 state: PhantomData,
304 table: PhantomData,
305 marker: PhantomData,
306 row: PhantomData,
307 grouped: PhantomData,
308 }
309 }
310
311 pub fn update<Table>(
313 &self,
314 table: Table,
315 ) -> update::UpdateBuilder<'a, Schema, update::UpdateInitial, Table>
316 where
317 Table: PostgresTable<'a>,
318 {
319 let sql = self.sql.clone().append(crate::helpers::update::<
320 Table,
321 PostgresSchemaType,
322 PostgresValue<'a>,
323 >(&table));
324
325 update::UpdateBuilder {
326 sql,
327 schema: PhantomData,
328 state: PhantomData,
329 table: PhantomData,
330 marker: PhantomData,
331 row: PhantomData,
332 grouped: PhantomData,
333 }
334 }
335
336 pub fn delete<Table>(
338 &self,
339 table: Table,
340 ) -> delete::DeleteBuilder<'a, Schema, delete::DeleteInitial, Table>
341 where
342 Table: PostgresTable<'a>,
343 {
344 let sql = self.sql.clone().append(crate::helpers::delete::<
345 Table,
346 PostgresSchemaType,
347 PostgresValue<'a>,
348 >(&table));
349
350 delete::DeleteBuilder {
351 sql,
352 schema: PhantomData,
353 state: PhantomData,
354 table: PhantomData,
355 marker: PhantomData,
356 row: PhantomData,
357 grouped: PhantomData,
358 }
359 }
360
361 #[must_use]
362 pub fn with<C>(&self, cte: &C) -> Self
363 where
364 C: CTEDefinition<'a>,
365 {
366 let sql = self
367 .sql
368 .clone()
369 .push(Token::COMMA)
370 .append(cte.cte_definition());
371 QueryBuilder {
372 sql,
373 schema: PhantomData,
374 state: PhantomData,
375 table: PhantomData,
376 marker: PhantomData,
377 row: PhantomData,
378 grouped: PhantomData,
379 }
380 }
381}
382
383impl<'a, Schema> QueryBuilder<'a, Schema, BuilderInit> {
384 pub fn insert<Table>(
386 &self,
387 table: Table,
388 ) -> insert::InsertBuilder<'a, Schema, insert::InsertInitial, Table>
389 where
390 Table: PostgresTable<'a>,
391 {
392 let sql = crate::helpers::insert::<Table>(&table);
393
394 insert::InsertBuilder {
395 sql,
396 schema: PhantomData,
397 state: PhantomData,
398 table: PhantomData,
399 marker: PhantomData,
400 row: PhantomData,
401 grouped: PhantomData,
402 }
403 }
404
405 pub fn update<Table>(
407 &self,
408 table: Table,
409 ) -> update::UpdateBuilder<'a, Schema, update::UpdateInitial, Table>
410 where
411 Table: PostgresTable<'a>,
412 {
413 let sql = crate::helpers::update::<Table, PostgresSchemaType, PostgresValue<'a>>(&table);
414
415 update::UpdateBuilder {
416 sql,
417 schema: PhantomData,
418 state: PhantomData,
419 table: PhantomData,
420 marker: PhantomData,
421 row: PhantomData,
422 grouped: PhantomData,
423 }
424 }
425
426 pub fn delete<Table>(
428 &self,
429 table: Table,
430 ) -> delete::DeleteBuilder<'a, Schema, delete::DeleteInitial, Table>
431 where
432 Table: PostgresTable<'a>,
433 {
434 let sql = crate::helpers::delete::<Table, PostgresSchemaType, PostgresValue<'a>>(&table);
435
436 delete::DeleteBuilder {
437 sql,
438 schema: PhantomData,
439 state: PhantomData,
440 table: PhantomData,
441 marker: PhantomData,
442 row: PhantomData,
443 grouped: PhantomData,
444 }
445 }
446
447 pub fn with<C>(&self, cte: &C) -> QueryBuilder<'a, Schema, CTEInit>
449 where
450 C: CTEDefinition<'a>,
451 {
452 let sql = SQL::from(Token::WITH).append(cte.cte_definition());
453 QueryBuilder {
454 sql,
455 schema: PhantomData,
456 state: PhantomData,
457 table: PhantomData,
458 marker: PhantomData,
459 row: PhantomData,
460 grouped: PhantomData,
461 }
462 }
463}
464
465#[cfg(test)]
467mod tests {
468 use super::*;
469
470 #[test]
471 fn test_query_builder_new() {
472 let qb = QueryBuilder::new::<()>();
473 let sql = qb.to_sql();
474 assert_eq!(sql.sql(), "");
475 assert_eq!(sql.params().count(), 0);
476 }
477
478 #[test]
479 fn test_builder_init_type() {
480 let _state = BuilderInit;
481 }
482}