1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
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);
    }
}