Implement ALTER TABLE DROP COLUMN (#148)

This implements `DROP [ COLUMN ] [ IF EXISTS ] column_name [ CASCADE ]`
sub-command of `ALTER TABLE`, which is what PostgreSQL supports https://www.postgresql.org/docs/12/sql-altertable.html
(except for the RESTRICT option)

Co-authored-by: Nickolay Ponomarev <asqueella@gmail.com>
This commit is contained in:
Jovansonlee Cesar 2020-06-17 04:39:52 +08:00 committed by GitHub
parent faeb7d440a
commit 26361fd854
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
4 changed files with 62 additions and 1 deletions

View file

@ -31,6 +31,7 @@ Check https://github.com/andygrove/sqlparser-rs/commits/master for undocumented
- Support bitwise AND (`&`), OR (`|`), XOR (`^`) (#181) - thanks @Dandandan! - Support bitwise AND (`&`), OR (`|`), XOR (`^`) (#181) - thanks @Dandandan!
- Add serde support to AST structs and enums (#196) - thanks @panarch! - Add serde support to AST structs and enums (#196) - thanks @panarch!
- Support `ALTER TABLE ADD COLUMN`, `RENAME COLUMN`, and `RENAME TO` (#203) - thanks @mashuai! - Support `ALTER TABLE ADD COLUMN`, `RENAME COLUMN`, and `RENAME TO` (#203) - thanks @mashuai!
- Support `ALTER TABLE DROP COLUMN` (#148) - thanks @ivanceras!
### Fixed ### Fixed
- Report an error for unterminated string literals (#165) - Report an error for unterminated string literals (#165)

View file

@ -27,6 +27,12 @@ pub enum AlterTableOperation {
AddColumn { column_def: ColumnDef }, AddColumn { column_def: ColumnDef },
/// TODO: implement `DROP CONSTRAINT <name>` /// TODO: implement `DROP CONSTRAINT <name>`
DropConstraint { name: Ident }, DropConstraint { name: Ident },
/// `DROP [ COLUMN ] [ IF EXISTS ] <column_name> [ CASCADE ]`
DropColumn {
column_name: Ident,
if_exists: bool,
cascade: bool,
},
/// `RENAME [ COLUMN ] <old_column_name> TO <new_column_name>` /// `RENAME [ COLUMN ] <old_column_name> TO <new_column_name>`
RenameColumn { RenameColumn {
old_column_name: Ident, old_column_name: Ident,
@ -44,6 +50,17 @@ impl fmt::Display for AlterTableOperation {
write!(f, "ADD COLUMN {}", column_def.to_string()) write!(f, "ADD COLUMN {}", column_def.to_string())
} }
AlterTableOperation::DropConstraint { name } => write!(f, "DROP CONSTRAINT {}", name), AlterTableOperation::DropConstraint { name } => write!(f, "DROP CONSTRAINT {}", name),
AlterTableOperation::DropColumn {
column_name,
if_exists,
cascade,
} => write!(
f,
"DROP COLUMN {}{}{}",
if *if_exists { "IF EXISTS " } else { "" },
column_name,
if *cascade { " CASCADE" } else { "" }
),
AlterTableOperation::RenameColumn { AlterTableOperation::RenameColumn {
old_column_name, old_column_name,
new_column_name, new_column_name,

View file

@ -1340,8 +1340,18 @@ impl Parser {
new_column_name, new_column_name,
} }
} }
} else if self.parse_keyword(Keyword::DROP) {
let _ = self.parse_keyword(Keyword::COLUMN);
let if_exists = self.parse_keywords(&[Keyword::IF, Keyword::EXISTS]);
let column_name = self.parse_identifier()?;
let cascade = self.parse_keyword(Keyword::CASCADE);
AlterTableOperation::DropColumn {
column_name,
if_exists,
cascade,
}
} else { } else {
return self.expected("ADD or RENAME after ALTER TABLE", self.peek_token()); return self.expected("ADD, RENAME, or DROP after ALTER TABLE", self.peek_token());
}; };
Ok(Statement::AlterTable { Ok(Statement::AlterTable {
name: table_name, name: table_name,

View file

@ -1388,6 +1388,39 @@ fn parse_alter_table_constraints() {
} }
} }
#[test]
fn parse_alter_table_drop_column() {
check_one("DROP COLUMN IF EXISTS is_active CASCADE");
one_statement_parses_to(
"ALTER TABLE tab DROP IF EXISTS is_active CASCADE",
"ALTER TABLE tab DROP COLUMN IF EXISTS is_active CASCADE",
);
one_statement_parses_to(
"ALTER TABLE tab DROP is_active CASCADE",
"ALTER TABLE tab DROP COLUMN is_active CASCADE",
);
fn check_one(constraint_text: &str) {
match verified_stmt(&format!("ALTER TABLE tab {}", constraint_text)) {
Statement::AlterTable {
name,
operation:
AlterTableOperation::DropColumn {
column_name,
if_exists,
cascade,
},
} => {
assert_eq!("tab", name.to_string());
assert_eq!("is_active", column_name.to_string());
assert_eq!(true, if_exists);
assert_eq!(true, cascade);
}
_ => unreachable!(),
}
}
}
#[test] #[test]
fn parse_bad_constraint() { fn parse_bad_constraint() {
let res = parse_sql_statements("ALTER TABLE tab ADD"); let res = parse_sql_statements("ALTER TABLE tab ADD");