mirror of
https://github.com/apache/datafusion-sqlparser-rs.git
synced 2025-08-04 06:18:17 +00:00
mysql unsigned datatype (#428)
* support MySQL UNSIGNED * fix: 🐛 `unsigned` is not column option * test: 💍 add `unsigned` test * fix: 🐛 `unsigned` is not column option * feat: 🎸 declare unsigned data_types * feat: 🎸 display unsigned * fix: 🐛 unsigned is not column type option * feat: 🎸 parse_data_type can parse unsigned * feat: 🎸 int or decimal or float is unsigned selectable * fix: 🐛 FLOAT/DOUBLE/DECIMAL + UNSIGNED is not recommended https://dev.mysql.com/doc/refman/8.0/en/numeric-type-attributes.html * test: 💍 add test * style: 💄 fmt
This commit is contained in:
parent
3af3ca07b6
commit
994b86a45c
4 changed files with 109 additions and 14 deletions
|
@ -45,12 +45,20 @@ pub enum DataType {
|
|||
Float(Option<u64>),
|
||||
/// Tiny integer with optional display width e.g. TINYINT or TINYINT(3)
|
||||
TinyInt(Option<u64>),
|
||||
/// Unsigned tiny integer with optional display width e.g. TINYINT UNSIGNED or TINYINT(3) UNSIGNED
|
||||
UnsignedTinyInt(Option<u64>),
|
||||
/// Small integer with optional display width e.g. SMALLINT or SMALLINT(5)
|
||||
SmallInt(Option<u64>),
|
||||
/// Unsigned small integer with optional display width e.g. SMALLINT UNSIGNED or SMALLINT(5) UNSIGNED
|
||||
UnsignedSmallInt(Option<u64>),
|
||||
/// Integer with optional display width e.g. INT or INT(11)
|
||||
Int(Option<u64>),
|
||||
/// Unsigned integer with optional display width e.g. INT UNSIGNED or INT(11) UNSIGNED
|
||||
UnsignedInt(Option<u64>),
|
||||
/// Big integer with optional display width e.g. BIGINT or BIGINT(20)
|
||||
BigInt(Option<u64>),
|
||||
/// Unsigned big integer with optional display width e.g. BIGINT UNSIGNED or BIGINT(20) UNSIGNED
|
||||
UnsignedBigInt(Option<u64>),
|
||||
/// Floating point e.g. REAL
|
||||
Real,
|
||||
/// Double e.g. DOUBLE PRECISION
|
||||
|
@ -86,9 +94,9 @@ pub enum DataType {
|
|||
impl fmt::Display for DataType {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
match self {
|
||||
DataType::Char(size) => format_type_with_optional_length(f, "CHAR", size),
|
||||
DataType::Char(size) => format_type_with_optional_length(f, "CHAR", size, false),
|
||||
DataType::Varchar(size) => {
|
||||
format_type_with_optional_length(f, "CHARACTER VARYING", size)
|
||||
format_type_with_optional_length(f, "CHARACTER VARYING", size, false)
|
||||
}
|
||||
DataType::Uuid => write!(f, "UUID"),
|
||||
DataType::Clob(size) => write!(f, "CLOB({})", size),
|
||||
|
@ -99,16 +107,32 @@ impl fmt::Display for DataType {
|
|||
if let Some(scale) = scale {
|
||||
write!(f, "NUMERIC({},{})", precision.unwrap(), scale)
|
||||
} else {
|
||||
format_type_with_optional_length(f, "NUMERIC", precision)
|
||||
format_type_with_optional_length(f, "NUMERIC", precision, false)
|
||||
}
|
||||
}
|
||||
DataType::Float(size) => format_type_with_optional_length(f, "FLOAT", size),
|
||||
DataType::TinyInt(zerofill) => format_type_with_optional_length(f, "TINYINT", zerofill),
|
||||
DataType::SmallInt(zerofill) => {
|
||||
format_type_with_optional_length(f, "SMALLINT", zerofill)
|
||||
DataType::Float(size) => format_type_with_optional_length(f, "FLOAT", size, false),
|
||||
DataType::TinyInt(zerofill) => {
|
||||
format_type_with_optional_length(f, "TINYINT", zerofill, false)
|
||||
}
|
||||
DataType::UnsignedTinyInt(zerofill) => {
|
||||
format_type_with_optional_length(f, "TINYINT", zerofill, true)
|
||||
}
|
||||
DataType::SmallInt(zerofill) => {
|
||||
format_type_with_optional_length(f, "SMALLINT", zerofill, false)
|
||||
}
|
||||
DataType::UnsignedSmallInt(zerofill) => {
|
||||
format_type_with_optional_length(f, "SMALLINT", zerofill, true)
|
||||
}
|
||||
DataType::Int(zerofill) => format_type_with_optional_length(f, "INT", zerofill, false),
|
||||
DataType::UnsignedInt(zerofill) => {
|
||||
format_type_with_optional_length(f, "INT", zerofill, true)
|
||||
}
|
||||
DataType::BigInt(zerofill) => {
|
||||
format_type_with_optional_length(f, "BIGINT", zerofill, false)
|
||||
}
|
||||
DataType::UnsignedBigInt(zerofill) => {
|
||||
format_type_with_optional_length(f, "BIGINT", zerofill, true)
|
||||
}
|
||||
DataType::Int(zerofill) => format_type_with_optional_length(f, "INT", zerofill),
|
||||
DataType::BigInt(zerofill) => format_type_with_optional_length(f, "BIGINT", zerofill),
|
||||
DataType::Real => write!(f, "REAL"),
|
||||
DataType::Double => write!(f, "DOUBLE"),
|
||||
DataType::Boolean => write!(f, "BOOLEAN"),
|
||||
|
@ -150,10 +174,14 @@ fn format_type_with_optional_length(
|
|||
f: &mut fmt::Formatter,
|
||||
sql_type: &'static str,
|
||||
len: &Option<u64>,
|
||||
unsigned: bool,
|
||||
) -> fmt::Result {
|
||||
write!(f, "{}", sql_type)?;
|
||||
if let Some(len) = len {
|
||||
write!(f, "({})", len)?;
|
||||
}
|
||||
if unsigned {
|
||||
write!(f, " UNSIGNED")?;
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
|
|
@ -499,6 +499,7 @@ define_keywords!(
|
|||
UNIQUE,
|
||||
UNKNOWN,
|
||||
UNNEST,
|
||||
UNSIGNED,
|
||||
UPDATE,
|
||||
UPPER,
|
||||
USAGE,
|
||||
|
|
|
@ -2382,12 +2382,38 @@ impl<'a> Parser<'a> {
|
|||
let _ = self.parse_keyword(Keyword::PRECISION);
|
||||
Ok(DataType::Double)
|
||||
}
|
||||
Keyword::TINYINT => Ok(DataType::TinyInt(self.parse_optional_precision()?)),
|
||||
Keyword::SMALLINT => Ok(DataType::SmallInt(self.parse_optional_precision()?)),
|
||||
Keyword::INT | Keyword::INTEGER => {
|
||||
Ok(DataType::Int(self.parse_optional_precision()?))
|
||||
Keyword::TINYINT => {
|
||||
let optional_precision = self.parse_optional_precision();
|
||||
if self.parse_keyword(Keyword::UNSIGNED) {
|
||||
Ok(DataType::UnsignedTinyInt(optional_precision?))
|
||||
} else {
|
||||
Ok(DataType::TinyInt(optional_precision?))
|
||||
}
|
||||
}
|
||||
Keyword::SMALLINT => {
|
||||
let optional_precision = self.parse_optional_precision();
|
||||
if self.parse_keyword(Keyword::UNSIGNED) {
|
||||
Ok(DataType::UnsignedSmallInt(optional_precision?))
|
||||
} else {
|
||||
Ok(DataType::SmallInt(optional_precision?))
|
||||
}
|
||||
}
|
||||
Keyword::INT | Keyword::INTEGER => {
|
||||
let optional_precision = self.parse_optional_precision();
|
||||
if self.parse_keyword(Keyword::UNSIGNED) {
|
||||
Ok(DataType::UnsignedInt(optional_precision?))
|
||||
} else {
|
||||
Ok(DataType::Int(optional_precision?))
|
||||
}
|
||||
}
|
||||
Keyword::BIGINT => {
|
||||
let optional_precision = self.parse_optional_precision();
|
||||
if self.parse_keyword(Keyword::UNSIGNED) {
|
||||
Ok(DataType::UnsignedBigInt(optional_precision?))
|
||||
} else {
|
||||
Ok(DataType::BigInt(optional_precision?))
|
||||
}
|
||||
}
|
||||
Keyword::BIGINT => Ok(DataType::BigInt(self.parse_optional_precision()?)),
|
||||
Keyword::VARCHAR => Ok(DataType::Varchar(self.parse_optional_precision()?)),
|
||||
Keyword::CHAR | Keyword::CHARACTER => {
|
||||
if self.parse_keyword(Keyword::VARYING) {
|
||||
|
|
|
@ -407,6 +407,46 @@ fn parse_create_table_with_minimum_display_width() {
|
|||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn parse_create_table_unsigned() {
|
||||
let sql = "CREATE TABLE foo (bar_tinyint TINYINT(3) UNSIGNED, bar_smallint SMALLINT(5) UNSIGNED, bar_int INT(11) UNSIGNED, bar_bigint BIGINT(20) UNSIGNED)";
|
||||
match mysql().verified_stmt(sql) {
|
||||
Statement::CreateTable { name, columns, .. } => {
|
||||
assert_eq!(name.to_string(), "foo");
|
||||
assert_eq!(
|
||||
vec![
|
||||
ColumnDef {
|
||||
name: Ident::new("bar_tinyint"),
|
||||
data_type: DataType::UnsignedTinyInt(Some(3)),
|
||||
collation: None,
|
||||
options: vec![],
|
||||
},
|
||||
ColumnDef {
|
||||
name: Ident::new("bar_smallint"),
|
||||
data_type: DataType::UnsignedSmallInt(Some(5)),
|
||||
collation: None,
|
||||
options: vec![],
|
||||
},
|
||||
ColumnDef {
|
||||
name: Ident::new("bar_int"),
|
||||
data_type: DataType::UnsignedInt(Some(11)),
|
||||
collation: None,
|
||||
options: vec![],
|
||||
},
|
||||
ColumnDef {
|
||||
name: Ident::new("bar_bigint"),
|
||||
data_type: DataType::UnsignedBigInt(Some(20)),
|
||||
collation: None,
|
||||
options: vec![],
|
||||
},
|
||||
],
|
||||
columns
|
||||
);
|
||||
}
|
||||
_ => unreachable!(),
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(not(feature = "bigdecimal"))]
|
||||
fn parse_simple_insert() {
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue