Add support for MS Varbinary(MAX) (#1714) (#1715)

This commit is contained in:
Tyler Brinks 2025-02-13 03:40:35 -07:00 committed by GitHub
parent 3e94877f03
commit a5bbb5e8ac
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
5 changed files with 116 additions and 9 deletions

View file

@ -85,7 +85,7 @@ pub enum DataType {
///
/// [standard]: https://jakewheat.github.io/sql-overview/sql-2016-foundation-grammar.html#binary-string-type
/// [MS SQL Server]: https://learn.microsoft.com/pt-br/sql/t-sql/data-types/binary-and-varbinary-transact-sql?view=sql-server-ver16
Varbinary(Option<u64>),
Varbinary(Option<BinaryLength>),
/// Large binary object with optional length e.g. BLOB, BLOB(1000), [standard], [Oracle]
///
/// [standard]: https://jakewheat.github.io/sql-overview/sql-2016-foundation-grammar.html#binary-large-object-string-type
@ -408,9 +408,7 @@ impl fmt::Display for DataType {
}
DataType::Clob(size) => format_type_with_optional_length(f, "CLOB", size, false),
DataType::Binary(size) => format_type_with_optional_length(f, "BINARY", size, false),
DataType::Varbinary(size) => {
format_type_with_optional_length(f, "VARBINARY", size, false)
}
DataType::Varbinary(size) => format_varbinary_type(f, "VARBINARY", size),
DataType::Blob(size) => format_type_with_optional_length(f, "BLOB", size, false),
DataType::TinyBlob => write!(f, "TINYBLOB"),
DataType::MediumBlob => write!(f, "MEDIUMBLOB"),
@ -673,6 +671,18 @@ fn format_character_string_type(
Ok(())
}
fn format_varbinary_type(
f: &mut fmt::Formatter,
sql_type: &str,
size: &Option<BinaryLength>,
) -> fmt::Result {
write!(f, "{sql_type}")?;
if let Some(size) = size {
write!(f, "({size})")?;
}
Ok(())
}
fn format_datetime_precision_and_tz(
f: &mut fmt::Formatter,
sql_type: &'static str,
@ -862,6 +872,32 @@ impl fmt::Display for CharLengthUnits {
}
}
#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
pub enum BinaryLength {
IntegerLength {
/// Default (if VARYING)
length: u64,
},
/// VARBINARY(MAX) used in T-SQL (Microsoft SQL Server)
Max,
}
impl fmt::Display for BinaryLength {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
BinaryLength::IntegerLength { length } => {
write!(f, "{}", length)?;
}
BinaryLength::Max => {
write!(f, "MAX")?;
}
}
Ok(())
}
}
/// Represents the data type of the elements in an array (if any) as well as
/// the syntax used to declare the array.
///

View file

@ -40,8 +40,8 @@ use sqlparser_derive::{Visit, VisitMut};
use crate::tokenizer::Span;
pub use self::data_type::{
ArrayElemTypeDef, CharLengthUnits, CharacterLength, DataType, EnumMember, ExactNumberInfo,
StructBracketKind, TimezoneInfo,
ArrayElemTypeDef, BinaryLength, CharLengthUnits, CharacterLength, DataType, EnumMember,
ExactNumberInfo, StructBracketKind, TimezoneInfo,
};
pub use self::dcl::{
AlterRoleOperation, ResetConfig, RoleOption, SecondaryRoles, SetConfigValue, Use,

View file

@ -8766,7 +8766,7 @@ impl<'a> Parser<'a> {
}
Keyword::CLOB => Ok(DataType::Clob(self.parse_optional_precision()?)),
Keyword::BINARY => Ok(DataType::Binary(self.parse_optional_precision()?)),
Keyword::VARBINARY => Ok(DataType::Varbinary(self.parse_optional_precision()?)),
Keyword::VARBINARY => Ok(DataType::Varbinary(self.parse_optional_binary_length()?)),
Keyword::BLOB => Ok(DataType::Blob(self.parse_optional_precision()?)),
Keyword::TINYBLOB => Ok(DataType::TinyBlob),
Keyword::MEDIUMBLOB => Ok(DataType::MediumBlob),
@ -9650,6 +9650,16 @@ impl<'a> Parser<'a> {
}
}
pub fn parse_optional_binary_length(&mut self) -> Result<Option<BinaryLength>, ParserError> {
if self.consume_token(&Token::LParen) {
let binary_length = self.parse_binary_length()?;
self.expect_token(&Token::RParen)?;
Ok(Some(binary_length))
} else {
Ok(None)
}
}
pub fn parse_character_length(&mut self) -> Result<CharacterLength, ParserError> {
if self.parse_keyword(Keyword::MAX) {
return Ok(CharacterLength::Max);
@ -9665,6 +9675,14 @@ impl<'a> Parser<'a> {
Ok(CharacterLength::IntegerLength { length, unit })
}
pub fn parse_binary_length(&mut self) -> Result<BinaryLength, ParserError> {
if self.parse_keyword(Keyword::MAX) {
return Ok(BinaryLength::Max);
}
let length = self.parse_literal_uint()?;
Ok(BinaryLength::IntegerLength { length })
}
pub fn parse_optional_precision_scale(
&mut self,
) -> Result<(Option<u64>, Option<u64>), ParserError> {