Skip to content

Commit f73a330

Browse files
committed
Add support for ALTER COLUMN TYPE in Redshift
1 parent 3bc9423 commit f73a330

File tree

6 files changed

+41
-36
lines changed

6 files changed

+41
-36
lines changed

src/ast/ddl.rs

Lines changed: 14 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -893,7 +893,10 @@ pub enum AlterColumnOperation {
893893
data_type: DataType,
894894
/// PostgreSQL specific
895895
using: Option<Expr>,
896+
/// Whether the statement included the optional `SET DATA` keywords
897+
had_set: bool,
896898
},
899+
897900
/// `ADD GENERATED { ALWAYS | BY DEFAULT } AS IDENTITY [ ( sequence_options ) ]`
898901
///
899902
/// Note: this is a PostgreSQL-specific operation.
@@ -914,12 +917,19 @@ impl fmt::Display for AlterColumnOperation {
914917
AlterColumnOperation::DropDefault => {
915918
write!(f, "DROP DEFAULT")
916919
}
917-
AlterColumnOperation::SetDataType { data_type, using } => {
920+
AlterColumnOperation::SetDataType {
921+
data_type,
922+
using,
923+
had_set,
924+
} => {
925+
if *had_set {
926+
write!(f, "SET DATA ")?;
927+
}
928+
write!(f, "TYPE {data_type}")?;
918929
if let Some(expr) = using {
919-
write!(f, "SET DATA TYPE {data_type} USING {expr}")
920-
} else {
921-
write!(f, "SET DATA TYPE {data_type}")
930+
write!(f, " USING {expr}")?;
922931
}
932+
Ok(())
923933
}
924934
AlterColumnOperation::AddGenerated {
925935
generated_as,

src/ast/spans.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -924,6 +924,7 @@ impl Spanned for AlterColumnOperation {
924924
AlterColumnOperation::SetDataType {
925925
data_type: _,
926926
using,
927+
had_set: _,
927928
} => using.as_ref().map_or(Span::empty(), |u| u.span()),
928929
AlterColumnOperation::AddGenerated { .. } => Span::empty(),
929930
}

src/parser/mod.rs

Lines changed: 18 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -8734,16 +8734,10 @@ impl<'a> Parser<'a> {
87348734
}
87358735
} else if self.parse_keywords(&[Keyword::DROP, Keyword::DEFAULT]) {
87368736
AlterColumnOperation::DropDefault {}
8737-
} else if self.parse_keywords(&[Keyword::SET, Keyword::DATA, Keyword::TYPE])
8738-
|| (is_postgresql && self.parse_keyword(Keyword::TYPE))
8739-
{
8740-
let data_type = self.parse_data_type()?;
8741-
let using = if is_postgresql && self.parse_keyword(Keyword::USING) {
8742-
Some(self.parse_expr()?)
8743-
} else {
8744-
None
8745-
};
8746-
AlterColumnOperation::SetDataType { data_type, using }
8737+
} else if self.parse_keywords(&[Keyword::SET, Keyword::DATA, Keyword::TYPE]) {
8738+
self.parse_set_data_type(true)?
8739+
} else if self.parse_keyword(Keyword::TYPE) {
8740+
self.parse_set_data_type(false)?
87478741
} else if self.parse_keywords(&[Keyword::ADD, Keyword::GENERATED]) {
87488742
let generated_as = if self.parse_keyword(Keyword::ALWAYS) {
87498743
Some(GeneratedAs::Always)
@@ -8909,6 +8903,20 @@ impl<'a> Parser<'a> {
89098903
Ok(operation)
89108904
}
89118905

8906+
fn parse_set_data_type(&mut self, had_set: bool) -> Result<AlterColumnOperation, ParserError> {
8907+
let data_type = self.parse_data_type()?;
8908+
let using = if self.parse_keyword(Keyword::USING) {
8909+
Some(self.parse_expr()?)
8910+
} else {
8911+
None
8912+
};
8913+
Ok(AlterColumnOperation::SetDataType {
8914+
data_type,
8915+
using,
8916+
had_set,
8917+
})
8918+
}
8919+
89128920
fn parse_part_or_partition(&mut self) -> Result<Partition, ParserError> {
89138921
let keyword = self.expect_one_of_keywords(&[Keyword::PART, Keyword::PARTITION])?;
89148922
match keyword {

tests/sqlparser_common.rs

Lines changed: 1 addition & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -5046,7 +5046,6 @@ fn parse_alter_table_alter_column() {
50465046

50475047
#[test]
50485048
fn parse_alter_table_alter_column_type() {
5049-
let alter_stmt = "ALTER TABLE tab";
50505049
match alter_table_op(verified_stmt(
50515050
"ALTER TABLE tab ALTER COLUMN is_active SET DATA TYPE TEXT",
50525051
)) {
@@ -5057,28 +5056,12 @@ fn parse_alter_table_alter_column_type() {
50575056
AlterColumnOperation::SetDataType {
50585057
data_type: DataType::Text,
50595058
using: None,
5059+
had_set: true,
50605060
}
50615061
);
50625062
}
50635063
_ => unreachable!(),
50645064
}
5065-
5066-
let dialect = TestedDialects::new(vec![Box::new(GenericDialect {})]);
5067-
5068-
let res =
5069-
dialect.parse_sql_statements(&format!("{alter_stmt} ALTER COLUMN is_active TYPE TEXT"));
5070-
assert_eq!(
5071-
ParserError::ParserError("Expected: SET/DROP NOT NULL, SET DEFAULT, or SET DATA TYPE after ALTER COLUMN, found: TYPE".to_string()),
5072-
res.unwrap_err()
5073-
);
5074-
5075-
let res = dialect.parse_sql_statements(&format!(
5076-
"{alter_stmt} ALTER COLUMN is_active SET DATA TYPE TEXT USING 'text'"
5077-
));
5078-
assert_eq!(
5079-
ParserError::ParserError("Expected: end of statement, found: USING".to_string()),
5080-
res.unwrap_err()
5081-
);
50825065
}
50835066

50845067
#[test]

tests/sqlparser_postgres.rs

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -764,10 +764,7 @@ fn parse_drop_extension() {
764764

765765
#[test]
766766
fn parse_alter_table_alter_column() {
767-
pg().one_statement_parses_to(
768-
"ALTER TABLE tab ALTER COLUMN is_active TYPE TEXT USING 'text'",
769-
"ALTER TABLE tab ALTER COLUMN is_active SET DATA TYPE TEXT USING 'text'",
770-
);
767+
pg().verified_stmt("ALTER TABLE tab ALTER COLUMN is_active TYPE TEXT USING 'text'");
771768

772769
match alter_table_op(
773770
pg().verified_stmt(
@@ -783,6 +780,7 @@ fn parse_alter_table_alter_column() {
783780
AlterColumnOperation::SetDataType {
784781
data_type: DataType::Text,
785782
using: Some(using_expr),
783+
had_set: true,
786784
}
787785
);
788786
}

tests/sqlparser_redshift.rs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -402,3 +402,8 @@ fn parse_extract_single_quotes() {
402402
fn parse_string_literal_backslash_escape() {
403403
redshift().one_statement_parses_to(r#"SELECT 'l\'auto'"#, "SELECT 'l''auto'");
404404
}
405+
406+
#[test]
407+
fn test_alter_column_type() {
408+
redshift().verified_stmt("ALTER TABLE customers ALTER COLUMN email TYPE TEXT");
409+
}

0 commit comments

Comments
 (0)