Skip to content

Commit 36b0974

Browse files
committed
Snowflake: accept bare column ALTER ... COMMENT continuation (COLUMN optional)
1 parent 988cd0a commit 36b0974

2 files changed

Lines changed: 56 additions & 2 deletions

File tree

src/parser/mod.rs

Lines changed: 17 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10878,6 +10878,18 @@ impl<'a> Parser<'a> {
1087810878
Ok(AlterTableOperation::AlterSortKey { columns })
1087910879
}
1088010880

10881+
/// Peek whether the upcoming tokens are a bare `<identifier> COMMENT ...`
10882+
/// continuation of a comma-separated `ALTER COLUMN ... COMMENT` list, i.e.
10883+
/// with the `COLUMN` keyword omitted. This shape is unambiguous against
10884+
/// every other `ALTER TABLE` operation, which are all keyword-led.
10885+
fn peek_bare_column_comment_continuation(&self) -> bool {
10886+
matches!(self.peek_nth_token(0).token, Token::Word(_))
10887+
&& matches!(
10888+
self.peek_nth_token(1).token,
10889+
Token::Word(w) if w.keyword == Keyword::COMMENT
10890+
)
10891+
}
10892+
1088110893
/// Parse a single `ALTER TABLE` operation and return an `AlterTableOperation`.
1088210894
pub fn parse_alter_table_operation(&mut self) -> Result<AlterTableOperation, ParserError> {
1088310895
let operation = if self.parse_keyword(Keyword::ADD) {
@@ -11191,11 +11203,14 @@ impl<'a> Parser<'a> {
1119111203
column_position,
1119211204
}
1119311205
} else if self.dialect.supports_alter_column_comment()
11194-
&& self.parse_keyword(Keyword::COLUMN)
11206+
&& (self.parse_keyword(Keyword::COLUMN)
11207+
|| self.peek_bare_column_comment_continuation())
1119511208
{
1119611209
// Continuation of a comma-separated `ALTER COLUMN ... COMMENT` list,
1119711210
// e.g. `... ALTER COLUMN c1 COMMENT 's1', COLUMN c2 COMMENT 's2'`.
11198-
// The second and later items carry `COLUMN` without a leading `ALTER`.
11211+
// The second and later items carry `COLUMN` without a leading `ALTER`,
11212+
// and Snowflake also accepts the bare form with `COLUMN` omitted:
11213+
// `... ALTER c1 COMMENT 's1', c2 COMMENT 's2'`.
1119911214
let column_name = self.parse_identifier()?;
1120011215
self.expect_keyword_is(Keyword::COMMENT)?;
1120111216
AlterTableOperation::AlterColumn {

tests/sqlparser_snowflake.rs

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2084,6 +2084,45 @@ fn test_alter_table_alter_column_comment() {
20842084
}
20852085
_ => unreachable!(),
20862086
}
2087+
2088+
// Bare multi-column form: `COLUMN` omitted on every clause (the shape dbt
2089+
// `persist_docs` emits). Canonicalises to the full `ALTER COLUMN` spelling.
2090+
let sql = "ALTER TABLE tab ALTER \"ID\" COMMENT 's1', \"NAME\" COMMENT $$$$";
2091+
let canonical = "ALTER TABLE tab ALTER COLUMN \"ID\" COMMENT 's1', ALTER COLUMN \"NAME\" COMMENT ''";
2092+
match snowflake().one_statement_parses_to(sql, canonical) {
2093+
Statement::AlterTable(AlterTable { operations, .. }) => {
2094+
assert_eq!(operations.len(), 2);
2095+
match (&operations[0], &operations[1]) {
2096+
(
2097+
AlterTableOperation::AlterColumn {
2098+
column_name: n1,
2099+
op: AlterColumnOperation::Comment { comment: c1 },
2100+
},
2101+
AlterTableOperation::AlterColumn {
2102+
column_name: n2,
2103+
op: AlterColumnOperation::Comment { comment: c2 },
2104+
},
2105+
) => {
2106+
assert_eq!(n1.to_string(), "\"ID\"");
2107+
assert_eq!(c1, "s1");
2108+
assert_eq!(n2.to_string(), "\"NAME\"");
2109+
assert_eq!(c2, "");
2110+
}
2111+
_ => unreachable!(),
2112+
}
2113+
}
2114+
_ => unreachable!(),
2115+
}
2116+
2117+
// Mixed form: `COLUMN` on the first clause, omitted on the second.
2118+
let sql = "ALTER TABLE tab ALTER COLUMN c1 COMMENT 's1', c2 COMMENT 's2'";
2119+
let canonical = "ALTER TABLE tab ALTER COLUMN c1 COMMENT 's1', ALTER COLUMN c2 COMMENT 's2'";
2120+
match snowflake().one_statement_parses_to(sql, canonical) {
2121+
Statement::AlterTable(AlterTable { operations, .. }) => {
2122+
assert_eq!(operations.len(), 2);
2123+
}
2124+
_ => unreachable!(),
2125+
}
20872126
}
20882127

20892128
#[test]

0 commit comments

Comments
 (0)