mirror of
https://github.com/apache/datafusion-sqlparser-rs.git
synced 2025-10-09 21:42:05 +00:00
Expand handling of LIMIT 1, 2
handling to include sqlite (#1447)
This commit is contained in:
parent
ce2686a169
commit
1e0460a7df
8 changed files with 61 additions and 24 deletions
|
@ -46,4 +46,8 @@ impl Dialect for ClickHouseDialect {
|
|||
fn require_interval_qualifier(&self) -> bool {
|
||||
true
|
||||
}
|
||||
|
||||
fn supports_limit_comma(&self) -> bool {
|
||||
true
|
||||
}
|
||||
}
|
||||
|
|
|
@ -99,4 +99,8 @@ impl Dialect for GenericDialect {
|
|||
fn supports_explain_with_utility_options(&self) -> bool {
|
||||
true
|
||||
}
|
||||
|
||||
fn supports_limit_comma(&self) -> bool {
|
||||
true
|
||||
}
|
||||
}
|
||||
|
|
|
@ -67,7 +67,7 @@ use alloc::boxed::Box;
|
|||
/// 1. user defined [`Dialect`]s can customize the parsing behavior
|
||||
/// 2. The differences between dialects can be clearly documented in the trait
|
||||
///
|
||||
/// `dialect_of!(parser Is SQLiteDialect | GenericDialect)` evaluates
|
||||
/// `dialect_of!(parser is SQLiteDialect | GenericDialect)` evaluates
|
||||
/// to `true` if `parser.dialect` is one of the [`Dialect`]s specified.
|
||||
macro_rules! dialect_of {
|
||||
( $parsed_dialect: ident is $($dialect_type: ty)|+ ) => {
|
||||
|
@ -323,6 +323,11 @@ pub trait Dialect: Debug + Any {
|
|||
false
|
||||
}
|
||||
|
||||
/// Does the dialect support parsing `LIMIT 1, 2` as `LIMIT 2 OFFSET 1`?
|
||||
fn supports_limit_comma(&self) -> bool {
|
||||
false
|
||||
}
|
||||
|
||||
/// Does the dialect support trailing commas in the projection list?
|
||||
fn supports_projection_trailing_commas(&self) -> bool {
|
||||
self.supports_trailing_commas()
|
||||
|
|
|
@ -93,6 +93,10 @@ impl Dialect for MySqlDialect {
|
|||
fn require_interval_qualifier(&self) -> bool {
|
||||
true
|
||||
}
|
||||
|
||||
fn supports_limit_comma(&self) -> bool {
|
||||
true
|
||||
}
|
||||
}
|
||||
|
||||
/// `LOCK TABLES`
|
||||
|
|
|
@ -73,4 +73,8 @@ impl Dialect for SQLiteDialect {
|
|||
fn supports_in_empty_list(&self) -> bool {
|
||||
true
|
||||
}
|
||||
|
||||
fn supports_limit_comma(&self) -> bool {
|
||||
true
|
||||
}
|
||||
}
|
||||
|
|
|
@ -8739,7 +8739,7 @@ impl<'a> Parser<'a> {
|
|||
offset = Some(self.parse_offset()?)
|
||||
}
|
||||
|
||||
if dialect_of!(self is GenericDialect | MySqlDialect | ClickHouseDialect)
|
||||
if self.dialect.supports_limit_comma()
|
||||
&& limit.is_some()
|
||||
&& offset.is_none()
|
||||
&& self.consume_token(&Token::Comma)
|
||||
|
|
|
@ -47,6 +47,14 @@ pub struct TestedDialects {
|
|||
}
|
||||
|
||||
impl TestedDialects {
|
||||
/// Create a TestedDialects with default options and the given dialects.
|
||||
pub fn new(dialects: Vec<Box<dyn Dialect>>) -> Self {
|
||||
Self {
|
||||
dialects,
|
||||
options: None,
|
||||
}
|
||||
}
|
||||
|
||||
fn new_parser<'a>(&self, dialect: &'a dyn Dialect) -> Parser<'a> {
|
||||
let parser = Parser::new(dialect);
|
||||
if let Some(options) = &self.options {
|
||||
|
@ -211,24 +219,21 @@ impl TestedDialects {
|
|||
|
||||
/// Returns all available dialects.
|
||||
pub fn all_dialects() -> TestedDialects {
|
||||
let all_dialects = vec![
|
||||
Box::new(GenericDialect {}) as Box<dyn Dialect>,
|
||||
Box::new(PostgreSqlDialect {}) as Box<dyn Dialect>,
|
||||
Box::new(MsSqlDialect {}) as Box<dyn Dialect>,
|
||||
Box::new(AnsiDialect {}) as Box<dyn Dialect>,
|
||||
Box::new(SnowflakeDialect {}) as Box<dyn Dialect>,
|
||||
Box::new(HiveDialect {}) as Box<dyn Dialect>,
|
||||
Box::new(RedshiftSqlDialect {}) as Box<dyn Dialect>,
|
||||
Box::new(MySqlDialect {}) as Box<dyn Dialect>,
|
||||
Box::new(BigQueryDialect {}) as Box<dyn Dialect>,
|
||||
Box::new(SQLiteDialect {}) as Box<dyn Dialect>,
|
||||
Box::new(DuckDbDialect {}) as Box<dyn Dialect>,
|
||||
Box::new(DatabricksDialect {}) as Box<dyn Dialect>,
|
||||
];
|
||||
TestedDialects {
|
||||
dialects: all_dialects,
|
||||
options: None,
|
||||
}
|
||||
TestedDialects::new(vec![
|
||||
Box::new(GenericDialect {}),
|
||||
Box::new(PostgreSqlDialect {}),
|
||||
Box::new(MsSqlDialect {}),
|
||||
Box::new(AnsiDialect {}),
|
||||
Box::new(SnowflakeDialect {}),
|
||||
Box::new(HiveDialect {}),
|
||||
Box::new(RedshiftSqlDialect {}),
|
||||
Box::new(MySqlDialect {}),
|
||||
Box::new(BigQueryDialect {}),
|
||||
Box::new(SQLiteDialect {}),
|
||||
Box::new(DuckDbDialect {}),
|
||||
Box::new(DatabricksDialect {}),
|
||||
Box::new(ClickHouseDialect {}),
|
||||
])
|
||||
}
|
||||
|
||||
/// Returns all dialects matching the given predicate.
|
||||
|
|
|
@ -6832,7 +6832,9 @@ fn parse_create_view_with_options() {
|
|||
#[test]
|
||||
fn parse_create_view_with_columns() {
|
||||
let sql = "CREATE VIEW v (has, cols) AS SELECT 1, 2";
|
||||
match verified_stmt(sql) {
|
||||
// TODO: why does this fail for ClickHouseDialect? (#1449)
|
||||
// match all_dialects().verified_stmt(sql) {
|
||||
match all_dialects_except(|d| d.is::<ClickHouseDialect>()).verified_stmt(sql) {
|
||||
Statement::CreateView {
|
||||
name,
|
||||
columns,
|
||||
|
@ -8624,17 +8626,26 @@ fn verified_expr(query: &str) -> Expr {
|
|||
|
||||
#[test]
|
||||
fn parse_offset_and_limit() {
|
||||
let sql = "SELECT foo FROM bar LIMIT 2 OFFSET 2";
|
||||
let sql = "SELECT foo FROM bar LIMIT 1 OFFSET 2";
|
||||
let expect = Some(Offset {
|
||||
value: Expr::Value(number("2")),
|
||||
rows: OffsetRows::None,
|
||||
});
|
||||
let ast = verified_query(sql);
|
||||
assert_eq!(ast.offset, expect);
|
||||
assert_eq!(ast.limit, Some(Expr::Value(number("2"))));
|
||||
assert_eq!(ast.limit, Some(Expr::Value(number("1"))));
|
||||
|
||||
// different order is OK
|
||||
one_statement_parses_to("SELECT foo FROM bar OFFSET 2 LIMIT 2", sql);
|
||||
one_statement_parses_to("SELECT foo FROM bar OFFSET 2 LIMIT 1", sql);
|
||||
|
||||
// mysql syntax is ok for some dialects
|
||||
TestedDialects::new(vec![
|
||||
Box::new(GenericDialect {}),
|
||||
Box::new(MySqlDialect {}),
|
||||
Box::new(SQLiteDialect {}),
|
||||
Box::new(ClickHouseDialect {}),
|
||||
])
|
||||
.one_statement_parses_to("SELECT foo FROM bar LIMIT 2, 1", sql);
|
||||
|
||||
// expressions are allowed
|
||||
let sql = "SELECT foo FROM bar LIMIT 1 + 2 OFFSET 3 * 4";
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue