edgedb_query/
lib.rs

1//! Edgedb-query crate aims to provide a bunch of traits or structs used
2//! by Edgedb-query-derive crate
3
4pub mod queries;
5pub mod models;
6
7use std::fmt::{Display, Formatter};
8pub use models::edge_query::EdgeQuery;
9pub use models::edge_query::ToEdgeQuery;
10pub use models::query_result::BasicResult;
11pub use queries::filter::Filter;
12pub use queries::select::Options;
13pub use queries::select::SelectOptions;
14pub use queries::select::OrderDir;
15pub use queries::select::OrderOptions;
16pub use queries::select::PageOptions;
17
18use edgedb_protocol::model::Uuid;
19use edgedb_protocol::value::Value;
20use crate::QueryType::{Delete, Insert, Select, Update};
21
22macro_rules! _to_edgeql_and_to_edge_scalar_impls {
23    ($($ty: ty => { scalar: $scalar: expr }),* $(,)?) => {
24        $(
25            impl ToEdgeQl for $ty {
26                fn to_edgeql(&self) -> EdgeQl {
27                    EdgeQl::new(self.to_string(), false)
28                }
29            }
30
31            impl ToEdgeScalar for $ty {
32                fn scalar() -> String {
33                    $scalar.to_owned()
34                }
35            }
36
37            impl ToEdgeShape for $ty {
38                fn shape() -> String {
39                    String::default()
40                }
41            }
42        )*
43    }
44}
45
46
47#[derive(Clone, Debug)]
48pub enum QueryType {
49    Insert,
50    Select,
51    Update,
52    Delete,
53    None,
54}
55
56impl Default for QueryType {
57    fn default() -> Self {
58        Self::None
59    }
60}
61
62impl From<String> for QueryType {
63    fn from(value: String) -> Self {
64       match value.to_lowercase().trim() {
65           "insert" => Insert,
66           "select" => Select,
67           "update" => Update,
68           "delete" => Delete,
69           _ => QueryType::None
70       }
71    }
72}
73
74impl Display for QueryType {
75    fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
76        match self {
77            Insert => write!(f, "insert"),
78            Select => write!(f, "select"),
79            Update => write!(f, "update"),
80            Delete => write!(f, "delete"),
81            QueryType::None => write!(f, ""),
82        }
83
84    }
85}
86
87#[derive(Default, Debug)]
88pub struct EdgeQl {
89    pub table_name: String,
90    pub query_type: QueryType,
91    pub content: String,
92    pub has_result: bool,
93}
94
95impl ToString for EdgeQl {
96    fn to_string(&self) -> String {
97        let s = match (self.content.clone().is_empty(), self.query_type.clone()) {
98            (true, QueryType::None) => String::default(),
99            (true, _) => format!("{} {}", self.query_type, self.table_name),
100            (false, QueryType::None) => self.content.clone(),
101            (false, _) => format!("{} {} {}", self.query_type, self.table_name, self.content),
102        };
103
104        if self.has_result {
105            format!("select ( {s}")
106        } else {
107            s
108        }
109    }
110}
111
112impl EdgeQl {
113    pub fn new(content: String, has_result: bool) -> Self {
114        Self {
115            table_name: String::default(),
116            query_type: QueryType::None,
117            content,
118            has_result,
119        }
120    }
121
122    pub fn detached(&mut self) -> Self {
123        Self {
124            table_name: format!("detached {}", self.table_name),
125            query_type: self.query_type.clone(),
126            content: self.content.clone(),
127            has_result: self.has_result,
128        }
129    }
130}
131
132
133pub trait ToEdgeQl {
134    /// Transform a struct into a edgeDB query language statement
135    fn to_edgeql(&self) -> EdgeQl;
136}
137
138pub trait ToEdgeScalar {
139    /// returns the cast expression corresponding to the self struct
140    fn scalar() -> String;
141}
142
143pub trait ToEdgeShape {
144    fn shape() -> String;
145}
146
147pub trait ToEdgeValue {
148    /// Transform a struct data into a edgedb_protocol::value::Value
149    fn to_edge_value(&self) -> Value;
150}
151
152pub trait EdgeResult {
153    fn returning_fields() -> Vec<&'static str>;
154}
155
156_to_edgeql_and_to_edge_scalar_impls!(
157    String => { scalar: "<str>" },
158    i8 => { scalar: "<int16>" },
159    u8 => { scalar: "<int16>" },
160    i16 => { scalar: "<int16>" },
161    u16 => { scalar: "<int16>" },
162    i32 => { scalar: "<int32>" },
163    u32 => { scalar: "<int32>" },
164    i64 => { scalar: "<int64>" },
165    u64 => { scalar: "<int64>" },
166    f32 => { scalar: "<float32>" },
167    f64 => { scalar: "<float64>" },
168    bool => { scalar: "<bool>" },
169    serde_json::Value => { scalar: "<json>" },
170    uuid::Uuid => { scalar:"<uuid>"},
171    chrono::DateTime<chrono::Utc> => { scalar: "<datetime>"},
172    chrono::DateTime<chrono::Local> => { scalar: "<cal::local_datetime>"},
173    chrono::Duration => { scalar : "<duration>"},
174    chrono::Date<chrono::Local> => { scalar: "<cal::local_date>"},
175    chrono::NaiveTime => { scalar: "<cal::local_time>"},
176    chrono::NaiveDate => { scalar: "<cal::local_date>"},
177);
178
179impl ToEdgeScalar for () {
180    fn scalar() -> String {
181        "".to_owned()
182    }
183}
184
185impl<T: ToEdgeQl> ToEdgeQl for Vec<T> {
186    fn to_edgeql(&self) -> EdgeQl {
187        let s = self
188            .iter()
189            .map(|s| s.to_edgeql().to_string())
190            .collect::<Vec<String>>()
191            .join(",");
192
193        EdgeQl::new(format!("[{}]", s), false)
194    }
195}
196
197impl<T: ToEdgeScalar + Default> ToEdgeScalar for Vec<T> {
198    fn scalar() -> String {
199        format!("<array{}>", T::scalar())
200    }
201}
202
203impl<T> ToEdgeShape for Vec<T> {
204    fn shape() -> String {
205        String::default()
206    }
207}
208
209impl ToEdgeValue for () {
210    fn to_edge_value(&self) -> Value {
211        Value::Nothing
212    }
213}
214
215impl ToEdgeValue for String {
216    fn to_edge_value(&self) -> Value {
217        Value::Str(self.to_string())
218    }
219}
220
221impl ToEdgeValue for i8 {
222    fn to_edge_value(&self) -> Value {
223        Value::Int16(*self as i16)
224    }
225}
226
227impl ToEdgeValue for u8 {
228    fn to_edge_value(&self) -> Value {
229        Value::Int16(*self as i16)
230    }
231}
232
233impl ToEdgeValue for i16 {
234    fn to_edge_value(&self) -> Value {
235        Value::Int16(*self)
236    }
237}
238
239impl ToEdgeValue for u16 {
240    fn to_edge_value(&self) -> Value {
241        Value::Int16(*self as i16)
242    }
243}
244
245impl ToEdgeValue for i32 {
246    fn to_edge_value(&self) -> Value {
247        Value::Int32(*self)
248    }
249}
250
251
252impl ToEdgeValue for u32 {
253    fn to_edge_value(&self) -> Value {
254        Value::Int32(*self as i32)
255    }
256}
257
258impl ToEdgeValue for i64 {
259    fn to_edge_value(&self) -> Value {
260        Value::Int64(*self)
261    }
262}
263
264
265impl ToEdgeValue for u64 {
266    fn to_edge_value(&self) -> Value {
267        Value::Int64(*self as i64)
268    }
269}
270
271impl ToEdgeValue for f32 {
272    fn to_edge_value(&self) -> Value {
273        Value::Float32(*self)
274    }
275}
276
277impl ToEdgeValue for f64 {
278    fn to_edge_value(&self) -> Value {
279        Value::Float64(*self)
280    }
281}
282
283impl ToEdgeValue for bool {
284    fn to_edge_value(&self) -> Value {
285        Value::Bool(*self)
286    }
287}
288
289impl<T: ToEdgeValue> ToEdgeValue for Vec<T> {
290    fn to_edge_value(&self) -> Value {
291        Value::Array(
292            self.iter()
293                .map(|t| t.to_edge_value())
294                .collect::<Vec<Value>>(),
295        )
296    }
297}
298
299impl ToEdgeValue for serde_json::Value {
300    fn to_edge_value(&self) -> Value {
301        Value::Json(self.to_string())
302    }
303}
304
305impl ToEdgeValue for Uuid {
306    fn to_edge_value(&self) -> Value {
307        Value::Uuid(Uuid::from_u128(self.as_u128()))
308    }
309}