1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
use super::FieldVal;
#[derive(Debug, Clone, Default)]
pub struct Statement<'a> {
pub filter: Option<Filter<'a>>,
pub sorts: Option<Vec<SortItem>>,
pub limit: Option<usize>,
pub offset: Option<usize>,
pub distinct: bool,
pub recursive_on: Option<&'a str>,
pub from: Option<&'a str>,
pub alias: Option<&'a str>,
}
impl<'a> Statement<'a> {
pub fn filter(mut self, f: Filter<'a>) -> Self {
self.filter = Some(f);
self
}
pub fn sort(mut self, field: &str, direction: SortDir) -> Self {
let mut sorts = self.sorts.unwrap_or_else(Vec::new);
sorts.push(SortItem(field.into(), direction));
self.sorts = Some(sorts);
self
}
pub fn limit(mut self, v: usize) -> Self {
self.limit = Some(v);
self
}
pub fn offset(mut self, v: usize) -> Self {
self.offset = Some(v);
self
}
pub fn distinct(mut self) -> Self {
self.distinct = true;
self
}
pub fn recursive_on(mut self, v: &'a str) -> Self {
self.recursive_on = Some(v);
self
}
pub fn from(mut self, v: &'a str) -> Self {
self.from = Some(v);
self
}
pub fn alias(mut self, v: &'a str) -> Self {
self.alias = Some(v);
self
}
}
#[derive(Debug, Clone)]
pub enum SortDir {
Ascend,
Descend,
}
#[derive(Debug, Clone)]
pub struct SortItem(pub String, pub SortDir);
#[derive(Debug, Clone)]
pub enum Filter<'a> {
CmpOp(CmpOp<'a>),
LogOp(Box<LogOp<'a>>),
Exists(Box<Statement<'a>>),
}
#[derive(Debug, Clone)]
pub enum LogOp<'a> {
And(Filter<'a>, Filter<'a>),
Or(Filter<'a>, Filter<'a>),
Not(Filter<'a>),
}
#[derive(Debug, Clone)]
pub enum CmpOp<'a> {
Gt(&'a str, FieldVal),
Lt(&'a str, FieldVal),
Eq(&'a str, FieldVal),
Ne(&'a str, FieldVal),
}
pub fn filter(v: Filter) -> Statement {
Statement::default().filter(v)
}
pub fn sort(field: &str, direction: SortDir) -> Statement {
Statement::default().sort(field, direction)
}
pub fn limit<'a>(v: usize) -> Statement<'a> {
Statement::default().limit(v)
}
pub fn offset<'a>(v: usize) -> Statement<'a> {
Statement::default().offset(v)
}
pub fn distinct<'a>() -> Statement<'a> {
Statement::default().distinct()
}
pub fn from(v: &str) -> Statement {
Statement::default().from(v)
}
pub fn gt(field: &str, value: impl Into<FieldVal>) -> Filter {
Filter::CmpOp(CmpOp::Gt(field, value.into()))
}
pub fn lt(field: &str, value: impl Into<FieldVal>) -> Filter {
Filter::CmpOp(CmpOp::Lt(field, value.into()))
}
pub fn eq(field: &str, value: impl Into<FieldVal>) -> Filter {
Filter::CmpOp(CmpOp::Eq(field, value.into()))
}
pub fn ne(field: &str, value: impl Into<FieldVal>) -> Filter {
Filter::CmpOp(CmpOp::Ne(field, value.into()))
}
pub fn and<'a>(f1: Filter<'a>, f2: Filter<'a>) -> Filter<'a> {
Filter::LogOp(Box::new(LogOp::And(f1, f2)))
}
pub fn or<'a>(f1: Filter<'a>, f2: Filter<'a>) -> Filter<'a> {
Filter::LogOp(Box::new(LogOp::Or(f1, f2)))
}
pub fn exists(s: Statement) -> Filter {
Filter::Exists(Box::new(s))
}
pub fn not(f: Filter) -> Filter {
Filter::LogOp(Box::new(LogOp::Not(f)))
}