Add support for first, last aggregate function parsing (#882)

* Add order by parsing to functions

* Fix doc error

* minor changes
This commit is contained in:
Mustafa Akur 2023-05-18 21:59:14 +03:00 committed by GitHub
parent 33b12acce7
commit 1b86abebe2
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
12 changed files with 96 additions and 7 deletions

View file

@ -3366,6 +3366,8 @@ pub struct Function {
// Some functions must be called without trailing parentheses, for example Postgres // Some functions must be called without trailing parentheses, for example Postgres
// do it for current_catalog, current_schema, etc. This flags is used for formatting. // do it for current_catalog, current_schema, etc. This flags is used for formatting.
pub special: bool, pub special: bool,
// Required ordering for the function (if empty, there is no requirement).
pub order_by: Vec<OrderByExpr>,
} }
#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)] #[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
@ -3392,12 +3394,18 @@ impl fmt::Display for Function {
if self.special { if self.special {
write!(f, "{}", self.name)?; write!(f, "{}", self.name)?;
} else { } else {
let order_by = if !self.order_by.is_empty() {
" ORDER BY "
} else {
""
};
write!( write!(
f, f,
"{}({}{})", "{}({}{}{order_by}{})",
self.name, self.name,
if self.distinct { "DISTINCT " } else { "" }, if self.distinct { "DISTINCT " } else { "" },
display_comma_separated(&self.args), display_comma_separated(&self.args),
display_comma_separated(&self.order_by),
)?; )?;
if let Some(o) = &self.over { if let Some(o) = &self.over {

View file

@ -480,7 +480,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, /// over: None, distinct: false, special: false, order_by: vec![],
/// }); /// });
/// } /// }
/// ControlFlow::<()>::Continue(()) /// ControlFlow::<()>::Continue(())

View file

@ -706,6 +706,7 @@ impl<'a> Parser<'a> {
over: None, over: None,
distinct: false, distinct: false,
special: true, special: true,
order_by: vec![],
})) }))
} }
Keyword::CURRENT_TIMESTAMP Keyword::CURRENT_TIMESTAMP
@ -881,7 +882,7 @@ impl<'a> Parser<'a> {
pub fn parse_function(&mut self, name: ObjectName) -> Result<Expr, ParserError> { pub fn parse_function(&mut self, name: ObjectName) -> Result<Expr, ParserError> {
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 = self.parse_optional_args()?; let (args, order_by) = self.parse_optional_args_with_orderby()?;
let over = if self.parse_keyword(Keyword::OVER) { let over = if self.parse_keyword(Keyword::OVER) {
// TBD: support window names (`OVER mywin`) in place of inline specification // TBD: support window names (`OVER mywin`) in place of inline specification
self.expect_token(&Token::LParen)?; self.expect_token(&Token::LParen)?;
@ -918,14 +919,15 @@ impl<'a> Parser<'a> {
over, over,
distinct, distinct,
special: false, special: false,
order_by,
})) }))
} }
pub fn parse_time_functions(&mut self, name: ObjectName) -> Result<Expr, ParserError> { pub fn parse_time_functions(&mut self, name: ObjectName) -> Result<Expr, ParserError> {
let args = if self.consume_token(&Token::LParen) { let (args, order_by) = if self.consume_token(&Token::LParen) {
self.parse_optional_args()? self.parse_optional_args_with_orderby()?
} else { } else {
vec![] (vec![], vec![])
}; };
Ok(Expr::Function(Function { Ok(Expr::Function(Function {
name, name,
@ -933,6 +935,7 @@ impl<'a> Parser<'a> {
over: None, over: None,
distinct: false, distinct: false,
special: false, special: false,
order_by,
})) }))
} }
@ -6376,6 +6379,23 @@ impl<'a> Parser<'a> {
} }
} }
pub fn parse_optional_args_with_orderby(
&mut self,
) -> Result<(Vec<FunctionArg>, Vec<OrderByExpr>), ParserError> {
if self.consume_token(&Token::RParen) {
Ok((vec![], vec![]))
} else {
let args = self.parse_comma_separated(Parser::parse_function_args)?;
let order_by = if self.parse_keywords(&[Keyword::ORDER, Keyword::BY]) {
self.parse_comma_separated(Parser::parse_order_by_expr)?
} else {
vec![]
};
self.expect_token(&Token::RParen)?;
Ok((args, order_by))
}
}
/// Parse a comma-delimited list of projections after SELECT /// Parse a comma-delimited list of projections after SELECT
pub fn parse_select_item(&mut self) -> Result<SelectItem, ParserError> { pub fn parse_select_item(&mut self) -> Result<SelectItem, ParserError> {
match self.parse_wildcard_expr()? { match self.parse_wildcard_expr()? {

View file

@ -437,6 +437,7 @@ fn parse_map_access_offset() {
over: None, over: None,
distinct: false, distinct: false,
special: false, special: false,
order_by: vec![],
})], })],
}) })
); );

View file

@ -52,6 +52,7 @@ fn parse_map_access_expr() {
over: None, over: None,
distinct: false, distinct: false,
special: false, special: false,
order_by: vec![],
})], })],
})], })],
into: None, into: None,
@ -88,6 +89,7 @@ fn parse_map_access_expr() {
over: None, over: None,
distinct: false, distinct: false,
special: false, special: false,
order_by: vec![],
})] })]
}), }),
op: BinaryOperator::NotEq, op: BinaryOperator::NotEq,
@ -135,6 +137,7 @@ fn parse_array_fn() {
over: None, over: None,
distinct: false, distinct: false,
special: false, special: false,
order_by: vec![],
}), }),
expr_from_projection(only(&select.projection)) expr_from_projection(only(&select.projection))
); );
@ -189,6 +192,7 @@ fn parse_delimited_identifiers() {
over: None, over: None,
distinct: false, distinct: false,
special: false, special: false,
order_by: vec![],
}), }),
expr_from_projection(&select.projection[1]), expr_from_projection(&select.projection[1]),
); );

View file

@ -840,6 +840,7 @@ fn parse_select_count_wildcard() {
over: None, over: None,
distinct: false, distinct: false,
special: false, special: false,
order_by: vec![],
}), }),
expr_from_projection(only(&select.projection)) expr_from_projection(only(&select.projection))
); );
@ -859,6 +860,7 @@ fn parse_select_count_distinct() {
over: None, over: None,
distinct: true, distinct: true,
special: false, special: false,
order_by: vec![],
}), }),
expr_from_projection(only(&select.projection)) expr_from_projection(only(&select.projection))
); );
@ -1696,6 +1698,7 @@ fn parse_select_having() {
over: None, over: None,
distinct: false, distinct: false,
special: false, special: false,
order_by: vec![],
})), })),
op: BinaryOperator::Gt, op: BinaryOperator::Gt,
right: Box::new(Expr::Value(number("1"))), right: Box::new(Expr::Value(number("1"))),
@ -1729,6 +1732,7 @@ fn parse_select_qualify() {
}), }),
distinct: false, distinct: false,
special: false, special: false,
order_by: vec![],
})), })),
op: BinaryOperator::Eq, op: BinaryOperator::Eq,
right: Box::new(Expr::Value(number("1"))), right: Box::new(Expr::Value(number("1"))),
@ -2076,6 +2080,29 @@ fn parse_array_agg_func() {
} }
} }
#[test]
fn parse_agg_with_order_by() {
let supported_dialects = TestedDialects {
dialects: vec![
Box::new(GenericDialect {}),
Box::new(PostgreSqlDialect {}),
Box::new(MsSqlDialect {}),
Box::new(AnsiDialect {}),
Box::new(HiveDialect {}),
],
options: None,
};
for sql in [
"SELECT FIRST_VALUE(x ORDER BY x) AS a FROM T",
"SELECT FIRST_VALUE(x ORDER BY x) FROM tbl",
"SELECT LAST_VALUE(x ORDER BY x, y) AS a FROM T",
"SELECT LAST_VALUE(x ORDER BY x ASC, y DESC) AS a FROM T",
] {
supported_dialects.verified_stmt(sql);
}
}
#[test] #[test]
fn parse_create_table() { fn parse_create_table() {
let sql = "CREATE TABLE uk_cities (\ let sql = "CREATE TABLE uk_cities (\
@ -3121,6 +3148,7 @@ fn parse_scalar_function_in_projection() {
over: None, over: None,
distinct: false, distinct: false,
special: false, special: false,
order_by: vec![],
}), }),
expr_from_projection(only(&select.projection)) expr_from_projection(only(&select.projection))
); );
@ -3239,6 +3267,7 @@ fn parse_named_argument_function() {
over: None, over: None,
distinct: false, distinct: false,
special: false, special: false,
order_by: vec![],
}), }),
expr_from_projection(only(&select.projection)) expr_from_projection(only(&select.projection))
); );
@ -3277,6 +3306,7 @@ fn parse_window_functions() {
}), }),
distinct: false, distinct: false,
special: false, special: false,
order_by: vec![],
}), }),
expr_from_projection(&select.projection[0]) expr_from_projection(&select.projection[0])
); );
@ -3675,6 +3705,7 @@ fn parse_at_timezone() {
over: None, over: None,
distinct: false, distinct: false,
special: false, special: false,
order_by: vec![],
})), })),
time_zone: "UTC-06:00".to_string(), time_zone: "UTC-06:00".to_string(),
}, },
@ -3701,6 +3732,7 @@ fn parse_at_timezone() {
over: None, over: None,
distinct: false, distinct: false,
special: false, special: false,
order_by: vec![],
},)), },)),
time_zone: "UTC-06:00".to_string(), time_zone: "UTC-06:00".to_string(),
},),), },),),
@ -3711,6 +3743,7 @@ fn parse_at_timezone() {
over: None, over: None,
distinct: false, distinct: false,
special: false, special: false,
order_by: vec![],
},), },),
alias: Ident { alias: Ident {
value: "hour".to_string(), value: "hour".to_string(),
@ -3868,6 +3901,7 @@ fn parse_table_function() {
over: None, over: None,
distinct: false, distinct: false,
special: false, special: false,
order_by: vec![],
}); });
assert_eq!(expr, expected_expr); assert_eq!(expr, expected_expr);
assert_eq!(alias, table_alias("a")) assert_eq!(alias, table_alias("a"))
@ -6292,6 +6326,7 @@ fn parse_time_functions() {
over: None, over: None,
distinct: false, distinct: false,
special: false, special: false,
order_by: vec![],
}), }),
expr_from_projection(&select.projection[0]) expr_from_projection(&select.projection[0])
); );
@ -6308,6 +6343,7 @@ fn parse_time_functions() {
over: None, over: None,
distinct: false, distinct: false,
special: false, special: false,
order_by: vec![],
}), }),
expr_from_projection(&select.projection[0]) expr_from_projection(&select.projection[0])
); );
@ -6324,6 +6360,7 @@ fn parse_time_functions() {
over: None, over: None,
distinct: false, distinct: false,
special: false, special: false,
order_by: vec![],
}), }),
expr_from_projection(&select.projection[0]) expr_from_projection(&select.projection[0])
); );
@ -6340,6 +6377,7 @@ fn parse_time_functions() {
over: None, over: None,
distinct: false, distinct: false,
special: false, special: false,
order_by: vec![],
}), }),
expr_from_projection(&select.projection[0]) expr_from_projection(&select.projection[0])
); );
@ -6356,6 +6394,7 @@ fn parse_time_functions() {
over: None, over: None,
distinct: false, distinct: false,
special: false, special: false,
order_by: vec![],
}), }),
expr_from_projection(&select.projection[0]) expr_from_projection(&select.projection[0])
); );
@ -6820,6 +6859,7 @@ fn parse_pivot_table() {
over: None, over: None,
distinct: false, distinct: false,
special: false, special: false,
order_by: vec![],
}), }),
value_column: vec![Ident::new("a"), Ident::new("MONTH")], value_column: vec![Ident::new("a"), Ident::new("MONTH")],
pivot_values: vec![ pivot_values: vec![

View file

@ -346,6 +346,7 @@ fn parse_delimited_identifiers() {
over: None, over: None,
distinct: false, distinct: false,
special: false, special: false,
order_by: vec![],
}), }),
expr_from_projection(&select.projection[1]), expr_from_projection(&select.projection[1]),
); );

View file

@ -177,6 +177,7 @@ fn parse_delimited_identifiers() {
over: None, over: None,
distinct: false, distinct: false,
special: false, special: false,
order_by: vec![],
}), }),
expr_from_projection(&select.projection[1]), expr_from_projection(&select.projection[1]),
); );

View file

@ -791,6 +791,7 @@ fn parse_insert_with_on_duplicate_update() {
over: None, over: None,
distinct: false, distinct: false,
special: false, special: false,
order_by: vec![],
}) })
}, },
Assignment { Assignment {
@ -803,6 +804,7 @@ fn parse_insert_with_on_duplicate_update() {
over: None, over: None,
distinct: false, distinct: false,
special: false, special: false,
order_by: vec![],
}) })
}, },
Assignment { Assignment {
@ -815,6 +817,7 @@ fn parse_insert_with_on_duplicate_update() {
over: None, over: None,
distinct: false, distinct: false,
special: false, special: false,
order_by: vec![],
}) })
}, },
Assignment { Assignment {
@ -827,6 +830,7 @@ fn parse_insert_with_on_duplicate_update() {
over: None, over: None,
distinct: false, distinct: false,
special: false, special: false,
order_by: vec![],
}) })
}, },
Assignment { Assignment {
@ -839,6 +843,7 @@ fn parse_insert_with_on_duplicate_update() {
over: None, over: None,
distinct: false, distinct: false,
special: false, special: false,
order_by: vec![],
}) })
}, },
])), ])),
@ -1182,6 +1187,7 @@ fn parse_table_colum_option_on_update() {
over: None, over: None,
distinct: false, distinct: false,
special: false, special: false,
order_by: vec![],
})), })),
},], },],
}], }],

