Skip to main content

sql_orm_query/
select.rs

1use crate::expr::{Expr, TableRef};
2use crate::join::Join;
3use crate::order::OrderBy;
4use crate::pagination::Pagination;
5use crate::predicate::Predicate;
6use sql_orm_core::{Entity, EntityColumn};
7use std::borrow::Cow;
8
9#[derive(Debug, Clone, PartialEq)]
10pub struct SelectProjection {
11    pub expr: Expr,
12    pub alias: Option<Cow<'static, str>>,
13}
14
15impl SelectProjection {
16    pub fn column<E: Entity>(column: EntityColumn<E>) -> Self {
17        let alias = column.column_name();
18        Self {
19            expr: Expr::from(column),
20            alias: Some(Cow::Borrowed(alias)),
21        }
22    }
23
24    pub fn expr(expr: Expr) -> Self {
25        let alias = match &expr {
26            Expr::Column(column) => Some(Cow::Borrowed(column.column_name)),
27            _ => None,
28        };
29
30        Self { expr, alias }
31    }
32
33    pub fn expr_as(expr: Expr, alias: impl Into<Cow<'static, str>>) -> Self {
34        Self {
35            expr,
36            alias: Some(alias.into()),
37        }
38    }
39}
40
41impl<E: Entity> From<EntityColumn<E>> for SelectProjection {
42    fn from(value: EntityColumn<E>) -> Self {
43        Self::column(value)
44    }
45}
46
47impl From<Expr> for SelectProjection {
48    fn from(value: Expr) -> Self {
49        Self::expr(value)
50    }
51}
52
53#[derive(Debug, Clone, PartialEq)]
54pub struct SelectQuery {
55    pub from: TableRef,
56    pub joins: Vec<Join>,
57    pub projection: Vec<SelectProjection>,
58    pub predicate: Option<Predicate>,
59    pub order_by: Vec<OrderBy>,
60    pub pagination: Option<Pagination>,
61}
62
63impl SelectQuery {
64    pub fn from_entity<E: Entity>() -> Self {
65        Self {
66            from: TableRef::for_entity::<E>(),
67            joins: Vec::new(),
68            projection: Vec::new(),
69            predicate: None,
70            order_by: Vec::new(),
71            pagination: None,
72        }
73    }
74
75    pub fn from_entity_as<E: Entity>(alias: &'static str) -> Self {
76        Self {
77            from: TableRef::for_entity_as::<E>(alias),
78            joins: Vec::new(),
79            projection: Vec::new(),
80            predicate: None,
81            order_by: Vec::new(),
82            pagination: None,
83        }
84    }
85
86    pub fn select<P, I>(mut self, projection: I) -> Self
87    where
88        P: Into<SelectProjection>,
89        I: IntoIterator<Item = P>,
90    {
91        self.projection = projection.into_iter().map(Into::into).collect();
92        self
93    }
94
95    pub fn filter(mut self, predicate: Predicate) -> Self {
96        self.predicate = Some(match self.predicate.take() {
97            Some(existing) => Predicate::and(vec![existing, predicate]),
98            None => predicate,
99        });
100        self
101    }
102
103    pub fn join(mut self, join: Join) -> Self {
104        self.joins.push(join);
105        self
106    }
107
108    pub fn inner_join<E: Entity>(self, on: Predicate) -> Self {
109        self.join(Join::inner_entity::<E>(on))
110    }
111
112    pub fn left_join<E: Entity>(self, on: Predicate) -> Self {
113        self.join(Join::left_entity::<E>(on))
114    }
115
116    pub fn inner_join_as<E: Entity>(self, alias: &'static str, on: Predicate) -> Self {
117        self.join(Join::inner_entity_as::<E>(alias, on))
118    }
119
120    pub fn left_join_as<E: Entity>(self, alias: &'static str, on: Predicate) -> Self {
121        self.join(Join::left_entity_as::<E>(alias, on))
122    }
123
124    pub fn order_by(mut self, order: OrderBy) -> Self {
125        self.order_by.push(order);
126        self
127    }
128
129    pub fn paginate(mut self, pagination: Pagination) -> Self {
130        self.pagination = Some(pagination);
131        self
132    }
133}
134
135#[derive(Debug, Clone, PartialEq)]
136pub struct CountQuery {
137    pub from: TableRef,
138    pub predicate: Option<Predicate>,
139}
140
141impl CountQuery {
142    pub fn from_entity<E: Entity>() -> Self {
143        Self {
144            from: TableRef::for_entity::<E>(),
145            predicate: None,
146        }
147    }
148
149    pub fn from_entity_as<E: Entity>(alias: &'static str) -> Self {
150        Self {
151            from: TableRef::for_entity_as::<E>(alias),
152            predicate: None,
153        }
154    }
155
156    pub fn filter(mut self, predicate: Predicate) -> Self {
157        self.predicate = Some(match self.predicate.take() {
158            Some(existing) => Predicate::and(vec![existing, predicate]),
159            None => predicate,
160        });
161        self
162    }
163}
164
165#[derive(Debug, Clone, PartialEq)]
166pub struct ExistsQuery {
167    pub from: TableRef,
168    pub joins: Vec<Join>,
169    pub predicate: Option<Predicate>,
170}
171
172impl ExistsQuery {
173    pub fn from_entity<E: Entity>() -> Self {
174        Self {
175            from: TableRef::for_entity::<E>(),
176            joins: Vec::new(),
177            predicate: None,
178        }
179    }
180
181    pub fn from_entity_as<E: Entity>(alias: &'static str) -> Self {
182        Self {
183            from: TableRef::for_entity_as::<E>(alias),
184            joins: Vec::new(),
185            predicate: None,
186        }
187    }
188
189    pub fn filter(mut self, predicate: Predicate) -> Self {
190        self.predicate = Some(match self.predicate.take() {
191            Some(existing) => Predicate::and(vec![existing, predicate]),
192            None => predicate,
193        });
194        self
195    }
196
197    pub fn join(mut self, join: Join) -> Self {
198        self.joins.push(join);
199        self
200    }
201
202    pub fn inner_join<E: Entity>(self, on: Predicate) -> Self {
203        self.join(Join::inner_entity::<E>(on))
204    }
205
206    pub fn left_join<E: Entity>(self, on: Predicate) -> Self {
207        self.join(Join::left_entity::<E>(on))
208    }
209
210    pub fn inner_join_as<E: Entity>(self, alias: &'static str, on: Predicate) -> Self {
211        self.join(Join::inner_entity_as::<E>(alias, on))
212    }
213
214    pub fn left_join_as<E: Entity>(self, alias: &'static str, on: Predicate) -> Self {
215        self.join(Join::left_entity_as::<E>(alias, on))
216    }
217}