ALTER TABLE DROP {COLUMN|CONSTRAINT} RESTRICT (#1651)

This commit is contained in:
Stepan Koltsov 2025-01-10 00:29:34 +00:00 committed by GitHub
parent 5a761dd6db
commit c54ba4dc41
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
4 changed files with 48 additions and 42 deletions

View file

@ -115,13 +115,13 @@ pub enum AlterTableOperation {
DropConstraint {
if_exists: bool,
name: Ident,
cascade: bool,
drop_behavior: Option<DropBehavior>,
},
/// `DROP [ COLUMN ] [ IF EXISTS ] <column_name> [ CASCADE ]`
DropColumn {
column_name: Ident,
if_exists: bool,
cascade: bool,
drop_behavior: Option<DropBehavior>,
},
/// `ATTACH PART|PARTITION <partition_expr>`
/// Note: this is a ClickHouse-specific operation, please refer to
@ -451,27 +451,35 @@ impl fmt::Display for AlterTableOperation {
AlterTableOperation::DropConstraint {
if_exists,
name,
cascade,
drop_behavior,
} => {
write!(
f,
"DROP CONSTRAINT {}{}{}",
if *if_exists { "IF EXISTS " } else { "" },
name,
if *cascade { " CASCADE" } else { "" },
match drop_behavior {
None => "",
Some(DropBehavior::Restrict) => " RESTRICT",
Some(DropBehavior::Cascade) => " CASCADE",
}
)
}
AlterTableOperation::DropPrimaryKey => write!(f, "DROP PRIMARY KEY"),
AlterTableOperation::DropColumn {
column_name,
if_exists,
cascade,
drop_behavior,
} => write!(
f,
"DROP COLUMN {}{}{}",
if *if_exists { "IF EXISTS " } else { "" },
column_name,
if *cascade { " CASCADE" } else { "" }
match drop_behavior {
None => "",
Some(DropBehavior::Restrict) => " RESTRICT",
Some(DropBehavior::Cascade) => " CASCADE",
}
),
AlterTableOperation::AttachPartition { partition } => {
write!(f, "ATTACH {partition}")

View file

@ -961,12 +961,12 @@ impl Spanned for AlterTableOperation {
AlterTableOperation::DropConstraint {
if_exists: _,
name,
cascade: _,
drop_behavior: _,
} => name.span,
AlterTableOperation::DropColumn {
column_name,
if_exists: _,
cascade: _,
drop_behavior: _,
} => column_name.span,
AlterTableOperation::AttachPartition { partition } => partition.span(),
AlterTableOperation::DetachPartition { partition } => partition.span(),

View file

@ -7680,11 +7680,11 @@ impl<'a> Parser<'a> {
} else if self.parse_keyword(Keyword::CONSTRAINT) {
let if_exists = self.parse_keywords(&[Keyword::IF, Keyword::EXISTS]);
let name = self.parse_identifier()?;
let cascade = self.parse_keyword(Keyword::CASCADE);
let drop_behavior = self.parse_optional_drop_behavior();
AlterTableOperation::DropConstraint {
if_exists,
name,
cascade,
drop_behavior,
}
} else if self.parse_keywords(&[Keyword::PRIMARY, Keyword::KEY])
&& dialect_of!(self is MySqlDialect | GenericDialect)
@ -7702,11 +7702,11 @@ impl<'a> Parser<'a> {
let _ = self.parse_keyword(Keyword::COLUMN); // [ COLUMN ]
let if_exists = self.parse_keywords(&[Keyword::IF, Keyword::EXISTS]);
let column_name = self.parse_identifier()?;
let cascade = self.parse_keyword(Keyword::CASCADE);
let drop_behavior = self.parse_optional_drop_behavior();
AlterTableOperation::DropColumn {
column_name,
if_exists,
cascade,
drop_behavior,
}
}
} else if self.parse_keyword(Keyword::PARTITION) {

View file

@ -4388,7 +4388,9 @@ fn parse_alter_table_constraints() {
#[test]
fn parse_alter_table_drop_column() {
check_one("DROP COLUMN IF EXISTS is_active");
check_one("DROP COLUMN IF EXISTS is_active CASCADE");
check_one("DROP COLUMN IF EXISTS is_active RESTRICT");
one_statement_parses_to(
"ALTER TABLE tab DROP IF EXISTS is_active CASCADE",
"ALTER TABLE tab DROP COLUMN IF EXISTS is_active CASCADE",
@ -4403,11 +4405,15 @@ fn parse_alter_table_drop_column() {
AlterTableOperation::DropColumn {
column_name,
if_exists,
cascade,
drop_behavior,
} => {
assert_eq!("is_active", column_name.to_string());
assert!(if_exists);
assert!(cascade);
match drop_behavior {
None => assert!(constraint_text.ends_with(" is_active")),
Some(DropBehavior::Restrict) => assert!(constraint_text.ends_with(" RESTRICT")),
Some(DropBehavior::Cascade) => assert!(constraint_text.ends_with(" CASCADE")),
}
}
_ => unreachable!(),
}
@ -4497,37 +4503,29 @@ fn parse_alter_table_alter_column_type() {
#[test]
fn parse_alter_table_drop_constraint() {
let alter_stmt = "ALTER TABLE tab";
match alter_table_op(verified_stmt(
"ALTER TABLE tab DROP CONSTRAINT constraint_name CASCADE",
)) {
AlterTableOperation::DropConstraint {
name: constr_name,
if_exists,
cascade,
} => {
assert_eq!("constraint_name", constr_name.to_string());
assert!(!if_exists);
assert!(cascade);
check_one("DROP CONSTRAINT IF EXISTS constraint_name");
check_one("DROP CONSTRAINT IF EXISTS constraint_name RESTRICT");
check_one("DROP CONSTRAINT IF EXISTS constraint_name CASCADE");
fn check_one(constraint_text: &str) {
match alter_table_op(verified_stmt(&format!("ALTER TABLE tab {constraint_text}"))) {
AlterTableOperation::DropConstraint {
name: constr_name,
if_exists,
drop_behavior,
} => {
assert_eq!("constraint_name", constr_name.to_string());
assert!(if_exists);
match drop_behavior {
None => assert!(constraint_text.ends_with(" constraint_name")),
Some(DropBehavior::Restrict) => assert!(constraint_text.ends_with(" RESTRICT")),
Some(DropBehavior::Cascade) => assert!(constraint_text.ends_with(" CASCADE")),
}
}
_ => unreachable!(),
}
_ => unreachable!(),
}
match alter_table_op(verified_stmt(
"ALTER TABLE tab DROP CONSTRAINT IF EXISTS constraint_name",
)) {
AlterTableOperation::DropConstraint {
name: constr_name,
if_exists,
cascade,
} => {
assert_eq!("constraint_name", constr_name.to_string());
assert!(if_exists);
assert!(!cascade);
}
_ => unreachable!(),
}
let res = parse_sql_statements(&format!("{alter_stmt} DROP CONSTRAINT is_active TEXT"));
let res = parse_sql_statements("ALTER TABLE tab DROP CONSTRAINT is_active TEXT");
assert_eq!(
ParserError::ParserError("Expected: end of statement, found: TEXT".to_string()),
res.unwrap_err()