View file

@ -2057,7 +2057,8 @@ fn test_composite_value() {
)))], )))],
over: None, over: None,
distinct: false, distinct: false,
special: false special: false,
order_by: vec![],
})))) }))))
}), }),
select.projection[0] select.projection[0]
@ -2219,6 +2220,7 @@ fn parse_current_functions() {
over: None, over: None,
distinct: false, distinct: false,
special: true, special: true,
order_by: vec![],
}), }),
expr_from_projection(&select.projection[0]) expr_from_projection(&select.projection[0])
); );
@ -2229,6 +2231,7 @@ fn parse_current_functions() {
over: None, over: None,
distinct: false, distinct: false,
special: true, special: true,
order_by: vec![],
}), }),
expr_from_projection(&select.projection[1]) expr_from_projection(&select.projection[1])
); );
@ -2239,6 +2242,7 @@ fn parse_current_functions() {
over: None, over: None,
distinct: false, distinct: false,
special: true, special: true,
order_by: vec![],
}), }),
expr_from_projection(&select.projection[2]) expr_from_projection(&select.projection[2])
); );
@ -2249,6 +2253,7 @@ fn parse_current_functions() {
over: None, over: None,
distinct: false, distinct: false,
special: true, special: true,
order_by: vec![],
}), }),
expr_from_projection(&select.projection[3]) expr_from_projection(&select.projection[3])
); );
@ -2503,6 +2508,7 @@ fn parse_delimited_identifiers() {
over: None, over: None,
distinct: false, distinct: false,
special: false, special: false,
order_by: vec![],
}), }),
expr_from_projection(&select.projection[1]), expr_from_projection(&select.projection[1]),
); );

View file

@ -132,6 +132,7 @@ fn parse_delimited_identifiers() {
over: None, over: None,
distinct: false, distinct: false,
special: false, special: false,
order_by: vec![],
}), }),
expr_from_projection(&select.projection[1]), expr_from_projection(&select.projection[1]),
); );

View file

@ -249,6 +249,7 @@ fn parse_delimited_identifiers() {
over: None, over: None,
distinct: false, distinct: false,
special: false, special: false,
order_by: vec![],
}), }),
expr_from_projection(&select.projection[1]), expr_from_projection(&select.projection[1]),
); );