Browse Source

Compile where clauses!

main
Dylan Baker 3 years ago
parent
commit
d3a6fb62ed
3 changed files with 132 additions and 32 deletions
  1. 22
    5
      src/ast.rs
  2. 88
    2
      src/compiler.rs
  3. 22
    25
      src/parser.rs

+ 22
- 5
src/ast.rs View File

12
 }
12
 }
13
 
13
 
14
 #[derive(Debug, PartialEq)]
14
 #[derive(Debug, PartialEq)]
15
-pub enum Where {
16
-    And(Vec<Where>),
17
-    Equals(KValue, KValue),
15
+pub struct Where {
16
+    pub predicates: Vec<Equals>,
17
+}
18
+
19
+impl Where {
20
+    pub fn new(predicates: Vec<Equals>) -> Self {
21
+        Self { predicates }
22
+    }
23
+}
24
+
25
+#[derive(Debug, PartialEq)]
26
+pub struct Equals {
27
+    pub left: KIdentifier,
28
+    pub right: KValue,
29
+}
30
+
31
+impl Equals {
32
+    pub fn new(left: KIdentifier, right: KValue) -> Self {
33
+        Self { left, right }
34
+    }
18
 }
35
 }
19
 
36
 
20
 #[derive(Debug, PartialEq)]
37
 #[derive(Debug, PartialEq)]
31
 
48
 
32
 #[derive(Debug, PartialEq)]
49
 #[derive(Debug, PartialEq)]
33
 pub struct KNumber {
50
 pub struct KNumber {
34
-    pub value: f32,
51
+    pub value: f64,
35
 }
52
 }
36
 
53
 
37
 #[derive(Debug, PartialEq)]
54
 #[derive(Debug, PartialEq)]
48
 }
65
 }
49
 
66
 
50
 impl KNumber {
67
 impl KNumber {
51
-    pub fn new(value: f32) -> Self {
68
+    pub fn new(value: f64) -> Self {
52
         Self { value }
69
         Self { value }
53
     }
70
     }
54
 }
71
 }

+ 88
- 2
src/compiler.rs View File

2
 
2
 
3
 use std::fmt::{Display, Formatter};
3
 use std::fmt::{Display, Formatter};
4
 
4
 
5
-use crate::ast::{Field, KIdentifier, Select};
5
+use crate::ast::{Field, KIdentifier, KValue, Select, Where};
6
 use crate::error::KappeError;
6
 use crate::error::KappeError;
7
 
7
 
8
 #[derive(Debug, PartialEq)]
8
 #[derive(Debug, PartialEq)]
38
         })
38
         })
39
         .collect();
39
         .collect();
40
 
40
 
41
+    let query = if let Some(where_clause) = expr.where_clause {
42
+        compile_where_clause(where_clause)
43
+    } else {
44
+        json!({ "match_all":{} })
45
+    };
46
+
41
     let body = json!({
47
     let body = json!({
42
-        "query": { "match_all":{} },
48
+        "query": query,
43
         "_source": Value::Array(field_names)
49
         "_source": Value::Array(field_names)
44
     });
50
     });
45
 
51
 
46
     Ok(Query::new(expr.source, body))
52
     Ok(Query::new(expr.source, body))
47
 }
53
 }
48
 
54
 
55
+pub fn compile_where_clause(where_clause: Where) -> Value {
56
+    let terms: Vec<Value> = where_clause
57
+        .predicates
58
+        .iter()
59
+        .map(|predicate| {
60
+            let mut map = serde_json::Map::new();
61
+            let key = predicate.left.name.clone();
62
+            let value = compile_kvalue(&predicate.right);
63
+            map.insert(key, value);
64
+            json!({ "term": Value::Object(map) })
65
+        })
66
+        .collect();
67
+
68
+    json!({
69
+        "bool": {
70
+            "filter": Value::Array(terms)
71
+        }
72
+    })
73
+}
74
+
75
+pub fn compile_kvalue(value: &KValue) -> Value {
76
+    match value {
77
+        KValue::Identifier(identifier) => Value::String(identifier.name.to_string()),
78
+        KValue::Number(number) => {
79
+            Value::Number(serde_json::Number::from_f64(number.value).unwrap())
80
+        }
81
+        KValue::String(string) => Value::String(string.value.to_string()),
82
+    }
83
+}
84
+
49
 #[cfg(test)]
85
 #[cfg(test)]
50
 mod tests {
86
 mod tests {
51
     use super::*;
87
     use super::*;
89
             )
125
             )
