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
// do it for current_catalog, current_schema, etc. This flags is used for formatting.
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)]
@ -3392,12 +3394,18 @@ impl fmt::Display for Function {
if self.special {
write!(f, "{}", self.name)?;
} else {
let order_by = if !self.order_by.is_empty() {
" ORDER BY "
} else {
""
};
write!(
f,
"{}({}{})",
"{}({}{}{order_by}{})",
self.name,
if self.distinct { "DISTINCT " } else { "" },
display_comma_separated(&self.args),
display_comma_separated(&self.order_by),
)?;
if let Some(o) = &self.over {

View file

@ -480,7 +480,7 @@ where
/// *expr = Expr::Function(Function {
/// name: ObjectName(vec![Ident::new("f")]),
/// 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(())

View file

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

View file

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

View file

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

View file

@ -840,6 +840,7 @@ fn parse_select_count_wildcard() {
over: None,
distinct: false,
special: false,
order_by: vec![],
}),
expr_from_projection(only(&select.projection))
);
@ -859,6 +860,7 @@ fn parse_select_count_distinct() {
over: None,
distinct: true,
special: false,
order_by: vec![],
}),
expr_from_projection(only(&select.projection))
);
@ -1696,6 +1698,7 @@ fn parse_select_having() {
over: None,
distinct: false,
special: false,
order_by: vec![],
})),
op: BinaryOperator::Gt,
right: Box::new(Expr::Value(number("1"))),
@ -1729,6 +1732,7 @@ fn parse_select_qualify() {
}),
distinct: false,
special: false,
order_by: vec![],
})),
op: BinaryOperator::Eq,
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]
fn parse_create_table() {
let sql = "CREATE TABLE uk_cities (\
@ -3121,6 +3148,7 @@ fn parse_scalar_function_in_projection() {
over: None,
distinct: false,
special: false,
order_by: vec![],
}),
expr_from_projection(only(&select.projection))
);
@ -3239,6 +3267,7 @@ fn parse_named_argument_function() {
over: None,
distinct: false,
special: false,
order_by: vec![],
}),
expr_from_projection(only(&select.projection))
);
@ -3277,6 +3306,7 @@ fn parse_window_functions() {
}),
distinct: false,
special: false,
order_by: vec![],
}),
expr_from_projection(&select.projection[0])
);
@ -3675,6 +3705,7 @@ fn parse_at_timezone() {
over: None,
distinct: false,
special: false,
order_by: vec![],
})),
time_zone: "UTC-06:00".to_string(),
},
@ -3701,6 +3732,7 @@ fn parse_at_timezone() {
over: None,
distinct: false,
special: false,
order_by: vec![],
},)),
time_zone: "UTC-06:00".to_string(),
},),),
@ -3711,6 +3743,7 @@ fn parse_at_timezone() {
over: None,
distinct: false,
special: false,
order_by: vec![],
},),
alias: Ident {
value: "hour".to_string(),
@ -3868,6 +3901,7 @@ fn parse_table_function() {
over: None,
distinct: false,
special: false,
order_by: vec![],
});
assert_eq!(expr, expected_expr);
assert_eq!(alias, table_alias("a"))
@ -6292,6 +6326,7 @@ fn parse_time_functions() {
over: None,
distinct: false,
special: false,
order_by: vec![],
}),
expr_from_projection(&select.projection[0])
);
@ -6308,6 +6343,7 @@ fn parse_time_functions() {
over: None,
distinct: false,
special: false,
order_by: vec![],
}),
expr_from_projection(&select.projection[0])
);
@ -6324,6 +6360,7 @@ fn parse_time_functions() {
over: None,
distinct: false,
special: false,
order_by: vec![],
}),
expr_from_projection(&select.projection[0])
);
@ -6340,6 +6377,7 @@ fn parse_time_functions() {
over: None,
distinct: false,
special: false,
order_by: vec![],
}),
expr_from_projection(&select.projection[0])
);
@ -6356,6 +6394,7 @@ fn parse_time_functions() {
over: None,
distinct: false,
special: false,
order_by: vec![],
}),
expr_from_projection(&select.projection[0])
);
@ -6820,6 +6859,7 @@ fn parse_pivot_table() {
over: None,
distinct: false,
special: false,
order_by: vec![],
}),
value_column: vec![Ident::new("a"), Ident::new("MONTH")],
pivot_values: vec![

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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