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.

parser.rs 6.6KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221
  1. use std::{iter::Peekable, slice::Iter};
  2. use crate::ast::{Equals, Field, KIdentifier, KNumber, KString, KValue, Select, Where};
  3. use crate::error::KappeError;
  4. use crate::token::{Token, TokenType};
  5. pub fn parse(tokens: Vec<Token>) -> Result<Select, KappeError> {
  6. parse_select_expression(&mut tokens.iter().peekable())
  7. }
  8. fn parse_select_expression(tokens: &mut Peekable<Iter<Token>>) -> Result<Select, KappeError> {
  9. eat(tokens, TokenType::Select)?;
  10. let fields = parse_fields(tokens)?;
  11. eat(tokens, TokenType::From)?;
  12. let source = eat(tokens, TokenType::Identfiier).and_then(|t| Ok(KIdentifier::new(&t.value)))?;
  13. let where_clause = parse_where_clause(tokens)?;
  14. Ok(Select {
  15. fields,
  16. source,
  17. where_clause,
  18. })
  19. }
  20. fn parse_fields(tokens: &mut Peekable<Iter<Token>>) -> Result<Vec<Field>, KappeError> {
  21. if current_token_is(tokens, TokenType::Star) {
  22. eat(tokens, TokenType::Star).and_then(|_| Ok(vec![Field::Star]))
  23. } else {
  24. let mut fields: Vec<Field> = vec![];
  25. loop {
  26. let field = eat(tokens, TokenType::Identfiier)?;
  27. fields.push(Field::Named(field.value.clone()));
  28. if current_token_is(tokens, TokenType::Comma) {
  29. eat(tokens, TokenType::Comma)?;
  30. } else {
  31. break;
  32. }
  33. }
  34. Ok(fields)
  35. }
  36. }
  37. fn parse_where_clause(tokens: &mut Peekable<Iter<Token>>) -> Result<Option<Where>, KappeError> {
  38. let mut predicates: Vec<Equals> = vec![];
  39. let where_clause = if current_token_is(tokens, TokenType::Where) {
  40. eat(tokens, TokenType::Where)?;
  41. let predicate = parse_predicate(tokens)?;
  42. predicates.push(predicate);
  43. if current_token_is(tokens, TokenType::Comma) {
  44. while current_token_is(tokens, TokenType::Comma) {
  45. eat(tokens, TokenType::Comma)?;
  46. let predicate = parse_predicate(tokens)?;
  47. predicates.push(predicate);
  48. }
  49. }
  50. Some(Where::new(predicates))
  51. } else {
  52. None
  53. };
  54. Ok(where_clause)
  55. }
  56. fn parse_predicate(tokens: &mut Peekable<Iter<Token>>) -> Result<Equals, KappeError> {
  57. let field = eat(tokens, TokenType::Identfiier)?;
  58. let field = KIdentifier::new(&field.value);
  59. eat(tokens, TokenType::Equals)?;
  60. let value: KValue = if current_token_is(tokens, TokenType::String) {
  61. let token = eat(tokens, TokenType::String)?;
  62. Ok(KValue::String(KString::new(&token.value)))
  63. } else if current_token_is(tokens, TokenType::Number) {
  64. let token = eat(tokens, TokenType::Number)?;
  65. match token.value.parse::<f64>() {
  66. Ok(n) => Ok(KValue::Number(KNumber::new(n))),
  67. Err(_) => Err(KappeError::new("Error converting number to f64")),
  68. }
  69. } else {
  70. Err(KappeError::new(
  71. "Invalid token on right-hand side of equals sign",
  72. ))
  73. }?;
  74. Ok(Equals::new(field, value))
  75. }
  76. fn current_token_is(tokens: &mut Peekable<Iter<Token>>, token_type: TokenType) -> bool {
  77. match tokens.peek() {
  78. Some(t) => t.token_type == token_type,
  79. None => false,
  80. }
  81. }
  82. fn eat<'a>(
  83. tokens: &'a mut Peekable<Iter<Token>>,
  84. token_type: TokenType,
  85. ) -> Result<&'a Token, KappeError> {
  86. match tokens.next() {
  87. Some(token) => {
  88. if token.token_type == token_type {
  89. Ok(token)
  90. } else {
  91. Err(KappeError::new(&format!(
  92. "Expected {} but got {}",
  93. token_type, token.token_type
  94. )))
  95. }
  96. }
  97. None => Err(KappeError::new("Unexpected end of tokens")),
  98. }
  99. }
  100. #[cfg(test)]
  101. mod tests {
  102. use super::*;
  103. use crate::lexer::scan;
  104. fn _parse(input: &str) -> Result<Select, KappeError> {
  105. let tokens = scan(input).unwrap();
  106. parse(tokens)
  107. }
  108. #[test]
  109. fn it_parses_a_simple_select() {
  110. assert_eq!(
  111. _parse("SELECT * FROM index").unwrap(),
  112. Select {
  113. fields: vec![Field::Star],
  114. source: KIdentifier::new("index"),
  115. where_clause: None
  116. },
  117. )
  118. }
  119. #[test]
  120. fn it_parses_a_select_with_field() {
  121. assert_eq!(
  122. _parse("SELECT field FROM index").unwrap(),
  123. Select {
  124. fields: vec![Field::Named("field".to_string())],
  125. source: KIdentifier::new("index"),
  126. where_clause: None
  127. },
  128. )
  129. }
  130. #[test]
  131. fn it_parses_a_select_with_multiple_fields() {
  132. assert_eq!(
  133. _parse("SELECT field_one, field_two FROM index").unwrap(),
  134. Select {
  135. fields: vec![
  136. Field::Named("field_one".to_string()),
  137. Field::Named("field_two".to_string())
  138. ],
  139. source: KIdentifier::new("index"),
  140. where_clause: None
  141. },
  142. )
  143. }
  144. #[test]
  145. fn it_parses_a_select_with_a_single_predicate_where_clause() {
  146. assert_eq!(
  147. _parse("SELECT * FROM index WHERE field = \"hello\"").unwrap(),
  148. Select {
  149. fields: vec![Field::Star],
  150. source: KIdentifier::new("index"),
  151. where_clause: Some(Where::new(vec![Equals::new(
  152. KIdentifier::new("field"),
  153. KValue::String(KString::new("hello")),
  154. )]))
  155. },
  156. )
  157. }
  158. #[test]
  159. fn it_parses_a_select_with_a_numeric_predicate() {
  160. assert_eq!(
  161. _parse("SELECT * FROM index WHERE field = 123").unwrap(),
  162. Select {
  163. fields: vec![Field::Star],
  164. source: KIdentifier::new("index"),
  165. where_clause: Some(Where::new(vec![Equals::new(
  166. KIdentifier::new("field"),
  167. KValue::Number(KNumber::new(123.0))
  168. ),]))
  169. },
  170. )
  171. }
  172. #[test]
  173. fn it_parses_a_select_with_a_multiple_predicate_where_clause() {
  174. assert_eq!(
  175. _parse("SELECT * FROM index WHERE field_one = \"hello\", field_two = \"world\"")
  176. .unwrap(),
  177. Select {
  178. fields: vec![Field::Star],
  179. source: KIdentifier::new("index"),
  180. where_clause: Some(Where::new(vec![
  181. Equals::new(
  182. KIdentifier::new("field_one"),
  183. KValue::String(KString::new("hello")),
  184. ),
  185. Equals::new(
  186. KIdentifier::new("field_two"),
  187. KValue::String(KString::new("world")),
  188. )
  189. ]))
  190. },
  191. )
  192. }
  193. }