edgedb_query/queries/
select.rs

1
2const ORDER_BY: &str = "order by";
3const LIMIT: &str = "limit";
4const OFFSET: &str = "offset";
5const ASC: &str = " asc";
6const DESC: &str = " desc";
7
8/// Options Trait represents an EdgeDB select query options :
9/// * order options
10/// * pagination options
11
12pub trait Options {
13
14    /// returns the query's order options
15    fn order_options(&self) -> Option<OrderOptions>;
16
17    /// returns the query's pagination options
18    fn page_options(&self) -> Option<PageOptions>;
19}
20
21/// Parse the select query options
22///
23/// __returns__ : the select options statment
24///
25/// ## Examples
26///
27/// ```
28/// use edgedb_query::queries::select::{OrderOptions, parse_options, SelectOptions, OrderDir, PageOptions};
29///
30/// let options = SelectOptions {
31///          order_options: Some(OrderOptions {
32///              order_by: String::from("name"),
33///              order_direction: Some(OrderDir::Desc),
34///          }),
35///          page_options: Some(PageOptions {
36///              limit: 10,
37///              offset: None
38///          })
39///      };
40///  let stmt = parse_options(&options, "users::User", vec!["name"]);
41///
42///  assert_eq!(" order by users::User.name desc limit 10".to_owned(), stmt)
43///
44/// ```
45pub fn parse_options<T: Options>(options: &T, table_name: impl Into<String>, result_fields: Vec<&str>) -> String {
46
47    let mut stmt = String::default();
48
49    let table_name = table_name.into();
50
51    if let Some(OrderOptions {
52                    order_by,
53                    order_direction,
54                }) = options.order_options().clone()
55    {
56        if !result_fields.contains(&order_by.as_str()) {
57            panic!("'order by' value must be one of {:#?}", result_fields)
58        }
59
60        stmt.push_str(format!(" {} {}.{}", ORDER_BY, table_name, order_by).as_str());
61
62        if let Some(OrderDir::Desc) = order_direction {
63            stmt.push_str(DESC)
64        } else {
65            stmt.push_str(ASC)
66        }
67    }
68
69    if let Some(PageOptions { limit, offset }) = options.page_options().clone() {
70        stmt.push_str(format!(" {} {}", LIMIT, limit).as_str());
71
72        if let Some(off) = offset {
73            stmt.push_str(format!(" {} {}", OFFSET, off).as_str());
74        }
75    }
76
77    stmt
78}
79
80/// Select query Order direction
81#[derive(Debug, Clone)]
82pub enum OrderDir {
83    Asc,
84    Desc,
85}
86
87/// Select query Order options
88#[derive(Debug, Clone)]
89pub struct OrderOptions {
90    pub order_by: String,
91    pub order_direction: Option<OrderDir>,
92}
93
94/// Select query Page Options
95#[derive(Debug, Clone)]
96pub struct PageOptions {
97    pub limit: u32,
98    pub offset: Option<u32>,
99}
100
101/// Select Options struct
102#[derive(Debug, Clone)]
103pub struct SelectOptions {
104    pub order_options: Option<OrderOptions>,
105    pub page_options: Option<PageOptions>,
106}
107
108impl Options for SelectOptions {
109
110    fn order_options(&self) -> Option<OrderOptions> {
111        self.order_options.clone()
112    }
113
114    fn page_options(&self) -> Option<PageOptions> {
115        self.page_options.clone()
116    }
117}