Skip to content

Commit 6d7e37e

Browse files
committed
Add support for COMMENT and CHARACTER SET field attributes
See https://dev.mysql.com/doc/refman/8.0/en/create-table.html
1 parent 6540c8b commit 6d7e37e

File tree

3 files changed

+48
-3
lines changed

3 files changed

+48
-3
lines changed

src/ast/ddl.rs

+9-2
Original file line numberDiff line numberDiff line change
@@ -14,12 +14,13 @@
1414
//! (commonly referred to as Data Definition Language, or DDL)
1515
1616
#[cfg(not(feature = "std"))]
17-
use alloc::{boxed::Box, string::ToString, vec::Vec};
17+
use alloc::{boxed::Box, string::String, string::ToString, vec::Vec};
1818
use core::fmt;
1919

2020
#[cfg(feature = "serde")]
2121
use serde::{Deserialize, Serialize};
2222

23+
use crate::ast::value::escape_single_quote_string;
2324
use crate::ast::{display_comma_separated, display_separated, DataType, Expr, Ident, ObjectName};
2425
use crate::tokenizer::Token;
2526

@@ -338,7 +339,9 @@ pub enum ColumnOption {
338339
/// `DEFAULT <restricted-expr>`
339340
Default(Expr),
340341
/// `{ PRIMARY KEY | UNIQUE }`
341-
Unique { is_primary: bool },
342+
Unique {
343+
is_primary: bool,
344+
},
342345
/// A referential integrity constraint (`[FOREIGN KEY REFERENCES
343346
/// <foreign_table> (<referred_columns>)
344347
/// { [ON DELETE <referential_action>] [ON UPDATE <referential_action>] |
@@ -356,6 +359,8 @@ pub enum ColumnOption {
356359
/// - MySQL's `AUTO_INCREMENT` or SQLite's `AUTOINCREMENT`
357360
/// - ...
358361
DialectSpecific(Vec<Token>),
362+
CharacterSet(ObjectName),
363+
Comment(String),
359364
}
360365

361366
impl fmt::Display for ColumnOption {
@@ -388,6 +393,8 @@ impl fmt::Display for ColumnOption {
388393
}
389394
Check(expr) => write!(f, "CHECK ({})", expr),
390395
DialectSpecific(val) => write!(f, "{}", display_separated(val, " ")),
396+
CharacterSet(n) => write!(f, "CHARACTER SET {}", n),
397+
Comment(v) => write!(f, "COMMENT '{}'", escape_single_quote_string(v)),
391398
}
392399
}
393400
}

src/parser.rs

+8-1
Original file line numberDiff line numberDiff line change
@@ -1785,8 +1785,15 @@ impl<'a> Parser<'a> {
17851785
}
17861786

17871787
pub fn parse_optional_column_option(&mut self) -> Result<Option<ColumnOption>, ParserError> {
1788-
if self.parse_keywords(&[Keyword::NOT, Keyword::NULL]) {
1788+
if self.parse_keywords(&[Keyword::CHARACTER, Keyword::SET]) {
1789+
Ok(Some(ColumnOption::CharacterSet(self.parse_object_name()?)))
1790+
} else if self.parse_keywords(&[Keyword::NOT, Keyword::NULL]) {
17891791
Ok(Some(ColumnOption::NotNull))
1792+
} else if self.parse_keywords(&[Keyword::COMMENT]) {
1793+
match self.next_token() {
1794+
Token::SingleQuotedString(value, ..) => Ok(Some(ColumnOption::Comment(value))),
1795+
unexpected => self.expected("string", unexpected),
1796+
}
17901797
} else if self.parse_keyword(Keyword::NULL) {
17911798
Ok(Some(ColumnOption::Null))
17921799
} else if self.parse_keyword(Keyword::DEFAULT) {

tests/sqlparser_mysql.rs

+31
Original file line numberDiff line numberDiff line change
@@ -211,6 +211,37 @@ fn parse_create_table_engine_default_charset() {
211211
}
212212
}
213213

214+
#[test]
215+
fn parse_create_table_comment_character_set() {
216+
let sql = "CREATE TABLE foo (s TEXT CHARACTER SET utf8mb4 COMMENT 'comment')";
217+
match mysql().verified_stmt(sql) {
218+
Statement::CreateTable { name, columns, .. } => {
219+
assert_eq!(name.to_string(), "foo");
220+
assert_eq!(
221+
vec![ColumnDef {
222+
name: Ident::new("s"),
223+
data_type: DataType::Text,
224+
collation: None,
225+
options: vec![
226+
ColumnOptionDef {
227+
name: None,
228+
option: ColumnOption::CharacterSet(ObjectName(vec![Ident::new(
229+
"utf8mb4"
230+
)]))
231+
},
232+
ColumnOptionDef {
233+
name: None,
234+
option: ColumnOption::Comment("comment".to_string())
235+
}
236+
],
237+
},],
238+
columns
239+
);
240+
}
241+
_ => unreachable!(),
242+
}
243+
}
244+
214245
#[test]
215246
fn parse_quote_identifiers() {
216247
let sql = "CREATE TABLE `PRIMARY` (`BEGIN` INT PRIMARY KEY)";

0 commit comments

Comments
 (0)