mirror of
https://github.com/apache/datafusion-sqlparser-rs.git
synced 2025-08-21 22:44:08 +00:00
Support FILTER
in over clause (#1007)
Co-authored-by: Andrew Lamb <andrew@nerdnetworks.org>
This commit is contained in:
parent
e857a45201
commit
ce62fe6d27
15 changed files with 102 additions and 2 deletions
|
@ -34,7 +34,7 @@ println!("AST: {:?}", ast);
|
||||||
This outputs
|
This outputs
|
||||||
|
|
||||||
```rust
|
```rust
|
||||||
AST: [Query(Query { ctes: [], body: Select(Select { distinct: false, projection: [UnnamedExpr(Identifier("a")), UnnamedExpr(Identifier("b")), UnnamedExpr(Value(Long(123))), UnnamedExpr(Function(Function { name: ObjectName(["myfunc"]), args: [Identifier("b")], over: None, distinct: false }))], from: [TableWithJoins { relation: Table { name: ObjectName(["table_1"]), alias: None, args: [], with_hints: [] }, joins: [] }], selection: Some(BinaryOp { left: BinaryOp { left: Identifier("a"), op: Gt, right: Identifier("b") }, op: And, right: BinaryOp { left: Identifier("b"), op: Lt, right: Value(Long(100)) } }), group_by: [], having: None }), order_by: [OrderByExpr { expr: Identifier("a"), asc: Some(false) }, OrderByExpr { expr: Identifier("b"), asc: None }], limit: None, offset: None, fetch: None })]
|
AST: [Query(Query { ctes: [], body: Select(Select { distinct: false, projection: [UnnamedExpr(Identifier("a")), UnnamedExpr(Identifier("b")), UnnamedExpr(Value(Long(123))), UnnamedExpr(Function(Function { name: ObjectName(["myfunc"]), args: [Identifier("b")], filter: None, over: None, distinct: false }))], from: [TableWithJoins { relation: Table { name: ObjectName(["table_1"]), alias: None, args: [], with_hints: [] }, joins: [] }], selection: Some(BinaryOp { left: BinaryOp { left: Identifier("a"), op: Gt, right: Identifier("b") }, op: And, right: BinaryOp { left: Identifier("b"), op: Lt, right: Value(Long(100)) } }), group_by: [], having: None }), order_by: [OrderByExpr { expr: Identifier("a"), asc: Some(false) }, OrderByExpr { expr: Identifier("b"), asc: None }], limit: None, offset: None, fetch: None })]
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -1070,8 +1070,11 @@ impl Display for WindowType {
|
||||||
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
|
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
|
||||||
#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
|
#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
|
||||||
pub struct WindowSpec {
|
pub struct WindowSpec {
|
||||||
|
/// `OVER (PARTITION BY ...)`
|
||||||
pub partition_by: Vec<Expr>,
|
pub partition_by: Vec<Expr>,
|
||||||
|
/// `OVER (ORDER BY ...)`
|
||||||
pub order_by: Vec<OrderByExpr>,
|
pub order_by: Vec<OrderByExpr>,
|
||||||
|
/// `OVER (window frame)`
|
||||||
pub window_frame: Option<WindowFrame>,
|
pub window_frame: Option<WindowFrame>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3729,6 +3732,8 @@ impl fmt::Display for CloseCursor {
|
||||||
pub struct Function {
|
pub struct Function {
|
||||||
pub name: ObjectName,
|
pub name: ObjectName,
|
||||||
pub args: Vec<FunctionArg>,
|
pub args: Vec<FunctionArg>,
|
||||||
|
/// e.g. `x > 5` in `COUNT(x) FILTER (WHERE x > 5)`
|
||||||
|
pub filter: Option<Box<Expr>>,
|
||||||
pub over: Option<WindowType>,
|
pub over: Option<WindowType>,
|
||||||
// aggregate functions may specify eg `COUNT(DISTINCT x)`
|
// aggregate functions may specify eg `COUNT(DISTINCT x)`
|
||||||
pub distinct: bool,
|
pub distinct: bool,
|
||||||
|
@ -3777,6 +3782,10 @@ impl fmt::Display for Function {
|
||||||
display_comma_separated(&self.order_by),
|
display_comma_separated(&self.order_by),
|
||||||
)?;
|
)?;
|
||||||
|
|
||||||
|
if let Some(filter_cond) = &self.filter {
|
||||||
|
write!(f, " FILTER (WHERE {filter_cond})")?;
|
||||||
|
}
|
||||||
|
|
||||||
if let Some(o) = &self.over {
|
if let Some(o) = &self.over {
|
||||||
write!(f, " OVER {o}")?;
|
write!(f, " OVER {o}")?;
|
||||||
}
|
}
|
||||||
|
|
|
@ -506,7 +506,7 @@ where
|
||||||
/// *expr = Expr::Function(Function {
|
/// *expr = Expr::Function(Function {
|
||||||
/// name: ObjectName(vec![Ident::new("f")]),
|
/// name: ObjectName(vec![Ident::new("f")]),
|
||||||
/// args: vec![FunctionArg::Unnamed(FunctionArgExpr::Expr(old_expr))],
|
/// args: vec![FunctionArg::Unnamed(FunctionArgExpr::Expr(old_expr))],
|
||||||
/// over: None, distinct: false, special: false, order_by: vec![],
|
/// filter: None, over: None, distinct: false, special: false, order_by: vec![],
|
||||||
/// });
|
/// });
|
||||||
/// }
|
/// }
|
||||||
/// ControlFlow::<()>::Continue(())
|
/// ControlFlow::<()>::Continue(())
|
||||||
|
|
|
@ -35,6 +35,10 @@ impl Dialect for SQLiteDialect {
|
||||||
|| ('\u{007f}'..='\u{ffff}').contains(&ch)
|
|| ('\u{007f}'..='\u{ffff}').contains(&ch)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn supports_filter_during_aggregation(&self) -> bool {
|
||||||
|
true
|
||||||
|
}
|
||||||
|
|
||||||
fn is_identifier_part(&self, ch: char) -> bool {
|
fn is_identifier_part(&self, ch: char) -> bool {
|
||||||
self.is_identifier_start(ch) || ch.is_ascii_digit()
|
self.is_identifier_start(ch) || ch.is_ascii_digit()
|
||||||
}
|
}
|
||||||
|
|
|
@ -772,6 +772,7 @@ impl<'a> Parser<'a> {
|
||||||
Ok(Expr::Function(Function {
|
Ok(Expr::Function(Function {
|
||||||
name: ObjectName(vec![w.to_ident()]),
|
name: ObjectName(vec![w.to_ident()]),
|
||||||
args: vec![],
|
args: vec![],
|
||||||
|
filter: None,
|
||||||
over: None,
|
over: None,
|
||||||
distinct: false,
|
distinct: false,
|
||||||
special: true,
|
special: true,
|
||||||
|
@ -957,6 +958,17 @@ impl<'a> Parser<'a> {
|
||||||
self.expect_token(&Token::LParen)?;
|
self.expect_token(&Token::LParen)?;
|
||||||
let distinct = self.parse_all_or_distinct()?.is_some();
|
let distinct = self.parse_all_or_distinct()?.is_some();
|
||||||
let (args, order_by) = self.parse_optional_args_with_orderby()?;
|
let (args, order_by) = self.parse_optional_args_with_orderby()?;
|
||||||
|
let filter = if self.dialect.supports_filter_during_aggregation()
|
||||||
|
&& self.parse_keyword(Keyword::FILTER)
|
||||||
|
&& self.consume_token(&Token::LParen)
|
||||||
|
&& self.parse_keyword(Keyword::WHERE)
|
||||||
|
{
|
||||||
|
let filter = Some(Box::new(self.parse_expr()?));
|
||||||
|
self.expect_token(&Token::RParen)?;
|
||||||
|
filter
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
};
|
||||||
let over = if self.parse_keyword(Keyword::OVER) {
|
let over = if self.parse_keyword(Keyword::OVER) {
|
||||||
if self.consume_token(&Token::LParen) {
|
if self.consume_token(&Token::LParen) {
|
||||||
let window_spec = self.parse_window_spec()?;
|
let window_spec = self.parse_window_spec()?;
|
||||||
|
@ -970,6 +982,7 @@ impl<'a> Parser<'a> {
|
||||||
Ok(Expr::Function(Function {
|
Ok(Expr::Function(Function {
|
||||||
name,
|
name,
|
||||||
args,
|
args,
|
||||||
|
filter,
|
||||||
over,
|
over,
|
||||||
distinct,
|
distinct,
|
||||||
special: false,
|
special: false,
|
||||||
|
@ -987,6 +1000,7 @@ impl<'a> Parser<'a> {
|
||||||
Ok(Expr::Function(Function {
|
Ok(Expr::Function(Function {
|
||||||
name,
|
name,
|
||||||
args,
|
args,
|
||||||
|
filter: None,
|
||||||
over: None,
|
over: None,
|
||||||
distinct: false,
|
distinct: false,
|
||||||
special,
|
special,
|
||||||
|
|
|
@ -564,6 +564,7 @@ fn parse_map_access_offset() {
|
||||||
args: vec![FunctionArg::Unnamed(FunctionArgExpr::Expr(Expr::Value(
|
args: vec![FunctionArg::Unnamed(FunctionArgExpr::Expr(Expr::Value(
|
||||||
number("0")
|
number("0")
|
||||||
))),],
|
))),],
|
||||||
|
filter: None,
|
||||||
over: None,
|
over: None,
|
||||||
distinct: false,
|
distinct: false,
|
||||||
special: false,
|
special: false,
|
||||||
|
|
|
@ -50,6 +50,7 @@ fn parse_map_access_expr() {
|
||||||
Value::SingleQuotedString("endpoint".to_string())
|
Value::SingleQuotedString("endpoint".to_string())
|
||||||
))),
|
))),
|
||||||
],
|
],
|
||||||
|
filter: None,
|
||||||
over: None,
|
over: None,
|
||||||
distinct: false,
|
distinct: false,
|
||||||
special: false,
|
special: false,
|
||||||
|
@ -89,6 +90,7 @@ fn parse_map_access_expr() {
|
||||||
Value::SingleQuotedString("app".to_string())
|
Value::SingleQuotedString("app".to_string())
|
||||||
))),
|
))),
|
||||||
],
|
],
|
||||||
|
filter: None,
|
||||||
over: None,
|
over: None,
|
||||||
distinct: false,
|
distinct: false,
|
||||||
special: false,
|
special: false,
|
||||||
|
@ -138,6 +140,7 @@ fn parse_array_fn() {
|
||||||
FunctionArg::Unnamed(FunctionArgExpr::Expr(Expr::Identifier(Ident::new("x1")))),
|
FunctionArg::Unnamed(FunctionArgExpr::Expr(Expr::Identifier(Ident::new("x1")))),
|
||||||
FunctionArg::Unnamed(FunctionArgExpr::Expr(Expr::Identifier(Ident::new("x2")))),
|
FunctionArg::Unnamed(FunctionArgExpr::Expr(Expr::Identifier(Ident::new("x2")))),
|
||||||
],
|
],
|
||||||
|
filter: None,
|
||||||
over: None,
|
over: None,
|
||||||
distinct: false,
|
distinct: false,
|
||||||
special: false,
|
special: false,
|
||||||
|
@ -196,6 +199,7 @@ fn parse_delimited_identifiers() {
|
||||||
&Expr::Function(Function {
|
&Expr::Function(Function {
|
||||||
name: ObjectName(vec![Ident::with_quote('"', "myfun")]),
|
name: ObjectName(vec![Ident::with_quote('"', "myfun")]),
|
||||||
args: vec![],
|
args: vec![],
|
||||||
|
filter: None,
|
||||||
over: None,
|
over: None,
|
||||||
distinct: false,
|
distinct: false,
|
||||||
special: false,
|
special: false,
|
||||||
|
|
|
@ -875,6 +875,7 @@ fn parse_select_count_wildcard() {
|
||||||
&Expr::Function(Function {
|
&Expr::Function(Function {
|
||||||
name: ObjectName(vec![Ident::new("COUNT")]),
|
name: ObjectName(vec![Ident::new("COUNT")]),
|
||||||
args: vec![FunctionArg::Unnamed(FunctionArgExpr::Wildcard)],
|
args: vec![FunctionArg::Unnamed(FunctionArgExpr::Wildcard)],
|
||||||
|
filter: None,
|
||||||
over: None,
|
over: None,
|
||||||
distinct: false,
|
distinct: false,
|
||||||
special: false,
|
special: false,
|
||||||
|
@ -895,6 +896,7 @@ fn parse_select_count_distinct() {
|
||||||
op: UnaryOperator::Plus,
|
op: UnaryOperator::Plus,
|
||||||
expr: Box::new(Expr::Identifier(Ident::new("x"))),
|
expr: Box::new(Expr::Identifier(Ident::new("x"))),
|
||||||
}))],
|
}))],
|
||||||
|
filter: None,
|
||||||
over: None,
|
over: None,
|
||||||
distinct: true,
|
distinct: true,
|
||||||
special: false,
|
special: false,
|
||||||
|
@ -1862,6 +1864,7 @@ fn parse_select_having() {
|
||||||
left: Box::new(Expr::Function(Function {
|
left: Box::new(Expr::Function(Function {
|
||||||
name: ObjectName(vec![Ident::new("COUNT")]),
|
name: ObjectName(vec![Ident::new("COUNT")]),
|
||||||
args: vec![FunctionArg::Unnamed(FunctionArgExpr::Wildcard)],
|
args: vec![FunctionArg::Unnamed(FunctionArgExpr::Wildcard)],
|
||||||
|
filter: None,
|
||||||
over: None,
|
over: None,
|
||||||
distinct: false,
|
distinct: false,
|
||||||
special: false,
|
special: false,
|
||||||
|
@ -1887,6 +1890,7 @@ fn parse_select_qualify() {
|
||||||
left: Box::new(Expr::Function(Function {
|
left: Box::new(Expr::Function(Function {
|
||||||
name: ObjectName(vec![Ident::new("ROW_NUMBER")]),
|
name: ObjectName(vec![Ident::new("ROW_NUMBER")]),
|
||||||
args: vec![],
|
args: vec![],
|
||||||
|
filter: None,
|
||||||
over: Some(WindowType::WindowSpec(WindowSpec {
|
over: Some(WindowType::WindowSpec(WindowSpec {
|
||||||
partition_by: vec![Expr::Identifier(Ident::new("p"))],
|
partition_by: vec![Expr::Identifier(Ident::new("p"))],
|
||||||
order_by: vec![OrderByExpr {
|
order_by: vec![OrderByExpr {
|
||||||
|
@ -3342,6 +3346,7 @@ fn parse_scalar_function_in_projection() {
|
||||||
args: vec![FunctionArg::Unnamed(FunctionArgExpr::Expr(
|
args: vec![FunctionArg::Unnamed(FunctionArgExpr::Expr(
|
||||||
Expr::Identifier(Ident::new("id"))
|
Expr::Identifier(Ident::new("id"))
|
||||||
))],
|
))],
|
||||||
|
filter: None,
|
||||||
over: None,
|
over: None,
|
||||||
distinct: false,
|
distinct: false,
|
||||||
special: false,
|
special: false,
|
||||||
|
@ -3461,6 +3466,7 @@ fn parse_named_argument_function() {
|
||||||
))),
|
))),
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
|
filter: None,
|
||||||
over: None,
|
over: None,
|
||||||
distinct: false,
|
distinct: false,
|
||||||
special: false,
|
special: false,
|
||||||
|
@ -3492,6 +3498,7 @@ fn parse_window_functions() {
|
||||||
&Expr::Function(Function {
|
&Expr::Function(Function {
|
||||||
name: ObjectName(vec![Ident::new("row_number")]),
|
name: ObjectName(vec![Ident::new("row_number")]),
|
||||||
args: vec![],
|
args: vec![],
|
||||||
|
filter: None,
|
||||||
over: Some(WindowType::WindowSpec(WindowSpec {
|
over: Some(WindowType::WindowSpec(WindowSpec {
|
||||||
partition_by: vec![],
|
partition_by: vec![],
|
||||||
order_by: vec![OrderByExpr {
|
order_by: vec![OrderByExpr {
|
||||||
|
@ -3535,6 +3542,7 @@ fn test_parse_named_window() {
|
||||||
quote_style: None,
|
quote_style: None,
|
||||||
}),
|
}),
|
||||||
))],
|
))],
|
||||||
|
filter: None,
|
||||||
over: Some(WindowType::NamedWindow(Ident {
|
over: Some(WindowType::NamedWindow(Ident {
|
||||||
value: "window1".to_string(),
|
value: "window1".to_string(),
|
||||||
quote_style: None,
|
quote_style: None,
|
||||||
|
@ -3560,6 +3568,7 @@ fn test_parse_named_window() {
|
||||||
quote_style: None,
|
quote_style: None,
|
||||||
}),
|
}),
|
||||||
))],
|
))],
|
||||||
|
filter: None,
|
||||||
over: Some(WindowType::NamedWindow(Ident {
|
over: Some(WindowType::NamedWindow(Ident {
|
||||||
value: "window2".to_string(),
|
value: "window2".to_string(),
|
||||||
quote_style: None,
|
quote_style: None,
|
||||||
|
@ -4029,6 +4038,7 @@ fn parse_at_timezone() {
|
||||||
quote_style: None,
|
quote_style: None,
|
||||||
}]),
|
}]),
|
||||||
args: vec![FunctionArg::Unnamed(FunctionArgExpr::Expr(zero.clone()))],
|
args: vec![FunctionArg::Unnamed(FunctionArgExpr::Expr(zero.clone()))],
|
||||||
|
filter: None,
|
||||||
over: None,
|
over: None,
|
||||||
distinct: false,
|
distinct: false,
|
||||||
special: false,
|
special: false,
|
||||||
|
@ -4056,6 +4066,7 @@ fn parse_at_timezone() {
|
||||||
quote_style: None,
|
quote_style: None,
|
||||||
},],),
|
},],),
|
||||||
args: vec![FunctionArg::Unnamed(FunctionArgExpr::Expr(zero))],
|
args: vec![FunctionArg::Unnamed(FunctionArgExpr::Expr(zero))],
|
||||||
|
filter: None,
|
||||||
over: None,
|
over: None,
|
||||||
distinct: false,
|
distinct: false,
|
||||||
special: false,
|
special: false,
|
||||||
|
@ -4067,6 +4078,7 @@ fn parse_at_timezone() {
|
||||||
Value::SingleQuotedString("%Y-%m-%dT%H".to_string()),
|
Value::SingleQuotedString("%Y-%m-%dT%H".to_string()),
|
||||||
),),),
|
),),),
|
||||||
],
|
],
|
||||||
|
filter: None,
|
||||||
over: None,
|
over: None,
|
||||||
distinct: false,
|
distinct: false,
|
||||||
special: false,
|
special: false,
|
||||||
|
@ -4225,6 +4237,7 @@ fn parse_table_function() {
|
||||||
args: vec![FunctionArg::Unnamed(FunctionArgExpr::Expr(Expr::Value(
|
args: vec![FunctionArg::Unnamed(FunctionArgExpr::Expr(Expr::Value(
|
||||||
Value::SingleQuotedString("1".to_owned()),
|
Value::SingleQuotedString("1".to_owned()),
|
||||||
)))],
|
)))],
|
||||||
|
filter: None,
|
||||||
over: None,
|
over: None,
|
||||||
distinct: false,
|
distinct: false,
|
||||||
special: false,
|
special: false,
|
||||||
|
@ -4376,6 +4389,7 @@ fn parse_unnest_in_from_clause() {
|
||||||
FunctionArg::Unnamed(FunctionArgExpr::Expr(Expr::Value(number("2")))),
|
FunctionArg::Unnamed(FunctionArgExpr::Expr(Expr::Value(number("2")))),
|
||||||
FunctionArg::Unnamed(FunctionArgExpr::Expr(Expr::Value(number("3")))),
|
FunctionArg::Unnamed(FunctionArgExpr::Expr(Expr::Value(number("3")))),
|
||||||
],
|
],
|
||||||
|
filter: None,
|
||||||
over: None,
|
over: None,
|
||||||
distinct: false,
|
distinct: false,
|
||||||
special: false,
|
special: false,
|
||||||
|
@ -4405,6 +4419,7 @@ fn parse_unnest_in_from_clause() {
|
||||||
FunctionArg::Unnamed(FunctionArgExpr::Expr(Expr::Value(number("2")))),
|
FunctionArg::Unnamed(FunctionArgExpr::Expr(Expr::Value(number("2")))),
|
||||||
FunctionArg::Unnamed(FunctionArgExpr::Expr(Expr::Value(number("3")))),
|
FunctionArg::Unnamed(FunctionArgExpr::Expr(Expr::Value(number("3")))),
|
||||||
],
|
],
|
||||||
|
filter: None,
|
||||||
over: None,
|
over: None,
|
||||||
distinct: false,
|
distinct: false,
|
||||||
special: false,
|
special: false,
|
||||||
|
@ -4416,6 +4431,7 @@ fn parse_unnest_in_from_clause() {
|
||||||
FunctionArg::Unnamed(FunctionArgExpr::Expr(Expr::Value(number("5")))),
|
FunctionArg::Unnamed(FunctionArgExpr::Expr(Expr::Value(number("5")))),
|
||||||
FunctionArg::Unnamed(FunctionArgExpr::Expr(Expr::Value(number("6")))),
|
FunctionArg::Unnamed(FunctionArgExpr::Expr(Expr::Value(number("6")))),
|
||||||
],
|
],
|
||||||
|
filter: None,
|
||||||
over: None,
|
over: None,
|
||||||
distinct: false,
|
distinct: false,
|
||||||
special: false,
|
special: false,
|
||||||
|
@ -6888,6 +6904,7 @@ fn parse_time_functions() {
|
||||||
let select_localtime_func_call_ast = Function {
|
let select_localtime_func_call_ast = Function {
|
||||||
name: ObjectName(vec![Ident::new(func_name)]),
|
name: ObjectName(vec![Ident::new(func_name)]),
|
||||||
args: vec![],
|
args: vec![],
|
||||||
|
filter: None,
|
||||||
over: None,
|
over: None,
|
||||||
distinct: false,
|
distinct: false,
|
||||||
special: false,
|
special: false,
|
||||||
|
@ -7374,6 +7391,7 @@ fn parse_pivot_table() {
|
||||||
args: (vec![FunctionArg::Unnamed(FunctionArgExpr::Expr(
|
args: (vec![FunctionArg::Unnamed(FunctionArgExpr::Expr(
|
||||||
Expr::CompoundIdentifier(vec![Ident::new("a"), Ident::new("amount"),])
|
Expr::CompoundIdentifier(vec![Ident::new("a"), Ident::new("amount"),])
|
||||||
))]),
|
))]),
|
||||||
|
filter: None,
|
||||||
over: None,
|
over: None,
|
||||||
distinct: false,
|
distinct: false,
|
||||||
special: false,
|
special: false,
|
||||||
|
@ -7523,6 +7541,7 @@ fn parse_pivot_unpivot_table() {
|
||||||
args: (vec![FunctionArg::Unnamed(FunctionArgExpr::Expr(
|
args: (vec![FunctionArg::Unnamed(FunctionArgExpr::Expr(
|
||||||
Expr::Identifier(Ident::new("population"))
|
Expr::Identifier(Ident::new("population"))
|
||||||
))]),
|
))]),
|
||||||
|
filter: None,
|
||||||
over: None,
|
over: None,
|
||||||
distinct: false,
|
distinct: false,
|
||||||
special: false,
|
special: false,
|
||||||
|
|
|
@ -346,6 +346,7 @@ fn parse_delimited_identifiers() {
|
||||||
&Expr::Function(Function {
|
&Expr::Function(Function {
|
||||||
name: ObjectName(vec![Ident::with_quote('"', "myfun")]),
|
name: ObjectName(vec![Ident::with_quote('"', "myfun")]),
|
||||||
args: vec![],
|
args: vec![],
|
||||||
|
filter: None,
|
||||||
over: None,
|
over: None,
|
||||||
distinct: false,
|
distinct: false,
|
||||||
special: false,
|
special: false,
|
||||||
|
|
|
@ -334,6 +334,7 @@ fn parse_delimited_identifiers() {
|
||||||
&Expr::Function(Function {
|
&Expr::Function(Function {
|
||||||
name: ObjectName(vec![Ident::with_quote('"', "myfun")]),
|
name: ObjectName(vec![Ident::with_quote('"', "myfun")]),
|
||||||
args: vec![],
|
args: vec![],
|
||||||
|
filter: None,
|
||||||
over: None,
|
over: None,
|
||||||
distinct: false,
|
distinct: false,
|
||||||
special: false,
|
special: false,
|
||||||
|
|
|
@ -1071,6 +1071,7 @@ fn parse_insert_with_on_duplicate_update() {
|
||||||
args: vec![FunctionArg::Unnamed(FunctionArgExpr::Expr(
|
args: vec![FunctionArg::Unnamed(FunctionArgExpr::Expr(
|
||||||
Expr::Identifier(Ident::new("description"))
|
Expr::Identifier(Ident::new("description"))
|
||||||
))],
|
))],
|
||||||
|
filter: None,
|
||||||
over: None,
|
over: None,
|
||||||
distinct: false,
|
distinct: false,
|
||||||
special: false,
|
special: false,
|
||||||
|
@ -1084,6 +1085,7 @@ fn parse_insert_with_on_duplicate_update() {
|
||||||
args: vec![FunctionArg::Unnamed(FunctionArgExpr::Expr(
|
args: vec![FunctionArg::Unnamed(FunctionArgExpr::Expr(
|
||||||
Expr::Identifier(Ident::new("perm_create"))
|
Expr::Identifier(Ident::new("perm_create"))
|
||||||
))],
|
))],
|
||||||
|
filter: None,
|
||||||
over: None,
|
over: None,
|
||||||
distinct: false,
|
distinct: false,
|
||||||
special: false,
|
special: false,
|
||||||
|
@ -1097,6 +1099,7 @@ fn parse_insert_with_on_duplicate_update() {
|
||||||
args: vec![FunctionArg::Unnamed(FunctionArgExpr::Expr(
|
args: vec![FunctionArg::Unnamed(FunctionArgExpr::Expr(
|
||||||
Expr::Identifier(Ident::new("perm_read"))
|
Expr::Identifier(Ident::new("perm_read"))
|
||||||
))],
|
))],
|
||||||
|
filter: None,
|
||||||
over: None,
|
over: None,
|
||||||
distinct: false,
|
distinct: false,
|
||||||
special: false,
|
special: false,
|
||||||
|
@ -1110,6 +1113,7 @@ fn parse_insert_with_on_duplicate_update() {
|
||||||
args: vec![FunctionArg::Unnamed(FunctionArgExpr::Expr(
|
args: vec![FunctionArg::Unnamed(FunctionArgExpr::Expr(
|
||||||
Expr::Identifier(Ident::new("perm_update"))
|
Expr::Identifier(Ident::new("perm_update"))
|
||||||
))],
|
))],
|
||||||
|
filter: None,
|
||||||
over: None,
|
over: None,
|
||||||
distinct: false,
|
distinct: false,
|
||||||
special: false,
|
special: false,
|
||||||
|
@ -1123,6 +1127,7 @@ fn parse_insert_with_on_duplicate_update() {
|
||||||
args: vec![FunctionArg::Unnamed(FunctionArgExpr::Expr(
|
args: vec![FunctionArg::Unnamed(FunctionArgExpr::Expr(
|
||||||
Expr::Identifier(Ident::new("perm_delete"))
|
Expr::Identifier(Ident::new("perm_delete"))
|
||||||
))],
|
))],
|
||||||
|
filter: None,
|
||||||
over: None,
|
over: None,
|
||||||
distinct: false,
|
distinct: false,
|
||||||
special: false,
|
special: false,
|
||||||
|
@ -1512,6 +1517,7 @@ fn parse_table_colum_option_on_update() {
|
||||||
option: ColumnOption::OnUpdate(Expr::Function(Function {
|
option: ColumnOption::OnUpdate(Expr::Function(Function {
|
||||||
name: ObjectName(vec![Ident::new("CURRENT_TIMESTAMP")]),
|
name: ObjectName(vec![Ident::new("CURRENT_TIMESTAMP")]),
|
||||||
args: vec![],
|
args: vec![],
|
||||||
|
filter: None,
|
||||||
over: None,
|
over: None,
|
||||||
distinct: false,
|
distinct: false,
|
||||||
special: false,
|
special: false,
|
||||||
|
|
|
@ -2275,6 +2275,7 @@ fn test_composite_value() {
|
||||||
named: true
|
named: true
|
||||||
}
|
}
|
||||||
)))],
|
)))],
|
||||||
|
filter: None,
|
||||||
over: None,
|
over: None,
|
||||||
distinct: false,
|
distinct: false,
|
||||||
special: false,
|
special: false,
|
||||||
|
@ -2436,6 +2437,7 @@ fn parse_current_functions() {
|
||||||
&Expr::Function(Function {
|
&Expr::Function(Function {
|
||||||
name: ObjectName(vec![Ident::new("CURRENT_CATALOG")]),
|
name: ObjectName(vec![Ident::new("CURRENT_CATALOG")]),
|
||||||
args: vec![],
|
args: vec![],
|
||||||
|
filter: None,
|
||||||
over: None,
|
over: None,
|
||||||
distinct: false,
|
distinct: false,
|
||||||
special: true,
|
special: true,
|
||||||
|
@ -2447,6 +2449,7 @@ fn parse_current_functions() {
|
||||||
&Expr::Function(Function {
|
&Expr::Function(Function {
|
||||||
name: ObjectName(vec![Ident::new("CURRENT_USER")]),
|
name: ObjectName(vec![Ident::new("CURRENT_USER")]),
|
||||||
args: vec![],
|
args: vec![],
|
||||||
|
filter: None,
|
||||||
over: None,
|
over: None,
|
||||||
distinct: false,
|
distinct: false,
|
||||||
special: true,
|
special: true,
|
||||||
|
@ -2458,6 +2461,7 @@ fn parse_current_functions() {
|
||||||
&Expr::Function(Function {
|
&Expr::Function(Function {
|
||||||
name: ObjectName(vec![Ident::new("SESSION_USER")]),
|
name: ObjectName(vec![Ident::new("SESSION_USER")]),
|
||||||
args: vec![],
|
args: vec![],
|
||||||
|
filter: None,
|
||||||
over: None,
|
over: None,
|
||||||
distinct: false,
|
distinct: false,
|
||||||
special: true,
|
special: true,
|
||||||
|
@ -2469,6 +2473,7 @@ fn parse_current_functions() {
|
||||||
&Expr::Function(Function {
|
&Expr::Function(Function {
|
||||||
name: ObjectName(vec![Ident::new("USER")]),
|
name: ObjectName(vec![Ident::new("USER")]),
|
||||||
args: vec![],
|
args: vec![],
|
||||||
|
filter: None,
|
||||||
over: None,
|
over: None,
|
||||||
distinct: false,
|
distinct: false,
|
||||||
special: true,
|
special: true,
|
||||||
|
@ -2919,6 +2924,7 @@ fn parse_delimited_identifiers() {
|
||||||
&Expr::Function(Function {
|
&Expr::Function(Function {
|
||||||
name: ObjectName(vec![Ident::with_quote('"', "myfun")]),
|
name: ObjectName(vec![Ident::with_quote('"', "myfun")]),
|
||||||
args: vec![],
|
args: vec![],
|
||||||
|
filter: None,
|
||||||
over: None,
|
over: None,
|
||||||
distinct: false,
|
distinct: false,
|
||||||
special: false,
|
special: false,
|
||||||
|
|
|
@ -137,6 +137,7 @@ fn parse_delimited_identifiers() {
|
||||||
&Expr::Function(Function {
|
&Expr::Function(Function {
|
||||||
name: ObjectName(vec![Ident::with_quote('"', "myfun")]),
|
name: ObjectName(vec![Ident::with_quote('"', "myfun")]),
|
||||||
args: vec![],
|
args: vec![],
|
||||||
|
filter: None,
|
||||||
over: None,
|
over: None,
|
||||||
distinct: false,
|
distinct: false,
|
||||||
special: false,
|
special: false,
|
||||||
|
|
|
@ -248,6 +248,7 @@ fn parse_delimited_identifiers() {
|
||||||
&Expr::Function(Function {
|
&Expr::Function(Function {
|
||||||
name: ObjectName(vec![Ident::with_quote('"', "myfun")]),
|
name: ObjectName(vec![Ident::with_quote('"', "myfun")]),
|
||||||
args: vec![],
|
args: vec![],
|
||||||
|
filter: None,
|
||||||
over: None,
|
over: None,
|
||||||
distinct: false,
|
distinct: false,
|
||||||
special: false,
|
special: false,
|
||||||
|
|
|
@ -290,6 +290,39 @@ fn parse_create_table_with_strict() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn parse_window_function_with_filter() {
|
||||||
|
for func_name in [
|
||||||
|
"row_number",
|
||||||
|
"rank",
|
||||||
|
"max",
|
||||||
|
"count",
|
||||||
|
"user_defined_function",
|
||||||
|
] {
|
||||||
|
let sql = format!("SELECT {}(x) FILTER (WHERE y) OVER () FROM t", func_name);
|
||||||
|
let select = sqlite().verified_only_select(&sql);
|
||||||
|
assert_eq!(select.to_string(), sql);
|
||||||
|
assert_eq!(
|
||||||
|
select.projection,
|
||||||
|
vec![SelectItem::UnnamedExpr(Expr::Function(Function {
|
||||||
|
name: ObjectName(vec![Ident::new(func_name)]),
|
||||||
|
args: vec![FunctionArg::Unnamed(FunctionArgExpr::Expr(
|
||||||
|
Expr::Identifier(Ident::new("x"))
|
||||||
|
))],
|
||||||
|
over: Some(WindowType::WindowSpec(WindowSpec {
|
||||||
|
partition_by: vec![],
|
||||||
|
order_by: vec![],
|
||||||
|
window_frame: None,
|
||||||
|
})),
|
||||||
|
filter: Some(Box::new(Expr::Identifier(Ident::new("y")))),
|
||||||
|
distinct: false,
|
||||||
|
special: false,
|
||||||
|
order_by: vec![]
|
||||||
|
}))]
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn parse_attach_database() {
|
fn parse_attach_database() {
|
||||||
let sql = "ATTACH DATABASE 'test.db' AS test";
|
let sql = "ATTACH DATABASE 'test.db' AS test";
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue