From 82074bf62c3b548865645150ece635608ce5c721 Mon Sep 17 00:00:00 2001 From: sabir-akhadov-localstack Date: Thu, 15 Oct 2026 12:25:43 +0200 Subject: [PATCH 1/3] Snowflake: Support ALTER TABLE ADD COLUMN IF NOT EXISTS Co-Authored-By: Przemyslaw Denkiewicz Co-Authored-By: Claude Opus 5.5 --- src/dialect/bigquery.rs | 5 +++++ src/dialect/duckdb.rs | 5 +++++ src/dialect/generic.rs | 4 ++++ src/dialect/mod.rs | 10 ++++++++++ src/dialect/postgresql.rs | 5 +++++ src/dialect/snowflake.rs | 5 +++++ src/parser/mod.rs | 3 +-- tests/sqlparser_common.rs | 7 +------ 8 files changed, 36 insertions(+), 8 deletions(-) diff --git a/src/dialect/bigquery.rs b/src/dialect/bigquery.rs index d34be9a40c..b29ac69fa8 100644 --- a/src/dialect/bigquery.rs +++ b/src/dialect/bigquery.rs @@ -179,4 +179,9 @@ impl Dialect for BigQueryDialect { fn supports_comma_separated_trim(&self) -> bool { true } + + /// See + fn supports_add_column_if_not_exists(&self) -> bool { + true + } } diff --git a/src/dialect/duckdb.rs b/src/dialect/duckdb.rs index 28ee240260..f24c81a6d0 100644 --- a/src/dialect/duckdb.rs +++ b/src/dialect/duckdb.rs @@ -146,4 +146,9 @@ impl Dialect for DuckDbDialect { fn supports_nested_comments(&self) -> bool { true } + + /// See + fn supports_add_column_if_not_exists(&self) -> bool { + true + } } diff --git a/src/dialect/generic.rs b/src/dialect/generic.rs index 09a5518595..8bb91508bb 100644 --- a/src/dialect/generic.rs +++ b/src/dialect/generic.rs @@ -332,4 +332,8 @@ impl Dialect for GenericDialect { fn supports_alter_column_position(&self) -> bool { true } + + fn supports_add_column_if_not_exists(&self) -> bool { + true + } } diff --git a/src/dialect/mod.rs b/src/dialect/mod.rs index f57907e1c1..f0bb1ae64f 100644 --- a/src/dialect/mod.rs +++ b/src/dialect/mod.rs @@ -1617,6 +1617,16 @@ pub trait Dialect: Debug + Any { false } + /// Returns true if the dialect supports `IF NOT EXISTS` in + /// `ALTER TABLE ... ADD [COLUMN]`. + /// Example: + /// ```sql + /// ALTER TABLE tbl ADD COLUMN IF NOT EXISTS c INT + /// ``` + fn supports_add_column_if_not_exists(&self) -> bool { + false + } + /// Returns true if the dialect considers the specified ident as a function /// that returns an identifier. Typically used to generate identifiers /// programmatically. diff --git a/src/dialect/postgresql.rs b/src/dialect/postgresql.rs index 3bec6ceba3..fce93a85db 100644 --- a/src/dialect/postgresql.rs +++ b/src/dialect/postgresql.rs @@ -368,4 +368,9 @@ impl Dialect for PostgreSqlDialect { fn supports_comment_optimizer_hint(&self) -> bool { true } + + /// See + fn supports_add_column_if_not_exists(&self) -> bool { + true + } } diff --git a/src/dialect/snowflake.rs b/src/dialect/snowflake.rs index 3ebc168645..78bc834680 100644 --- a/src/dialect/snowflake.rs +++ b/src/dialect/snowflake.rs @@ -721,6 +721,11 @@ impl Dialect for SnowflakeDialect { fn supports_comma_separated_trim(&self) -> bool { true } + + /// See + fn supports_add_column_if_not_exists(&self) -> bool { + true + } } // Peeks ahead to identify tokens that are expected after diff --git a/src/parser/mod.rs b/src/parser/mod.rs index 6daad0f6e5..65c78d9b24 100644 --- a/src/parser/mod.rs +++ b/src/parser/mod.rs @@ -10818,8 +10818,7 @@ impl<'a> Parser<'a> { } else { let column_keyword = self.parse_keyword(Keyword::COLUMN); - let if_not_exists = if dialect_of!(self is PostgreSqlDialect | BigQueryDialect | DuckDbDialect | GenericDialect) - { + let if_not_exists = if self.dialect.supports_add_column_if_not_exists() { self.parse_keywords(&[Keyword::IF, Keyword::NOT, Keyword::EXISTS]) || if_not_exists } else { diff --git a/tests/sqlparser_common.rs b/tests/sqlparser_common.rs index ea542b5020..2e3922ef15 100644 --- a/tests/sqlparser_common.rs +++ b/tests/sqlparser_common.rs @@ -5453,12 +5453,7 @@ fn parse_alter_table_add_column() { #[test] fn parse_alter_table_add_column_if_not_exists() { - let dialects = TestedDialects::new(vec![ - Box::new(PostgreSqlDialect {}), - Box::new(BigQueryDialect {}), - Box::new(GenericDialect {}), - Box::new(DuckDbDialect {}), - ]); + let dialects = all_dialects_where(|d| d.supports_add_column_if_not_exists()); match alter_table_op(dialects.verified_stmt("ALTER TABLE tab ADD IF NOT EXISTS foo TEXT")) { AlterTableOperation::AddColumn { if_not_exists, .. } => { From 98d242c987ac005d29f8e5f9bbf7eecc09816725 Mon Sep 17 00:00:00 2001 From: sabir-akhadov-localstack Date: Thu, 15 Oct 2026 12:29:08 +0200 Subject: [PATCH 2/3] Use stable DuckDB docs link Co-Authored-By: Claude Opus 5.5 --- src/dialect/duckdb.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/dialect/duckdb.rs b/src/dialect/duckdb.rs index f24c81a6d0..f3b44bb03d 100644 --- a/src/dialect/duckdb.rs +++ b/src/dialect/duckdb.rs @@ -147,7 +147,7 @@ impl Dialect for DuckDbDialect { true } - /// See + /// See fn supports_add_column_if_not_exists(&self) -> bool { true } From 4087bc831a61085eb6da20c8be55d8392a53c8c8 Mon Sep 17 00:00:00 2001 From: sabir-akhadov-localstack Date: Thu, 15 Oct 2026 14:25:54 +0200 Subject: [PATCH 3/3] Clarify supports_add_column_if_not_exists doc Co-Authored-By: Claude Opus 5.5 --- src/dialect/mod.rs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/dialect/mod.rs b/src/dialect/mod.rs index f0bb1ae64f..6ddb239e39 100644 --- a/src/dialect/mod.rs +++ b/src/dialect/mod.rs @@ -1617,8 +1617,7 @@ pub trait Dialect: Debug + Any { false } - /// Returns true if the dialect supports `IF NOT EXISTS` in - /// `ALTER TABLE ... ADD [COLUMN]`. + /// Returns true if the dialect supports `ALTER TABLE ... ADD [COLUMN] IF NOT EXISTS `. /// Example: /// ```sql /// ALTER TABLE tbl ADD COLUMN IF NOT EXISTS c INT