use serde_json::{json, Value}; use std::fmt::{Display, Formatter}; use crate::error::KappeError; use crate::parser::{Field, Identifier, Select}; #[derive(Debug, PartialEq)] pub struct Query { pub source: Identifier, pub body: Value, } impl Query { pub fn new(source: Identifier, body: Value) -> Self { Self { source, body } } } impl Display for Query { fn fmt(&self, f: &mut Formatter) -> std::fmt::Result { let header = format!("GET /{}/_search", self.source.name); let body = match serde_json::to_string_pretty(&self.body) { Ok(body) => body, Err(_) => return Err(std::fmt::Error {}), }; write!(f, "{}\n{}", header, body) } } pub fn compile(expr: Select) -> Result { let field_names: Vec = expr .fields .iter() .map(|f| match f { Field::Star => Value::String("*".to_string()), Field::Named(name) => Value::String(name.clone()), }) .collect(); let body = json!({ "query": { "match_all":{} }, "_source": Value::Array(field_names) }); Ok(Query::new(expr.source, body)) } #[cfg(test)] mod tests { use super::*; use crate::lexer::scan; use crate::parser::parse; fn _compile(input: &str) -> Result { let tokens = scan(input).unwrap(); let select = parse(tokens).unwrap(); compile(select) } #[test] fn it_compiles_a_simple_select() { assert_eq!( _compile("SELECT * FROM bar").unwrap(), Query::new( Identifier::new("bar"), json!({ "query": { "match_all": {} }, "_source": ["*"] }) ) ) } #[test] fn it_compiles_a_select_with_specific_fields() { assert_eq!( _compile("SELECT foo FROM bar").unwrap(), Query::new( Identifier::new("bar"), json!({ "query": { "match_all": {} }, "_source": ["foo"] }) ) ) } }