1use async_graphql::Enum;
2use serde::{Deserialize, Serialize};
3use std::fmt::Display;
4use strum::EnumString;
5
6#[derive(Enum, Debug, Copy, Clone, Eq, PartialEq, EnumString, Serialize, Deserialize)]
7pub enum Direction {
8 #[graphql(name = "asc")]
9 #[strum(serialize = "asc", serialize = "ASC")]
10 Asc,
11 #[graphql(name = "desc")]
12 #[strum(serialize = "desc", serialize = "DESC")]
13 Desc,
14}
15
16impl Display for Direction {
17 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
18 match self {
19 Direction::Asc => write!(f, "ASC"),
20 Direction::Desc => write!(f, "DESC"),
21 }
22 }
23}
24#[derive(Debug, Clone)]
25pub struct OrderPredicate<'a> {
26 pub column: &'a str,
27 pub direction: Direction,
28}
29
30impl<'a> From<OrderPredicate<'a>> for String {
31 fn from(value: OrderPredicate<'a>) -> Self {
32 format!("{} {}", value.column, value.direction)
33 }
34}
35
36#[derive(Debug, Default, Clone)]
37pub struct OrderBy<'a>(&'a [OrderPredicate<'a>]);
38
39impl<'a> OrderBy<'a> {
40 pub fn new(values: &'a [OrderPredicate]) -> Self {
41 Self(values)
42 }
43
44 pub fn to_sql(&self) -> String {
45 let mut stmt = "".to_string();
46 if let Some(value) = self.0.first() {
47 stmt.push_str(value.column);
48 stmt.push(' ');
49 stmt.push_str(value.direction.to_string().as_str());
50 }
51
52 for value in self.0.iter().skip(1) {
53 stmt.push_str(", ");
54 stmt.push_str(value.column);
55 stmt.push(' ');
56 stmt.push_str(Direction::Asc.to_string().as_str());
57 }
58
59 stmt
60 }
61}
62
63pub fn asc(column: &str) -> OrderPredicate {
64 OrderPredicate {
65 column,
66 direction: Direction::Asc,
67 }
68}
69
70pub fn desc(column: &str) -> OrderPredicate {
71 OrderPredicate {
72 column,
73 direction: Direction::Desc,
74 }
75}