Skip to content

Commit 015caca

Browse files
authored
Redshift alter column type no set (#1912)
1 parent a339822 commit 015caca

File tree

7 files changed

+58
-27
lines changed

7 files changed

+58
-27
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+
/// Set to true if the statement includes the `SET DATA TYPE` 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/dialect/mod.rs

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1060,6 +1060,15 @@ pub trait Dialect: Debug + Any {
10601060
fn supports_space_separated_column_options(&self) -> bool {
10611061
false
10621062
}
1063+
1064+
/// Returns true if the dialect supports the `USING` clause in an `ALTER COLUMN` statement.
1065+
/// Example:
1066+
/// ```sql
1067+
/// ALTER TABLE tbl ALTER COLUMN col SET DATA TYPE <type> USING <exp>`
1068+
/// ```
1069+
fn supports_alter_column_type_using(&self) -> bool {
1070+
false
1071+
}
10631072
}
10641073

10651074
/// This represents the operators for which precedence must be defined

src/dialect/postgresql.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -258,4 +258,8 @@ impl Dialect for PostgreSqlDialect {
258258
fn supports_set_names(&self) -> bool {
259259
true
260260
}
261+
262+
fn supports_alter_column_type_using(&self) -> bool {
263+
true
264+
}
261265
}

src/parser/mod.rs

Lines changed: 20 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,22 @@ 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.dialect.supports_alter_column_type_using()
8909+
&& self.parse_keyword(Keyword::USING)
8910+
{
8911+
Some(self.parse_expr()?)
8912+
} else {
8913+
None
8914+
};
8915+
Ok(AlterColumnOperation::SetDataType {
8916+
data_type,
8917+
using,
8918+
had_set,
8919+
})
8920+
}
8921+
89128922
fn parse_part_or_partition(&mut self) -> Result<Partition, ParserError> {
89138923
let keyword = self.expect_one_of_keywords(&[Keyword::PART, Keyword::PARTITION])?;
89148924
match keyword {

tests/sqlparser_common.rs

Lines changed: 8 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -5057,22 +5057,21 @@ fn parse_alter_table_alter_column_type() {
50575057
AlterColumnOperation::SetDataType {
50585058
data_type: DataType::Text,
50595059
using: None,
5060+
had_set: true,
50605061
}
50615062
);
50625063
}
50635064
_ => unreachable!(),
50645065
}
5066+
verified_stmt(&format!("{alter_stmt} ALTER COLUMN is_active TYPE TEXT"));
50655067

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-
);
5068+
let dialects = all_dialects_where(|d| d.supports_alter_column_type_using());
5069+
dialects.verified_stmt(&format!(
5070+
"{alter_stmt} ALTER COLUMN is_active SET DATA TYPE TEXT USING 'text'"
5071+
));
50745072

5075-
let res = dialect.parse_sql_statements(&format!(
5073+
let dialects = all_dialects_except(|d| d.supports_alter_column_type_using());
5074+
let res = dialects.parse_sql_statements(&format!(
50765075
"{alter_stmt} ALTER COLUMN is_active SET DATA TYPE TEXT USING 'text'"
50775076
));
50785077
assert_eq!(

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
}

0 commit comments

Comments
 (0)