Skip to content

Commit f2b7af9

Browse files
committed
feat: support mysql partition selection
1 parent 9c2e8bc commit f2b7af9

File tree

4 files changed

+55
-0
lines changed

4 files changed

+55
-0
lines changed

src/ast/query.rs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -665,6 +665,8 @@ pub enum TableFactor {
665665
/// Optional version qualifier to facilitate table time-travel, as
666666
/// supported by BigQuery and MSSQL.
667667
version: Option<TableVersion>,
668+
/// Partition selection, supported by Mysql.
669+
partitions: Vec<Expr>,
668670
},
669671
Derived {
670672
lateral: bool,
@@ -725,8 +727,12 @@ impl fmt::Display for TableFactor {
725727
args,
726728
with_hints,
727729
version,
730+
partitions,
728731
} => {
729732
write!(f, "{name}")?;
733+
if !partitions.is_empty() {
734+
write!(f, "PARTITION ({})", display_comma_separated(partitions))?;
735+
}
730736
if let Some(args) = args {
731737
write!(f, "({})", display_comma_separated(args))?;
732738
}

src/keywords.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -716,6 +716,8 @@ pub const RESERVED_FOR_TABLE_ALIAS: &[Keyword] = &[
716716
Keyword::QUALIFY,
717717
Keyword::WINDOW,
718718
Keyword::END,
719+
// for MYSQL PARTITION SELECTION
720+
Keyword::PARTITION,
719721
];
720722

721723
/// Can't be used as a column alias, so that `SELECT <expr> alias`

src/parser/mod.rs

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6210,6 +6210,20 @@ impl<'a> Parser<'a> {
62106210
} else {
62116211
let name = self.parse_object_name()?;
62126212

6213+
let partitions = if dialect_of!(self is MySqlDialect)
6214+
&& self.parse_keyword(Keyword::PARTITION)
6215+
{
6216+
let mut partitions = self.parse_comma_separated(|p| p.parse_tuple(true, false))?;
6217+
if partitions.len() != 1 {
6218+
return Err(ParserError::ParserError(format!(
6219+
"Partition expect one tuple"
6220+
)));
6221+
}
6222+
partitions.remove(0)
6223+
} else {
6224+
vec![]
6225+
};
6226+
62136227
// Parse potential version qualifier
62146228
let version = self.parse_table_version()?;
62156229

@@ -6244,6 +6258,7 @@ impl<'a> Parser<'a> {
62446258
args,
62456259
with_hints,
62466260
version,
6261+
partitions,
62476262
})
62486263
}
62496264
}
@@ -8034,4 +8049,35 @@ mod tests {
80348049
"sql parser error: Unexpected token following period in identifier: *",
80358050
);
80368051
}
8052+
8053+
#[test]
8054+
fn test_mysql_partition_selection() {
8055+
let sql = "SELECT * FROM employees PARTITION (p0, p2)";
8056+
let expected = vec!["p0", "p2"];
8057+
8058+
let ast: Vec<Statement> = Parser::parse_sql(&MySqlDialect {}, sql).unwrap();
8059+
assert_eq!(ast.len(), 1);
8060+
if let Statement::Query(v) = &ast[0] {
8061+
if let SetExpr::Select(select) = &*v.body {
8062+
assert_eq!(select.from.len(), 1);
8063+
let from: &TableWithJoins = &select.from[0];
8064+
let table_factor = &from.relation;
8065+
if let TableFactor::Table { partitions, .. } = table_factor {
8066+
let actual: Vec<&str> = partitions
8067+
.iter()
8068+
.map(|expr| {
8069+
if let Expr::Identifier(ident) = &expr {
8070+
ident.value.as_str()
8071+
} else {
8072+
""
8073+
}
8074+
})
8075+
.collect();
8076+
assert_eq!(expected, actual);
8077+
}
8078+
}
8079+
} else {
8080+
panic!("fail to parse mysql partition selection");
8081+
}
8082+
}
80378083
}

src/test_utils.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -222,6 +222,7 @@ pub fn table(name: impl Into<String>) -> TableFactor {
222222
args: None,
223223
with_hints: vec![],
224224
version: None,
225+
partitions: vec![],
225226
}
226227
}
227228

0 commit comments

Comments
 (0)