mirror of
https://github.com/apache/datafusion-sqlparser-rs.git
synced 2025-08-22 23:14:07 +00:00
clickhouse: add support for LIMIT BY (#977)
This commit is contained in:
parent
993769ec02
commit
2786c7eaf1
7 changed files with 56 additions and 1 deletions
|
@ -35,6 +35,10 @@ pub struct Query {
|
||||||
pub order_by: Vec<OrderByExpr>,
|
pub order_by: Vec<OrderByExpr>,
|
||||||
/// `LIMIT { <N> | ALL }`
|
/// `LIMIT { <N> | ALL }`
|
||||||
pub limit: Option<Expr>,
|
pub limit: Option<Expr>,
|
||||||
|
|
||||||
|
/// `LIMIT { <N> } BY { <expr>,<expr>,... } }`
|
||||||
|
pub limit_by: Vec<Expr>,
|
||||||
|
|
||||||
/// `OFFSET <N> [ { ROW | ROWS } ]`
|
/// `OFFSET <N> [ { ROW | ROWS } ]`
|
||||||
pub offset: Option<Offset>,
|
pub offset: Option<Offset>,
|
||||||
/// `FETCH { FIRST | NEXT } <N> [ PERCENT ] { ROW | ROWS } | { ONLY | WITH TIES }`
|
/// `FETCH { FIRST | NEXT } <N> [ PERCENT ] { ROW | ROWS } | { ONLY | WITH TIES }`
|
||||||
|
@ -58,6 +62,9 @@ impl fmt::Display for Query {
|
||||||
if let Some(ref offset) = self.offset {
|
if let Some(ref offset) = self.offset {
|
||||||
write!(f, " {offset}")?;
|
write!(f, " {offset}")?;
|
||||||
}
|
}
|
||||||
|
if !self.limit_by.is_empty() {
|
||||||
|
write!(f, " BY {}", display_separated(&self.limit_by, ", "))?;
|
||||||
|
}
|
||||||
if let Some(ref fetch) = self.fetch {
|
if let Some(ref fetch) = self.fetch {
|
||||||
write!(f, " {fetch}")?;
|
write!(f, " {fetch}")?;
|
||||||
}
|
}
|
||||||
|
|
|
@ -5431,6 +5431,7 @@ impl<'a> Parser<'a> {
|
||||||
with,
|
with,
|
||||||
body: Box::new(SetExpr::Insert(insert)),
|
body: Box::new(SetExpr::Insert(insert)),
|
||||||
limit: None,
|
limit: None,
|
||||||
|
limit_by: vec![],
|
||||||
order_by: vec![],
|
order_by: vec![],
|
||||||
offset: None,
|
offset: None,
|
||||||
fetch: None,
|
fetch: None,
|
||||||
|
@ -5442,6 +5443,7 @@ impl<'a> Parser<'a> {
|
||||||
with,
|
with,
|
||||||
body: Box::new(SetExpr::Update(update)),
|
body: Box::new(SetExpr::Update(update)),
|
||||||
limit: None,
|
limit: None,
|
||||||
|
limit_by: vec![],
|
||||||
order_by: vec![],
|
order_by: vec![],
|
||||||
offset: None,
|
offset: None,
|
||||||
fetch: None,
|
fetch: None,
|
||||||
|
@ -5468,7 +5470,7 @@ impl<'a> Parser<'a> {
|
||||||
offset = Some(self.parse_offset()?)
|
offset = Some(self.parse_offset()?)
|
||||||
}
|
}
|
||||||
|
|
||||||
if dialect_of!(self is GenericDialect | MySqlDialect)
|
if dialect_of!(self is GenericDialect | MySqlDialect | ClickHouseDialect)
|
||||||
&& limit.is_some()
|
&& limit.is_some()
|
||||||
&& offset.is_none()
|
&& offset.is_none()
|
||||||
&& self.consume_token(&Token::Comma)
|
&& self.consume_token(&Token::Comma)
|
||||||
|
@ -5483,6 +5485,14 @@ impl<'a> Parser<'a> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let limit_by = if dialect_of!(self is ClickHouseDialect | GenericDialect)
|
||||||
|
&& self.parse_keyword(Keyword::BY)
|
||||||
|
{
|
||||||
|
self.parse_comma_separated(Parser::parse_expr)?
|
||||||
|
} else {
|
||||||
|
vec![]
|
||||||
|
};
|
||||||
|
|
||||||
let fetch = if self.parse_keyword(Keyword::FETCH) {
|
let fetch = if self.parse_keyword(Keyword::FETCH) {
|
||||||
Some(self.parse_fetch()?)
|
Some(self.parse_fetch()?)
|
||||||
} else {
|
} else {
|
||||||
|
@ -5499,6 +5509,7 @@ impl<'a> Parser<'a> {
|
||||||
body,
|
body,
|
||||||
order_by,
|
order_by,
|
||||||
limit,
|
limit,
|
||||||
|
limit_by,
|
||||||
offset,
|
offset,
|
||||||
fetch,
|
fetch,
|
||||||
locks,
|
locks,
|
||||||
|
|
|
@ -25,6 +25,7 @@ use sqlparser::ast::TableFactor::Table;
|
||||||
use sqlparser::ast::*;
|
use sqlparser::ast::*;
|
||||||
|
|
||||||
use sqlparser::dialect::ClickHouseDialect;
|
use sqlparser::dialect::ClickHouseDialect;
|
||||||
|
use sqlparser::dialect::GenericDialect;
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn parse_map_access_expr() {
|
fn parse_map_access_expr() {
|
||||||
|
@ -344,9 +345,26 @@ fn parse_double_equal() {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn parse_limit_by() {
|
||||||
|
clickhouse_and_generic().verified_stmt(
|
||||||
|
r#"SELECT * FROM default.last_asset_runs_mv ORDER BY created_at DESC LIMIT 1 BY asset"#,
|
||||||
|
);
|
||||||
|
clickhouse_and_generic().verified_stmt(
|
||||||
|
r#"SELECT * FROM default.last_asset_runs_mv ORDER BY created_at DESC LIMIT 1 BY asset, toStartOfDay(created_at)"#,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
fn clickhouse() -> TestedDialects {
|
fn clickhouse() -> TestedDialects {
|
||||||
TestedDialects {
|
TestedDialects {
|
||||||
dialects: vec![Box::new(ClickHouseDialect {})],
|
dialects: vec![Box::new(ClickHouseDialect {})],
|
||||||
options: None,
|
options: None,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn clickhouse_and_generic() -> TestedDialects {
|
||||||
|
TestedDialects {
|
||||||
|
dialects: vec![Box::new(ClickHouseDialect {}), Box::new(GenericDialect {})],
|
||||||
|
options: None,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -261,6 +261,7 @@ fn parse_update_set_from() {
|
||||||
}))),
|
}))),
|
||||||
order_by: vec![],
|
order_by: vec![],
|
||||||
limit: None,
|
limit: None,
|
||||||
|
limit_by: vec![],
|
||||||
offset: None,
|
offset: None,
|
||||||
fetch: None,
|
fetch: None,
|
||||||
locks: vec![],
|
locks: vec![],
|
||||||
|
@ -2662,6 +2663,7 @@ fn parse_create_table_as_table() {
|
||||||
}))),
|
}))),
|
||||||
order_by: vec![],
|
order_by: vec![],
|
||||||
limit: None,
|
limit: None,
|
||||||
|
limit_by: vec![],
|
||||||
offset: None,
|
offset: None,
|
||||||
fetch: None,
|
fetch: None,
|
||||||
locks: vec![],
|
locks: vec![],
|
||||||
|
@ -2685,6 +2687,7 @@ fn parse_create_table_as_table() {
|
||||||
}))),
|
}))),
|
||||||
order_by: vec![],
|
order_by: vec![],
|
||||||
limit: None,
|
limit: None,
|
||||||
|
limit_by: vec![],
|
||||||
offset: None,
|
offset: None,
|
||||||
fetch: None,
|
fetch: None,
|
||||||
locks: vec![],
|
locks: vec![],
|
||||||
|
@ -3976,6 +3979,7 @@ fn parse_interval_and_or_xor() {
|
||||||
}))),
|
}))),
|
||||||
order_by: vec![],
|
order_by: vec![],
|
||||||
limit: None,
|
limit: None,
|
||||||
|
limit_by: vec![],
|
||||||
offset: None,
|
offset: None,
|
||||||
fetch: None,
|
fetch: None,
|
||||||
locks: vec![],
|
locks: vec![],
|
||||||
|
@ -6392,6 +6396,7 @@ fn parse_merge() {
|
||||||
}))),
|
}))),
|
||||||
order_by: vec![],
|
order_by: vec![],
|
||||||
limit: None,
|
limit: None,
|
||||||
|
limit_by: vec![],
|
||||||
offset: None,
|
offset: None,
|
||||||
fetch: None,
|
fetch: None,
|
||||||
locks: vec![],
|
locks: vec![],
|
||||||
|
|
|
@ -92,6 +92,7 @@ fn parse_create_procedure() {
|
||||||
body: vec![Statement::Query(Box::new(Query {
|
body: vec![Statement::Query(Box::new(Query {
|
||||||
with: None,
|
with: None,
|
||||||
limit: None,
|
limit: None,
|
||||||
|
limit_by: vec![],
|
||||||
offset: None,
|
offset: None,
|
||||||
fetch: None,
|
fetch: None,
|
||||||
locks: vec![],
|
locks: vec![],
|
||||||
|
@ -493,6 +494,7 @@ fn parse_substring_in_select() {
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
Box::new(Query {
|
Box::new(Query {
|
||||||
with: None,
|
with: None,
|
||||||
|
|
||||||
body: Box::new(SetExpr::Select(Box::new(Select {
|
body: Box::new(SetExpr::Select(Box::new(Select {
|
||||||
distinct: Some(Distinct::Distinct),
|
distinct: Some(Distinct::Distinct),
|
||||||
top: None,
|
top: None,
|
||||||
|
@ -532,6 +534,7 @@ fn parse_substring_in_select() {
|
||||||
}))),
|
}))),
|
||||||
order_by: vec![],
|
order_by: vec![],
|
||||||
limit: None,
|
limit: None,
|
||||||
|
limit_by: vec![],
|
||||||
offset: None,
|
offset: None,
|
||||||
fetch: None,
|
fetch: None,
|
||||||
locks: vec![],
|
locks: vec![],
|
||||||
|
|
|
@ -562,6 +562,7 @@ fn parse_escaped_quote_identifiers_with_escape() {
|
||||||
}))),
|
}))),
|
||||||
order_by: vec![],
|
order_by: vec![],
|
||||||
limit: None,
|
limit: None,
|
||||||
|
limit_by: vec![],
|
||||||
offset: None,
|
offset: None,
|
||||||
fetch: None,
|
fetch: None,
|
||||||
locks: vec![],
|
locks: vec![],
|
||||||
|
@ -604,6 +605,7 @@ fn parse_escaped_quote_identifiers_with_no_escape() {
|
||||||
}))),
|
}))),
|
||||||
order_by: vec![],
|
order_by: vec![],
|
||||||
limit: None,
|
limit: None,
|
||||||
|
limit_by: vec![],
|
||||||
offset: None,
|
offset: None,
|
||||||
fetch: None,
|
fetch: None,
|
||||||
locks: vec![],
|
locks: vec![],
|
||||||
|
@ -643,6 +645,7 @@ fn parse_escaped_backticks_with_escape() {
|
||||||
}))),
|
}))),
|
||||||
order_by: vec![],
|
order_by: vec![],
|
||||||
limit: None,
|
limit: None,
|
||||||
|
limit_by: vec![],
|
||||||
offset: None,
|
offset: None,
|
||||||
fetch: None,
|
fetch: None,
|
||||||
locks: vec![],
|
locks: vec![],
|
||||||
|
@ -682,6 +685,7 @@ fn parse_escaped_backticks_with_no_escape() {
|
||||||
}))),
|
}))),
|
||||||
order_by: vec![],
|
order_by: vec![],
|
||||||
limit: None,
|
limit: None,
|
||||||
|
limit_by: vec![],
|
||||||
offset: None,
|
offset: None,
|
||||||
fetch: None,
|
fetch: None,
|
||||||
locks: vec![],
|
locks: vec![],
|
||||||
|
@ -956,6 +960,7 @@ fn parse_simple_insert() {
|
||||||
})),
|
})),
|
||||||
order_by: vec![],
|
order_by: vec![],
|
||||||
limit: None,
|
limit: None,
|
||||||
|
limit_by: vec![],
|
||||||
offset: None,
|
offset: None,
|
||||||
fetch: None,
|
fetch: None,
|
||||||
locks: vec![],
|
locks: vec![],
|
||||||
|
@ -991,6 +996,7 @@ fn parse_empty_row_insert() {
|
||||||
})),
|
})),
|
||||||
order_by: vec![],
|
order_by: vec![],
|
||||||
limit: None,
|
limit: None,
|
||||||
|
limit_by: vec![],
|
||||||
offset: None,
|
offset: None,
|
||||||
fetch: None,
|
fetch: None,
|
||||||
locks: vec![],
|
locks: vec![],
|
||||||
|
@ -1049,6 +1055,7 @@ fn parse_insert_with_on_duplicate_update() {
|
||||||
})),
|
})),
|
||||||
order_by: vec![],
|
order_by: vec![],
|
||||||
limit: None,
|
limit: None,
|
||||||
|
limit_by: vec![],
|
||||||
offset: None,
|
offset: None,
|
||||||
fetch: None,
|
fetch: None,
|
||||||
locks: vec![],
|
locks: vec![],
|
||||||
|
@ -1428,6 +1435,7 @@ fn parse_substring_in_select() {
|
||||||
}))),
|
}))),
|
||||||
order_by: vec![],
|
order_by: vec![],
|
||||||
limit: None,
|
limit: None,
|
||||||
|
limit_by: vec![],
|
||||||
offset: None,
|
offset: None,
|
||||||
fetch: None,
|
fetch: None,
|
||||||
locks: vec![],
|
locks: vec![],
|
||||||
|
@ -1708,6 +1716,7 @@ fn parse_hex_string_introducer() {
|
||||||
}))),
|
}))),
|
||||||
order_by: vec![],
|
order_by: vec![],
|
||||||
limit: None,
|
limit: None,
|
||||||
|
limit_by: vec![],
|
||||||
offset: None,
|
offset: None,
|
||||||
fetch: None,
|
fetch: None,
|
||||||
locks: vec![],
|
locks: vec![],
|
||||||
|
|
|
@ -1000,6 +1000,7 @@ fn parse_copy_to() {
|
||||||
}))),
|
}))),
|
||||||
order_by: vec![],
|
order_by: vec![],
|
||||||
limit: None,
|
limit: None,
|
||||||
|
limit_by: vec![],
|
||||||
offset: None,
|
offset: None,
|
||||||
fetch: None,
|
fetch: None,
|
||||||
locks: vec![],
|
locks: vec![],
|
||||||
|
@ -2046,6 +2047,7 @@ fn parse_array_subquery_expr() {
|
||||||
}),
|
}),
|
||||||
order_by: vec![],
|
order_by: vec![],
|
||||||
limit: None,
|
limit: None,
|
||||||
|
limit_by: vec![],
|
||||||
offset: None,
|
offset: None,
|
||||||
fetch: None,
|
fetch: None,
|
||||||
locks: vec![],
|
locks: vec![],
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue