A tool to compile SQL to Elasticsearch queries
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

compiler.rs 2.4KB

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