Skip to content

Commit 7f571f6

Browse files
committed
sql-parser: select from clause (function)
1 parent a7dc83f commit 7f571f6

File tree

1 file changed

+140
-38
lines changed

1 file changed

+140
-38
lines changed

src/parser/select/mod.rs

+140-38
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,8 @@ mod values;
22

33
use crate::expression::IdentifierParser;
44
use crate::{
5-
DistinctType, Expression, Identifier, IndexedType, Keyword, SelectFrom, SelectFromSubquery,
6-
SelectFromTable, TokenType,
5+
DistinctType, Expression, Identifier, IndexedType, Keyword, SelectFrom, SelectFromFunction,
6+
SelectFromSubquery, SelectFromTable, TokenType,
77
};
88

99
use super::expression::ExpressionParser;
@@ -22,6 +22,8 @@ pub trait SelectStatementParser {
2222
fn parse_select_column(&mut self) -> Result<SelectItem, ParsingError>;
2323

2424
fn parse_select_from_clause(&mut self) -> Result<Option<SelectFrom>, ParsingError>;
25+
26+
fn parse_alias_if_exists(&mut self) -> Result<Option<String>, ParsingError>;
2527
}
2628

2729
impl<'a> SelectStatementParser for Parser<'a> {
@@ -138,40 +140,57 @@ impl<'a> SelectStatementParser for Parser<'a> {
138140
}
139141

140142
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-
};
143+
dbg!("parse_select_from_clause");
144+
if self.peek_as(TokenType::LeftParen).is_ok() {
145+
self.consume_as(TokenType::LeftParen)?;
146+
147+
let arguments = self.parse_comma_separated_expressions()?;
162148

163-
return Ok(Some(SelectFrom::Table(SelectFromTable {
164-
table_id: id,
165-
alias,
166-
indexed_type,
167-
})));
149+
self.consume_as(TokenType::RightParen)?;
150+
let alias = self.parse_alias_if_exists()?;
151+
return Ok(Some(SelectFrom::Function(SelectFromFunction {
152+
function_name: id,
153+
arguments,
154+
alias,
155+
})));
156+
} else {
157+
let alias = self.parse_alias_if_exists()?;
158+
159+
let indexed_type = {
160+
if self.consume_as_keyword(Keyword::Indexed).is_ok() {
161+
self.consume_as_keyword(Keyword::By)?;
162+
Some(IndexedType::Indexed(self.consume_as_id()?))
163+
} else if self.consume_as_keyword(Keyword::Not).is_ok() {
164+
self.consume_as_keyword(Keyword::Indexed)?;
165+
Some(IndexedType::NotIndexed)
166+
} else {
167+
None
168+
}
169+
};
170+
171+
return Ok(Some(SelectFrom::Table(SelectFromTable {
172+
table_id: id,
173+
alias,
174+
indexed_type,
175+
})));
176+
}
168177
}
169178

170179
// TODO: Parse table-or-subquery
171180
return Ok(None);
172181
}
173182
Ok(None)
174183
}
184+
185+
fn parse_alias_if_exists(&mut self) -> Result<Option<String>, ParsingError> {
186+
if self.consume_as_keyword(Keyword::As).is_ok() {
187+
Ok(Some(self.consume_as_id()?))
188+
} else if let Ok(value) = self.consume_as_id() {
189+
Ok(Some(value.to_string()))
190+
} else {
191+
Ok(None)
192+
}
193+
}
175194
}
176195

