Skip to content

Commit 24ceee9

Browse files
committed
sql_parser: select (window-defn parser)
1 parent fc4e73e commit 24ceee9

File tree

7 files changed

+396
-243
lines changed

7 files changed

+396
-243
lines changed

src/ast/expression.rs

+9
Original file line numberDiff line numberDiff line change
@@ -258,6 +258,15 @@ pub struct WindowDefinition {
258258
pub frame_spec: Option<FrameSpec>,
259259
}
260260

261+
/// A window definition
262+
#[derive(Debug, PartialEq, Clone, Default)]
263+
pub struct NamedWindowDefinition {
264+
/// The window name
265+
pub window_name: String,
266+
/// The window definition
267+
pub window_definition: WindowDefinition,
268+
}
269+
261270
/// Nulls ordering
262271
#[derive(Debug, PartialEq, Clone)]
263272
pub enum NullsOrdering {

src/ast/select.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
use super::{Expression, Identifier, OrderingTerm, WindowDefinition};
1+
use super::{Expression, Identifier, NamedWindowDefinition, OrderingTerm};
22
use std::fmt::Display;
33

44
/// An enum representing the possible types of SELECT statements
@@ -32,7 +32,7 @@ pub struct SelectStatement {
3232
pub having: Option<Box<Expression>>,
3333

3434
/// The WINDOW clause
35-
pub window: Option<Vec<WindowDefinition>>,
35+
pub window: Option<Vec<NamedWindowDefinition>>,
3636

3737
/// The ORDER BY clause
3838
pub order_by: Option<OrderingTerm>,

src/parser/expression/function_expr.rs

+3-225
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
use crate::{
2-
BetweenFrameSpec, BetweenFrameSpecType, Expression, FrameSpec, FrameSpecExclude, FrameSpecType,
3-
FrameType, Function, FunctionArg, FunctionArgType, Identifier, Keyword, NullsOrdering,
4-
Ordering, OrderingTerm, OverClause, Parser, ParsingError, TokenType, WindowDefinition,
2+
parser::window_definition::WindowDefinitionParser, Expression, Function, FunctionArg,
3+
FunctionArgType, Identifier, Keyword, OverClause, Parser, ParsingError, TokenType,
54
};
65

76
use super::ExpressionParser;
@@ -13,22 +12,8 @@ pub trait FunctionParser {
1312
/// Parse a function argument
1413
fn parse_function_arg(&mut self) -> Result<FunctionArg, ParsingError>;
1514

16-
/// Parse a function ordering terms
17-
fn parse_function_ordering_terms(&mut self) -> Result<Vec<OrderingTerm>, ParsingError>;
18-
1915
/// Parse a function filter clause
2016
fn parse_function_filter_clause(&mut self) -> Result<Expression, ParsingError>;
21-
22-
/// Parse a function over clause
23-
fn parse_window_definition(&mut self) -> Result<WindowDefinition, ParsingError>;
24-
25-
/// Parse a frame spec
26-
fn parse_function_over_clause_frame_spec(&mut self) -> Result<FrameSpec, ParsingError>;
27-
28-
/// Parse a frame spec between clause
29-
fn parse_function_over_clause_frame_spec_between(
30-
&mut self,
31-
) -> Result<FrameSpecType, ParsingError>;
3217
}
3318

3419
impl<'a> FunctionParser for Parser<'a> {
@@ -122,7 +107,7 @@ impl<'a> FunctionParser for Parser<'a> {
122107

123108
match last_expression {
124109
FunctionArgType::Expression(expression) => {
125-
let ordering_terms = self.parse_function_ordering_terms()?;
110+
let ordering_terms = self.parse_ordering_terms()?;
126111
let arg = FunctionArgType::OrderedBy(expression, ordering_terms);
127112
function_argument.arguments.push(arg);
128113
}
@@ -144,54 +129,6 @@ impl<'a> FunctionParser for Parser<'a> {
144129
}
145130
}
146131

147-
/// Parse a function ordering terms
148-
fn parse_function_ordering_terms(&mut self) -> Result<Vec<OrderingTerm>, ParsingError> {
149-
let mut ordering_terms = vec![];
150-
151-
while let Ok(expression) = self.parse_expression() {
152-
// No need to check for CollateExpression, because it will be parsed as an Expression
153-
154-
let mut ordering_term = OrderingTerm {
155-
expression: Box::new(expression),
156-
ordering: None,
157-
nulls_ordering: None,
158-
};
159-
160-
if let Ok(Keyword::Asc) = self.peek_as_keyword() {
161-
ordering_term.ordering = Some(Ordering::Asc);
162-
self.consume_as_keyword(Keyword::Asc)?;
163-
} else if let Ok(Keyword::Desc) = self.peek_as_keyword() {
164-
ordering_term.ordering = Some(Ordering::Desc);
165-
self.consume_as_keyword(Keyword::Desc)?;
166-
}
167-
168-
if let Ok(Keyword::Nulls) = self.peek_as_keyword() {
169-
self.consume_as_keyword(Keyword::Nulls)?;
170-
171-
if let Ok(Keyword::First) = self.peek_as_keyword() {
172-
ordering_term.nulls_ordering = Some(NullsOrdering::First);
173-
self.consume_as_keyword(Keyword::First)?;
174-
} else if let Ok(Keyword::Last) = self.peek_as_keyword() {
175-
ordering_term.nulls_ordering = Some(NullsOrdering::Last);
176-
self.consume_as_keyword(Keyword::Last)?;
177-
} else {
178-
return Err(ParsingError::UnexpectedToken(format!(
179-
"Expected FIRST or LAST keyword, got: {}",
180-
self.peek_token()?.token_type
181-
)));
182-
}
183-
}
184-
185-
ordering_terms.push(ordering_term);
186-
187-
if self.consume_as(TokenType::Comma).is_err() {
188-
break;
189-
}
190-
}
191-
192-
Ok(ordering_terms)
193-
}
194-
195132
/// Parse a function filter clause
196133
fn parse_function_filter_clause(&mut self) -> Result<Expression, ParsingError> {
197134
// Consume the opening left parenthesis
@@ -205,165 +142,6 @@ impl<'a> FunctionParser for Parser<'a> {
205142
self.consume_as(TokenType::RightParen)?;
206143
Ok(expression)
207144
}
208-
209-
/// Parse a function over clause
210-
fn parse_window_definition(&mut self) -> Result<WindowDefinition, ParsingError> {
211-
self.consume_as(TokenType::LeftParen)?;
212-
213-
let mut over_clause = WindowDefinition::default();
214-
if let Ok(base_window_name) = self.peek_as_id() {
215-
over_clause.base_window_name = Some(base_window_name.to_string());
216-
self.consume_as_id()?;
217-
}
218-
219-
if let Ok(Keyword::Partition) = self.peek_as_keyword() {
220-
self.consume_as_keyword(Keyword::Partition)?;
221-
222-
self.consume_as_keyword(Keyword::By)?;
223-
224-
while let Ok(expression) = self.parse_expression() {
225-
match over_clause.partition_by.as_mut() {
226-
Some(partition_by) => partition_by.push(expression),
227-
None => over_clause.partition_by = Some(vec![expression]),
228-
}
229-
if self.peek_as(TokenType::Comma).is_ok() {
230-
self.consume_token()?;
231-
} else {
232-
break;
233-
}
234-
}
235-
}
236-
237-
if let Ok(Keyword::Order) = self.peek_as_keyword() {
238-
self.consume_as_keyword(Keyword::Order)?;
239-
240-
self.consume_as_keyword(Keyword::By)?;
241-
let ordering_terms = self.parse_function_ordering_terms()?;
242-
over_clause.order_by = Some(ordering_terms);
243-
}
244-
245-
// frame spec
246-
if let Ok(Keyword::Range | Keyword::Rows | Keyword::Groups) = self.peek_as_keyword() {
247-
// do not consume the keyword, as it will be used in the frame spec parsing
248-
over_clause.frame_spec = Some(self.parse_function_over_clause_frame_spec()?);
249-
}
250-
251-
self.consume_as(TokenType::RightParen)?;
252-
253-
Ok(over_clause)
254-
}
255-
256-
fn parse_function_over_clause_frame_spec(&mut self) -> Result<FrameSpec, ParsingError> {
257-
let frame_type = match self.peek_as_keyword()? {
258-
Keyword::Range => FrameType::Range,
259-
Keyword::Rows => FrameType::Rows,
260-
Keyword::Groups => FrameType::Groups,
261-
_ => {
262-
return Err(ParsingError::UnexpectedToken(format!(
263-
"Expected frame type, got: {}",
264-
self.peek_token()?.token_type
265-
)))
266-
}
267-
};
268-
269-
// consume the frame type token
270-
self.consume_token()?;
271-
272-
let frame_spec_type: FrameSpecType = if self.consume_as_keyword(Keyword::Between).is_ok() {
273-
self.parse_function_over_clause_frame_spec_between()?
274-
} else if self.consume_as_keyword(Keyword::Unbounded).is_ok() {
275-
self.consume_as_keyword(Keyword::Preceding)?;
276-
FrameSpecType::UnboundedPreceding
277-
} else if self.consume_as_keyword(Keyword::Current).is_ok() {
278-
self.consume_as_keyword(Keyword::Row)?;
279-
FrameSpecType::CurrentRow
280-
} else {
281-
let expression = self.parse_expression()?;
282-
self.consume_as_keyword(Keyword::Preceding)?;
283-
FrameSpecType::Preceding(Box::new(expression))
284-
};
285-
286-
let mut exclude = None;
287-
288-
if self.consume_as_keyword(Keyword::Exclude).is_ok() {
289-
if self.consume_as_keyword(Keyword::No).is_ok() {
290-
self.consume_as_keyword(Keyword::Others)?;
291-
exclude = Some(FrameSpecExclude::NoOthers);
292-
} else if self.consume_as_keyword(Keyword::Current).is_ok() {
293-
self.consume_as_keyword(Keyword::Row)?;
294-
exclude = Some(FrameSpecExclude::CurrentRow);
295-
} else if self.consume_as_keyword(Keyword::Group).is_ok() {
296-
exclude = Some(FrameSpecExclude::Group);
297-
} else if self.consume_as_keyword(Keyword::Ties).is_ok() {
298-
exclude = Some(FrameSpecExclude::Ties);
299-
} else {
300-
return Err(ParsingError::UnexpectedToken(format!(
301-
"Expected Exclude type, got: {}",
302-
self.peek_token()?.token_type
303-
)));
304-
}
305-
}
306-
307-
Ok(FrameSpec {
308-
frame_type,
309-
frame_spec_type,
310-
exclude,
311-
})
312-
}
313-
314-
fn parse_function_over_clause_frame_spec_between(
315-
&mut self,
316-
) -> Result<FrameSpecType, ParsingError> {
317-
let start = if self.consume_as_keyword(Keyword::Unbounded).is_ok() {
318-
self.consume_as_keyword(Keyword::Preceding)?;
319-
BetweenFrameSpecType::UnboundedPreceding
320-
} else if self.consume_as_keyword(Keyword::Current).is_ok() {
321-
self.consume_as_keyword(Keyword::Row)?;
322-
BetweenFrameSpecType::CurrentRow
323-
} else {
324-
let expression = self.parse_expression()?;
325-
match self.peek_as_keyword()? {
326-
Keyword::Preceding => {
327-
self.consume_as_keyword(Keyword::Preceding)?;
328-
BetweenFrameSpecType::Preceding(Box::new(expression))
329-
}
330-
Keyword::Following => {
331-
self.consume_as_keyword(Keyword::Following)?;
332-
BetweenFrameSpecType::Following(Box::new(expression))
333-
}
334-
_ => {
335-
return Err(ParsingError::UnexpectedToken(format!(
336-
"Expected PRECEDING or FOLLOWING keyword, got: {}",
337-
self.peek_token()?.token_type
338-
)));
339-
}
340-
}
341-
};
342-
343-
self.consume_as_keyword(Keyword::And)?;
344-
345-
let end = if self.consume_as_keyword(Keyword::Unbounded).is_ok() {
346-
self.consume_as_keyword(Keyword::Following)?;
347-
BetweenFrameSpecType::UnboundedFollowing
348-
} else if self.consume_as_keyword(Keyword::Current).is_ok() {
349-
self.consume_as_keyword(Keyword::Row)?;
350-
BetweenFrameSpecType::CurrentRow
351-
} else {
352-
let expression = self.parse_expression()?;
353-
354-
if self.consume_as_keyword(Keyword::Preceding).is_ok() {
355-
BetweenFrameSpecType::Preceding(Box::new(expression))
356-
} else if self.consume_as_keyword(Keyword::Following).is_ok() {
357-
BetweenFrameSpecType::Following(Box::new(expression))
358-
} else {
359-
return Err(ParsingError::UnexpectedToken(format!(
360-
"Expected PRECEDING or FOLLOWING keyword, got: {}",
361-
self.peek_token()?.token_type
362-
)));
363-
}
364-
};
365-
Ok(FrameSpecType::Between(BetweenFrameSpec { start, end }))
366-
}
367145
}
368146

369147
#[cfg(test)]

src/parser/expression/mod.rs

+5-7
Original file line numberDiff line numberDiff line change
@@ -12,25 +12,24 @@ mod like_expr;
1212
mod raise_expr;
1313
mod regexp_match_expr;
1414

15+
use crate::{
16+
BinaryOp, Expression, Keyword, LiteralValue, Parser, ParsingError, TokenType,
17+
UnaryMatchingExpression, UnaryOp,
18+
};
1519
use between_expr::BetweenExpressionParser;
1620
use case_expr::CaseExpressionParser;
1721
use cast_expr::CastExpressionParser;
1822
use collate_expr::CollateExpressionParser;
1923
pub use data_type::DataTypeParser;
2024
use exists_expr::ExistsExpressionParser;
21-
use function_expr::FunctionParser;
25+
pub use function_expr::FunctionParser;
2226
pub use identifier::IdentifierParser;
2327
use in_expr::InExpressionParser;
2428
use is_expr::IsExpressionParser;
2529
use like_expr::LikeExpressionParser;
2630
use raise_expr::RaiseExpressionParser;
2731
use regexp_match_expr::RegexpMatchExpressionParser;
2832

29-
use crate::{
30-
BinaryOp, Expression, Keyword, LiteralValue, Parser, ParsingError, TokenType,
31-
UnaryMatchingExpression, UnaryOp,
32-
};
33-
3433
use once_cell::sync::Lazy;
3534
use std::collections::HashMap;
3635

@@ -398,7 +397,6 @@ pub(crate) mod test_utils {
398397
use crate::{
399398
BinaryOp, DataType, ExistsStatement, Function, FunctionArg, Identifier, LiteralValue,
400399
OverClause, Parser, RaiseFunction, SelectStatementType, Statement, UnaryOp,
401-
WindowDefinition,
402400
};
403401

404402
pub fn run_sunny_day_test_with_multiple_expressions(

src/parser/mod.rs

+2-3
Original file line numberDiff line numberDiff line change
@@ -3,12 +3,12 @@ use std::iter::Peekable;
33
mod alter;
44
mod column_definition;
55
mod drop;
6+
mod errors;
67
pub(crate) mod expression;
78
mod select;
89
mod sqlite;
910
mod trx;
10-
11-
mod errors;
11+
mod window_definition;
1212

1313
#[cfg(test)]
1414
mod test_utils;
@@ -19,7 +19,6 @@ use drop::DropStatementParser;
1919
pub use errors::*;
2020
use select::{SelectStatementParser, ValuesStatementParser};
2121
use sqlite::SQLite3StatementParser;
22-
2322
use trx::TransactionStatementParser;
2423

2524
/// A parser for SQLite SQL statements

0 commit comments

Comments
 (0)