mirror of
https://github.com/apache/datafusion-sqlparser-rs.git
synced 2025-07-08 01:15:00 +00:00
parent
3e94877f03
commit
a5bbb5e8ac
5 changed files with 116 additions and 9 deletions
|
@ -85,7 +85,7 @@ pub enum DataType {
|
||||||
///
|
///
|
||||||
/// [standard]: https://jakewheat.github.io/sql-overview/sql-2016-foundation-grammar.html#binary-string-type
|
/// [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
|
/// [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]
|
/// 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
|
/// [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::Clob(size) => format_type_with_optional_length(f, "CLOB", size, false),
|
||||||
DataType::Binary(size) => format_type_with_optional_length(f, "BINARY", size, false),
|
DataType::Binary(size) => format_type_with_optional_length(f, "BINARY", size, false),
|
||||||
DataType::Varbinary(size) => {
|
DataType::Varbinary(size) => format_varbinary_type(f, "VARBINARY", size),
|
||||||
format_type_with_optional_length(f, "VARBINARY", size, false)
|
|
||||||
}
|
|
||||||
DataType::Blob(size) => format_type_with_optional_length(f, "BLOB", size, false),
|
DataType::Blob(size) => format_type_with_optional_length(f, "BLOB", size, false),
|
||||||
DataType::TinyBlob => write!(f, "TINYBLOB"),
|
DataType::TinyBlob => write!(f, "TINYBLOB"),
|
||||||
DataType::MediumBlob => write!(f, "MEDIUMBLOB"),
|
DataType::MediumBlob => write!(f, "MEDIUMBLOB"),
|
||||||
|
@ -673,6 +671,18 @@ fn format_character_string_type(
|
||||||
Ok(())
|
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(
|
fn format_datetime_precision_and_tz(
|
||||||
f: &mut fmt::Formatter,
|
f: &mut fmt::Formatter,
|
||||||
sql_type: &'static str,
|
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
|
/// Represents the data type of the elements in an array (if any) as well as
|
||||||
/// the syntax used to declare the array.
|
/// the syntax used to declare the array.
|
||||||
///
|
///
|
||||||
|
|
|
@ -40,8 +40,8 @@ use sqlparser_derive::{Visit, VisitMut};
|
||||||
use crate::tokenizer::Span;
|
use crate::tokenizer::Span;
|
||||||
|
|
||||||
pub use self::data_type::{
|
pub use self::data_type::{
|
||||||
ArrayElemTypeDef, CharLengthUnits, CharacterLength, DataType, EnumMember, ExactNumberInfo,
|
ArrayElemTypeDef, BinaryLength, CharLengthUnits, CharacterLength, DataType, EnumMember,
|
||||||
StructBracketKind, TimezoneInfo,
|
ExactNumberInfo, StructBracketKind, TimezoneInfo,
|
||||||
};
|
};
|
||||||
pub use self::dcl::{
|
pub use self::dcl::{
|
||||||
AlterRoleOperation, ResetConfig, RoleOption, SecondaryRoles, SetConfigValue, Use,
|
AlterRoleOperation, ResetConfig, RoleOption, SecondaryRoles, SetConfigValue, Use,
|
||||||
|
|
|
@ -8766,7 +8766,7 @@ impl<'a> Parser<'a> {
|
||||||
}
|
}
|
||||||
Keyword::CLOB => Ok(DataType::Clob(self.parse_optional_precision()?)),
|
Keyword::CLOB => Ok(DataType::Clob(self.parse_optional_precision()?)),
|
||||||
Keyword::BINARY => Ok(DataType::Binary(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::BLOB => Ok(DataType::Blob(self.parse_optional_precision()?)),
|
||||||
Keyword::TINYBLOB => Ok(DataType::TinyBlob),
|
Keyword::TINYBLOB => Ok(DataType::TinyBlob),
|
||||||
Keyword::MEDIUMBLOB => Ok(DataType::MediumBlob),
|
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> {
|
pub fn parse_character_length(&mut self) -> Result<CharacterLength, ParserError> {
|
||||||
if self.parse_keyword(Keyword::MAX) {
|
if self.parse_keyword(Keyword::MAX) {
|
||||||
return Ok(CharacterLength::Max);
|
return Ok(CharacterLength::Max);
|
||||||
|
@ -9665,6 +9675,14 @@ impl<'a> Parser<'a> {
|
||||||
Ok(CharacterLength::IntegerLength { length, unit })
|
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(
|
pub fn parse_optional_precision_scale(
|
||||||
&mut self,
|
&mut self,
|
||||||
) -> Result<(Option<u64>, Option<u64>), ParserError> {
|
) -> Result<(Option<u64>, Option<u64>), ParserError> {
|
||||||
|
|
|
@ -2633,7 +2633,7 @@ fn parse_cast() {
|
||||||
&Expr::Cast {
|
&Expr::Cast {
|
||||||
kind: CastKind::Cast,
|
kind: CastKind::Cast,
|
||||||
expr: Box::new(Expr::Identifier(Ident::new("id"))),
|
expr: Box::new(Expr::Identifier(Ident::new("id"))),
|
||||||
data_type: DataType::Varbinary(Some(50)),
|
data_type: DataType::Varbinary(Some(BinaryLength::IntegerLength { length: 50 })),
|
||||||
format: None,
|
format: None,
|
||||||
},
|
},
|
||||||
expr_from_projection(only(&select.projection))
|
expr_from_projection(only(&select.projection))
|
||||||
|
|
|
@ -26,7 +26,7 @@ use helpers::attached_token::AttachedToken;
|
||||||
use sqlparser::tokenizer::Span;
|
use sqlparser::tokenizer::Span;
|
||||||
use test_utils::*;
|
use test_utils::*;
|
||||||
|
|
||||||
use sqlparser::ast::DataType::{Int, Text};
|
use sqlparser::ast::DataType::{Int, Text, Varbinary};
|
||||||
use sqlparser::ast::DeclareAssignment::MsSqlAssignment;
|
use sqlparser::ast::DeclareAssignment::MsSqlAssignment;
|
||||||
use sqlparser::ast::Value::SingleQuotedString;
|
use sqlparser::ast::Value::SingleQuotedString;
|
||||||
use sqlparser::ast::*;
|
use sqlparser::ast::*;
|
||||||
|
@ -1796,6 +1796,59 @@ fn parse_mssql_set_session_value() {
|
||||||
ms().verified_stmt("SET ANSI_NULLS, ANSI_PADDING ON");
|
ms().verified_stmt("SET ANSI_NULLS, ANSI_PADDING ON");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn parse_mssql_varbinary_max_length() {
|
||||||
|
let sql = "CREATE TABLE example (var_binary_col VARBINARY(MAX))";
|
||||||
|
|
||||||
|
match ms_and_generic().verified_stmt(sql) {
|
||||||
|
Statement::CreateTable(CreateTable { name, columns, .. }) => {
|
||||||
|
assert_eq!(
|
||||||
|
name,
|
||||||
|
ObjectName::from(vec![Ident {
|
||||||
|
value: "example".to_string(),
|
||||||
|
quote_style: None,
|
||||||
|
span: Span::empty(),
|
||||||
|
}])
|
||||||
|
);
|
||||||
|
assert_eq!(
|
||||||
|
columns,
|
||||||
|
vec![ColumnDef {
|
||||||
|
name: Ident::new("var_binary_col"),
|
||||||
|
data_type: Varbinary(Some(BinaryLength::Max)),
|
||||||
|
collation: None,
|
||||||
|
options: vec![]
|
||||||
|
},],
|
||||||
|
);
|
||||||
|
}
|
||||||
|
_ => unreachable!(),
|
||||||
|
}
|
||||||
|
|
||||||
|
let sql = "CREATE TABLE example (var_binary_col VARBINARY(50))";
|
||||||
|
|
||||||
|
match ms_and_generic().verified_stmt(sql) {
|
||||||
|
Statement::CreateTable(CreateTable { name, columns, .. }) => {
|
||||||
|
assert_eq!(
|
||||||
|
name,
|
||||||
|
ObjectName::from(vec![Ident {
|
||||||
|
value: "example".to_string(),
|
||||||
|
quote_style: None,
|
||||||
|
span: Span::empty(),
|
||||||
|
}])
|
||||||
|
);
|
||||||
|
assert_eq!(
|
||||||
|
columns,
|
||||||
|
vec![ColumnDef {
|
||||||
|
name: Ident::new("var_binary_col"),
|
||||||
|
data_type: Varbinary(Some(BinaryLength::IntegerLength { length: 50 })),
|
||||||
|
collation: None,
|
||||||
|
options: vec![]
|
||||||
|
},],
|
||||||
|
);
|
||||||
|
}
|
||||||
|
_ => unreachable!(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fn ms() -> TestedDialects {
|
fn ms() -> TestedDialects {
|
||||||
TestedDialects::new(vec![Box::new(MsSqlDialect {})])
|
TestedDialects::new(vec![Box::new(MsSqlDialect {})])
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue