1use crate::common::PostgresSchemaType;
2use crate::helpers;
3use crate::traits::PostgresTable;
4use crate::values::PostgresValue;
5use core::marker::PhantomData;
6use drizzle_core::ToSQL;
7use drizzle_core::traits::SQLTable;
8use paste::paste;
9
10use super::ExecutableState;
12
13pub use drizzle_core::builder::{
18 AsCteState, SelectFromSet, SelectGroupSet, SelectInitial, SelectJoinSet, SelectLimitSet,
19 SelectOffsetSet, SelectOrderSet, SelectSetOpSet, SelectWhereSet,
20};
21
22pub trait SelectOrderAllowed {}
27impl SelectOrderAllowed for SelectFromSet {}
28impl SelectOrderAllowed for SelectJoinSet {}
29impl SelectOrderAllowed for SelectWhereSet {}
30impl SelectOrderAllowed for SelectGroupSet {}
31
32#[doc(hidden)]
33pub trait SelectWhereAllowed: drizzle_core::WhereAllowed {}
34
35impl SelectWhereAllowed for SelectFromSet {}
36impl SelectWhereAllowed for SelectJoinSet {}
37
38#[derive(Debug, Clone, Copy, Default)]
40pub struct SelectForSet;
41
42#[doc(hidden)]
47macro_rules! join_impl {
48 () => {
49 join_impl!(@natural natural, Join::new().natural(), drizzle_core::AfterJoin);
50 join_impl!(@natural natural_left, Join::new().natural().left(), drizzle_core::AfterLeftJoin);
51 join_impl!(left, Join::new().left(), drizzle_core::AfterLeftJoin);
52 join_impl!(left_outer, Join::new().left().outer(), drizzle_core::AfterLeftJoin);
53 join_impl!(@natural natural_left_outer, Join::new().natural().left().outer(), drizzle_core::AfterLeftJoin);
54 join_impl!(@natural natural_right, Join::new().natural().right(), drizzle_core::AfterRightJoin);
55 join_impl!(right, Join::new().right(), drizzle_core::AfterRightJoin);
56 join_impl!(right_outer, Join::new().right().outer(), drizzle_core::AfterRightJoin);
57 join_impl!(@natural natural_right_outer, Join::new().natural().right().outer(), drizzle_core::AfterRightJoin);
58 join_impl!(@natural natural_full, Join::new().natural().full(), drizzle_core::AfterFullJoin);
59 join_impl!(full, Join::new().full(), drizzle_core::AfterFullJoin);
60 join_impl!(full_outer, Join::new().full().outer(), drizzle_core::AfterFullJoin);
61 join_impl!(@natural natural_full_outer, Join::new().natural().full().outer(), drizzle_core::AfterFullJoin);
62 join_impl!(inner, Join::new().inner(), drizzle_core::AfterJoin);
63 join_using_impl!(left, drizzle_core::AfterLeftJoin);
65 join_using_impl!(left_outer, drizzle_core::AfterLeftJoin);
66 join_using_impl!(right, drizzle_core::AfterRightJoin);
67 join_using_impl!(right_outer, drizzle_core::AfterRightJoin);
68 join_using_impl!(full, drizzle_core::AfterFullJoin);
69 join_using_impl!(full_outer, drizzle_core::AfterFullJoin);
70 join_using_impl!(inner, drizzle_core::AfterJoin);
71 join_using_impl!(); };
73 (@natural $type:ident, $join_expr:expr, $join_trait:path) => {
74 paste! {
75 #[allow(clippy::type_complexity)]
78 pub fn [<$type _join>]<J: crate::helpers::JoinSource<'a>>(
79 self,
80 source: J,
81 ) -> SelectBuilder<'a, S, SelectJoinSet, J::JoinedTable, <M as drizzle_core::ScopePush<J::JoinedTable>>::Out, <M as $join_trait<R, J::JoinedTable>>::NewRow, G>
82 where
83 M: $join_trait<R, J::JoinedTable> + drizzle_core::ScopePush<J::JoinedTable>,
84 {
85 use drizzle_core::{Join, ToSQL};
86 SelectBuilder {
87 sql: self
88 .sql
89 .append($join_expr.to_sql())
90 .append(drizzle_core::SQL::raw(" "))
91 .append(source.into_join_source_sql()),
92 schema: PhantomData,
93 state: PhantomData,
94 table: PhantomData,
95 marker: PhantomData,
96 row: PhantomData,
97 grouped: PhantomData,
98 }
99 }
100 }
101 };
102 ($type:ident, $join_expr:expr, $join_trait:path) => {
103 paste! {
104 pub fn [<$type _join>]<J: crate::helpers::JoinArg<'a, T>>(
106 self,
107 arg: J,
108 ) -> SelectBuilder<'a, S, SelectJoinSet, J::JoinedTable, <M as drizzle_core::ScopePush<J::JoinedTable>>::Out, <M as $join_trait<R, J::JoinedTable>>::NewRow, G>
109 where
110 M: $join_trait<R, J::JoinedTable> + drizzle_core::ScopePush<J::JoinedTable>,
111 {
112 use drizzle_core::Join;
113 SelectBuilder {
114 sql: self.sql.append(arg.into_join_sql($join_expr)),
115 schema: PhantomData,
116 state: PhantomData,
117 table: PhantomData,
118 marker: PhantomData,
119 row: PhantomData,
120 grouped: PhantomData,
121 }
122 }
123 }
124 };
125}
126
127macro_rules! join_using_impl {
128 () => {
129 pub fn join_using<U: PostgresTable<'a>>(
131 self,
132 table: U,
133 columns: impl ToSQL<'a, PostgresValue<'a>>,
134 ) -> SelectBuilder<
135 'a,
136 S,
137 SelectJoinSet,
138 U,
139 <M as drizzle_core::ScopePush<U>>::Out,
140 <M as drizzle_core::AfterJoin<R, U>>::NewRow,
141 G,
142 >
143 where
144 M: drizzle_core::AfterJoin<R, U> + drizzle_core::ScopePush<U>,
145 {
146 SelectBuilder {
147 sql: self.sql.append(helpers::join_using(table, columns)),
148 schema: PhantomData,
149 state: PhantomData,
150 table: PhantomData,
151 marker: PhantomData,
152 row: PhantomData,
153 grouped: PhantomData,
154 }
155 }
156 };
157 ($type:ident, $join_trait:path) => {
158 paste! {
159 pub fn [<$type _join_using>]<U: PostgresTable<'a>>(
161 self,
162 table: U,
163 columns: impl ToSQL<'a, PostgresValue<'a>>,
164 ) -> SelectBuilder<
165 'a,
166 S,
167 SelectJoinSet,
168 U,
169 <M as drizzle_core::ScopePush<U>>::Out,
170 <M as $join_trait<R, U>>::NewRow,
171 G,
172 >
173 where
174 M: $join_trait<R, U> + drizzle_core::ScopePush<U>,
175 {
176 SelectBuilder {
177 sql: self.sql.append(helpers::[<$type _join_using>](table, columns)),
178 schema: PhantomData,
179 state: PhantomData,
180 table: PhantomData,
181 marker: PhantomData,
182 row: PhantomData,
183 grouped: PhantomData,
184 }
185 }
186 }
187 };
188}
189
190impl ExecutableState for SelectForSet {}
195
196pub type SelectBuilder<'a, Schema, State, Table = (), Marker = (), Row = (), Grouped = ()> =
202 super::QueryBuilder<'a, Schema, State, Table, Marker, Row, Grouped>;
203
204impl<'a, S, M> SelectBuilder<'a, S, SelectInitial, (), M> {
209 #[inline]
211 #[allow(clippy::type_complexity)]
212 pub fn from<T>(
213 self,
214 query: T,
215 ) -> SelectBuilder<
216 'a,
217 S,
218 SelectFromSet,
219 T,
220 drizzle_core::Scoped<M, drizzle_core::Cons<T, drizzle_core::Nil>>,
221 <M as drizzle_core::ResolveRow<T>>::Row,
222 >
223 where
224 T: ToSQL<'a, PostgresValue<'a>>,
225 M: drizzle_core::ResolveRow<T>,
226 {
227 SelectBuilder {
228 sql: self.sql.append(helpers::from(query)),
229 schema: PhantomData,
230 state: PhantomData,
231 table: PhantomData,
232 marker: PhantomData,
233 row: PhantomData,
234 grouped: PhantomData,
235 }
236 }
237}
238
239impl<'a, S, State, T, M, R, G> SelectBuilder<'a, S, State, T, M, R, G>
245where
246 State: drizzle_core::JoinAllowed,
247{
248 #[inline]
250 #[allow(clippy::type_complexity)]
251 pub fn join<J: crate::helpers::JoinArg<'a, T>>(
252 self,
253 arg: J,
254 ) -> SelectBuilder<
255 'a,
256 S,
257 SelectJoinSet,
258 J::JoinedTable,
259 <M as drizzle_core::ScopePush<J::JoinedTable>>::Out,
260 <M as drizzle_core::AfterJoin<R, J::JoinedTable>>::NewRow,
261 G,
262 >
263 where
264 M: drizzle_core::AfterJoin<R, J::JoinedTable> + drizzle_core::ScopePush<J::JoinedTable>,
265 {
266 use drizzle_core::Join;
267 SelectBuilder {
268 sql: self.sql.append(arg.into_join_sql(Join::new())),
269 schema: PhantomData,
270 state: PhantomData,
271 table: PhantomData,
272 marker: PhantomData,
273 row: PhantomData,
274 grouped: PhantomData,
275 }
276 }
277
278 join_impl!();
279
280 #[inline]
285 #[allow(clippy::type_complexity)]
286 pub fn cross_join<Arg: crate::helpers::CrossJoinArg<'a, T>>(
287 self,
288 arg: Arg,
289 ) -> SelectBuilder<
290 'a,
291 S,
292 SelectJoinSet,
293 Arg::JoinedTable,
294 <M as drizzle_core::ScopePush<Arg::JoinedTable>>::Out,
295 <M as drizzle_core::AfterJoin<R, Arg::JoinedTable>>::NewRow,
296 G,
297 >
298 where
299 M: drizzle_core::AfterJoin<R, Arg::JoinedTable> + drizzle_core::ScopePush<Arg::JoinedTable>,
300 {
301 SelectBuilder {
302 sql: self.sql.append(arg.into_cross_join_sql()),
303 schema: PhantomData,
304 state: PhantomData,
305 table: PhantomData,
306 marker: PhantomData,
307 row: PhantomData,
308 grouped: PhantomData,
309 }
310 }
311
312 #[inline]
314 #[allow(clippy::type_complexity)]
315 pub fn inner_join_lateral<J>(
316 self,
317 arg: J,
318 ) -> SelectBuilder<
319 'a,
320 S,
321 SelectJoinSet,
322 J::JoinedTable,
323 <M as drizzle_core::ScopePush<J::JoinedTable>>::Out,
324 <M as drizzle_core::AfterJoin<R, J::JoinedTable>>::NewRow,
325 G,
326 >
327 where
328 J: drizzle_core::LateralArg<'a, PostgresValue<'a>>,
329 M: drizzle_core::AfterJoin<R, J::JoinedTable> + drizzle_core::ScopePush<J::JoinedTable>,
330 {
331 use drizzle_core::Join;
332 SelectBuilder {
333 sql: self.sql.append(arg.into_lateral_sql(Join::new().inner())),
334 schema: PhantomData,
335 state: PhantomData,
336 table: PhantomData,
337 marker: PhantomData,
338 row: PhantomData,
339 grouped: PhantomData,
340 }
341 }
342
343 #[inline]
345 #[allow(clippy::type_complexity)]
346 pub fn left_join_lateral<J, SelectionProof>(
347 self,
348 arg: J,
349 ) -> SelectBuilder<
350 'a,
351 S,
352 SelectJoinSet,
353 J::JoinedTable,
354 <M as drizzle_core::ScopePush<J::JoinedTable>>::Out,
355 <M as drizzle_core::AfterLeftJoin<R, J::JoinedTable>>::NewRow,
356 G,
357 >
358 where
359 J: drizzle_core::LateralArg<'a, PostgresValue<'a>>,
360 M: drizzle_core::AfterLeftJoin<R, J::JoinedTable>
361 + drizzle_core::ScopePush<J::JoinedTable>
362 + drizzle_core::LeftLateralSelection<SelectionProof>,
363 {
364 use drizzle_core::Join;
365 SelectBuilder {
366 sql: self.sql.append(arg.into_lateral_sql(Join::new().left())),
367 schema: PhantomData,
368 state: PhantomData,
369 table: PhantomData,
370 marker: PhantomData,
371 row: PhantomData,
372 grouped: PhantomData,
373 }
374 }
375
376 #[inline]
378 #[allow(clippy::type_complexity)]
379 pub fn cross_join_lateral<Source>(
380 self,
381 source: Source,
382 ) -> SelectBuilder<
383 'a,
384 S,
385 SelectJoinSet,
386 Source::JoinedTable,
387 <M as drizzle_core::ScopePush<Source::JoinedTable>>::Out,
388 <M as drizzle_core::AfterJoin<R, Source::JoinedTable>>::NewRow,
389 G,
390 >
391 where
392 Source: drizzle_core::LateralSource<'a, PostgresValue<'a>>,
393 M: drizzle_core::AfterJoin<R, Source::JoinedTable>
394 + drizzle_core::ScopePush<Source::JoinedTable>,
395 {
396 SelectBuilder {
397 sql: self.sql.append(source.into_cross_lateral_sql()),
398 schema: PhantomData,
399 state: PhantomData,
400 table: PhantomData,
401 marker: PhantomData,
402 row: PhantomData,
403 grouped: PhantomData,
404 }
405 }
406}
407
408impl<'a, S, State, T, M, R, G> SelectBuilder<'a, S, State, T, M, R, G>
410where
411 State: SelectWhereAllowed,
412{
413 #[inline]
415 pub fn r#where<E>(self, condition: E) -> SelectBuilder<'a, S, SelectWhereSet, T, M, R, G>
416 where
417 E: drizzle_core::expr::Expr<'a, PostgresValue<'a>>,
418 E::SQLType: drizzle_core::types::BooleanLike,
419 {
420 SelectBuilder {
421 sql: self.sql.append(helpers::r#where(condition)),
422 schema: PhantomData,
423 state: PhantomData,
424 table: PhantomData,
425 marker: PhantomData,
426 row: PhantomData,
427 grouped: PhantomData,
428 }
429 }
430}
431
432impl<'a, S, State, T, M, R, G> SelectBuilder<'a, S, State, T, M, R, G>
434where
435 State: drizzle_core::GroupByAllowed,
436{
437 pub fn group_by<Gr>(
445 self,
446 columns: Gr,
447 ) -> SelectBuilder<'a, S, SelectGroupSet, T, M, R, Gr::Columns>
448 where
449 Gr: drizzle_core::IntoGroupBy<'a, PostgresValue<'a>>,
450 {
451 SelectBuilder {
452 sql: self.sql.append(helpers::group_by_expr(columns)),
453 schema: PhantomData,
454 state: PhantomData,
455 table: PhantomData,
456 marker: PhantomData,
457 row: PhantomData,
458 grouped: PhantomData,
459 }
460 }
461}
462
463impl<'a, S, State, T, M, R, G> SelectBuilder<'a, S, State, T, M, R, G>
465where
466 State: drizzle_core::HavingAllowed,
467{
468 pub fn having<E>(self, condition: E) -> SelectBuilder<'a, S, SelectGroupSet, T, M, R, G>
470 where
471 E: drizzle_core::expr::Expr<'a, PostgresValue<'a>>,
472 E::SQLType: drizzle_core::types::BooleanLike,
473 {
474 SelectBuilder {
475 sql: self.sql.append(helpers::having(condition)),
476 schema: PhantomData,
477 state: PhantomData,
478 table: PhantomData,
479 marker: PhantomData,
480 row: PhantomData,
481 grouped: PhantomData,
482 }
483 }
484}
485
486impl<'a, S, State, T, M, R, G> SelectBuilder<'a, S, State, T, M, R, G>
488where
489 State: SelectOrderAllowed,
490{
491 #[inline]
493 pub fn order_by<TOrderBy>(
494 self,
495 expressions: TOrderBy,
496 ) -> SelectBuilder<'a, S, SelectOrderSet, T, M, R, G>
497 where
498 TOrderBy: ToSQL<'a, PostgresValue<'a>>,
499 {
500 SelectBuilder {
501 sql: self.sql.append(helpers::order_by(expressions)),
502 schema: PhantomData,
503 state: PhantomData,
504 table: PhantomData,
505 marker: PhantomData,
506 row: PhantomData,
507 grouped: PhantomData,
508 }
509 }
510}
511
512impl<'a, S, T, M, R, G> SelectBuilder<'a, S, SelectSetOpSet, T, M, R, G> {
515 #[inline]
519 pub fn order_by<TOrderBy>(
520 self,
521 expressions: TOrderBy,
522 ) -> SelectBuilder<'a, S, SelectOrderSet, T, M, R, G>
523 where
524 TOrderBy: ToSQL<'a, PostgresValue<'a>>,
525 {
526 SelectBuilder {
527 sql: self
528 .sql
529 .append(drizzle_core::helpers::set_order_by(expressions)),
530 schema: PhantomData,
531 state: PhantomData,
532 table: PhantomData,
533 marker: PhantomData,
534 row: PhantomData,
535 grouped: PhantomData,
536 }
537 }
538}
539
540impl<'a, S, State, T, M, R, G> SelectBuilder<'a, S, State, T, M, R, G>
542where
543 State: drizzle_core::LimitAllowed,
544{
545 #[inline]
552 #[must_use]
553 #[track_caller]
554 pub fn limit<P>(self, limit: P) -> SelectBuilder<'a, S, SelectLimitSet, T, M, R, G>
555 where
556 P: drizzle_core::PaginationArg<'a, PostgresValue<'a>>,
557 {
558 SelectBuilder {
559 sql: self.sql.append(helpers::limit(limit)),
560 schema: PhantomData,
561 state: PhantomData,
562 table: PhantomData,
563 marker: PhantomData,
564 row: PhantomData,
565 grouped: PhantomData,
566 }
567 }
568}
569
570impl<'a, S, State, T, M, R, G> SelectBuilder<'a, S, State, T, M, R, G>
572where
573 State: drizzle_core::OffsetAllowed,
574{
575 #[inline]
582 #[must_use]
583 #[track_caller]
584 pub fn offset<P>(self, offset: P) -> SelectBuilder<'a, S, SelectOffsetSet, T, M, R, G>
585 where
586 P: drizzle_core::PaginationArg<'a, PostgresValue<'a>>,
587 {
588 SelectBuilder {
589 sql: self.sql.append(helpers::offset(offset)),
590 schema: PhantomData,
591 state: PhantomData,
592 table: PhantomData,
593 marker: PhantomData,
594 row: PhantomData,
595 grouped: PhantomData,
596 }
597 }
598}
599
600impl<'a, S, State, T, M, R, G> SelectBuilder<'a, S, State, T, M, R, G>
605where
606 State: ExecutableState,
607{
608 #[inline]
616 #[must_use]
617 pub fn alias<Tag, ScopeProof, AggProof>(
618 self,
619 _tag: Tag,
620 ) -> drizzle_core::Derived<
621 'a,
622 PostgresValue<'a>,
623 Tag,
624 <M as drizzle_core::DerivedSelection<
625 'a,
626 PostgresValue<'a>,
627 PostgresSchemaType,
628 T,
629 >>::Projection,
630 Self,
631 >
632 where
633 Tag: drizzle_core::Tag,
634 M: drizzle_core::DerivedSelection<'a, PostgresValue<'a>, PostgresSchemaType, T>
635 + drizzle_core::row::MarkerScopeValidFor<ScopeProof>
636 + drizzle_core::row::MarkerAggValidFor<G, AggProof>,
637 <M as drizzle_core::DerivedSelection<
638 'a,
639 PostgresValue<'a>,
640 PostgresSchemaType,
641 T,
642 >>::Projection: drizzle_core::DerivedProjection<Tag>,
643{
644 unsafe { drizzle_core::Derived::new_unchecked(self) }
647 }
648}
649
650impl<'a, S, State, T, M, R, G> SelectBuilder<'a, S, State, T, M, R, G>
651where
652 State: AsCteState,
653 T: SQLTable<'a, PostgresSchemaType, PostgresValue<'a>>,
654{
655 #[inline]
657 #[must_use]
658 pub fn into_cte<Tag: drizzle_core::Tag + 'static>(
659 self,
660 ) -> super::CTEView<
661 'a,
662 <T as SQLTable<'a, PostgresSchemaType, PostgresValue<'a>>>::Aliased<Tag>,
663 Self,
664 > {
665 let name = Tag::NAME;
666 super::CTEView::new(
667 <T as SQLTable<'a, PostgresSchemaType, PostgresValue<'a>>>::alias::<Tag>(),
668 name,
669 self,
670 )
671 }
672}
673
674impl<'a, S, State, T, M, R, G> SelectBuilder<'a, S, State, T, M, R, G>
679where
680 State: ExecutableState,
681{
682 pub fn union(
684 self,
685 other: impl IntoSelect<'a, S, M, R>,
686 ) -> SelectBuilder<'a, S, SelectSetOpSet, T, M, R, G> {
687 SelectBuilder {
688 sql: helpers::union(self.sql, other.into_select()),
689 schema: PhantomData,
690 state: PhantomData,
691 table: PhantomData,
692 marker: PhantomData,
693 row: PhantomData,
694 grouped: PhantomData,
695 }
696 }
697
698 pub fn union_all(
700 self,
701 other: impl IntoSelect<'a, S, M, R>,
702 ) -> SelectBuilder<'a, S, SelectSetOpSet, T, M, R, G> {
703 SelectBuilder {
704 sql: helpers::union_all(self.sql, other.into_select()),
705 schema: PhantomData,
706 state: PhantomData,
707 table: PhantomData,
708 marker: PhantomData,
709 row: PhantomData,
710 grouped: PhantomData,
711 }
712 }
713
714 pub fn intersect(
716 self,
717 other: impl IntoSelect<'a, S, M, R>,
718 ) -> SelectBuilder<'a, S, SelectSetOpSet, T, M, R, G> {
719 SelectBuilder {
720 sql: helpers::intersect(self.sql, other.into_select()),
721 schema: PhantomData,
722 state: PhantomData,
723 table: PhantomData,
724 marker: PhantomData,
725 row: PhantomData,
726 grouped: PhantomData,
727 }
728 }
729
730 pub fn intersect_all(
732 self,
733 other: impl IntoSelect<'a, S, M, R>,
734 ) -> SelectBuilder<'a, S, SelectSetOpSet, T, M, R, G> {
735 SelectBuilder {
736 sql: helpers::intersect_all(self.sql, other.into_select()),
737 schema: PhantomData,
738 state: PhantomData,
739 table: PhantomData,
740 marker: PhantomData,
741 row: PhantomData,
742 grouped: PhantomData,
743 }
744 }
745
746 pub fn except(
748 self,
749 other: impl IntoSelect<'a, S, M, R>,
750 ) -> SelectBuilder<'a, S, SelectSetOpSet, T, M, R, G> {
751 SelectBuilder {
752 sql: helpers::except(self.sql, other.into_select()),
753 schema: PhantomData,
754 state: PhantomData,
755 table: PhantomData,
756 marker: PhantomData,
757 row: PhantomData,
758 grouped: PhantomData,
759 }
760 }
761
762 pub fn except_all(
764 self,
765 other: impl IntoSelect<'a, S, M, R>,
766 ) -> SelectBuilder<'a, S, SelectSetOpSet, T, M, R, G> {
767 SelectBuilder {
768 sql: helpers::except_all(self.sql, other.into_select()),
769 schema: PhantomData,
770 state: PhantomData,
771 table: PhantomData,
772 marker: PhantomData,
773 row: PhantomData,
774 grouped: PhantomData,
775 }
776 }
777}
778
779impl<'a, S, State, T, M, R, G> drizzle_core::expr::Expr<'a, PostgresValue<'a>>
784 for SelectBuilder<'a, S, State, T, M, R, G>
785where
786 State: ExecutableState,
787 M: drizzle_core::expr::SubqueryType<'a, PostgresValue<'a>>,
788{
789 type SQLType = <M as drizzle_core::expr::SubqueryType<'a, PostgresValue<'a>>>::SQLType;
790 type Nullable = drizzle_core::expr::Null;
791 type Aggregate = drizzle_core::expr::Scalar;
792}
793
794pub trait IntoSelect<'a, S, M, R> {
801 type State: ExecutableState;
802 type Table;
803 fn into_select(self) -> SelectBuilder<'a, S, Self::State, Self::Table, M, R>;
804}
805
806impl<'a, S, State: ExecutableState, T, M, R, G> IntoSelect<'a, S, M, R>
807 for SelectBuilder<'a, S, State, T, M, R, G>
808{
809 type State = State;
810 type Table = T;
811 fn into_select(self) -> SelectBuilder<'a, S, State, T, M, R> {
812 SelectBuilder {
813 sql: self.sql,
814 schema: PhantomData,
815 state: PhantomData,
816 table: PhantomData,
817 marker: PhantomData,
818 row: PhantomData,
819 grouped: PhantomData,
820 }
821 }
822}
823
824mod insert_select_private {
825 use super::{
826 SelectForSet, SelectFromSet, SelectGroupSet, SelectJoinSet, SelectLimitSet,
827 SelectOffsetSet, SelectOrderSet, SelectSetOpSet, SelectWhereSet,
828 };
829
830 pub trait Sealed {}
831 pub trait Completed: super::ExecutableState {}
832
833 impl Completed for SelectFromSet {}
834 impl Completed for SelectJoinSet {}
835 impl Completed for SelectWhereSet {}
836 impl Completed for SelectGroupSet {}
837 impl Completed for SelectOrderSet {}
838 impl Completed for SelectLimitSet {}
839 impl Completed for SelectOffsetSet {}
840 impl Completed for SelectSetOpSet {}
841 impl Completed for SelectForSet {}
842}
843
844#[doc(hidden)]
846pub trait CompletedSelect<'a, S, R>: insert_select_private::Sealed {
847 type Marker;
848 type Grouped;
849
850 fn into_select_sql(self) -> drizzle_core::SQL<'a, PostgresValue<'a>>;
851}
852
853#[doc(hidden)]
855pub trait IntoSelectQuery<'a, S, R> {
856 type Marker;
857 type Grouped;
858 type Select: CompletedSelect<'a, S, R, Marker = Self::Marker, Grouped = Self::Grouped>;
859
860 fn into_select_query(self) -> Self::Select;
861}
862
863impl<'a, S, State, T, M, R, G> insert_select_private::Sealed
864 for SelectBuilder<'a, S, State, T, M, R, G>
865where
866 State: insert_select_private::Completed,
867{
868}
869
870impl<'a, S, State, T, M, R, G> CompletedSelect<'a, S, R> for SelectBuilder<'a, S, State, T, M, R, G>
871where
872 State: insert_select_private::Completed,
873{
874 type Marker = M;
875 type Grouped = G;
876
877 fn into_select_sql(self) -> drizzle_core::SQL<'a, PostgresValue<'a>> {
878 self.sql
879 }
880}
881
882impl<'a, S, State, T, M, R, G> IntoSelectQuery<'a, S, R> for SelectBuilder<'a, S, State, T, M, R, G>
883where
884 State: insert_select_private::Completed,
885{
886 type Marker = M;
887 type Grouped = G;
888 type Select = Self;
889
890 fn into_select_query(self) -> Self::Select {
891 self
892 }
893}
894
895pub trait ForLockableState {}
901
902impl ForLockableState for SelectFromSet {}
903impl ForLockableState for SelectWhereSet {}
904impl ForLockableState for SelectOrderSet {}
905impl ForLockableState for SelectLimitSet {}
906impl ForLockableState for SelectOffsetSet {}
907impl ForLockableState for SelectJoinSet {}
908impl ForLockableState for SelectGroupSet {}
909
910impl<'a, S, State, T, M, R, G> SelectBuilder<'a, S, State, T, M, R, G>
911where
912 State: ForLockableState,
913{
914 #[must_use]
916 pub fn for_update(self) -> SelectBuilder<'a, S, SelectForSet, T, M, R, G> {
917 SelectBuilder {
918 sql: self.sql.append(helpers::for_update()),
919 schema: PhantomData,
920 state: PhantomData,
921 table: PhantomData,
922 marker: PhantomData,
923 row: PhantomData,
924 grouped: PhantomData,
925 }
926 }
927
928 #[must_use]
930 pub fn for_share(self) -> SelectBuilder<'a, S, SelectForSet, T, M, R, G> {
931 SelectBuilder {
932 sql: self.sql.append(helpers::for_share()),
933 schema: PhantomData,
934 state: PhantomData,
935 table: PhantomData,
936 marker: PhantomData,
937 row: PhantomData,
938 grouped: PhantomData,
939 }
940 }
941
942 #[must_use]
944 pub fn for_no_key_update(self) -> SelectBuilder<'a, S, SelectForSet, T, M, R, G> {
945 SelectBuilder {
946 sql: self.sql.append(helpers::for_no_key_update()),
947 schema: PhantomData,
948 state: PhantomData,
949 table: PhantomData,
950 marker: PhantomData,
951 row: PhantomData,
952 grouped: PhantomData,
953 }
954 }
955
956 #[must_use]
958 pub fn for_key_share(self) -> SelectBuilder<'a, S, SelectForSet, T, M, R, G> {
959 SelectBuilder {
960 sql: self.sql.append(helpers::for_key_share()),
961 schema: PhantomData,
962 state: PhantomData,
963 table: PhantomData,
964 marker: PhantomData,
965 row: PhantomData,
966 grouped: PhantomData,
967 }
968 }
969
970 pub fn for_update_of<U: PostgresTable<'a>>(
972 self,
973 table: U,
974 ) -> SelectBuilder<'a, S, SelectForSet, T, M, R, G> {
975 SelectBuilder {
976 sql: self.sql.append(helpers::for_update_of(table.name())),
977 schema: PhantomData,
978 state: PhantomData,
979 table: PhantomData,
980 marker: PhantomData,
981 row: PhantomData,
982 grouped: PhantomData,
983 }
984 }
985
986 pub fn for_share_of<U: PostgresTable<'a>>(
988 self,
989 table: U,
990 ) -> SelectBuilder<'a, S, SelectForSet, T, M, R, G> {
991 SelectBuilder {
992 sql: self.sql.append(helpers::for_share_of(table.name())),
993 schema: PhantomData,
994 state: PhantomData,
995 table: PhantomData,
996 marker: PhantomData,
997 row: PhantomData,
998 grouped: PhantomData,
999 }
1000 }
1001}
1002
1003impl<S, T, M, R, G> SelectBuilder<'_, S, SelectForSet, T, M, R, G> {
1008 #[must_use]
1010 pub fn nowait(self) -> Self {
1011 SelectBuilder {
1012 sql: self.sql.append(helpers::nowait()),
1013 schema: PhantomData,
1014 state: PhantomData,
1015 table: PhantomData,
1016 marker: PhantomData,
1017 row: PhantomData,
1018 grouped: PhantomData,
1019 }
1020 }
1021
1022 #[must_use]
1024 pub fn skip_locked(self) -> Self {
1025 SelectBuilder {
1026 sql: self.sql.append(helpers::skip_locked()),
1027 schema: PhantomData,
1028 state: PhantomData,
1029 table: PhantomData,
1030 marker: PhantomData,
1031 row: PhantomData,
1032 grouped: PhantomData,
1033 }
1034 }
1035}
1036
1037#[cfg(test)]
1038mod tests {
1039 use super::*;
1040 use drizzle_core::{SQL, ToSQL};
1041
1042 #[test]
1043 fn test_select_builder_creation() {
1044 let builder = SelectBuilder::<(), SelectInitial> {
1045 sql: SQL::raw("SELECT *"),
1046 schema: PhantomData,
1047 state: PhantomData,
1048 table: PhantomData,
1049 marker: PhantomData,
1050 row: PhantomData,
1051 grouped: PhantomData,
1052 };
1053
1054 assert_eq!(builder.to_sql().sql(), "SELECT *");
1055 }
1056}