ocarina 0.1.0

A small package that is working on abstracting sql.
Documentation
use super::*;
pub struct Parser {
    query: String,
    tokens: Vec<String>,
    keyword_indexs: Vec<usize>,
    expressions: Vec<expression::Expression>,
}

impl Parser {
    /// init a parser, that is working with a single query
    /// TODO access the need for changing or modifing the query inside the parser from some public
    /// methods, in order to just have one parser that can be used multiple times.
    pub fn new(query: String) -> Parser {
        Parser {
            query,
            tokens: Vec::new(),
            keyword_indexs: Vec::new(),
            expressions: Vec::new(),
        }
    }
    /// Overwrite the current values in order to process a new query
    /// this includes the vectors as well as the set query.
    /// TODO check the "runtime complexity"
    pub fn set_new_query(&mut self, new_query: String) {
        self.tokens = Vec::new();
        self.keyword_indexs = Vec::new();
        self.expressions = Vec::new();
        self.query = new_query;
    }
    /// split the query based on the white space in between. Will later be further processed in
    /// in order to generate a realtion between used keywords and their trailing data.
    pub fn split_query(&mut self) {
        // split string on space and load into a vec for later process.
        self.tokens = self
            .query
            .split_whitespace()
            .map(|s| s.to_string())
            .collect();
    }
    /// search for keywords and their index in the query, so that we can split the query apart
    /// based on the keywords position and its following arguments.
    ///
    /// # Calls build_expressions_from_keywords in order to combine the keyword with the data to an
    /// expression
    pub fn find_keywords(&mut self) {
        for i in 0..self.tokens.len() {
            //TODO check if following code has a good runtime complexity.
            if grammar::unwrap_string(self.tokens[i].to_string()) != grammar::Keyword::UNKNOWN {
                self.keyword_indexs.push(i);
            }
        }
        self.build_expressions_from_keywords();
    }
    /// combine the keywords with the trailing data that is used to create the expressions from the
    /// query.
    /// These queries will later be abstracted and combined.
    fn build_expressions_from_keywords(&mut self) {
        if self.keyword_indexs.is_empty() {
            panic!("No keywords have been found inside the query");
        }
        // the string parts between key_word_index 1 and index 2, serve as the expression data for
        // the first keywords
        for i in 0..self.keyword_indexs.len() {
            if i == self.keyword_indexs.len() - 1 {
                self.expressions.push(expression::Expression::new(
                    self.tokens[self.keyword_indexs[i]].to_string(),
                    self.tokens[self.keyword_indexs[i] + 1..self.tokens.len()].to_vec(),
                ));
            } else {
                // at the last object of the array, just return all data that is left in the token
                // array as the data for the given keyword that is at the last position for the
                // keyword_index_vec.
                self.expressions.push(expression::Expression::new(
                    self.tokens[self.keyword_indexs[i]].to_string(),
                    self.tokens[self.keyword_indexs[i] + 1..self.keyword_indexs[i + 1]].to_vec(),
                ));
            }
        }
    }
}

#[cfg(test)]
mod tests {
    use super::*;
    #[test]
    fn splitting_sql_query() {
        let query = "SELECT * FROM a";
        let mut parser = Parser::new(query.to_owned());
        parser.split_query();
        assert_eq!(parser.tokens, vec!["SELECT", "*", "FROM", "a"]);
    }

    #[test]
    fn indexing_of_keywords() {
        let query = "SELECT * FROM a";
        let mut parser = Parser::new(query.to_owned());
        parser.split_query();
        parser.find_keywords();
        assert_eq!(parser.keyword_indexs, vec![0, 2]);
    }

    #[test]
    fn correct_expression_building() {
        let query = "SELECT * FROM a";
        let mut parser = Parser::new(query.to_owned());
        parser.split_query();
        parser.find_keywords();

        let token_list = vec![
            expression::Expression::new(String::from("SELECT"), vec![String::from("*")]),
            expression::Expression::new(String::from("FROM"), vec![String::from("a")]),
        ];
        assert_eq!(token_list, parser.expressions);
    }

    #[test]
    fn special_query_input() {
        let query = "SELECT * FROM a WHERE a = 1";
        let mut parser = Parser::new(query.to_owned());
        parser.split_query();
        parser.find_keywords();
        let expression_listing = vec![
            expression::Expression::new(String::from("SELECT"), vec![String::from("*")]),
            expression::Expression::new(String::from("FROM"), vec![String::from("a")]),
            expression::Expression::new(
                String::from("WHERE"),
                vec![String::from("a"), String::from("="), String::from("1")],
            ),
        ];
        assert_eq!(expression_listing, parser.expressions);
    }
    /// after implement a sorting for the commands into the correct order,
    /// check if the sorting of the vec is performet in a correct and fast/efficient way, so that
    /// it can be used in the code without stoping the exectution of a query.
    #[test]
    fn order_commands_in_value_order() {}

    #[test]
    fn special_query_input_2() {
        let query = "SELECT a,b FROM a WHERE a = 1 ORDER test";
        let mut parser = Parser::new(query.to_owned());
        parser.split_query();
        parser.find_keywords();
        let expression_listing = vec![
            expression::Expression::new(String::from("SELECT"), vec![String::from("a,b")]),
            expression::Expression::new(String::from("FROM"), vec![String::from("a")]),
            expression::Expression::new(
                String::from("WHERE"),
                vec![String::from("a"), String::from("="), String::from("1")],
            ),
            expression::Expression::new(String::from("ORDER"), vec![String::from("test")]),
        ];
        assert_eq!(expression_listing, parser.expressions);
    }
}