Skip to content

Commit bc7137f

Browse files
committed
sql-parser: select values parser
1 parent f18740a commit bc7137f

File tree

3 files changed

+130
-6
lines changed

3 files changed

+130
-6
lines changed

README.md

+3-2
Original file line numberDiff line numberDiff line change
@@ -58,15 +58,16 @@ The items were taken from the official SQLite documentation
5858

5959
### Advanced statements
6060

61-
#### SELECT Statement ![progress](https://progress-bar.xyz/0/?scale=9&suffix=%%%20(0%20of%209)&width=140)
61+
#### SELECT Statement ![progress](https://progress-bar.xyz/1/?scale=9&suffix=%%%20(1%20of%209)&width=140)
6262

63+
1. [values-stmt](https://www.sqlite.org/syntax/select-core.html) ✅
6364
1. [result-columns](https://www.sqlite.org/syntax/result-column.html)
6465
1. [table-or-subquery](https://www.sqlite.org/lang_select.html#tablename)
6566
1. [join-clauses](https://www.sqlite.org/syntax/join-clause.html)
6667
1. [where-group-by-having-clause](https://www.sqlite.org/lang_select.html#where)
6768
1. [window-functions](https://www.sqlite.org/syntax/window-defn.html)
6869
1. [select-core-stmt](https://www.sqlite.org/syntax/select-core.html)
69-
1. [values-stmt](https://www.sqlite.org/syntax/select-core.html)
70+
7071
1. [with-compound-stmt](https://www.sqlite.org/syntax/factored-select-stmt.html)
7172
1. [order-by-and-limit-clause](https://www.sqlite.org/lang_select.html#orderby)
7273
1. [common-table-expressions](https://www.sqlite.org/syntax/common-table-expression.html)

src/parser/expression/mod.rs

+1-2
Original file line numberDiff line numberDiff line change
@@ -397,8 +397,7 @@ pub(crate) mod test_utils {
397397
use crate::ast::{Expression, SelectItem};
398398
use crate::{
399399
BinaryOp, DataType, ExistsStatement, Function, FunctionArg, Identifier, LiteralValue,
400-
Parser, RaiseFunction, SelectStatement, SelectStatementType, Statement, UnaryOp,
401-
WindowDefinition,
400+
Parser, RaiseFunction, SelectStatementType, Statement, UnaryOp, WindowDefinition,
402401
};
403402

404403
pub fn run_sunny_day_test_with_multiple_expressions(

src/parser/select/values.rs

+126-2
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,135 @@
1-
use crate::{Parser, ParsingError, ValuesStatement};
1+
use crate::{
2+
expression::ExpressionParser, Expression, Keyword, Parser, ParsingError, TokenType,
3+
ValuesStatement,
4+
};
25

36
pub trait ValuesStatementParser {
47
fn parse_values_statement(&mut self) -> Result<ValuesStatement, ParsingError>;
8+
9+
fn parse_values_group(&mut self) -> Result<Vec<Expression>, ParsingError>;
510
}
611

712
impl<'a> ValuesStatementParser for Parser<'a> {
813
fn parse_values_statement(&mut self) -> Result<ValuesStatement, ParsingError> {
9-
Ok(ValuesStatement { values: Vec::new() })
14+
self.consume_as_keyword(Keyword::Values)?;
15+
let mut values = Vec::new();
16+
17+
// Check if the first token is a left parenthesis
18+
// which is mandatory for the VALUES statement
19+
self.peek_as(TokenType::LeftParen)?;
20+
21+
while self.peek_as(TokenType::LeftParen).is_ok() {
22+
let group = self.parse_values_group()?;
23+
24+
values.push(group);
25+
26+
// check if the current token is a comma, then consume it
27+
// otherwise break the loop
28+
if self.consume_as(TokenType::Comma).is_err() {
29+
break;
30+
}
31+
}
32+
33+
Ok(ValuesStatement { values })
34+
}
35+
36+
fn parse_values_group(&mut self) -> Result<Vec<Expression>, ParsingError> {
37+
self.consume_as(TokenType::LeftParen)?;
38+
39+
let mut group = Vec::new();
40+
41+
while let Ok(expression) = self.parse_expression() {
42+
group.push(expression);
43+
44+
if self.consume_as(TokenType::Comma).is_err() {
45+
break;
46+
}
47+
}
48+
49+
self.consume_as(TokenType::RightParen)?;
50+
51+
Ok(group)
52+
}
53+
}
54+
55+
#[cfg(test)]
56+
pub(crate) mod select_values_tests {
57+
use crate::{BinaryOp, Expression, SelectStatementType, Statement, ValuesStatement};
58+
59+
use crate::parser::expression::test_utils::*;
60+
use crate::parser::test_utils::run_sunny_day_test;
61+
62+
fn values_statement(values: Vec<Vec<Expression>>) -> Statement {
63+
Statement::Select(SelectStatementType::Values(ValuesStatement { values }))
64+
}
65+
66+
#[test]
67+
pub fn test_values_statement_parser_single_value() {
68+
run_sunny_day_test(
69+
"VALUES (1)",
70+
values_statement(vec![vec![numeric_literal_expression("1")]]),
71+
);
72+
}
73+
74+
#[test]
75+
pub fn test_values_statement_parser_multiple_values() {
76+
run_sunny_day_test(
77+
"VALUES (1, 2, 3)",
78+
values_statement(vec![vec![
79+
numeric_literal_expression("1"),
80+
numeric_literal_expression("2"),
81+
numeric_literal_expression("3"),
82+
]]),
83+
);
84+
}
85+
86+
#[test]
87+
pub fn test_values_statement_parser_multiple_expressions() {
88+
run_sunny_day_test(
89+
"VALUES (1 + 2, 3 * 4)",
90+
values_statement(vec![vec![
91+
binary_op_expression(
92+
BinaryOp::Plus,
93+
numeric_literal_expression("1"),
94+
numeric_literal_expression("2"),
95+
),
96+
binary_op_expression(
97+
BinaryOp::Mul,
98+
numeric_literal_expression("3"),
99+
numeric_literal_expression("4"),
100+
),
101+
]]),
102+
);
103+
}
104+
105+
#[test]
106+
pub fn test_values_statement_parser_multiple_groups() {
107+
run_sunny_day_test(
108+
"VALUES (1), (2), (3)",
109+
values_statement(vec![
110+
vec![numeric_literal_expression("1")],
111+
vec![numeric_literal_expression("2")],
112+
vec![numeric_literal_expression("3")],
113+
]),
114+
);
115+
}
116+
117+
#[test]
118+
pub fn test_values_statement_parser_multiple_groups_with_expressions() {
119+
run_sunny_day_test(
120+
"VALUES (1 + 2), (3 * 4)",
121+
values_statement(vec![
122+
vec![binary_op_expression(
123+
BinaryOp::Plus,
124+
numeric_literal_expression("1"),
125+
numeric_literal_expression("2"),
126+
)],
127+
vec![binary_op_expression(
128+
BinaryOp::Mul,
129+
numeric_literal_expression("3"),
130+
numeric_literal_expression("4"),
131+
)],
132+
]),
133+
);
10134
}
11135
}

0 commit comments

Comments
 (0)