Browse Source

Compile select expressions

main
Dylan Baker 3 years ago
parent
commit
db1927ee16
5 changed files with 147 additions and 0 deletions
  1. 31
    0
      Cargo.lock
  2. 2
    0
      Cargo.toml
  3. 86
    0
      src/compiler.rs
  4. 27
    0
      src/error.rs
  5. 1
    0
      src/lib.rs

+ 31
- 0
Cargo.lock View File

@@ -15,8 +15,16 @@ version = "0.1.0"
15 15
 dependencies = [
16 16
  "lazy_static",
17 17
  "regex",
18
+ "serde",
19
+ "serde_json",
18 20
 ]
19 21
 
22
+[[package]]
23
+name = "itoa"
24
+version = "0.4.7"
25
+source = "registry+https://github.com/rust-lang/crates.io-index"
26
+checksum = "dd25036021b0de88a0aff6b850051563c6516d0bf53f8638938edbb9de732736"
27
+
20 28
 [[package]]
21 29
 name = "lazy_static"
22 30
 version = "1.4.0"
@@ -45,3 +53,26 @@ name = "regex-syntax"
45 53
 version = "0.6.23"
46 54
 source = "registry+https://github.com/rust-lang/crates.io-index"
47 55
 checksum = "24d5f089152e60f62d28b835fbff2cd2e8dc0baf1ac13343bef92ab7eed84548"
56
+
57
+[[package]]
58
+name = "ryu"
59
+version = "1.0.5"
60
+source = "registry+https://github.com/rust-lang/crates.io-index"
61
+checksum = "71d301d4193d031abdd79ff7e3dd721168a9572ef3fe51a1517aba235bd8f86e"
62
+
63
+[[package]]
64
+name = "serde"
65
+version = "1.0.125"
66
+source = "registry+https://github.com/rust-lang/crates.io-index"
67
+checksum = "558dc50e1a5a5fa7112ca2ce4effcb321b0300c0d4ccf0776a9f60cd89031171"
68
+
69
+[[package]]
70
+name = "serde_json"
71
+version = "1.0.64"
72
+source = "registry+https://github.com/rust-lang/crates.io-index"
73
+checksum = "799e97dc9fdae36a5c8b8f2cae9ce2ee9fdce2058c57a93e6099d919fd982f79"
74
+dependencies = [
75
+ "itoa",
76
+ "ryu",
77
+ "serde",
78
+]

+ 2
- 0
Cargo.toml View File

@@ -9,3 +9,5 @@ edition = "2018"
9 9
 [dependencies]
10 10
 lazy_static = "1.4.0"
11 11
 regex = "1.4.5"
12
+serde = "1.0.125"
13
+serde_json = "1.0.64"

+ 86
- 0
src/compiler.rs View File

@@ -0,0 +1,86 @@
1
+use serde_json::{json, Value};
2
+
3
+use crate::error::CompilerError;
4
+use crate::parser::{Field, Identifier, Select};
5
+
6
+#[derive(Debug, PartialEq)]
7
+pub struct Query {
8
+    pub source: Identifier,
9
+    pub body: Value,
10
+}
11
+
12
+impl Query {
13
+    pub fn new(source: Identifier, body: Value) -> Self {
14
+        Self { source, body }
15
+    }
16
+}
17
+
18
+pub fn compile(expr: Select) -> Result<Query, CompilerError> {
19
+    let mut source = false;
20
+    let field_names: Vec<Value> = expr
21
+        .fields
22
+        .iter()
23
+        .map(|f| match f {
24
+            Field::Star => {
25
+                source = true;
26
+                Value::String("*".to_string())
27
+            }
28
+            Field::Named(name) => Value::String(name.clone()),
29
+        })
30
+        .collect();
31
+
32
+    let body = json!({
33
+        "query": { "match_all":{} },
34
+        "_source": source,
35
+        "fields": Value::Array(field_names)
36
+    });
37
+
38
+    Ok(Query::new(expr.source, body))
39
+}
40
+
41
+#[cfg(test)]
42
+mod tests {
43
+    use super::*;
44
+    use crate::lexer::scan;
45
+    use crate::parser::parse;
46
+
47
+    fn _compile(input: &str) -> Result<Query, CompilerError> {
48
+        let tokens = scan(input).unwrap();
49
+        let select = parse(tokens).unwrap();
50
+        compile(select)
51
+    }
52
+
53
+    #[test]
54
+    fn it_compiles_a_simple_select() {
55
+        assert_eq!(
56
+            _compile("SELECT * FROM bar").unwrap(),
57
+            Query::new(
58
+                Identifier::new("bar"),
59
+                json!({
60
+                    "query": {
61
+                        "match_all": {}
62
+                    },
63
+                    "fields": ["*"],
64
+                    "_source": true
65
+                })
66
+            )
67
+        )
68
+    }
69
+
70
+    #[test]
71
+    fn it_compiles_a_select_with_specific_fields() {
72
+        assert_eq!(
73
+            _compile("SELECT foo FROM bar").unwrap(),
74
+            Query::new(
75
+                Identifier::new("bar"),
76
+                json!({
77
+                    "query": {
78
+                        "match_all": {}
79
+                    },
80
+                    "fields": ["foo"],
81
+                    "_source": false
82
+                })
83
+            )
84
+        )
85
+    }
86
+}

+ 27
- 0
src/error.rs View File

@@ -53,3 +53,30 @@ impl From<ParserError> for std::io::Error {
53 53
         Self::new(std::io::ErrorKind::InvalidInput, e.message)
54 54
     }
55 55
 }
56
+
57
+#[derive(Debug, PartialEq)]
58
+pub struct CompilerError {
59
+    message: String,
60
+}
61
+
62
+impl CompilerError {
63
+    pub fn new(message: &str) -> Self {
64
+        Self {
65
+            message: message.to_string(),
66
+        }
67
+    }
68
+}
69
+
70
+impl Display for CompilerError {
71
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
72
+        write!(f, "{}", &self.message)
73
+    }
74
+}
75
+
76
+impl Error for CompilerError {}
77
+
78
+impl From<CompilerError> for std::io::Error {
79
+    fn from(e: CompilerError) -> Self {
80
+        Self::new(std::io::ErrorKind::InvalidInput, e.message)
81
+    }
82
+}

+ 1
- 0
src/lib.rs View File

@@ -1,3 +1,4 @@
1
+pub mod compiler;
1 2
 pub mod error;
2 3
 pub mod lexer;
3 4
 pub mod parser;

Loading…
Cancel
Save