feat: support pg type alias (#933)

This commit is contained in:
Kikkon 2023-07-27 18:20:24 +08:00 committed by GitHub
parent 53593f1982
commit 0ddb853410
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
4 changed files with 163 additions and 2 deletions

View file

@ -97,6 +97,14 @@ pub enum DataType {
TinyInt(Option<u64>),
/// Unsigned tiny integer with optional display width e.g. TINYINT UNSIGNED or TINYINT(3) UNSIGNED
UnsignedTinyInt(Option<u64>),
/// Int2 as alias for SmallInt in [postgresql]
/// Note: Int2 mean 2 bytes in postgres (not 2 bits)
/// Int2 with optional display width e.g. INT2 or INT2(5)
///
/// [postgresql]: https://www.postgresql.org/docs/15/datatype.html
Int2(Option<u64>),
/// Unsigned Int2 with optional display width e.g. INT2 Unsigned or INT2(5) Unsigned
UnsignedInt2(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
@ -109,20 +117,44 @@ pub enum DataType {
///
/// [1]: https://dev.mysql.com/doc/refman/8.0/en/integer-types.html
UnsignedMediumInt(Option<u64>),
/// Integer with optional display width e.g. INT or INT(11)
/// Int with optional display width e.g. INT or INT(11)
Int(Option<u64>),
/// Int4 as alias for Integer in [postgresql]
/// Note: Int4 mean 4 bytes in postgres (not 4 bits)
/// Int4 with optional display width e.g. Int4 or Int4(11)
///
/// [postgresql]: https://www.postgresql.org/docs/15/datatype.html
Int4(Option<u64>),
/// Integer with optional display width e.g. INTEGER or INTEGER(11)
Integer(Option<u64>),
/// Unsigned integer with optional display width e.g. INT UNSIGNED or INT(11) UNSIGNED
/// Unsigned int with optional display width e.g. INT UNSIGNED or INT(11) UNSIGNED
UnsignedInt(Option<u64>),
/// Unsigned int4 with optional display width e.g. INT4 UNSIGNED or INT4(11) UNSIGNED
UnsignedInt4(Option<u64>),
/// Unsigned integer with optional display width e.g. INTGER UNSIGNED or INTEGER(11) UNSIGNED
UnsignedInteger(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>),
/// Int8 as alias for Bigint in [postgresql]
/// Note: Int8 mean 8 bytes in postgres (not 8 bits)
/// Int8 with optional display width e.g. INT8 or INT8(11)
///
/// [postgresql]: https://www.postgresql.org/docs/15/datatype.html
Int8(Option<u64>),
/// Unsigned Int8 with optional display width e.g. INT8 UNSIGNED or INT8(11) UNSIGNED
UnsignedInt8(Option<u64>),
/// FLOAT4 as alias for Real in [postgresql]
///
/// [postgresql]: https://www.postgresql.org/docs/15/datatype.html
FLOAT4,
/// Floating point e.g. REAL
Real,
/// FLOAT8 as alias for Double in [postgresql]
///
/// [postgresql]: https://www.postgresql.org/docs/15/datatype.html
FLOAT8,
/// Double
Double,
/// Double PRECISION e.g. [standard], [postgresql]
@ -130,6 +162,10 @@ pub enum DataType {
/// [standard]: https://jakewheat.github.io/sql-overview/sql-2016-foundation-grammar.html#approximate-numeric-type
/// [postgresql]: https://www.postgresql.org/docs/current/datatype-numeric.html
DoublePrecision,
/// Bool as alias for Boolean in [postgresql]
///
/// [postgresql]: https://www.postgresql.org/docs/15/datatype.html
Bool,
/// Boolean
Boolean,
/// Date
@ -213,6 +249,12 @@ impl fmt::Display for DataType {
DataType::UnsignedTinyInt(zerofill) => {
format_type_with_optional_length(f, "TINYINT", zerofill, true)
}
DataType::Int2(zerofill) => {
format_type_with_optional_length(f, "INT2", zerofill, false)
}
DataType::UnsignedInt2(zerofill) => {
format_type_with_optional_length(f, "INT2", zerofill, true)
}
DataType::SmallInt(zerofill) => {
format_type_with_optional_length(f, "SMALLINT", zerofill, false)
}
@ -229,6 +271,12 @@ impl fmt::Display for DataType {
DataType::UnsignedInt(zerofill) => {
format_type_with_optional_length(f, "INT", zerofill, true)
}
DataType::Int4(zerofill) => {
format_type_with_optional_length(f, "INT4", zerofill, false)
}
DataType::UnsignedInt4(zerofill) => {
format_type_with_optional_length(f, "INT4", zerofill, true)
}
DataType::Integer(zerofill) => {
format_type_with_optional_length(f, "INTEGER", zerofill, false)
}
@ -241,9 +289,18 @@ impl fmt::Display for DataType {
DataType::UnsignedBigInt(zerofill) => {
format_type_with_optional_length(f, "BIGINT", zerofill, true)
}
DataType::Int8(zerofill) => {
format_type_with_optional_length(f, "INT8", zerofill, false)
}
DataType::UnsignedInt8(zerofill) => {
format_type_with_optional_length(f, "INT8", zerofill, true)
}
DataType::Real => write!(f, "REAL"),
DataType::FLOAT4 => write!(f, "FLOAT4"),
DataType::Double => write!(f, "DOUBLE"),
DataType::FLOAT8 => write!(f, "FLOAT8"),
DataType::DoublePrecision => write!(f, "DOUBLE PRECISION"),
DataType::Bool => write!(f, "BOOL"),
DataType::Boolean => write!(f, "BOOLEAN"),
DataType::Date => write!(f, "DATE"),
DataType::Time(precision, timezone_info) => {

View file

@ -111,6 +111,7 @@ define_keywords!(
BINARY,
BLOB,
BLOOMFILTER,
BOOL,
BOOLEAN,
BOTH,
BTREE,
@ -263,6 +264,8 @@ define_keywords!(
FIRST,
FIRST_VALUE,
FLOAT,
FLOAT4,
FLOAT8,
FLOOR,
FOLLOWING,
FOR,
@ -317,6 +320,9 @@ define_keywords!(
INSENSITIVE,
INSERT,
INT,
INT2,
INT4,
INT8,
INTEGER,
INTERSECT,
INTERSECTION,

View file

@ -4560,8 +4560,11 @@ impl<'a> Parser<'a> {
let mut data = match next_token.token {
Token::Word(w) => match w.keyword {
Keyword::BOOLEAN => Ok(DataType::Boolean),
Keyword::BOOL => Ok(DataType::Bool),
Keyword::FLOAT => Ok(DataType::Float(self.parse_optional_precision()?)),
Keyword::REAL => Ok(DataType::Real),
Keyword::FLOAT4 => Ok(DataType::FLOAT4),
Keyword::FLOAT8 => Ok(DataType::FLOAT8),
Keyword::DOUBLE => {
if self.parse_keyword(Keyword::PRECISION) {
Ok(DataType::DoublePrecision)
@ -4577,6 +4580,14 @@ impl<'a> Parser<'a> {
Ok(DataType::TinyInt(optional_precision?))
}
}
Keyword::INT2 => {
let optional_precision = self.parse_optional_precision();
if self.parse_keyword(Keyword::UNSIGNED) {
Ok(DataType::UnsignedInt2(optional_precision?))
} else {
Ok(DataType::Int2(optional_precision?))
}
}
Keyword::SMALLINT => {
let optional_precision = self.parse_optional_precision();
if self.parse_keyword(Keyword::UNSIGNED) {
@ -4601,6 +4612,14 @@ impl<'a> Parser<'a> {
Ok(DataType::Int(optional_precision?))
}
}
Keyword::INT4 => {
let optional_precision = self.parse_optional_precision();
if self.parse_keyword(Keyword::UNSIGNED) {
Ok(DataType::UnsignedInt4(optional_precision?))
} else {
Ok(DataType::Int4(optional_precision?))
}
}
Keyword::INTEGER => {
let optional_precision = self.parse_optional_precision();
if self.parse_keyword(Keyword::UNSIGNED) {
@ -4617,6 +4636,14 @@ impl<'a> Parser<'a> {
Ok(DataType::BigInt(optional_precision?))
}
}
Keyword::INT8 => {
let optional_precision = self.parse_optional_precision();
if self.parse_keyword(Keyword::UNSIGNED) {
Ok(DataType::UnsignedInt8(optional_precision?))
} else {
Ok(DataType::Int8(optional_precision?))
}
}
Keyword::VARCHAR => Ok(DataType::Varchar(self.parse_optional_character_length()?)),
Keyword::NVARCHAR => Ok(DataType::Nvarchar(self.parse_optional_precision()?)),
Keyword::CHARACTER => {

View file

@ -2945,3 +2945,74 @@ fn parse_truncate() {
truncate
);
}
#[test]
fn parse_create_table_with_alias() {
let sql = "CREATE TABLE public.datatype_aliases
(
int8_col INT8,
int4_col INT4,
int2_col INT2,
float8_col FLOAT8,
float4_col FLOAT4,
bool_col BOOL,
);";
match pg_and_generic().one_statement_parses_to(sql, "") {
Statement::CreateTable {
name,
columns,
constraints,
with_options: _with_options,
if_not_exists: false,
external: false,
file_format: None,
location: None,
..
} => {
assert_eq!("public.datatype_aliases", name.to_string());
assert_eq!(
columns,
vec![
ColumnDef {
name: "int8_col".into(),
data_type: DataType::Int8(None),
collation: None,
options: vec![]
},
ColumnDef {
name: "int4_col".into(),
data_type: DataType::Int4(None),
collation: None,
options: vec![]
},
ColumnDef {
name: "int2_col".into(),
data_type: DataType::Int2(None),
collation: None,
options: vec![]
},
ColumnDef {
name: "float8_col".into(),
data_type: DataType::FLOAT8,
collation: None,
options: vec![]
},
ColumnDef {
name: "float4_col".into(),
data_type: DataType::FLOAT4,
collation: None,
options: vec![]
},
ColumnDef {
name: "bool_col".into(),
data_type: DataType::Bool,
collation: None,
options: vec![]
},
]
);
assert!(constraints.is_empty());
}
_ => unreachable!(),
}
}