Skip to content

Commit b229246

Browse files
yoavcloudayman-sigma
authored andcommitted
Redshift alter column type no set (apache#1912)
1 parent acd99b9 commit b229246

7 files changed

Lines changed: 58 additions & 27 deletions

File tree

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
@@ -1065,6 +1065,15 @@ pub trait Dialect: Debug + Any {
10651065
fn supports_space_separated_column_options(&self) -> bool {
10661066
false
10671067
}
1068+
1069+
/// Returns true if the dialect supports the `USING` clause in an `ALTER COLUMN` statement.
1070+
/// Example:
1071+
/// ```sql
1072+
/// ALTER TABLE tbl ALTER COLUMN col SET DATA TYPE <type> USING <exp>`
1073+
/// ```
1074+
fn supports_alter_column_type_using(&self) -> bool {
1075+
false
1076+
}
10681077
}
10691078

10701079
/// 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
@@ -8765,16 +8765,10 @@ impl<'a> Parser<'a> {
87658765
}
87668766
} else if self.parse_keywords(&[Keyword::DROP, Keyword::DEFAULT]) {
87678767
AlterColumnOperation::DropDefault {}
8768-
} else if self.parse_keywords(&[Keyword::SET, Keyword::DATA, Keyword::TYPE])
8769-
|| (is_postgresql && self.parse_keyword(Keyword::TYPE))
8770-
{
8771-
let data_type = self.parse_data_type()?;
8772-
let using = if is_postgresql && self.parse_keyword(Keyword::USING) {
8773-
Some(self.parse_expr()?)
8774-
} else {
8775-
None
8776-
};
8777-
AlterColumnOperation::SetDataType { data_type, using }
8768+
} else if self.parse_keywords(&[Keyword::SET, Keyword::DATA, Keyword::TYPE]) {
8769+
self.parse_set_data_type(true)?
8770+
} else if self.parse_keyword(Keyword::TYPE) {
8771+
self.parse_set_data_type(false)?
87788772
} else if self.parse_keywords(&[Keyword::ADD, Keyword::GENERATED]) {
87798773
let generated_as = if self.parse_keyword(Keyword::ALWAYS) {
87808774
Some(GeneratedAs::Always)
@@ -8940,6 +8934,22 @@ impl<'a> Parser<'a> {
89408934
Ok(operation)
89418935
}
89428936

8937+
fn parse_set_data_type(&mut self, had_set: bool) -> Result<AlterColumnOperation, ParserError> {
8938+
let data_type = self.parse_data_type()?;
8939+
let using = if self.dialect.supports_alter_column_type_using()
8940+
&& self.parse_keyword(Keyword::USING)
8941+
{
8942+
Some(self.parse_expr()?)
8943+
} else {
8944+
None
8945+
};
8946+
Ok(AlterColumnOperation::SetDataType {
8947+
data_type,
8948+
using,
8949+
had_set,
8950+
})
8951+
}
8952+
89438953
fn parse_part_or_partition(&mut self) -> Result<Partition, ParserError> {
89448954
let keyword = self.expect_one_of_keywords(&[Keyword::PART, Keyword::PARTITION])?;
89458955
match keyword {

tests/sqlparser_common.rs

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

5067-
let dialect = TestedDialects::new(vec![Box::new(GenericDialect {})]);
5068-
5069-
let res =
5070-
dialect.parse_sql_statements(&format!("{alter_stmt} ALTER COLUMN is_active TYPE TEXT"));
5071-
assert_eq!(
5072-
ParserError::ParserError("Expected: SET/DROP NOT NULL, SET DEFAULT, or SET DATA TYPE after ALTER COLUMN, found: TYPE".to_string()),
5073-
res.unwrap_err()
5074-
);
5069+
let dialects = all_dialects_where(|d| d.supports_alter_column_type_using());
5070+
dialects.verified_stmt(&format!(
5071+
"{alter_stmt} ALTER COLUMN is_active SET DATA TYPE TEXT USING 'text'"
5072+
));
50755073

5076-
let res = dialect.parse_sql_statements(&format!(
5074+
let dialects = all_dialects_except(|d| d.supports_alter_column_type_using());
5075+
let res = dialects.parse_sql_statements(&format!(
50775076
"{alter_stmt} ALTER COLUMN is_active SET DATA TYPE TEXT USING 'text'"
50785077
));
50795078
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)