Support MySQL size variants for BLOB and TEXT columns (#1564)

This commit is contained in:
Michael Victor Zink 2024-11-30 04:55:54 -08:00 committed by GitHub
parent a134910a36
commit 48b0e4db4e
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
4 changed files with 59 additions and 0 deletions

View file

@ -76,6 +76,18 @@ pub enum DataType {
/// [standard]: https://jakewheat.github.io/sql-overview/sql-2016-foundation-grammar.html#binary-large-object-string-type
/// [Oracle]: https://docs.oracle.com/javadb/10.8.3.0/ref/rrefblob.html
Blob(Option<u64>),
/// [MySQL] blob with up to 2**8 bytes
///
/// [MySQL]: https://dev.mysql.com/doc/refman/9.1/en/blob.html
TinyBlob,
/// [MySQL] blob with up to 2**24 bytes
///
/// [MySQL]: https://dev.mysql.com/doc/refman/9.1/en/blob.html
MediumBlob,
/// [MySQL] blob with up to 2**32 bytes
///
/// [MySQL]: https://dev.mysql.com/doc/refman/9.1/en/blob.html
LongBlob,
/// Variable-length binary data with optional length.
///
/// [bigquery]: https://cloud.google.com/bigquery/docs/reference/standard-sql/data-types#bytes_type
@ -275,6 +287,18 @@ pub enum DataType {
Regclass,
/// Text
Text,
/// [MySQL] text with up to 2**8 bytes
///
/// [MySQL]: https://dev.mysql.com/doc/refman/9.1/en/blob.html
TinyText,
/// [MySQL] text with up to 2**24 bytes
///
/// [MySQL]: https://dev.mysql.com/doc/refman/9.1/en/blob.html
MediumText,
/// [MySQL] text with up to 2**32 bytes
///
/// [MySQL]: https://dev.mysql.com/doc/refman/9.1/en/blob.html
LongText,
/// String with optional length.
String(Option<u64>),
/// A fixed-length string e.g [ClickHouse][1].
@ -355,6 +379,9 @@ impl fmt::Display for DataType {
format_type_with_optional_length(f, "VARBINARY", size, false)
}
DataType::Blob(size) => format_type_with_optional_length(f, "BLOB", size, false),
DataType::TinyBlob => write!(f, "TINYBLOB"),
DataType::MediumBlob => write!(f, "MEDIUMBLOB"),
DataType::LongBlob => write!(f, "LONGBLOB"),
DataType::Bytes(size) => format_type_with_optional_length(f, "BYTES", size, false),
DataType::Numeric(info) => {
write!(f, "NUMERIC{info}")
@ -486,6 +513,9 @@ impl fmt::Display for DataType {
DataType::JSONB => write!(f, "JSONB"),
DataType::Regclass => write!(f, "REGCLASS"),
DataType::Text => write!(f, "TEXT"),
DataType::TinyText => write!(f, "TINYTEXT"),
DataType::MediumText => write!(f, "MEDIUMTEXT"),
DataType::LongText => write!(f, "LONGTEXT"),
DataType::String(size) => format_type_with_optional_length(f, "STRING", size, false),
DataType::Bytea => write!(f, "BYTEA"),
DataType::Array(ty) => match ty {

View file

@ -453,6 +453,8 @@ define_keywords!(
LOCKED,
LOGIN,
LOGS,
LONGBLOB,
LONGTEXT,
LOWCARDINALITY,
LOWER,
LOW_PRIORITY,
@ -471,7 +473,9 @@ define_keywords!(
MAXVALUE,
MAX_DATA_EXTENSION_TIME_IN_DAYS,
MEASURES,
MEDIUMBLOB,
MEDIUMINT,
MEDIUMTEXT,
MEMBER,
MERGE,
METADATA,
@ -765,7 +769,9 @@ define_keywords!(
TIMEZONE_HOUR,
TIMEZONE_MINUTE,
TIMEZONE_REGION,
TINYBLOB,
TINYINT,
TINYTEXT,
TO,
TOP,
TOTALS,

View file

@ -8129,6 +8129,9 @@ impl<'a> Parser<'a> {
Keyword::BINARY => Ok(DataType::Binary(self.parse_optional_precision()?)),
Keyword::VARBINARY => Ok(DataType::Varbinary(self.parse_optional_precision()?)),
Keyword::BLOB => Ok(DataType::Blob(self.parse_optional_precision()?)),
Keyword::TINYBLOB => Ok(DataType::TinyBlob),
Keyword::MEDIUMBLOB => Ok(DataType::MediumBlob),
Keyword::LONGBLOB => Ok(DataType::LongBlob),
Keyword::BYTES => Ok(DataType::Bytes(self.parse_optional_precision()?)),
Keyword::UUID => Ok(DataType::Uuid),
Keyword::DATE => Ok(DataType::Date),
@ -8188,6 +8191,9 @@ impl<'a> Parser<'a> {
Ok(DataType::FixedString(character_length))
}
Keyword::TEXT => Ok(DataType::Text),
Keyword::TINYTEXT => Ok(DataType::TinyText),
Keyword::MEDIUMTEXT => Ok(DataType::MediumText),
Keyword::LONGTEXT => Ok(DataType::LongText),
Keyword::BYTEA => Ok(DataType::Bytea),
Keyword::NUMERIC => Ok(DataType::Numeric(
self.parse_exact_number_optional_precision_scale()?,

View file

@ -3014,3 +3014,20 @@ fn parse_bitstring_literal() {
))]
);
}
#[test]
fn parse_longblob_type() {
let sql = "CREATE TABLE foo (bar LONGBLOB)";
let stmt = mysql_and_generic().verified_stmt(sql);
if let Statement::CreateTable(CreateTable { columns, .. }) = stmt {
assert_eq!(columns.len(), 1);
assert_eq!(columns[0].data_type, DataType::LongBlob);
} else {
unreachable!()
}
mysql_and_generic().verified_stmt("CREATE TABLE foo (bar TINYBLOB)");
mysql_and_generic().verified_stmt("CREATE TABLE foo (bar MEDIUMBLOB)");
mysql_and_generic().verified_stmt("CREATE TABLE foo (bar TINYTEXT)");
mysql_and_generic().verified_stmt("CREATE TABLE foo (bar MEDIUMTEXT)");
mysql_and_generic().verified_stmt("CREATE TABLE foo (bar LONGTEXT)");
}