90
         )
126
         )
91
     }
127
     }
128
+
129
+    #[test]
130
+    fn it_compiles_a_select_with_a_single_predicate_where_clause() {
131
+        let mut map: serde_json::Map<String, Value> = serde_json::Map::new();
132
+        map.insert("baz".to_string(), Value::String("quux".to_string()));
133
+        assert_eq!(
134
+            _compile("SELECT * FROM bar WHERE baz = \"quux\"").unwrap(),
135
+            Query::new(
136
+                KIdentifier::new("bar"),
137
+                json!({
138
+                    "query": {
139
+                        "bool": {
140
+                            "filter": [
141
+                                json!({ "term": Value::Object(map) })
142
+                            ]
143
+                        }
144
+                    },
145
+                    "_source": ["*"]
146
+                })
147
+            )
148
+        )
149
+    }
150
+
151
+    #[test]
152
+    fn it_compiles_a_select_with_a_multiple_predicate_where_claus() {
153
+        let mut map_one: serde_json::Map<String, Value> = serde_json::Map::new();
154
+        map_one.insert("baz".to_string(), Value::String("quux".to_string()));
155
+        let mut map_two: serde_json::Map<String, Value> = serde_json::Map::new();
156
+        map_two.insert(
157
+            "bop".to_string(),
158
+            Value::Number(serde_json::Number::from_f64(5.0).unwrap()),
159
+        );
160
+        assert_eq!(
161
+            _compile("SELECT * FROM bar WHERE baz = \"quux\", bop = 5").unwrap(),
162
+            Query::new(
163
+                KIdentifier::new("bar"),
164
+                json!({
165
+                    "query": {
166
+                        "bool": {
167
+                            "filter": [
168
+                                json!({ "term": Value::Object(map_one) }),
169
+                                json!({ "term": Value::Object(map_two) }),
170
+                            ]
171
+                        }
172
+                    },
173
+                    "_source": ["*"]
174
+                })
175
+            )
176
+        )
177
+    }
92
 }
178
 }

+ 22
- 25
src/parser.rs View File

1
 use std::{iter::Peekable, slice::Iter};
1
 use std::{iter::Peekable, slice::Iter};
2
 
2
 
3
-use crate::ast::{Field, KIdentifier, KNumber, KString, KValue, Select, Where};
3
+use crate::ast::{Equals, Field, KIdentifier, KNumber, KString, KValue, Select, Where};
4
 use crate::error::KappeError;
4
 use crate::error::KappeError;
5
 use crate::token::{Token, TokenType};
5
 use crate::token::{Token, TokenType};
6
 
6
 
45
 }
45
 }
46
 
46
 
47
 fn parse_where_clause(tokens: &mut Peekable<Iter<Token>>) -> Result<Option<Where>, KappeError> {
47
 fn parse_where_clause(tokens: &mut Peekable<Iter<Token>>) -> Result<Option<Where>, KappeError> {
48
+    let mut predicates: Vec<Equals> = vec![];
48
     let where_clause = if current_token_is(tokens, TokenType::Where) {
49
     let where_clause = if current_token_is(tokens, TokenType::Where) {
49
         eat(tokens, TokenType::Where)?;
50
         eat(tokens, TokenType::Where)?;
50
 
51
 
51
         let predicate = parse_predicate(tokens)?;
52
         let predicate = parse_predicate(tokens)?;
53
+        predicates.push(predicate);
52
 
54
 
53
         if current_token_is(tokens, TokenType::Comma) {
55
         if current_token_is(tokens, TokenType::Comma) {
54
-            let mut predicates: Vec<Where> = vec![];
55
-            predicates.push(predicate);
56
-
57
             while current_token_is(tokens, TokenType::Comma) {
56
             while current_token_is(tokens, TokenType::Comma) {
58
                 eat(tokens, TokenType::Comma)?;
57
                 eat(tokens, TokenType::Comma)?;
59
                 let predicate = parse_predicate(tokens)?;
58
                 let predicate = parse_predicate(tokens)?;
60
                 predicates.push(predicate);
59
                 predicates.push(predicate);
61
             }
60
             }
62
-
63
-            Some(Where::And(predicates))
64
-        } else {
65
-            Some(predicate)
66
         }
61
         }
62
+
63
+        Some(Where::new(predicates))
67
     } else {
64
     } else {
68
         None
65
         None
69
     };
66
     };
71
     Ok(where_clause)
68
     Ok(where_clause)
72
 }
69
 }
