Skip to content

Commit 9a04d23

Browse files
committed
feat: support mysql charset
1 parent 12a3e97 commit 9a04d23

File tree

3 files changed

+32
-11
lines changed

3 files changed

+32
-11
lines changed

src/ast/data_type.rs

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -25,10 +25,10 @@ use super::value::escape_single_quote_string;
2525
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
2626
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
2727
pub enum DataType {
28-
/// Fixed-length character type e.g. CHAR(10)
29-
Char(Option<u64>),
28+
/// Fixed-length character type e.g. CHAR(10), CHAR CHARACTER set utf8mb4
29+
Char(Option<u64>, Option<String>),
3030
/// Variable-length character type e.g. VARCHAR(10)
31-
Varchar(Option<u64>),
31+
Varchar(Option<u64>, Option<String>),
3232
/// Uuid type
3333
Uuid,
3434
/// Large character object e.g. CLOB(1000)
@@ -94,8 +94,8 @@ pub enum DataType {
9494
impl fmt::Display for DataType {
9595
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
9696
match self {
97-
DataType::Char(size) => format_type_with_optional_length(f, "CHAR", size, false),
98-
DataType::Varchar(size) => {
97+
DataType::Char(size, _) => format_type_with_optional_length(f, "CHAR", size, false),
98+
DataType::Varchar(size, _) => {
9999
format_type_with_optional_length(f, "CHARACTER VARYING", size, false)
100100
}
101101
DataType::Uuid => write!(f, "UUID"),

src/ast/mod.rs

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -240,6 +240,7 @@ pub enum Expr {
240240
Cast {
241241
expr: Box<Expr>,
242242
data_type: DataType,
243+
collation: Option<String>,
243244
},
244245
/// TRY_CAST an expression to a different data type e.g. `TRY_CAST(foo AS VARCHAR(123))`
245246
// this differs from CAST in the choice of how to implement invalid conversions
@@ -396,7 +397,9 @@ impl fmt::Display for Expr {
396397
write!(f, "{} {}", op, expr)
397398
}
398399
}
399-
Expr::Cast { expr, data_type } => write!(f, "CAST({} AS {})", expr, data_type),
400+
Expr::Cast {
401+
expr, data_type, ..
402+
} => write!(f, "CAST({} AS {})", expr, data_type),
400403
Expr::TryCast { expr, data_type } => write!(f, "TRY_CAST({} AS {})", expr, data_type),
401404
Expr::Extract { field, expr } => write!(f, "EXTRACT({} FROM {})", field, expr),
402405
Expr::Collate { expr, collation } => write!(f, "{} COLLATE {}", expr, collation),

src/parser.rs

Lines changed: 23 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -740,9 +740,19 @@ impl<'a> Parser<'a> {
740740
self.expect_keyword(Keyword::AS)?;
741741
let data_type = self.parse_data_type()?;
742742
self.expect_token(&Token::RParen)?;
743+
let collation = if self.parse_keywords(&[Keyword::COLLATE]) {
744+
match self.next_token() {
745+
Token::Word(w) => Some(w.value),
746+
unexpected => self.expected("identifier", unexpected)?,
747+
}
748+
} else {
749+
None
750+
};
751+
743752
Ok(Expr::Cast {
744753
expr: Box::new(expr),
745754
data_type,
755+
collation,
746756
})
747757
}
748758

@@ -1240,6 +1250,7 @@ impl<'a> Parser<'a> {
12401250
Ok(Expr::Cast {
12411251
expr: Box::new(expr),
12421252
data_type: self.parse_data_type()?,
1253+
collation: None,
12431254
})
12441255
}
12451256

@@ -2430,12 +2441,19 @@ impl<'a> Parser<'a> {
24302441
Ok(DataType::BigInt(optional_precision?))
24312442
}
24322443
}
2433-
Keyword::VARCHAR => Ok(DataType::Varchar(self.parse_optional_precision()?)),
2444+
Keyword::VARCHAR => Ok(DataType::Varchar(self.parse_optional_precision()?, None)),
24342445
Keyword::CHAR | Keyword::CHARACTER => {
2435-
if self.parse_keyword(Keyword::VARYING) {
2436-
Ok(DataType::Varchar(self.parse_optional_precision()?))
2437-
} else {
2438-
Ok(DataType::Char(self.parse_optional_precision()?))
2446+
let is_var = self.parse_keyword(Keyword::VARYING);
2447+
let precision = self.parse_optional_precision()?;
2448+
let mut charset: Option<String> = None;
2449+
// handle CAST('test' AS CHAR CHARACTER SET utf8mb4);
2450+
if self.parse_keywords(&[Keyword::CHARACTER, Keyword::SET]) {
2451+
let name = self.parse_identifier()?;
2452+
charset = Some(name.value);
2453+
}
2454+
match is_var {
2455+
true => Ok(DataType::Varchar(precision, charset)),
2456+
_ => Ok(DataType::Char(precision, charset)),
24392457
}
24402458
}
24412459
Keyword::UUID => Ok(DataType::Uuid),

0 commit comments

Comments
 (0)