Skip to content

Commit a7dc83f

Browse files
committed
sql-parser: select from clause (table name with indexed)
1 parent 749dd24 commit a7dc83f

File tree

2 files changed

+131
-1
lines changed

2 files changed

+131
-1
lines changed

src/ast/select.rs

+10
Original file line numberDiff line numberDiff line change
@@ -83,6 +83,16 @@ pub struct SelectFromTable {
8383
pub indexed_type: Option<IndexedType>,
8484
}
8585

86+
impl From<Identifier> for SelectFromTable {
87+
fn from(table_id: Identifier) -> Self {
88+
Self {
89+
table_id,
90+
alias: None,
91+
indexed_type: None,
92+
}
93+
}
94+
}
95+
8696
/// An enum representing the possible indexed types
8797
#[derive(Debug, PartialEq, Clone)]
8898
pub enum IndexedType {

src/parser/select/mod.rs

+121-1
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,9 @@
11
mod values;
22

3+
use crate::expression::IdentifierParser;
34
use crate::{
4-
DistinctType, Expression, Identifier, Keyword, SelectFrom, SelectFromSubquery, TokenType,
5+
DistinctType, Expression, Identifier, IndexedType, Keyword, SelectFrom, SelectFromSubquery,
6+
SelectFromTable, TokenType,
57
};
68

79
use super::expression::ExpressionParser;
@@ -135,6 +137,36 @@ impl<'a> SelectStatementParser for Parser<'a> {
135137
}
136138
}
137139

140+
if let Ok(id) = self.parse_identifier() {
141+
let alias = {
142+
if self.consume_as_keyword(Keyword::As).is_ok() {
143+
Some(self.consume_as_id()?)
144+
} else if let Ok(value) = self.consume_as_id() {
145+
Some(value.to_string())
146+
} else {
147+
None
148+
}
149+
};
150+
151+
let indexed_type = {
152+
if self.consume_as_keyword(Keyword::Indexed).is_ok() {
153+
self.consume_as_keyword(Keyword::By)?;
154+
Some(IndexedType::Indexed(self.consume_as_id()?))
155+
} else if self.consume_as_keyword(Keyword::Not).is_ok() {
156+
self.consume_as_keyword(Keyword::Indexed)?;
157+
Some(IndexedType::NotIndexed)
158+
} else {
159+
None
160+
}
161+
};
162+
163+
return Ok(Some(SelectFrom::Table(SelectFromTable {
164+
table_id: id,
165+
alias,
166+
indexed_type,
167+
})));
168+
}
169+
138170
// TODO: Parse table-or-subquery
139171
return Ok(None);
140172
}
@@ -382,6 +414,94 @@ mod test_select_result_columns {
382414
}
383415
}
384416

417+
#[cfg(test)]
418+
mod test_select_from_table_indexed {
419+
use super::test_utils::select_statement_with_from;
420+
use crate::parser::test_utils::*;
421+
use crate::{Identifier, IndexedType, SelectFrom, SelectFromTable, Statement};
422+
423+
#[test]
424+
fn test_select_from_table() {
425+
let expected_statement = select_statement_with_from(SelectFrom::Table(
426+
SelectFromTable::from(Identifier::Single("table_1".to_string())),
427+
));
428+
429+
run_sunny_day_test(
430+
"SELECT * FROM table_1",
431+
Statement::Select(expected_statement),
432+
);
433+
}
434+
435+
#[test]
436+
fn test_select_from_table_with_schema() {
437+
let expected_statement =
438+
select_statement_with_from(SelectFrom::Table(SelectFromTable::from(
439+
Identifier::Compound(vec!["schema_1".to_string(), "table_1".to_string()]),
440+
)));
441+
442+
run_sunny_day_test(
443+
"SELECT * FROM schema_1.table_1",
444+
Statement::Select(expected_statement),
445+
);
446+
}
447+
448+
#[test]
449+
fn test_select_from_table_with_alias() {
450+
let expected_statement = select_statement_with_from(SelectFrom::Table(SelectFromTable {
451+
table_id: Identifier::Compound(vec!["schema_1".to_string(), "table_1".to_string()]),
452+
alias: Some("alias".to_string()),
453+
indexed_type: None,
454+
}));
455+
456+
run_sunny_day_test(
457+
"SELECT * FROM schema_1.table_1 AS alias",
458+
Statement::Select(expected_statement),
459+
);
460+
}
461+
462+
#[test]
463+
fn test_select_from_table_with_alias_without_as_keyword() {
464+
let expected_statement = select_statement_with_from(SelectFrom::Table(SelectFromTable {
465+
table_id: Identifier::Single("table_1".to_string()),
466+
alias: Some("alias".to_string()),
467+
indexed_type: None,
468+
}));
469+
470+
run_sunny_day_test(
471+
"SELECT * FROM table_1 alias",
472+
Statement::Select(expected_statement),
473+
);
474+
}
475+
476+
#[test]
477+
fn test_select_from_table_with_alias_indexed() {
478+
let expected_statement = select_statement_with_from(SelectFrom::Table(SelectFromTable {
479+
table_id: Identifier::Single("table_1".to_string()),
480+
alias: Some("alias".to_string()),
481+
indexed_type: Some(IndexedType::Indexed("index_1".to_string())),
482+
}));
483+
484+
run_sunny_day_test(
485+
"SELECT * FROM table_1 alias INDEXED BY index_1",
486+
Statement::Select(expected_statement),
487+
);
488+
}
489+
490+
#[test]
491+
fn test_select_from_table_not_indexed() {
492+
let expected_statement = select_statement_with_from(SelectFrom::Table(SelectFromTable {
493+
table_id: Identifier::Single("table_1".to_string()),
494+
alias: None,
495+
indexed_type: Some(IndexedType::NotIndexed),
496+
}));
497+
498+
run_sunny_day_test(
499+
"SELECT * FROM table_1 NOT INDEXED",
500+
Statement::Select(expected_statement),
501+
);
502+
}
503+
}
504+
385505
#[cfg(test)]
386506
mod test_select_from_subquery {
387507
use super::test_utils::{select_statement_with_columns, select_statement_with_from};

0 commit comments

Comments
 (0)