73
 
70
 
74
-fn parse_predicate(tokens: &mut Peekable<Iter<Token>>) -> Result<Where, KappeError> {
71
+fn parse_predicate(tokens: &mut Peekable<Iter<Token>>) -> Result<Equals, KappeError> {
75
     let field = eat(tokens, TokenType::Identfiier)?;
72
     let field = eat(tokens, TokenType::Identfiier)?;
76
-    let field = KValue::Identifier(KIdentifier::new(&field.value));
73
+    let field = KIdentifier::new(&field.value);
77
 
74
 
78
     eat(tokens, TokenType::Equals)?;
75
     eat(tokens, TokenType::Equals)?;
79
 
76
 
82
         Ok(KValue::String(KString::new(&token.value)))
79
         Ok(KValue::String(KString::new(&token.value)))
83
     } else if current_token_is(tokens, TokenType::Number) {
80
     } else if current_token_is(tokens, TokenType::Number) {
84
         let token = eat(tokens, TokenType::Number)?;
81
         let token = eat(tokens, TokenType::Number)?;
85
-        match token.value.parse::<f32>() {
82
+        match token.value.parse::<f64>() {
86
             Ok(n) => Ok(KValue::Number(KNumber::new(n))),
83
             Ok(n) => Ok(KValue::Number(KNumber::new(n))),
87
-            Err(_) => Err(KappeError::new("Error converting number to f32")),
84
+            Err(_) => Err(KappeError::new("Error converting number to f64")),
88
         }
85
         }
89
     } else {
86
     } else {
90
         Err(KappeError::new(
87
         Err(KappeError::new(
92
         ))
89
         ))
93
     }?;
90
     }?;
94
 
91
 
95
-    Ok(Where::Equals(field, value))
92
+    Ok(Equals::new(field, value))
96
 }
93
 }
97
 
94
 
98
 fn current_token_is(tokens: &mut Peekable<Iter<Token>>, token_type: TokenType) -> bool {
95
 fn current_token_is(tokens: &mut Peekable<Iter<Token>>, token_type: TokenType) -> bool {
177
             Select {
174
             Select {
178
                 fields: vec![Field::Star],
175
                 fields: vec![Field::Star],
179
                 source: KIdentifier::new("index"),
176
                 source: KIdentifier::new("index"),
180
-                where_clause: Some(Where::Equals(
181
-                    KValue::Identifier(KIdentifier::new("field")),
177
+                where_clause: Some(Where::new(vec![Equals::new(
178
+                    KIdentifier::new("field"),
182
                     KValue::String(KString::new("hello")),
179
                     KValue::String(KString::new("hello")),
183
-                ))
180
+                )]))
184
             },
181
             },
185
         )
182
         )
186
     }
183
     }
192
             Select {
189
             Select {
193
                 fields: vec![Field::Star],
190
                 fields: vec![Field::Star],
194
                 source: KIdentifier::new("index"),
191
                 source: KIdentifier::new("index"),
195
-                where_clause: Some(Where::Equals(
196
-                    KValue::Identifier(KIdentifier::new("field")),
197
-                    KValue::Number(KNumber::new(123.0)),
198
-                ))
192
+                where_clause: Some(Where::new(vec![Equals::new(
193
+                    KIdentifier::new("field"),
194
+                    KValue::Number(KNumber::new(123.0))
195
+                ),]))
199
             },
196
             },
200
         )
197
         )
201
     }
198
     }
208
             Select {
205
             Select {
209
                 fields: vec![Field::Star],
206
                 fields: vec![Field::Star],
210
                 source: KIdentifier::new("index"),
207
                 source: KIdentifier::new("index"),
211
-                where_clause: Some(Where::And(vec![
212
-                    Where::Equals(
213
-                        KValue::Identifier(KIdentifier::new("field_one")),
208
+                where_clause: Some(Where::new(vec![
209
+                    Equals::new(
210
+                        KIdentifier::new("field_one"),
214
                         KValue::String(KString::new("hello")),
211
                         KValue::String(KString::new("hello")),
215
                     ),
212
                     ),
216
-                    Where::Equals(
217
-                        KValue::Identifier(KIdentifier::new("field_two")),
213
+                    Equals::new(
214
+                        KIdentifier::new("field_two"),
218
                         KValue::String(KString::new("world")),
215
                         KValue::String(KString::new("world")),
219
                     )
216
                     )
220
                 ]))
217
                 ]))

Loading…
Cancel
Save