agent_patch
runs/2026-02-21__03-36-16__gpt-5-1-codex-mini/flux-pr-1918/flux-pr-1918.1-of-1.2026-02-21__03-36-16__gpt-5-1-codex-mini/agent-logs/agent.patch
9711 bytes
diff --git a/tmp/agent-patch-flux-pr-1918.1-of-1.2026-02-21__03-36-16__gpt-5-1-codex-mini/app/src/ast/ddl.rs b/app/src/ast/ddl.rs
index 7e46a59..f62491e 100644
--- a/tmp/agent-patch-flux-pr-1918.1-of-1.2026-02-21__03-36-16__gpt-5-1-codex-mini/app/src/ast/ddl.rs
+++ b/app/src/ast/ddl.rs
@@ -140,10 +140,10 @@ pub enum AlterTableOperation {
name: Ident,
drop_behavior: Option<DropBehavior>,
},
- /// `DROP [ COLUMN ] [ IF EXISTS ] <column_name> [ CASCADE ]`
+ /// `DROP [ COLUMN ] [ IF EXISTS ] <column_name> [, ...] [ CASCADE ]`
DropColumn {
has_column_keyword: bool,
- column_name: Ident,
+ column_names: Vec<Ident>,
if_exists: bool,
drop_behavior: Option<DropBehavior>,
},
@@ -631,21 +631,28 @@ impl fmt::Display for AlterTableOperation {
AlterTableOperation::DropIndex { name } => write!(f, "DROP INDEX {name}"),
AlterTableOperation::DropColumn {
has_column_keyword,
- column_name,
+ column_names,
if_exists,
drop_behavior,
- } => write!(
- f,
- "DROP {}{}{}{}",
- if *has_column_keyword { "COLUMN " } else { "" },
- if *if_exists { "IF EXISTS " } else { "" },
- column_name,
- match drop_behavior {
- None => "",
- Some(DropBehavior::Restrict) => " RESTRICT",
- Some(DropBehavior::Cascade) => " CASCADE",
+ } => {
+ write!(f, "DROP ")?;
+ if *has_column_keyword {
+ write!(f, "COLUMN ")?;
}
- ),
+ if *if_exists {
+ write!(f, "IF EXISTS ")?;
+ }
+ write!(f, "{}", display_comma_separated(column_names))?;
+ write!(
+ f,
+ "{}",
+ match drop_behavior {
+ None => "",
+ Some(DropBehavior::Restrict) => " RESTRICT",
+ Some(DropBehavior::Cascade) => " CASCADE",
+ }
+ )
+ }
AlterTableOperation::AttachPartition { partition } => {
write!(f, "ATTACH {partition}")
}
diff --git a/tmp/agent-patch-flux-pr-1918.1-of-1.2026-02-21__03-36-16__gpt-5-1-codex-mini/app/src/ast/spans.rs b/app/src/ast/spans.rs
index 1d790ab..423fe4f 100644
--- a/tmp/agent-patch-flux-pr-1918.1-of-1.2026-02-21__03-36-16__gpt-5-1-codex-mini/app/src/ast/spans.rs
+++ b/app/src/ast/spans.rs
@@ -1112,10 +1112,10 @@ impl Spanned for AlterTableOperation {
} => name.span,
AlterTableOperation::DropColumn {
has_column_keyword: _,
- column_name,
+ column_names,
if_exists: _,
drop_behavior: _,
- } => column_name.span,
+ } => union_spans(column_names.iter().map(|name| name.span)),
AlterTableOperation::AttachPartition { partition } => partition.span(),
AlterTableOperation::DetachPartition { partition } => partition.span(),
AlterTableOperation::FreezePartition {
diff --git a/tmp/agent-patch-flux-pr-1918.1-of-1.2026-02-21__03-36-16__gpt-5-1-codex-mini/app/src/dialect/mod.rs b/app/src/dialect/mod.rs
index 3345380..c0b7cf5 100644
--- a/tmp/agent-patch-flux-pr-1918.1-of-1.2026-02-21__03-36-16__gpt-5-1-codex-mini/app/src/dialect/mod.rs
+++ b/app/src/dialect/mod.rs
@@ -494,6 +494,12 @@ pub trait Dialect: Debug + Any {
false
}
+ /// Returns true if the dialect supports dropping multiple columns in a
+ /// single `ALTER TABLE ... DROP COLUMN` clause like `DROP COLUMN a, b`.
+ fn supports_drop_column_list(&self) -> bool {
+ false
+ }
+
/// Returns true if the dialect supports double dot notation for object names
///
/// Example
diff --git a/tmp/agent-patch-flux-pr-1918.1-of-1.2026-02-21__03-36-16__gpt-5-1-codex-mini/app/src/dialect/snowflake.rs b/app/src/dialect/snowflake.rs
index ee770b0..e370cf4 100644
--- a/tmp/agent-patch-flux-pr-1918.1-of-1.2026-02-21__03-36-16__gpt-5-1-codex-mini/app/src/dialect/snowflake.rs
+++ b/app/src/dialect/snowflake.rs
@@ -130,6 +130,10 @@ impl Dialect for SnowflakeDialect {
true
}
+ fn supports_drop_column_list(&self) -> bool {
+ true
+ }
+
fn parse_statement(&self, parser: &mut Parser) -> Option<Result<Statement, ParserError>> {
if parser.parse_keyword(Keyword::BEGIN) {
return Some(parser.parse_begin_exception_end());
diff --git a/tmp/agent-patch-flux-pr-1918.1-of-1.2026-02-21__03-36-16__gpt-5-1-codex-mini/app/src/parser/mod.rs b/app/src/parser/mod.rs
index 32f8a97..ad283e4 100644
--- a/tmp/agent-patch-flux-pr-1918.1-of-1.2026-02-21__03-36-16__gpt-5-1-codex-mini/app/src/parser/mod.rs
+++ b/app/src/parser/mod.rs
@@ -8675,11 +8675,15 @@ impl<'a> Parser<'a> {
} else {
let has_column_keyword = self.parse_keyword(Keyword::COLUMN); // [ COLUMN ]
let if_exists = self.parse_keywords(&[Keyword::IF, Keyword::EXISTS]);
- let column_name = self.parse_identifier()?;
+ let column_names = if self.dialect.supports_drop_column_list() {
+ self.parse_comma_separated(Parser::parse_identifier)?
+ } else {
+ vec![self.parse_identifier()?]
+ };
let drop_behavior = self.parse_optional_drop_behavior();
AlterTableOperation::DropColumn {
has_column_keyword,
- column_name,
+ column_names,
if_exists,
drop_behavior,
}
diff --git a/tmp/agent-patch-flux-pr-1918.1-of-1.2026-02-21__03-36-16__gpt-5-1-codex-mini/app/tests/sqlparser_common.rs b/app/tests/sqlparser_common.rs
index 1bdd302..8405ef5 100644
--- a/tmp/agent-patch-flux-pr-1918.1-of-1.2026-02-21__03-36-16__gpt-5-1-codex-mini/app/tests/sqlparser_common.rs
+++ b/app/tests/sqlparser_common.rs
@@ -5000,11 +5000,12 @@ fn parse_alter_table_drop_column() {
match alter_table_op(verified_stmt(&format!("ALTER TABLE tab {constraint_text}"))) {
AlterTableOperation::DropColumn {
has_column_keyword: true,
- column_name,
+ column_names,
if_exists,
drop_behavior,
} => {
- assert_eq!("is_active", column_name.to_string());
+ assert_eq!(1, column_names.len());
+ assert_eq!("is_active", column_names[0].to_string());
assert!(if_exists);
match drop_behavior {
None => assert!(constraint_text.ends_with(" is_active")),
diff --git a/tmp/agent-patch-flux-pr-1918.1-of-1.2026-02-21__03-36-16__gpt-5-1-codex-mini/app/tests/sqlparser_mysql.rs b/app/tests/sqlparser_mysql.rs
index 9224a00..79e2259 100644
--- a/tmp/agent-patch-flux-pr-1918.1-of-1.2026-02-21__03-36-16__gpt-5-1-codex-mini/app/tests/sqlparser_mysql.rs
+++ b/app/tests/sqlparser_mysql.rs
@@ -2876,7 +2876,7 @@ fn parse_alter_table_with_algorithm() {
vec![
AlterTableOperation::DropColumn {
has_column_keyword: true,
- column_name: Ident::new("password_digest"),
+ column_names: vec![Ident::new("password_digest")],
if_exists: false,
drop_behavior: None,
},
@@ -2924,7 +2924,7 @@ fn parse_alter_table_with_lock() {
vec![
AlterTableOperation::DropColumn {
has_column_keyword: true,
- column_name: Ident::new("password_digest"),
+ column_names: vec![Ident::new("password_digest")],
if_exists: false,
drop_behavior: None,
},
diff --git a/tmp/agent-patch-flux-pr-1918.1-of-1.2026-02-21__03-36-16__gpt-5-1-codex-mini/app/tests/sqlparser_snowflake.rs b/app/tests/sqlparser_snowflake.rs
index 8a1558b..5f47c4a 100644
--- a/tmp/agent-patch-flux-pr-1918.1-of-1.2026-02-21__03-36-16__gpt-5-1-codex-mini/app/tests/sqlparser_snowflake.rs
+++ b/app/tests/sqlparser_snowflake.rs
@@ -1446,6 +1446,34 @@ fn test_array_agg_func() {
}
}
+#[test]
+fn test_snowflake_alter_table_drop_multiple_columns() {
+ let statement = snowflake().verified_stmt(
+ "ALTER TABLE tab DROP COLUMN IF EXISTS col_one, col_two CASCADE",
+ );
+ match statement {
+ Statement::AlterTable { operations, .. } => {
+ assert_eq!(operations.len(), 1);
+ match &operations[0] {
+ AlterTableOperation::DropColumn {
+ column_names,
+ if_exists,
+ drop_behavior,
+ ..
+ } => {
+ assert_eq!(2, column_names.len());
+ assert_eq!("col_one", column_names[0].to_string());
+ assert_eq!("col_two", column_names[1].to_string());
+ assert!(if_exists);
+ assert_eq!(Some(DropBehavior::Cascade), *drop_behavior);
+ }
+ _ => unreachable!(),
+ }
+ }
+ _ => unreachable!(),
+ }
+}
+
fn snowflake() -> TestedDialects {
TestedDialects::new(vec![Box::new(SnowflakeDialect {})])
}