agent_patch
runs/2026-02-28__18-27-22__gpt-5-1-codex-mini/flux-pr-1918/flux-pr-1918.1-of-1.2026-02-28__18-27-22__gpt-5-1-codex-mini/agent-logs/agent.patch
8588 bytes
diff --git a/tmp/agent-patch-flux-pr-1918.1-of-1.2026-02-28__18-27-22__gpt-5-1-codex-mini/app/changelog/0.57.0.md b/app/changelog/0.57.0.md
index 200bb73..d917371 100644
--- a/tmp/agent-patch-flux-pr-1918.1-of-1.2026-02-28__18-27-22__gpt-5-1-codex-mini/app/changelog/0.57.0.md
+++ b/app/changelog/0.57.0.md
@@ -64,6 +64,7 @@ This release consists of 39 commits from 19 contributors. See credits at the end
- chore: Replace archived actions-rs/install action [#1876](https://github.com/apache/datafusion-sqlparser-rs/pull/1876) (assignUser)
- Allow `IF NOT EXISTS` after table name for Snowflake [#1881](https://github.com/apache/datafusion-sqlparser-rs/pull/1881) (bombsimon)
- Support `DISTINCT AS { STRUCT | VALUE }` for BigQuery [#1880](https://github.com/apache/datafusion-sqlparser-rs/pull/1880) (bombsimon)
+- Snowflake: parse ALTER TABLE `DROP COLUMN` with multiple columns [#1918](https://github.com/apache/datafusion-sqlparser-rs/pull/1918) (OpenAI Codex)
## Credits
@@ -92,4 +93,3 @@ Thank you to everyone who contributed to this release. Here is a breakdown of co
```
Thank you also to everyone who contributed in other ways such as filing issues, reviewing PRs, and providing feedback on this release.
-
diff --git a/tmp/agent-patch-flux-pr-1918.1-of-1.2026-02-28__18-27-22__gpt-5-1-codex-mini/app/src/ast/ddl.rs b/app/src/ast/ddl.rs
index 7e46a59..a95ba38 100644
--- a/tmp/agent-patch-flux-pr-1918.1-of-1.2026-02-28__18-27-22__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> [, <column_name> ...] [ CASCADE ]`
DropColumn {
has_column_keyword: bool,
- column_name: Ident,
+ column_names: Vec<Ident>,
if_exists: bool,
drop_behavior: Option<DropBehavior>,
},
@@ -631,7 +631,7 @@ 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!(
@@ -639,7 +639,7 @@ impl fmt::Display for AlterTableOperation {
"DROP {}{}{}{}",
if *has_column_keyword { "COLUMN " } else { "" },
if *if_exists { "IF EXISTS " } else { "" },
- column_name,
+ display_comma_separated(column_names),
match drop_behavior {
None => "",
Some(DropBehavior::Restrict) => " RESTRICT",
diff --git a/tmp/agent-patch-flux-pr-1918.1-of-1.2026-02-28__18-27-22__gpt-5-1-codex-mini/app/src/ast/spans.rs b/app/src/ast/spans.rs
index 1d790ab..dcdf3ea 100644
--- a/tmp/agent-patch-flux-pr-1918.1-of-1.2026-02-28__18-27-22__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,
+ } => Span::union_iter(column_names.iter().map(|ident| ident.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-28__18-27-22__gpt-5-1-codex-mini/app/src/parser/mod.rs b/app/src/parser/mod.rs
index 32f8a97..273f719 100644
--- a/tmp/agent-patch-flux-pr-1918.1-of-1.2026-02-28__18-27-22__gpt-5-1-codex-mini/app/src/parser/mod.rs
+++ b/app/src/parser/mod.rs
@@ -8675,11 +8675,16 @@ 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 allow_multiple_columns = dialect_of!(self is SnowflakeDialect);
+ let column_names = if allow_multiple_columns {
+ 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-28__18-27-22__gpt-5-1-codex-mini/app/tests/sqlparser_common.rs b/app/tests/sqlparser_common.rs
index 1bdd302..c1c8484 100644
--- a/tmp/agent-patch-flux-pr-1918.1-of-1.2026-02-28__18-27-22__gpt-5-1-codex-mini/app/tests/sqlparser_common.rs
+++ b/app/tests/sqlparser_common.rs
@@ -5000,11 +5000,11 @@ 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!(vec![Ident::new("is_active")], column_names);
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-28__18-27-22__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-28__18-27-22__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-28__18-27-22__gpt-5-1-codex-mini/app/tests/sqlparser_snowflake.rs b/app/tests/sqlparser_snowflake.rs
index 8a1558b..b181a95 100644
--- a/tmp/agent-patch-flux-pr-1918.1-of-1.2026-02-28__18-27-22__gpt-5-1-codex-mini/app/tests/sqlparser_snowflake.rs
+++ b/app/tests/sqlparser_snowflake.rs
@@ -1646,6 +1646,28 @@ fn test_alter_table_clustering() {
snowflake_and_generic().verified_stmt("ALTER TABLE tbl RESUME RECLUSTER");
}
+#[test]
+fn test_snowflake_drop_multiple_columns() {
+ let sql = "ALTER TABLE tbl DROP COLUMN IF EXISTS col_a, col_b CASCADE";
+ match alter_table_op_with_name(snowflake().verified_stmt(sql), "tbl") {
+ AlterTableOperation::DropColumn {
+ has_column_keyword,
+ column_names,
+ if_exists,
+ drop_behavior,
+ } => {
+ assert!(has_column_keyword);
+ assert_eq!(
+ vec![Ident::new("col_a"), Ident::new("col_b")],
+ column_names
+ );
+ assert!(if_exists);
+ assert_eq!(Some(DropBehavior::Cascade), drop_behavior);
+ }
+ _ => unreachable!(),
+ };
+}
+
#[test]
fn test_alter_iceberg_table() {
snowflake_and_generic().verified_stmt("ALTER ICEBERG TABLE tbl DROP CLUSTERING KEY");