177196
#[cfg(test)]
@@ -545,26 +564,109 @@ mod test_select_from_subquery {
545564

546565
run_sunny_day_test(
547566
"SELECT * FROM (SELECT t.* ) as alias",
567+
Statement::Select(expected_statement.clone()),
568+
);
569+
570+
// without the as keyword
571+
run_sunny_day_test(
572+
"SELECT * FROM (SELECT t.* ) alias",
573+
Statement::Select(expected_statement.clone()),
574+
);
575+
}
576+
}
577+
578+
#[cfg(test)]
579+
mod test_select_from_table_function {
580+
use super::test_utils::select_statement_with_from;
581+
use crate::expression::test_utils::{
582+
binary_op_expression, identifier_expression, numeric_literal_expression,
583+
};
584+
use crate::parser::test_utils::*;
585+
use crate::{BinaryOp, Identifier, SelectFrom, SelectFromFunction, Statement};
586+
587+
#[test]
588+
fn test_select_from_table_function() {
589+
let expected_statement =
590+
select_statement_with_from(SelectFrom::Function(SelectFromFunction {
591+
function_name: Identifier::Single("function_1".to_string()),
592+
arguments: vec![numeric_literal_expression("1")],
593+
alias: None,
594+
}));
595+
596+
run_sunny_day_test(
597+
"SELECT * FROM function_1(1)",
548598
Statement::Select(expected_statement),
549599
);
550600
}
551601

552602
#[test]
553-
fn test_select_from_subquery_aliased_without_as_keyword() {
603+
fn test_select_from_table_function_with_schema() {
554604
let expected_statement =
555-
select_statement_with_from(SelectFrom::Subquery(SelectFromSubquery {
556-
subquery: Box::new(SelectStatementType::Select(select_statement_with_columns(
557-
DistinctType::None,
558-
vec![SelectItem::Expression(Expression::Identifier(
559-
Identifier::Single("t1".to_string()),
560-
))],
561-
))),
562-
alias: Some("alias".to_string()),
605+
select_statement_with_from(SelectFrom::Function(SelectFromFunction {
606+
function_name: Identifier::Compound(vec![
607+
"schema_1".to_string(),
608+
"function_1".to_string(),
609+
]),
610+
arguments: vec![binary_op_expression(
611+
BinaryOp::Plus,
612+
numeric_literal_expression("1"),
613+
numeric_literal_expression("2"),
614+
)],
615+
alias: None,
563616
}));
564617

565618
run_sunny_day_test(
566-
"SELECT * FROM (SELECT t1) alias",
619+
"SELECT * FROM schema_1.function_1(1+2)",
567620
Statement::Select(expected_statement),
568621
);
569622
}
623+
624+
#[test]
625+
fn test_select_from_table_function_with_multiple_arguments() {
626+
let expected_statement =
627+
select_statement_with_from(SelectFrom::Function(SelectFromFunction {
628+
function_name: Identifier::Compound(vec![
629+
"schema_1".to_string(),
630+
"function_1".to_string(),
631+
]),
632+
arguments: vec![
633+
numeric_literal_expression("1"),
634+
identifier_expression(&["col1"]),
635+
numeric_literal_expression("3"),
636+
],
637+
alias: None,
638+
}));
639+
640+
run_sunny_day_test(
641+
"SELECT * FROM schema_1.function_1(1, col1, 3)",
642+
Statement::Select(expected_statement),
643+
);
644+
}
645+
646+
#[test]
647+
fn test_select_from_table_function_with_alias() {
648+
let expected_statement =
649+
select_statement_with_from(SelectFrom::Function(SelectFromFunction {
650+
function_name: Identifier::Compound(vec![
651+
"schema_1".to_string(),
652+
"function_1".to_string(),
653+
]),
654+
arguments: vec![
655+
numeric_literal_expression("1"),
656+
numeric_literal_expression("2"),
657+
numeric_literal_expression("3"),
658+
],
659+
alias: Some("alias".to_string()),
660+
}));
661+
662+
run_sunny_day_test(
663+
"SELECT * FROM schema_1.function_1(1, 2, 3) AS alias",
664+
Statement::Select(expected_statement.clone()),
665+
);
666+
667+
run_sunny_day_test(
668+
"SELECT * FROM schema_1.function_1(1, 2, 3) alias",
669+
Statement::Select(expected_statement.clone()),
670+
);
671+
}
570672
}

0 commit comments

Comments
 (0)