Skip to content

Commit 7b49c69

Browse files
authored
Support Modify Column for MySQL dialect (#1216)
1 parent 4604628 commit 7b49c69

File tree

4 files changed

+135
-0
lines changed

4 files changed

+135
-0
lines changed

src/ast/ddl.rs

+24
Original file line numberDiff line numberDiff line change
@@ -134,6 +134,14 @@ pub enum AlterTableOperation {
134134
/// MySQL `ALTER TABLE` only [FIRST | AFTER column_name]
135135
column_position: Option<MySQLColumnPosition>,
136136
},
137+
// CHANGE [ COLUMN ] <col_name> <data_type> [ <options> ]
138+
ModifyColumn {
139+
col_name: Ident,
140+
data_type: DataType,
141+
options: Vec<ColumnOption>,
142+
/// MySQL `ALTER TABLE` only [FIRST | AFTER column_name]
143+
column_position: Option<MySQLColumnPosition>,
144+
},
137145
/// `RENAME CONSTRAINT <old_constraint_name> TO <new_constraint_name>`
138146
///
139147
/// Note: this is a PostgreSQL-specific operation.
@@ -292,6 +300,22 @@ impl fmt::Display for AlterTableOperation {
292300

293301
Ok(())
294302
}
303+
AlterTableOperation::ModifyColumn {
304+
col_name,
305+
data_type,
306+
options,
307+
column_position,
308+
} => {
309+
write!(f, "MODIFY COLUMN {col_name} {data_type}")?;
310+
if !options.is_empty() {
311+
write!(f, " {}", display_separated(options, " "))?;
312+
}
313+
if let Some(position) = column_position {
314+
write!(f, " {position}")?;
315+
}
316+
317+
Ok(())
318+
}
295319
AlterTableOperation::RenameConstraint { old_name, new_name } => {
296320
write!(f, "RENAME CONSTRAINT {old_name} TO {new_name}")
297321
}

src/keywords.rs

+1
Original file line numberDiff line numberDiff line change
@@ -438,6 +438,7 @@ define_keywords!(
438438
MOD,
439439
MODE,
440440
MODIFIES,
441+
MODIFY,
441442
MODULE,
442443
MONTH,
443444
MSCK,

src/parser/mod.rs

+17
Original file line numberDiff line numberDiff line change
@@ -5757,6 +5757,23 @@ impl<'a> Parser<'a> {
57575757
options,
57585758
column_position,
57595759
}
5760+
} else if self.parse_keyword(Keyword::MODIFY) {
5761+
let _ = self.parse_keyword(Keyword::COLUMN); // [ COLUMN ]
5762+
let col_name = self.parse_identifier(false)?;
5763+
let data_type = self.parse_data_type()?;
5764+
let mut options = vec![];
5765+
while let Some(option) = self.parse_optional_column_option()? {
5766+
options.push(option);
5767+
}
5768+
5769+
let column_position = self.parse_column_position()?;
5770+
5771+
AlterTableOperation::ModifyColumn {
5772+
col_name,
5773+
data_type,
5774+
options,
5775+
column_position,
5776+
}
57605777
} else if self.parse_keyword(Keyword::ALTER) {
57615778
let _ = self.parse_keyword(Keyword::COLUMN); // [ COLUMN ]
57625779
let column_name = self.parse_identifier(false)?;

tests/sqlparser_mysql.rs

+93
Original file line numberDiff line numberDiff line change
@@ -2218,6 +2218,99 @@ fn parse_alter_table_change_column_with_column_position() {
22182218
assert_eq!(expected_operation_after, operation);
22192219
}
22202220

2221+
#[test]
2222+
fn parse_alter_table_modify_column() {
2223+
let expected_name = ObjectName(vec![Ident::new("orders")]);
2224+
let expected_operation = AlterTableOperation::ModifyColumn {
2225+
col_name: Ident::new("description"),
2226+
data_type: DataType::Text,
2227+
options: vec![ColumnOption::NotNull],
2228+
column_position: None,
2229+
};
2230+
2231+
let sql1 = "ALTER TABLE orders MODIFY COLUMN description TEXT NOT NULL";
2232+
let operation =
2233+
alter_table_op_with_name(mysql().verified_stmt(sql1), &expected_name.to_string());
2234+
assert_eq!(expected_operation, operation);
2235+
2236+
let sql2 = "ALTER TABLE orders MODIFY description TEXT NOT NULL";
2237+
let operation = alter_table_op_with_name(
2238+
mysql().one_statement_parses_to(sql2, sql1),
2239+
&expected_name.to_string(),
2240+
);
2241+
assert_eq!(expected_operation, operation);
2242+
2243+
let expected_operation = AlterTableOperation::ModifyColumn {
2244+
col_name: Ident::new("description"),
2245+
data_type: DataType::Text,
2246+
options: vec![ColumnOption::NotNull],
2247+
column_position: Some(MySQLColumnPosition::First),
2248+
};
2249+
let sql3 = "ALTER TABLE orders MODIFY COLUMN description TEXT NOT NULL FIRST";
2250+
let operation =
2251+
alter_table_op_with_name(mysql().verified_stmt(sql3), &expected_name.to_string());
2252+
assert_eq!(expected_operation, operation);
2253+
2254+
let expected_operation = AlterTableOperation::ModifyColumn {
2255+
col_name: Ident::new("description"),
2256+
data_type: DataType::Text,
2257+
options: vec![ColumnOption::NotNull],
2258+
column_position: Some(MySQLColumnPosition::After(Ident {
2259+
value: String::from("foo"),
2260+
quote_style: None,
2261+
})),
2262+
};
2263+
let sql4 = "ALTER TABLE orders MODIFY COLUMN description TEXT NOT NULL AFTER foo";
2264+
let operation =
2265+
alter_table_op_with_name(mysql().verified_stmt(sql4), &expected_name.to_string());
2266+
assert_eq!(expected_operation, operation);
2267+
}
2268+
2269+
#[test]
2270+
fn parse_alter_table_modify_column_with_column_position() {
2271+
let expected_name = ObjectName(vec![Ident::new("orders")]);
2272+
let expected_operation_first = AlterTableOperation::ModifyColumn {
2273+
col_name: Ident::new("description"),
2274+
data_type: DataType::Text,
2275+
options: vec![ColumnOption::NotNull],
2276+
column_position: Some(MySQLColumnPosition::First),
2277+
};
2278+
2279+
let sql1 = "ALTER TABLE orders MODIFY COLUMN description TEXT NOT NULL FIRST";
2280+
let operation =
2281+
alter_table_op_with_name(mysql().verified_stmt(sql1), &expected_name.to_string());
2282+
assert_eq!(expected_operation_first, operation);
2283+
2284+
let sql2 = "ALTER TABLE orders MODIFY description TEXT NOT NULL FIRST";
2285+
let operation = alter_table_op_with_name(
2286+
mysql().one_statement_parses_to(sql2, sql1),
2287+
&expected_name.to_string(),
2288+
);
2289+
assert_eq!(expected_operation_first, operation);
2290+
2291+
let expected_operation_after = AlterTableOperation::ModifyColumn {
2292+
col_name: Ident::new("description"),
2293+
data_type: DataType::Text,
2294+
options: vec![ColumnOption::NotNull],
2295+
column_position: Some(MySQLColumnPosition::After(Ident {
2296+
value: String::from("total_count"),
2297+
quote_style: None,
2298+
})),
2299+
};
2300+
2301+
let sql1 = "ALTER TABLE orders MODIFY COLUMN description TEXT NOT NULL AFTER total_count";
2302+
let operation =
2303+
alter_table_op_with_name(mysql().verified_stmt(sql1), &expected_name.to_string());
2304+
assert_eq!(expected_operation_after, operation);
2305+
2306+
let sql2 = "ALTER TABLE orders MODIFY description TEXT NOT NULL AFTER total_count";
2307+
let operation = alter_table_op_with_name(
2308+
mysql().one_statement_parses_to(sql2, sql1),
2309+
&expected_name.to_string(),
2310+
);
2311+
assert_eq!(expected_operation_after, operation);
2312+
}
2313+
22212314
#[test]
22222315
fn parse_substring_in_select() {
22232316
let sql = "SELECT DISTINCT SUBSTRING(description, 0, 1) FROM test";

0 commit comments

Comments
 (0)