gluesql_core/ast_builder/select/
order_by.rs1use {
2 super::{Prebuild, ValuesNode},
3 crate::{
4 ast::Query,
5 ast_builder::{
6 ExprNode, FilterNode, GroupByNode, HashJoinNode, HavingNode, JoinConstraintNode,
7 JoinNode, LimitNode, OffsetNode, OrderByExprList, ProjectNode, QueryNode, SelectNode,
8 TableFactorNode,
9 },
10 result::Result,
11 },
12};
13
14#[derive(Clone, Debug)]
15pub enum PrevNode<'a> {
16 Select(SelectNode<'a>),
17 Having(HavingNode<'a>),
18 GroupBy(GroupByNode<'a>),
19 Filter(FilterNode<'a>),
20 JoinNode(JoinNode<'a>),
21 JoinConstraint(JoinConstraintNode<'a>),
22 HashJoin(Box<HashJoinNode<'a>>),
23 ProjectNode(Box<ProjectNode<'a>>),
24 Values(ValuesNode<'a>),
25}
26
27impl<'a> Prebuild<Query> for PrevNode<'a> {
28 fn prebuild(self) -> Result<Query> {
29 match self {
30 Self::Select(node) => node.prebuild(),
31 Self::Having(node) => node.prebuild(),
32 Self::GroupBy(node) => node.prebuild(),
33 Self::Filter(node) => node.prebuild(),
34 Self::JoinNode(node) => node.prebuild(),
35 Self::JoinConstraint(node) => node.prebuild(),
36 Self::HashJoin(node) => node.prebuild(),
37 Self::ProjectNode(node) => node.prebuild(),
38 Self::Values(node) => node.prebuild(),
39 }
40 }
41}
42
43impl<'a> From<SelectNode<'a>> for PrevNode<'a> {
44 fn from(node: SelectNode<'a>) -> Self {
45 PrevNode::Select(node)
46 }
47}
48
49impl<'a> From<HavingNode<'a>> for PrevNode<'a> {
50 fn from(node: HavingNode<'a>) -> Self {
51 PrevNode::Having(node)
52 }
53}
54
55impl<'a> From<GroupByNode<'a>> for PrevNode<'a> {
56 fn from(node: GroupByNode<'a>) -> Self {
57 PrevNode::GroupBy(node)
58 }
59}
60
61impl<'a> From<FilterNode<'a>> for PrevNode<'a> {
62 fn from(node: FilterNode<'a>) -> Self {
63 PrevNode::Filter(node)
64 }
65}
66
67impl<'a> From<JoinNode<'a>> for PrevNode<'a> {
68 fn from(node: JoinNode<'a>) -> Self {
69 PrevNode::JoinNode(node)
70 }
71}
72
73impl<'a> From<JoinConstraintNode<'a>> for PrevNode<'a> {
74 fn from(node: JoinConstraintNode<'a>) -> Self {
75 PrevNode::JoinConstraint(node)
76 }
77}
78
79impl<'a> From<HashJoinNode<'a>> for PrevNode<'a> {
80 fn from(node: HashJoinNode<'a>) -> Self {
81 PrevNode::HashJoin(Box::new(node))
82 }
83}
84
85impl<'a> From<ProjectNode<'a>> for PrevNode<'a> {
86 fn from(node: ProjectNode<'a>) -> Self {
87 PrevNode::ProjectNode(Box::new(node))
88 }
89}
90
91impl<'a> From<ValuesNode<'a>> for PrevNode<'a> {
92 fn from(node: ValuesNode<'a>) -> Self {
93 PrevNode::Values(node)
94 }
95}
96
97#[derive(Clone, Debug)]
98pub struct OrderByNode<'a> {
99 prev_node: PrevNode<'a>,
100 expr_list: OrderByExprList<'a>,
101}
102
103impl<'a> OrderByNode<'a> {
104 pub fn new<N: Into<PrevNode<'a>>, T: Into<OrderByExprList<'a>>>(
105 prev_node: N,
106 expr_list: T,
107 ) -> Self {
108 Self {
109 prev_node: prev_node.into(),
110 expr_list: expr_list.into(),
111 }
112 }
113
114 pub fn offset<T: Into<ExprNode<'a>>>(self, expr: T) -> OffsetNode<'a> {
115 OffsetNode::new(self, expr)
116 }
117
118 pub fn limit<T: Into<ExprNode<'a>>>(self, expr: T) -> LimitNode<'a> {
119 LimitNode::new(self, expr)
120 }
121
122 pub fn alias_as(self, table_alias: &'a str) -> TableFactorNode {
123 QueryNode::OrderByNode(self).alias_as(table_alias)
124 }
125}
126
127impl<'a> Prebuild<Query> for OrderByNode<'a> {
128 fn prebuild(self) -> Result<Query> {
129 let mut node_data = self.prev_node.prebuild()?;
130 node_data.order_by = self.expr_list.try_into()?;
131
132 Ok(node_data)
133 }
134}
135
136#[cfg(test)]
137mod tests {
138 use {
139 crate::{
140 ast::{
141 Join, JoinConstraint, JoinExecutor, JoinOperator, Query, Select, SetExpr,
142 Statement, TableFactor, TableWithJoins,
143 },
144 ast_builder::{col, table, test, Build, ExprNode, OrderByExprList, SelectItemList},
145 },
146 pretty_assertions::assert_eq,
147 };
148
149 #[test]
150 fn order_by() {
151 let actual = table("Foo").select().order_by(vec!["name desc"]).build();
153 let expected = "
154 SELECT * FROM Foo
155 ORDER BY name DESC
156 ";
157 test(actual, expected);
158
159 let actual = table("Bar")
161 .select()
162 .order_by("name asc, id desc, country")
163 .offset(10)
164 .build();
165 let expected = "
166 SELECT * FROM Bar
167 ORDER BY name asc, id desc, country
168 OFFSET 10
169 ";
170 test(actual, expected);
171
172 let actual = table("Bar")
174 .select()
175 .group_by("name")
176 .order_by(vec!["id desc"])
177 .build();
178 let expected = "
179 SELECT * FROM Bar
180 GROUP BY name
181 ORDER BY id desc
182 ";
183 test(actual, expected);
184
185 let actual = table("Foo")
187 .select()
188 .group_by("city")
189 .having("COUNT(name) < 100")
190 .order_by(ExprNode::Identifier("name".into()))
191 .offset(2)
192 .limit(3)
193 .build();
194 let expected = "
195 SELECT * FROM Foo
196 GROUP BY city
197 HAVING COUNT(name) < 100
198 ORDER BY name
199 OFFSET 2
200 LIMIT 3
201 ";
202 test(actual, expected);
203
204 let actual = table("Foo")
206 .select()
207 .filter("id > 10")
208 .filter("id < 20")
209 .order_by("id asc")
210 .build();
211 let expected = "
212 SELECT * FROM Foo
213 WHERE id > 10 AND id < 20
214 ORDER BY id ASC";
215 test(actual, expected);
216
217 let actual = table("Foo")
219 .select()
220 .project("id")
221 .order_by("id asc")
222 .build();
223 let expected = "SELECT id FROM Foo ORDER BY id asc";
224 test(actual, expected);
225
226 let actual = table("Foo")
228 .select()
229 .join("Bar")
230 .order_by("Foo.id desc")
231 .build();
232 let expected = "
233 SELECT * FROM Foo
234 JOIN Bar
235 ORDER BY Foo.id desc
236 ";
237 test(actual, expected);
238
239 let actual = table("Foo")
241 .select()
242 .join("Bar")
243 .on("Foo.id = Bar.id")
244 .order_by("Foo.id desc")
245 .build();
246 let expected = "
247 SELECT * FROM Foo
248 JOIN Bar ON Foo.id = Bar.id
249 ORDER BY Foo.id desc
250 ";
251 test(actual, expected);
252
253 let actual = table("Player")
255 .select()
256 .join("PlayerItem")
257 .hash_executor("PlayerItem.user_id", "Player.id")
258 .order_by("Player.score DESC")
259 .build();
260 let expected = {
261 let join = Join {
262 relation: TableFactor::Table {
263 name: "PlayerItem".to_owned(),
264 alias: None,
265 index: None,
266 },
267 join_operator: JoinOperator::Inner(JoinConstraint::None),
268 join_executor: JoinExecutor::Hash {
269 key_expr: col("PlayerItem.user_id").try_into().unwrap(),
270 value_expr: col("Player.id").try_into().unwrap(),
271 where_clause: None,
272 },
273 };
274 let select = Select {
275 projection: SelectItemList::from("*").try_into().unwrap(),
276 from: TableWithJoins {
277 relation: TableFactor::Table {
278 name: "Player".to_owned(),
279 alias: None,
280 index: None,
281 },
282 joins: vec![join],
283 },
284 selection: None,
285 group_by: Vec::new(),
286 having: None,
287 };
288
289 Ok(Statement::Query(Query {
290 body: SetExpr::Select(Box::new(select)),
291 order_by: OrderByExprList::from("Player.score DESC")
292 .try_into()
293 .unwrap(),
294 limit: None,
295 offset: None,
296 }))
297 };
298 assert_eq!(actual, expected);
299
300 let actual = table("Foo")
302 .select()
303 .order_by(vec!["name desc"])
304 .alias_as("Sub")
305 .select()
306 .build();
307 let expected = "
308 SELECT * FROM (
309 SELECT * FROM Foo
310 ORDER BY name DESC
311 ) Sub
312 ";
313 test(actual, expected);
314 }
315}