mirror of
https://github.com/apache/datafusion-sqlparser-rs.git
synced 2025-10-10 05:52:13 +00:00
Support multiple PARTITION
statements in ALTER TABLE ADD
statement (#1011)
Co-authored-by: Chris A <chrisa@indeed.com> Co-authored-by: Andrew Lamb <andrew@nerdnetworks.org>
This commit is contained in:
parent
9832adb376
commit
004a8dc5dd
5 changed files with 51 additions and 10 deletions
|
@ -69,7 +69,7 @@ pub enum AlterTableOperation {
|
||||||
/// Add Partitions
|
/// Add Partitions
|
||||||
AddPartitions {
|
AddPartitions {
|
||||||
if_not_exists: bool,
|
if_not_exists: bool,
|
||||||
new_partitions: Vec<Expr>,
|
new_partitions: Vec<Partition>,
|
||||||
},
|
},
|
||||||
DropPartitions {
|
DropPartitions {
|
||||||
partitions: Vec<Expr>,
|
partitions: Vec<Expr>,
|
||||||
|
@ -119,8 +119,8 @@ impl fmt::Display for AlterTableOperation {
|
||||||
new_partitions,
|
new_partitions,
|
||||||
} => write!(
|
} => write!(
|
||||||
f,
|
f,
|
||||||
"ADD{ine} PARTITION ({})",
|
"ADD{ine} {}",
|
||||||
display_comma_separated(new_partitions),
|
display_separated(new_partitions, " "),
|
||||||
ine = if *if_not_exists { " IF NOT EXISTS" } else { "" }
|
ine = if *if_not_exists { " IF NOT EXISTS" } else { "" }
|
||||||
),
|
),
|
||||||
AlterTableOperation::AddConstraint(c) => write!(f, "ADD {c}"),
|
AlterTableOperation::AddConstraint(c) => write!(f, "ADD {c}"),
|
||||||
|
@ -771,3 +771,21 @@ impl fmt::Display for UserDefinedTypeCompositeAttributeDef {
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// PARTITION statement used in ALTER TABLE et al. such as in Hive SQL
|
||||||
|
#[derive(Debug, Clone, PartialEq, Eq, Hash, PartialOrd, Ord)]
|
||||||
|
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
|
||||||
|
#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
|
||||||
|
pub struct Partition {
|
||||||
|
pub partitions: Vec<Expr>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl fmt::Display for Partition {
|
||||||
|
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||||
|
write!(
|
||||||
|
f,
|
||||||
|
"PARTITION ({})",
|
||||||
|
display_comma_separated(&self.partitions)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -31,8 +31,9 @@ pub use self::data_type::{
|
||||||
pub use self::dcl::{AlterRoleOperation, ResetConfig, RoleOption, SetConfigValue};
|
pub use self::dcl::{AlterRoleOperation, ResetConfig, RoleOption, SetConfigValue};
|
||||||
pub use self::ddl::{
|
pub use self::ddl::{
|
||||||
AlterColumnOperation, AlterIndexOperation, AlterTableOperation, ColumnDef, ColumnOption,
|
AlterColumnOperation, AlterIndexOperation, AlterTableOperation, ColumnDef, ColumnOption,
|
||||||
ColumnOptionDef, GeneratedAs, IndexType, KeyOrIndexDisplay, ProcedureParam, ReferentialAction,
|
ColumnOptionDef, GeneratedAs, IndexType, KeyOrIndexDisplay, Partition, ProcedureParam,
|
||||||
TableConstraint, UserDefinedTypeCompositeAttributeDef, UserDefinedTypeRepresentation,
|
ReferentialAction, TableConstraint, UserDefinedTypeCompositeAttributeDef,
|
||||||
|
UserDefinedTypeRepresentation,
|
||||||
};
|
};
|
||||||
pub use self::operator::{BinaryOperator, UnaryOperator};
|
pub use self::operator::{BinaryOperator, UnaryOperator};
|
||||||
pub use self::query::{
|
pub use self::query::{
|
||||||
|
|
|
@ -18,6 +18,10 @@ use crate::dialect::Dialect;
|
||||||
pub struct GenericDialect;
|
pub struct GenericDialect;
|
||||||
|
|
||||||
impl Dialect for GenericDialect {
|
impl Dialect for GenericDialect {
|
||||||
|
fn is_delimited_identifier_start(&self, ch: char) -> bool {
|
||||||
|
ch == '"' || ch == '`'
|
||||||
|
}
|
||||||
|
|
||||||
fn is_identifier_start(&self, ch: char) -> bool {
|
fn is_identifier_start(&self, ch: char) -> bool {
|
||||||
ch.is_alphabetic() || ch == '_' || ch == '#' || ch == '@'
|
ch.is_alphabetic() || ch == '_' || ch == '#' || ch == '@'
|
||||||
}
|
}
|
||||||
|
|
|
@ -4195,6 +4195,13 @@ impl<'a> Parser<'a> {
|
||||||
Ok(SqlOption { name, value })
|
Ok(SqlOption { name, value })
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn parse_partition(&mut self) -> Result<Partition, ParserError> {
|
||||||
|
self.expect_token(&Token::LParen)?;
|
||||||
|
let partitions = self.parse_comma_separated(Parser::parse_expr)?;
|
||||||
|
self.expect_token(&Token::RParen)?;
|
||||||
|
Ok(Partition { partitions })
|
||||||
|
}
|
||||||
|
|
||||||
pub fn parse_alter_table_operation(&mut self) -> Result<AlterTableOperation, ParserError> {
|
pub fn parse_alter_table_operation(&mut self) -> Result<AlterTableOperation, ParserError> {
|
||||||
let operation = if self.parse_keyword(Keyword::ADD) {
|
let operation = if self.parse_keyword(Keyword::ADD) {
|
||||||
if let Some(constraint) = self.parse_optional_table_constraint()? {
|
if let Some(constraint) = self.parse_optional_table_constraint()? {
|
||||||
|
@ -4202,13 +4209,18 @@ impl<'a> Parser<'a> {
|
||||||
} else {
|
} else {
|
||||||
let if_not_exists =
|
let if_not_exists =
|
||||||
self.parse_keywords(&[Keyword::IF, Keyword::NOT, Keyword::EXISTS]);
|
self.parse_keywords(&[Keyword::IF, Keyword::NOT, Keyword::EXISTS]);
|
||||||
|
let mut new_partitions = vec![];
|
||||||
|
loop {
|
||||||
if self.parse_keyword(Keyword::PARTITION) {
|
if self.parse_keyword(Keyword::PARTITION) {
|
||||||
self.expect_token(&Token::LParen)?;
|
new_partitions.push(self.parse_partition()?);
|
||||||
let partitions = self.parse_comma_separated(Parser::parse_expr)?;
|
} else {
|
||||||
self.expect_token(&Token::RParen)?;
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if !new_partitions.is_empty() {
|
||||||
AlterTableOperation::AddPartitions {
|
AlterTableOperation::AddPartitions {
|
||||||
if_not_exists,
|
if_not_exists,
|
||||||
new_partitions: partitions,
|
new_partitions,
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
let column_keyword = self.parse_keyword(Keyword::COLUMN);
|
let column_keyword = self.parse_keyword(Keyword::COLUMN);
|
||||||
|
|
|
@ -128,6 +128,12 @@ fn test_add_partition() {
|
||||||
hive().verified_stmt(add);
|
hive().verified_stmt(add);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_add_multiple_partitions() {
|
||||||
|
let add = "ALTER TABLE db.table ADD IF NOT EXISTS PARTITION (`a` = 'asdf', `b` = 2) PARTITION (`a` = 'asdh', `b` = 3)";
|
||||||
|
hive().verified_stmt(add);
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_drop_partition() {
|
fn test_drop_partition() {
|
||||||
let drop = "ALTER TABLE db.table DROP PARTITION (a = 1)";
|
let drop = "ALTER TABLE db.table DROP PARTITION (a = 1)";
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue