mirror of
https://github.com/apache/datafusion-sqlparser-rs.git
synced 2025-08-30 18:57:21 +00:00
Support for IF NOT EXISTS
in ALTER TABLE ADD COLUMN (#707)
This commit is contained in:
parent
bae682255d
commit
886875f3bf
3 changed files with 110 additions and 11 deletions
|
@ -30,8 +30,15 @@ use crate::tokenizer::Token;
|
|||
pub enum AlterTableOperation {
|
||||
/// `ADD <table_constraint>`
|
||||
AddConstraint(TableConstraint),
|
||||
/// `ADD [ COLUMN ] <column_def>`
|
||||
AddColumn { column_def: ColumnDef },
|
||||
/// `ADD [COLUMN] [IF NOT EXISTS] <column_def>`
|
||||
AddColumn {
|
||||
/// `[COLUMN]`.
|
||||
column_keyword: bool,
|
||||
/// `[IF NOT EXISTS]`
|
||||
if_not_exists: bool,
|
||||
/// <column_def>.
|
||||
column_def: ColumnDef,
|
||||
},
|
||||
/// `DROP CONSTRAINT [ IF EXISTS ] <name>`
|
||||
DropConstraint {
|
||||
if_exists: bool,
|
||||
|
@ -100,8 +107,21 @@ impl fmt::Display for AlterTableOperation {
|
|||
ine = if *if_not_exists { " IF NOT EXISTS" } else { "" }
|
||||
),
|
||||
AlterTableOperation::AddConstraint(c) => write!(f, "ADD {}", c),
|
||||
AlterTableOperation::AddColumn { column_def } => {
|
||||
write!(f, "ADD COLUMN {}", column_def)
|
||||
AlterTableOperation::AddColumn {
|
||||
column_keyword,
|
||||
if_not_exists,
|
||||
column_def,
|
||||
} => {
|
||||
write!(f, "ADD")?;
|
||||
if *column_keyword {
|
||||
write!(f, " COLUMN")?;
|
||||
}
|
||||
if *if_not_exists {
|
||||
write!(f, " IF NOT EXISTS")?;
|
||||
}
|
||||
write!(f, " {column_def}")?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
AlterTableOperation::AlterColumn { column_name, op } => {
|
||||
write!(f, "ALTER COLUMN {} {}", column_name, op)
|
||||
|
@ -416,8 +436,8 @@ impl fmt::Display for KeyOrIndexDisplay {
|
|||
|
||||
/// Indexing method used by that index.
|
||||
///
|
||||
/// This structure isn't present on ANSI, but is found at least in [MySQL CREATE TABLE][1],
|
||||
/// [MySQL CREATE INDEX][2], and [Postgresql CREATE INDEX][3] statements.
|
||||
/// This structure isn't present on ANSI, but is found at least in [`MySQL` CREATE TABLE][1],
|
||||
/// [`MySQL` CREATE INDEX][2], and [Postgresql CREATE INDEX][3] statements.
|
||||
///
|
||||
/// [1]: https://dev.mysql.com/doc/refman/8.0/en/create-table.html
|
||||
/// [2]: https://dev.mysql.com/doc/refman/8.0/en/create-index.html
|
||||
|
@ -466,7 +486,7 @@ impl fmt::Display for ColumnDef {
|
|||
/// they are allowed to be named. The specification distinguishes between
|
||||
/// constraints (NOT NULL, UNIQUE, PRIMARY KEY, and CHECK), which can be named
|
||||
/// and can appear in any order, and other options (DEFAULT, GENERATED), which
|
||||
/// cannot be named and must appear in a fixed order. PostgreSQL, however,
|
||||
/// cannot be named and must appear in a fixed order. `PostgreSQL`, however,
|
||||
/// allows preceding any option with `CONSTRAINT <name>`, even those that are
|
||||
/// not really constraints, like NULL and DEFAULT. MSSQL is less permissive,
|
||||
/// allowing DEFAULT, UNIQUE, PRIMARY KEY and CHECK to be named, but not NULL or
|
||||
|
|
|
@ -3205,9 +3205,22 @@ impl<'a> Parser<'a> {
|
|||
new_partitions: partitions,
|
||||
}
|
||||
} else {
|
||||
let _ = self.parse_keyword(Keyword::COLUMN);
|
||||
let column_keyword = self.parse_keyword(Keyword::COLUMN);
|
||||
|
||||
let if_not_exists = if dialect_of!(self is PostgreSqlDialect | BigQueryDialect | GenericDialect)
|
||||
{
|
||||
self.parse_keywords(&[Keyword::IF, Keyword::NOT, Keyword::EXISTS])
|
||||
|| if_not_exists
|
||||
} else {
|
||||
false
|
||||
};
|
||||
|
||||
let column_def = self.parse_column_def()?;
|
||||
AlterTableOperation::AddColumn { column_def }
|
||||
AlterTableOperation::AddColumn {
|
||||
column_keyword,
|
||||
if_not_exists,
|
||||
column_def,
|
||||
}
|
||||
}
|
||||
}
|
||||
} else if self.parse_keyword(Keyword::RENAME) {
|
||||
|
@ -5858,7 +5871,6 @@ mod tests {
|
|||
|
||||
#[cfg(test)]
|
||||
mod test_parse_data_type {
|
||||
|
||||
use crate::ast::{
|
||||
CharLengthUnits, CharacterLength, DataType, ExactNumberInfo, ObjectName, TimezoneInfo,
|
||||
};
|
||||
|
|
|
@ -2528,8 +2528,15 @@ fn parse_alter_table() {
|
|||
match one_statement_parses_to(add_column, "ALTER TABLE tab ADD COLUMN foo TEXT") {
|
||||
Statement::AlterTable {
|
||||
name,
|
||||
operation: AlterTableOperation::AddColumn { column_def },
|
||||
operation:
|
||||
AlterTableOperation::AddColumn {
|
||||
column_keyword,
|
||||
if_not_exists,
|
||||
column_def,
|
||||
},
|
||||
} => {
|
||||
assert!(column_keyword);
|
||||
assert!(!if_not_exists);
|
||||
assert_eq!("tab", name.to_string());
|
||||
assert_eq!("foo", column_def.name.to_string());
|
||||
assert_eq!("TEXT", column_def.data_type.to_string());
|
||||
|
@ -2567,6 +2574,66 @@ fn parse_alter_table() {
|
|||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn parse_alter_table_add_column() {
|
||||
match verified_stmt("ALTER TABLE tab ADD foo TEXT") {
|
||||
Statement::AlterTable {
|
||||
operation: AlterTableOperation::AddColumn { column_keyword, .. },
|
||||
..
|
||||
} => {
|
||||
assert!(!column_keyword);
|
||||
}
|
||||
_ => unreachable!(),
|
||||
};
|
||||
|
||||
match verified_stmt("ALTER TABLE tab ADD COLUMN foo TEXT") {
|
||||
Statement::AlterTable {
|
||||
operation: AlterTableOperation::AddColumn { column_keyword, .. },
|
||||
..
|
||||
} => {
|
||||
assert!(column_keyword);
|
||||
}
|
||||
_ => unreachable!(),
|
||||
};
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn parse_alter_table_add_column_if_not_exists() {
|
||||
let dialects = TestedDialects {
|
||||
dialects: vec![
|
||||
Box::new(PostgreSqlDialect {}),
|
||||
Box::new(BigQueryDialect {}),
|
||||
Box::new(GenericDialect {}),
|
||||
],
|
||||
};
|
||||
|
||||
match dialects.verified_stmt("ALTER TABLE tab ADD IF NOT EXISTS foo TEXT") {
|
||||
Statement::AlterTable {
|
||||
operation: AlterTableOperation::AddColumn { if_not_exists, .. },
|
||||
..
|
||||
} => {
|
||||
assert!(if_not_exists);
|
||||
}
|
||||
_ => unreachable!(),
|
||||
};
|
||||
|
||||
match dialects.verified_stmt("ALTER TABLE tab ADD COLUMN IF NOT EXISTS foo TEXT") {
|
||||
Statement::AlterTable {
|
||||
operation:
|
||||
AlterTableOperation::AddColumn {
|
||||
column_keyword,
|
||||
if_not_exists,
|
||||
..
|
||||
},
|
||||
..
|
||||
} => {
|
||||
assert!(column_keyword);
|
||||
assert!(if_not_exists);
|
||||
}
|
||||
_ => unreachable!(),
|
||||
};
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn parse_alter_table_constraints() {
|
||||
check_one("CONSTRAINT address_pkey PRIMARY KEY (address_id)");
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue