|
| 1 | +use crate::{ |
| 2 | + expression::IdentifierParser, |
| 3 | + parser::{insert::InsertStatementParser, select::SelectStatementParser}, |
| 4 | + CreateIndexStatement, Keyword, Parser, ParsingError, |
| 5 | +}; |
1 | 6 |
|
| 7 | +use super::CreateStatementParser; |
| 8 | + |
| 9 | +pub trait CreateIndexStatementParser { |
| 10 | + fn parse_create_index_statement( |
| 11 | + &mut self, |
| 12 | + unique: bool, |
| 13 | + ) -> Result<CreateIndexStatement, ParsingError>; |
| 14 | +} |
| 15 | + |
| 16 | +impl<'a> CreateIndexStatementParser for Parser<'a> { |
| 17 | + fn parse_create_index_statement( |
| 18 | + &mut self, |
| 19 | + unique: bool, |
| 20 | + ) -> Result<CreateIndexStatement, ParsingError> { |
| 21 | + self.consume_as_keyword(Keyword::Index)?; |
| 22 | + |
| 23 | + let if_not_exists = self.parse_if_not_exists()?; |
| 24 | + let index_name = self.parse_identifier()?; |
| 25 | + self.consume_as_keyword(Keyword::On)?; |
| 26 | + let table_name = self.parse_identifier()?; |
| 27 | + |
| 28 | + let columns = self.parse_indexed_columns()?; |
| 29 | + |
| 30 | + let where_clause = self.parse_where_clause()?; |
| 31 | + |
| 32 | + Ok(CreateIndexStatement { |
| 33 | + unique, |
| 34 | + if_not_exists, |
| 35 | + index_name, |
| 36 | + table_name, |
| 37 | + columns, |
| 38 | + where_clause, |
| 39 | + }) |
| 40 | + } |
| 41 | +} |
| 42 | + |
| 43 | +#[cfg(test)] |
| 44 | +mod test_utils { |
| 45 | + use crate::{ |
| 46 | + expression::test_utils::identifier_expression, CreateIndexStatement, Identifier, |
| 47 | + IndexedColumn, |
| 48 | + }; |
| 49 | + |
| 50 | + pub fn create_index_statement() -> CreateIndexStatement { |
| 51 | + CreateIndexStatement { |
| 52 | + unique: false, |
| 53 | + if_not_exists: false, |
| 54 | + index_name: Identifier::from("index_name"), |
| 55 | + table_name: Identifier::from("table_name"), |
| 56 | + columns: vec![IndexedColumn { |
| 57 | + column: identifier_expression(&["column1"]), |
| 58 | + ordering: None, |
| 59 | + }], |
| 60 | + where_clause: None, |
| 61 | + } |
| 62 | + } |
| 63 | +} |
| 64 | + |
| 65 | +#[cfg(test)] |
| 66 | +mod test_create_index_statement_parser { |
| 67 | + use test_utils::create_index_statement; |
| 68 | + |
| 69 | + use crate::{ |
| 70 | + expression::test_utils::{ |
| 71 | + binary_op_expression, identifier_expression, numeric_literal_expression, |
| 72 | + }, |
| 73 | + parser::test_utils::run_sunny_day_test, |
| 74 | + BinaryOp, Identifier, IndexedColumn, Statement, |
| 75 | + }; |
| 76 | + |
| 77 | + use super::*; |
| 78 | + |
| 79 | + #[test] |
| 80 | + fn test_parse_create_index_statement() { |
| 81 | + let sql = "CREATE INDEX index_name ON table_name (column1)"; |
| 82 | + let expected = create_index_statement(); |
| 83 | + run_sunny_day_test(sql, Statement::CreateIndex(expected)); |
| 84 | + } |
| 85 | + |
| 86 | + #[test] |
| 87 | + fn test_parse_create_unique_index_statement() { |
| 88 | + let sql = "CREATE UNIQUE INDEX index_name ON table_name (column1)"; |
| 89 | + let mut expected = create_index_statement(); |
| 90 | + expected.unique = true; |
| 91 | + run_sunny_day_test(sql, Statement::CreateIndex(expected)); |
| 92 | + } |
| 93 | + |
| 94 | + #[test] |
| 95 | + fn test_parse_create_index_statement_with_schema() { |
| 96 | + let sql = "CREATE INDEX schema_name.index_name ON table_name (column1)"; |
| 97 | + let mut expected = create_index_statement(); |
| 98 | + expected.index_name = |
| 99 | + Identifier::Compound(vec!["schema_name".to_string(), "index_name".to_string()]); |
| 100 | + run_sunny_day_test(sql, Statement::CreateIndex(expected)); |
| 101 | + } |
| 102 | + |
| 103 | + #[test] |
| 104 | + fn test_parse_create_index_statement_with_multiple_columns() { |
| 105 | + let sql = "CREATE INDEX index_name ON table_name (column1, column2, column3, column4)"; |
| 106 | + let mut expected = create_index_statement(); |
| 107 | + expected.columns = vec![ |
| 108 | + IndexedColumn { |
| 109 | + column: identifier_expression(&["column1"]), |
| 110 | + ordering: None, |
| 111 | + }, |
| 112 | + IndexedColumn { |
| 113 | + column: identifier_expression(&["column2"]), |
| 114 | + ordering: None, |
| 115 | + }, |
| 116 | + IndexedColumn { |
| 117 | + column: identifier_expression(&["column3"]), |
| 118 | + ordering: None, |
| 119 | + }, |
| 120 | + IndexedColumn { |
| 121 | + column: identifier_expression(&["column4"]), |
| 122 | + ordering: None, |
| 123 | + }, |
| 124 | + ]; |
| 125 | + run_sunny_day_test(sql, Statement::CreateIndex(expected)); |
| 126 | + } |
| 127 | + |
| 128 | + #[test] |
| 129 | + fn test_parse_create_index_statement_with_if_not_exists() { |
| 130 | + let sql = "CREATE INDEX IF NOT EXISTS index_name ON table_name (column1)"; |
| 131 | + let mut expected = create_index_statement(); |
| 132 | + expected.if_not_exists = true; |
| 133 | + run_sunny_day_test(sql, Statement::CreateIndex(expected)); |
| 134 | + } |
| 135 | + |
| 136 | + #[test] |
| 137 | + fn test_parse_create_index_statement_with_where_clause() { |
| 138 | + let sql = "CREATE INDEX index_name ON table_name (column1) WHERE column1 = 1"; |
| 139 | + let mut expected = create_index_statement(); |
| 140 | + expected.where_clause = Some(Box::new(binary_op_expression( |
| 141 | + BinaryOp::Equals, |
| 142 | + identifier_expression(&["column1"]), |
| 143 | + numeric_literal_expression("1"), |
| 144 | + ))); |
| 145 | + run_sunny_day_test(sql, Statement::CreateIndex(expected)); |
| 146 | + } |
| 147 | +} |
0 commit comments