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};
7
8#[derive(Debug, Clone, PartialEq)]
9pub struct SelectProjection {
10    pub expr: Expr,
11    pub alias: Option<&'static str>,
12}
13
14impl SelectProjection {
15    pub fn column<E: Entity>(column: EntityColumn<E>) -> Self {
16        let alias = column.column_name();
17        Self {
18            expr: Expr::from(column),
19            alias: Some(alias),
20        }
21    }
22
23    pub fn expr(expr: Expr) -> Self {
24        let alias = match &expr {
25            Expr::Column(column) => Some(column.column_name),
26            _ => None,
27        };
28
29        Self { expr, alias }
30    }
31
32    pub fn expr_as(expr: Expr, alias: &'static str) -> Self {
33        Self {
34            expr,
35            alias: Some(alias),
36        }
37    }
38}
39
40impl<E: Entity> From<EntityColumn<E>> for SelectProjection {
41    fn from(value: EntityColumn<E>) -> Self {
42        Self::column(value)
43    }
44}
45
46impl From<Expr> for SelectProjection {
47    fn from(value: Expr) -> Self {
48        Self::expr(value)
49    }
50}
51
52#[derive(Debug, Clone, PartialEq)]
53pub struct SelectQuery {
54    pub from: TableRef,
55    pub joins: Vec<Join>,
56    pub projection: Vec<SelectProjection>,
57    pub predicate: Option<Predicate>,
58    pub order_by: Vec<OrderBy>,
59    pub pagination: Option<Pagination>,
60}
61
62impl SelectQuery {
63    pub fn from_entity<E: Entity>() -> Self {
64        Self {
65            from: TableRef::for_entity::<E>(),
66            joins: Vec::new(),
67            projection: Vec::new(),
68            predicate: None,
69            order_by: Vec::new(),
70            pagination: None,
71        }
72    }
73
74    pub fn from_entity_as<E: Entity>(alias: &'static str) -> Self {
75        Self {
76            from: TableRef::for_entity_as::<E>(alias),
77            joins: Vec::new(),
78            projection: Vec::new(),
79            predicate: None,
80            order_by: Vec::new(),
81            pagination: None,
82        }
83    }
84
85    pub fn select<P, I>(mut self, projection: I) -> Self
86    where
87        P: Into<SelectProjection>,
88        I: IntoIterator<Item = P>,
89    {
90        self.projection = projection.into_iter().map(Into::into).collect();
91        self
92    }
93
94    pub fn filter(mut self, predicate: Predicate) -> Self {
95        self.predicate = Some(match self.predicate.take() {
96            Some(existing) => Predicate::and(vec![existing, predicate]),
97            None => predicate,
98        });
99        self
100    }
101
102    pub fn join(mut self, join: Join) -> Self {
103        self.joins.push(join);
104        self
105    }
106
107    pub fn inner_join<E: Entity>(self, on: Predicate) -> Self {
108        self.join(Join::inner_entity::<E>(on))
109    }
110
111    pub fn left_join<E: Entity>(self, on: Predicate) -> Self {
112        self.join(Join::left_entity::<E>(on))
113    }
114
115    pub fn inner_join_as<E: Entity>(self, alias: &'static str, on: Predicate) -> Self {
116        self.join(Join::inner_entity_as::<E>(alias, on))
117    }
118
119    pub fn left_join_as<E: Entity>(self, alias: &'static str, on: Predicate) -> Self {
120        self.join(Join::left_entity_as::<E>(alias, on))
121    }
122
123    pub fn order_by(mut self, order: OrderBy) -> Self {
124        self.order_by.push(order);
125        self
126    }
127
128    pub fn paginate(mut self, pagination: Pagination) -> Self {
129        self.pagination = Some(pagination);
130        self
131    }
132}
133
134#[derive(Debug, Clone, PartialEq)]
135pub struct CountQuery {
136    pub from: TableRef,
137    pub predicate: Option<Predicate>,
138}
139
140impl CountQuery {
141    pub fn from_entity<E: Entity>() -> Self {
142        Self {
143            from: TableRef::for_entity::<E>(),
144            predicate: None,
145        }
146    }
147
148    pub fn from_entity_as<E: Entity>(alias: &'static str) -> Self {
149        Self {
150            from: TableRef::for_entity_as::<E>(alias),
151            predicate: None,
152        }
153    }
154
155    pub fn filter(mut self, predicate: Predicate) -> Self {
156        self.predicate = Some(match self.predicate.take() {
157            Some(existing) => Predicate::and(vec![existing, predicate]),
158            None => predicate,
159        });
160        self
161    }
162}