This is an automated email from the ASF dual-hosted git repository.
nicholasjiang pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/paimon-rust.git
The following commit(s) were added to refs/heads/main by this push:
new f051e23 feat: Implement serde for boolean and array (#48)
f051e23 is described below
commit f051e23013a317ae4119a434c329e12095fe2d0f
Author: Xuanwo <[email protected]>
AuthorDate: Sat Aug 10 18:26:37 2024 +0800
feat: Implement serde for boolean and array (#48)
---
crates/paimon/src/spec/schema.rs | 10 +-
crates/paimon/src/spec/types.rs | 401 +++++++++++++++++++++------------------
2 files changed, 216 insertions(+), 195 deletions(-)
diff --git a/crates/paimon/src/spec/schema.rs b/crates/paimon/src/spec/schema.rs
index c2c91a2..349652d 100644
--- a/crates/paimon/src/spec/schema.rs
+++ b/crates/paimon/src/spec/schema.rs
@@ -17,9 +17,8 @@
use crate::spec::types::DataType;
use serde::{Deserialize, Serialize};
-use serde_with::{serde_as, DisplayFromStr};
+use serde_with::serde_as;
use std::collections::HashMap;
-use std::fmt::{Display, Formatter};
/// The table schema for paimon table.
///
@@ -48,7 +47,6 @@ pub struct DataField {
id: i32,
name: String,
#[serde(rename = "type")]
- #[serde_as(as = "DisplayFromStr")]
typ: DataType,
description: Option<String>,
}
@@ -95,12 +93,6 @@ impl DataField {
}
}
-impl Display for DataField {
- fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
- write!(f, "{}", self.typ)
- }
-}
-
pub fn escape_identifier(identifier: &str) -> String {
identifier.replace('"', "\"\"")
}
diff --git a/crates/paimon/src/spec/types.rs b/crates/paimon/src/spec/types.rs
index 84d7115..5039caa 100644
--- a/crates/paimon/src/spec/types.rs
+++ b/crates/paimon/src/spec/types.rs
@@ -18,7 +18,11 @@
use crate::error::*;
use crate::spec::DataField;
use bitflags::bitflags;
-use serde::{Deserialize, Serialize};
+use serde::de::{MapAccess, Visitor};
+use serde::ser::SerializeStruct;
+use serde::{Deserialize, Deserializer, Serialize, Serializer};
+use serde_with::{DeserializeFromStr, SerializeDisplay};
+use std::fmt;
use std::fmt::{Debug, Display, Formatter};
use std::str::FromStr;
@@ -47,7 +51,8 @@ bitflags! {
/// Data type for paimon table.
///
/// Impl Reference:
<https://github.com/apache/paimon/blob/release-0.8.2/paimon-common/src/main/java/org/apache/paimon/types/DataType.java#L45>
-#[derive(Debug, Clone, PartialEq, Eq, Deserialize, Serialize, Hash)]
+#[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize, Deserialize)]
+#[serde(untagged)]
pub enum DataType {
/// Data type of a boolean with a (possibly) three-valued logic of `TRUE`,
`FALSE`, `UNKNOWN`.
Boolean(BooleanType),
@@ -126,63 +131,17 @@ impl DataType {
}
}
-impl Display for DataType {
- fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
- match self {
- DataType::Boolean(v) => write!(f, "{v}"),
- DataType::TinyInt(v) => write!(f, "{v}"),
- DataType::SmallInt(v) => write!(f, "{v}"),
- DataType::Int(v) => write!(f, "{v}"),
- DataType::BigInt(v) => write!(f, "{v}"),
- DataType::Decimal(v) => write!(f, "{v}"),
- DataType::Double(v) => write!(f, "{v}"),
- DataType::Float(v) => write!(f, "{v}"),
- DataType::Binary(v) => write!(f, "{v}"),
- DataType::VarBinary(v) => write!(f, "{v}"),
- DataType::Char(v) => write!(f, "{v}"),
- DataType::VarChar(v) => write!(f, "{v}"),
- DataType::Date(v) => write!(f, "{v}"),
- DataType::LocalZonedTimestamp(v) => write!(f, "{v}"),
- DataType::Time(v) => write!(f, "{v}"),
- DataType::Timestamp(v) => write!(f, "{v}"),
- DataType::Array(v) => write!(f, "{v}"),
- DataType::Map(v) => write!(f, "{v}"),
- DataType::Multiset(v) => write!(f, "{v}"),
- DataType::Row(v) => write!(f, "{v}"),
- }
- }
-}
-
-impl FromStr for DataType {
- type Err = Error;
-
- fn from_str(_: &str) -> Result<Self, Self::Err> {
- todo!()
- }
-}
-
/// ArrayType for paimon.
///
/// Data type of an array of elements with same subtype.
///
/// Impl Reference:
<https://github.com/apache/paimon/blob/release-0.8.2/paimon-common/src/main/java/org/apache/paimon/types/ArrayType.java>.
-#[derive(Debug, Clone, PartialEq, Eq, Deserialize, Serialize, Hash)]
-#[serde(rename_all = "camelCase")]
+#[derive(Debug, Clone, PartialEq, Eq, Hash)]
pub struct ArrayType {
nullable: bool,
element_type: Box<DataType>,
}
-impl Display for ArrayType {
- fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
- write!(f, "ARRAY<{}>", self.element_type)?;
- if !self.nullable {
- write!(f, " NOT NULL")?;
- }
- Ok(())
- }
-}
-
impl ArrayType {
pub fn new(element_type: DataType) -> Self {
Self::with_nullable(true, element_type)
@@ -200,12 +159,94 @@ impl ArrayType {
}
}
+impl Serialize for ArrayType {
+ fn serialize<S>(&self, serializer: S) -> std::result::Result<S::Ok,
S::Error>
+ where
+ S: Serializer,
+ {
+ let mut s = serializer.serialize_struct("ArrayType", 2)?;
+ let typ = if self.nullable {
+ "ARRAY"
+ } else {
+ "ARRAY NOT NULL"
+ };
+ s.serialize_field("type", typ)?;
+ s.serialize_field("element", &self.element_type)?;
+ s.end()
+ }
+}
+
+impl<'de> Deserialize<'de> for ArrayType {
+ fn deserialize<D>(deserializer: D) -> std::result::Result<Self, D::Error>
+ where
+ D: Deserializer<'de>,
+ {
+ #[derive(Deserialize)]
+ #[serde(field_identifier, rename_all = "lowercase")]
+ enum Field {
+ Type,
+ Element,
+ }
+
+ struct ArrayTypeVisitor;
+
+ impl<'de> Visitor<'de> for ArrayTypeVisitor {
+ type Value = ArrayType;
+
+ fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result
{
+ formatter.write_str("ArrayType")
+ }
+
+ fn visit_map<V>(self, mut map: V) ->
std::result::Result<ArrayType, V::Error>
+ where
+ V: MapAccess<'de>,
+ {
+ let mut nullable = None;
+ let mut element: Option<DataType> = None;
+ while let Some(key) = map.next_key()? {
+ match key {
+ Field::Type => {
+ if nullable.is_some() {
+ return
Err(serde::de::Error::duplicate_field("type"));
+ }
+ match map.next_value()? {
+ "ARRAY" => nullable = Some(true),
+ "ARRAY NOT NULL" => nullable = Some(false),
+ v => Err(serde::de::Error::invalid_value(
+ serde::de::Unexpected::Str(v),
+ &"ARRAY or ARRAY NOT NULL",
+ ))?,
+ }
+ }
+ Field::Element => {
+ if element.is_some() {
+ return
Err(serde::de::Error::duplicate_field("element"));
+ }
+ element = Some(map.next_value()?);
+ }
+ }
+ }
+
+ Ok(ArrayType {
+ nullable: nullable.ok_or_else(||
serde::de::Error::missing_field("type"))?,
+ element_type: element
+ .ok_or_else(||
serde::de::Error::missing_field("element"))?
+ .into(),
+ })
+ }
+ }
+
+ const FIELDS: &[&str] = &["type", "element"];
+ deserializer.deserialize_struct("ArrayType", FIELDS, ArrayTypeVisitor)
+ }
+}
+
/// BigIntType for paimon.
///
/// Data type of an 8-byte (2^64) signed integer with values from
-9,223,372,036,854,775,808 to 9,223,372,036,854,775,807.
///
/// Impl Reference:
<https://github.com/apache/paimon/blob/release-0.8.2/paimon-common/src/main/java/org/apache/paimon/types/BigIntType.java>.
-#[derive(Debug, Clone, PartialEq, Eq, Deserialize, Serialize, Hash)]
+#[derive(Debug, Clone, PartialEq, Eq, Deserialize, SerializeDisplay, Hash)]
pub struct BigIntType {
nullable: bool,
}
@@ -248,7 +289,7 @@ impl BigIntType {
/// Data type of a fixed-length binary string (=a sequence of bytes).
///
/// Impl Reference:
<https://github.com/apache/paimon/blob/release-0.8.2/paimon-common/src/main/java/org/apache/paimon/types/BinaryType.java>.
-#[derive(Debug, Clone, PartialEq, Eq, Deserialize, Serialize, Hash)]
+#[derive(Debug, Clone, PartialEq, Eq, Deserialize, SerializeDisplay, Hash)]
#[serde(rename_all = "camelCase")]
pub struct BinaryType {
nullable: bool,
@@ -306,7 +347,7 @@ impl BinaryType {
/// Data type of a boolean with a (possibly) three-valued logic of `TRUE`,
`FALSE`, `UNKNOWN`.
///
/// Impl Reference:
<https://github.com/apache/paimon/blob/master/paimon-common/src/release-0.8.2/java/org/apache/paimon/types/BooleanType.java>.
-#[derive(Debug, Clone, PartialEq, Eq, Deserialize, Serialize, Hash)]
+#[derive(Debug, Clone, PartialEq, Eq, DeserializeFromStr, SerializeDisplay,
Hash)]
pub struct BooleanType {
nullable: bool,
}
@@ -321,6 +362,20 @@ impl Display for BooleanType {
}
}
+impl FromStr for BooleanType {
+ type Err = Error;
+
+ fn from_str(s: &str) -> Result<Self, Self::Err> {
+ match s {
+ "BOOLEAN" => Ok(Self { nullable: true }),
+ "BOOLEAN NOT NULL" => Ok(Self { nullable: false }),
+ v => Err(Error::DataTypeInvalid {
+ message: format!("invalid boolean type: {v}"),
+ })?,
+ }
+ }
+}
+
impl Default for BooleanType {
fn default() -> Self {
Self::new()
@@ -346,7 +401,7 @@ impl BooleanType {
/// Data type of a fixed-length character string.
///
/// Impl Reference:
<https://github.com/apache/paimon/blob/release-0.8.2/paimon-common/src/main/java/org/apache/paimon/types/CharType.java>.
-#[derive(Debug, Clone, PartialEq, Hash, Eq, Deserialize, Serialize)]
+#[derive(Debug, Clone, PartialEq, Hash, Eq, Deserialize, SerializeDisplay)]
#[serde(rename_all = "camelCase")]
pub struct CharType {
nullable: bool,
@@ -404,7 +459,7 @@ impl CharType {
/// Data type of a date consisting of `year-month-day` with values ranging
from `0000-01-01` to `9999-12-31`
///
/// Impl Reference:
<https://github.com/apache/paimon/blob/release-0.8.2/paimon-common/src/main/java/org/apache/paimon/types/DateType.java>.
-#[derive(Debug, Clone, PartialEq, Hash, Eq, Deserialize, Serialize)]
+#[derive(Debug, Clone, PartialEq, Hash, Eq, Deserialize, SerializeDisplay)]
pub struct DateType {
nullable: bool,
}
@@ -444,7 +499,7 @@ impl DateType {
/// Data type of a decimal number with fixed precision and scale.
///
/// Impl Reference:
<https://github.com/apache/paimon/blob/release-0.8.2/paimon-common/src/main/java/org/apache/paimon/types/DecimalType.java>.
-#[derive(Debug, Clone, PartialEq, Eq, Deserialize, Serialize, Hash)]
+#[derive(Debug, Clone, PartialEq, Eq, Deserialize, SerializeDisplay, Hash)]
pub struct DecimalType {
nullable: bool,
@@ -531,7 +586,7 @@ impl DecimalType {
/// Data type of an 8-byte double precision floating point number.
///
/// Impl Reference:
<https://github.com/apache/paimon/blob/release-0.8.2/paimon-common/src/main/java/org/apache/paimon/types/DoubleType.java>.
-#[derive(Debug, Clone, PartialEq, Eq, Deserialize, Serialize, Hash)]
+#[derive(Debug, Clone, PartialEq, Eq, Deserialize, SerializeDisplay, Hash)]
pub struct DoubleType {
nullable: bool,
}
@@ -569,7 +624,7 @@ impl DoubleType {
/// FloatType for paimon.
///
/// Impl Reference:
<https://github.com/apache/paimon/blob/release-0.8.2/paimon-common/src/main/java/org/apache/paimon/types/FloatType.java>.
-#[derive(Debug, Clone, PartialEq, Eq, Deserialize, Serialize, Hash)]
+#[derive(Debug, Clone, PartialEq, Eq, Deserialize, SerializeDisplay, Hash)]
pub struct FloatType {
nullable: bool,
}
@@ -609,7 +664,7 @@ impl FloatType {
/// Data type of a 4-byte (2^32) signed integer with values from
-2,147,483,648 to 2,147,483,647.
///
/// Impl Reference:
<https://github.com/apache/paimon/blob/release-0.8.2/paimon-common/src/main/java/org/apache/paimon/types/IntType.java>.
-#[derive(Debug, Clone, PartialEq, Eq, Deserialize, Serialize, Hash)]
+#[derive(Debug, Clone, PartialEq, Eq, Deserialize, SerializeDisplay, Hash)]
pub struct IntType {
nullable: bool,
}
@@ -652,7 +707,7 @@ impl IntType {
/// Data type of a timestamp WITH LOCAL time zone consisting of
`year-month-day hour:minute:second[.fractional] zone` with up to nanosecond
precision and values ranging from `0000-01-01 00:00:00.000000000 +14:59` to
`9999-12-31 23:59:59.999999999 -14:59`. Leap seconds (23:59:60 and 23:59:61)
are not supported as the semantics are closer to a point in time than a
wall-clock time.
///
/// Impl Reference:
<https://github.com/apache/paimon/blob/release-0.8.2/paimon-common/src/main/java/org/apache/paimon/types/TimestampType.java>.
-#[derive(Debug, Clone, PartialEq, Eq, Deserialize, Serialize, Hash)]
+#[derive(Debug, Clone, PartialEq, Eq, Deserialize, SerializeDisplay, Hash)]
pub struct LocalZonedTimestampType {
nullable: bool,
precision: u32,
@@ -720,7 +775,7 @@ impl LocalZonedTimestampType {
/// Data type of a 2-byte (2^16) signed integer with values from -32,768 to
32,767.
///
/// Impl Reference:
<https://github.com/apache/paimon/blob/release-0.8.2/paimon-common/src/main/java/org/apache/paimon/types/SmallIntType.java>.
-#[derive(Debug, Clone, PartialEq, Eq, Deserialize, Serialize, Hash)]
+#[derive(Debug, Clone, PartialEq, Eq, Deserialize, SerializeDisplay, Hash)]
pub struct SmallIntType {
nullable: bool,
}
@@ -764,7 +819,7 @@ impl SmallIntType {
/// up to nanosecond precision and values ranging from `00:00:00.000000000` to
`23:59:59.999999999`.
///
/// Impl Reference:
<https://github.com/apache/paimon/blob/release-0.8.2/paimon-common/src/main/java/org/apache/paimon/types/TimeType.java>.
-#[derive(Debug, Clone, PartialEq, Eq, Deserialize, Serialize, Hash)]
+#[derive(Debug, Clone, PartialEq, Eq, Deserialize, SerializeDisplay, Hash)]
pub struct TimeType {
nullable: bool,
precision: u32,
@@ -829,7 +884,7 @@ impl TimeType {
/// Data type of a timestamp WITHOUT time zone consisting of `year-month-day
hour:minute:second[.fractional]` with up to nanosecond precision and values
ranging from `0000-01-01 00:00:00.000000000` to `9999-12-31 23:59:59.999999999`.
///
/// Impl Reference:
<https://github.com/apache/paimon/blob/release-0.8.2/paimon-common/src/main/java/org/apache/paimon/types/TimestampType.java>.
-#[derive(Debug, Clone, PartialEq, Eq, Deserialize, Serialize, Hash)]
+#[derive(Debug, Clone, PartialEq, Eq, Deserialize, SerializeDisplay, Hash)]
pub struct TimestampType {
nullable: bool,
precision: u32,
@@ -894,7 +949,7 @@ impl TimestampType {
/// Data type of a 1-byte signed integer with values from -128 to 127.
///
/// Impl Reference:
<https://github.com/apache/paimon/blob/master/paimon-common/src/release-0.8.2/java/org/apache/paimon/types/TinyIntType.java>.
-#[derive(Debug, Clone, PartialEq, Eq, Deserialize, Serialize, Hash)]
+#[derive(Debug, Clone, PartialEq, Eq, Deserialize, SerializeDisplay, Hash)]
pub struct TinyIntType {
nullable: bool,
}
@@ -937,7 +992,7 @@ impl TinyIntType {
/// Data type of a variable-length binary string (=a sequence of bytes).
///
/// Impl Reference:
<https://github.com/apache/paimon/blob/release-0.8.2/paimon-common/src/main/java/org/apache/paimon/types/VarBinaryType.java>.
-#[derive(Debug, Clone, PartialEq, Eq, Deserialize, Serialize, Hash)]
+#[derive(Debug, Clone, PartialEq, Eq, Deserialize, SerializeDisplay, Hash)]
pub struct VarBinaryType {
nullable: bool,
length: u32,
@@ -995,7 +1050,7 @@ impl VarBinaryType {
/// Data type of a variable-length character string.
///
/// Impl Reference:
<https://github.com/apache/paimon/blob/release-0.8.2/paimon-common/src/main/java/org/apache/paimon/types/VarCharType.java>.
-#[derive(Debug, Clone, PartialEq, Eq, Deserialize, Serialize, Hash)]
+#[derive(Debug, Clone, PartialEq, Eq, Deserialize, SerializeDisplay, Hash)]
pub struct VarCharType {
nullable: bool,
length: u32,
@@ -1064,16 +1119,6 @@ pub struct MapType {
value_type: Box<DataType>,
}
-impl Display for MapType {
- fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
- write!(f, "MAP<{}, {}>", self.key_type, self.value_type)?;
- if !self.nullable {
- write!(f, " NOT NULL")?;
- }
- Ok(())
- }
-}
-
impl MapType {
pub fn new(key_type: DataType, value_type: DataType) -> Self {
Self::with_nullable(true, key_type, value_type)
@@ -1104,16 +1149,6 @@ pub struct MultisetType {
element_type: Box<DataType>,
}
-impl Display for MultisetType {
- fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
- write!(f, "MULTISET<{}>", self.element_type)?;
- if !self.nullable {
- write!(f, " NOT NULL")?;
- }
- Ok(())
- }
-}
-
impl MultisetType {
pub fn new(element_type: DataType) -> Self {
Self::with_nullable(true, element_type)
@@ -1145,22 +1180,6 @@ pub struct RowType {
fields: Vec<DataField>,
}
-impl Display for RowType {
- fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
- let fields = self
- .fields
- .iter()
- .map(|field| field.to_string())
- .collect::<Vec<String>>()
- .join(", ");
- write!(f, "ROW<{}>", fields)?;
- if !self.nullable {
- write!(f, " NOT NULL")?;
- }
- Ok(())
- }
-}
-
impl RowType {
pub const fn new(fields: Vec<DataField>) -> Self {
Self::with_nullable(true, fields)
@@ -1182,160 +1201,170 @@ mod tests {
#[test]
fn test_data_type_to_string() {
+ assert_eq!(BooleanType::with_nullable(true).to_string(), "BOOLEAN");
assert_eq!(
- DataType::Boolean(BooleanType::with_nullable(true)).to_string(),
- "BOOLEAN"
- );
- assert_eq!(
- DataType::Boolean(BooleanType::with_nullable(false)).to_string(),
+ BooleanType::with_nullable(false).to_string(),
"BOOLEAN NOT NULL"
);
+ assert_eq!(TinyIntType::with_nullable(true).to_string(), "TINYINT");
assert_eq!(
- DataType::TinyInt(TinyIntType::with_nullable(true)).to_string(),
- "TINYINT"
- );
- assert_eq!(
- DataType::TinyInt(TinyIntType::with_nullable(false)).to_string(),
+ TinyIntType::with_nullable(false).to_string(),
"TINYINT NOT NULL"
);
+ assert_eq!(SmallIntType::with_nullable(true).to_string(), "SMALLINT");
assert_eq!(
- DataType::SmallInt(SmallIntType::with_nullable(true)).to_string(),
- "SMALLINT"
- );
- assert_eq!(
- DataType::SmallInt(SmallIntType::with_nullable(false)).to_string(),
+ SmallIntType::with_nullable(false).to_string(),
"SMALLINT NOT NULL"
);
+ assert_eq!(IntType::with_nullable(true).to_string(), "INTEGER");
assert_eq!(
- DataType::Int(IntType::with_nullable(true)).to_string(),
- "INTEGER"
- );
- assert_eq!(
- DataType::Int(IntType::with_nullable(false)).to_string(),
+ IntType::with_nullable(false).to_string(),
"INTEGER NOT NULL"
);
+ assert_eq!(BigIntType::with_nullable(true).to_string(), "BIGINT");
assert_eq!(
- DataType::BigInt(BigIntType::with_nullable(true)).to_string(),
- "BIGINT"
- );
- assert_eq!(
- DataType::BigInt(BigIntType::with_nullable(false)).to_string(),
+ BigIntType::with_nullable(false).to_string(),
"BIGINT NOT NULL"
);
assert_eq!(
- DataType::Decimal(DecimalType::with_nullable(true, 10,
2).unwrap()).to_string(),
+ DecimalType::with_nullable(true, 10, 2).unwrap().to_string(),
"DECIMAL(10, 2)"
);
assert_eq!(
- DataType::Decimal(DecimalType::with_nullable(false, 10,
2).unwrap()).to_string(),
+ DecimalType::with_nullable(false, 10, 2)
+ .unwrap()
+ .to_string(),
"DECIMAL(10, 2) NOT NULL"
);
+ assert_eq!(DoubleType::with_nullable(true).to_string(), "DOUBLE");
assert_eq!(
- DataType::Double(DoubleType::with_nullable(true)).to_string(),
- "DOUBLE"
- );
- assert_eq!(
- DataType::Double(DoubleType::with_nullable(false)).to_string(),
+ DoubleType::with_nullable(false).to_string(),
"DOUBLE NOT NULL"
);
+ assert_eq!(FloatType::with_nullable(true).to_string(), "FLOAT");
assert_eq!(
- DataType::Float(FloatType::with_nullable(true)).to_string(),
- "FLOAT"
- );
- assert_eq!(
- DataType::Float(FloatType::with_nullable(false)).to_string(),
+ FloatType::with_nullable(false).to_string(),
"FLOAT NOT NULL"
);
assert_eq!(
- DataType::Binary(BinaryType::with_nullable(true,
10).unwrap()).to_string(),
+ BinaryType::with_nullable(true, 10).unwrap().to_string(),
"BINARY(10)"
);
assert_eq!(
- DataType::Binary(BinaryType::with_nullable(false,
10).unwrap()).to_string(),
+ BinaryType::with_nullable(false, 10).unwrap().to_string(),
"BINARY(10) NOT NULL"
);
assert_eq!(
- DataType::VarBinary(VarBinaryType::try_new(true,
10).unwrap()).to_string(),
+ VarBinaryType::try_new(true, 10).unwrap().to_string(),
"VARBINARY(10)"
);
assert_eq!(
- DataType::VarBinary(VarBinaryType::try_new(false,
10).unwrap()).to_string(),
+ VarBinaryType::try_new(false, 10).unwrap().to_string(),
"VARBINARY(10) NOT NULL"
);
assert_eq!(
- DataType::Char(CharType::with_nullable(true,
10).unwrap()).to_string(),
+ CharType::with_nullable(true, 10).unwrap().to_string(),
"CHAR(10)"
);
assert_eq!(
- DataType::Char(CharType::with_nullable(false,
10).unwrap()).to_string(),
+ CharType::with_nullable(false, 10).unwrap().to_string(),
"CHAR(10) NOT NULL"
);
assert_eq!(
- DataType::VarChar(VarCharType::with_nullable(true,
10).unwrap()).to_string(),
+ VarCharType::with_nullable(true, 10).unwrap().to_string(),
"VARCHAR(10)"
);
assert_eq!(
- DataType::VarChar(VarCharType::with_nullable(false,
10).unwrap()).to_string(),
+ VarCharType::with_nullable(false, 10).unwrap().to_string(),
"VARCHAR(10) NOT NULL"
);
+ assert_eq!(DateType::with_nullable(true).to_string(), "DATE");
+ assert_eq!(DateType::with_nullable(false).to_string(), "DATE NOT
NULL");
assert_eq!(
- DataType::Date(DateType::with_nullable(true)).to_string(),
- "DATE"
- );
- assert_eq!(
- DataType::Date(DateType::with_nullable(false)).to_string(),
- "DATE NOT NULL"
- );
- assert_eq!(
-
DataType::LocalZonedTimestamp(LocalZonedTimestampType::with_nullable(true,
6).unwrap())
+ LocalZonedTimestampType::with_nullable(true, 6)
+ .unwrap()
.to_string(),
"TIMESTAMP WITH LOCAL TIME ZONE(6)"
);
assert_eq!(
- DataType::LocalZonedTimestamp(
- LocalZonedTimestampType::with_nullable(false, 6).unwrap()
- )
- .to_string(),
+ LocalZonedTimestampType::with_nullable(false, 6)
+ .unwrap()
+ .to_string(),
"TIMESTAMP WITH LOCAL TIME ZONE(6) NOT NULL"
);
assert_eq!(
- DataType::Time(TimeType::with_nullable(true,
6).unwrap()).to_string(),
+ TimeType::with_nullable(true, 6).unwrap().to_string(),
"TIME(6)"
);
assert_eq!(
- DataType::Time(TimeType::with_nullable(false,
6).unwrap()).to_string(),
+ TimeType::with_nullable(false, 6).unwrap().to_string(),
"TIME(6) NOT NULL"
);
assert_eq!(
- DataType::Timestamp(TimestampType::with_nullable(false,
6).unwrap()).to_string(),
+ TimestampType::with_nullable(false, 6).unwrap().to_string(),
"TIMESTAMP(6) NOT NULL"
);
assert_eq!(
- DataType::Timestamp(TimestampType::with_nullable(true,
6).unwrap()).to_string(),
+ TimestampType::with_nullable(true, 6).unwrap().to_string(),
"TIMESTAMP(6)"
);
- let int_type = DataType::Int(IntType::with_nullable(true));
- let arr_type = DataType::Array(ArrayType::with_nullable(true,
int_type.clone()));
- assert_eq!(arr_type.to_string(), "ARRAY<INTEGER>");
- assert_eq!(
- DataType::Array(ArrayType::with_nullable(true,
arr_type.clone())).to_string(),
- "ARRAY<ARRAY<INTEGER>>"
- );
- let map_type = DataType::Map(MapType::with_nullable(
- true,
- int_type.clone(),
- arr_type.clone(),
- ));
- assert_eq!(map_type.to_string(), "MAP<INTEGER, ARRAY<INTEGER>>");
- let multiset_type =
DataType::Multiset(MultisetType::with_nullable(true, int_type.clone()));
- assert_eq!(multiset_type.to_string(), "MULTISET<INTEGER>");
- let row_type = DataType::Row(RowType::with_nullable(
- true,
- vec![
- DataField::new(1, "a".to_string(), int_type.clone()),
- DataField::new(2, "b".to_string(), arr_type.clone()),
- ],
- ));
- assert_eq!(row_type.to_string(), "ROW<INTEGER, ARRAY<INTEGER>>");
+ }
+
+ /// TODO: replace expect with exist fixture.
+ #[test]
+ fn test_data_type_serialize() {
+ // name, input, expect.
+ let cases = vec![
+ (
+ "boolean",
+ DataType::Boolean(BooleanType::with_nullable(true)),
+ r#""BOOLEAN""#,
+ ),
+ (
+ "array with boolean",
+ DataType::Array(ArrayType {
+ nullable: false,
+ element_type:
DataType::Boolean(BooleanType::with_nullable(false)).into(),
+ }),
+ r#"{"type":"ARRAY NOT NULL","element":"BOOLEAN NOT NULL"}"#,
+ ),
+ ];
+
+ for (name, input, expect) in cases {
+ assert_eq!(
+ serde_json::to_string(&input).unwrap(),
+ expect,
+ "test data type serialize for {name}"
+ )
+ }
+ }
+
+ /// TODO: replace expect with exist fixture.
+ #[test]
+ fn test_data_type_deserialize() {
+ // name, input, expect.
+ let cases = vec![
+ (
+ "boolean",
+ r#""BOOLEAN""#,
+ DataType::Boolean(BooleanType::with_nullable(true)),
+ ),
+ (
+ "array with boolean",
+ r#"{"type":"ARRAY NOT NULL","element":"BOOLEAN NOT NULL"}"#,
+ DataType::Array(ArrayType {
+ nullable: false,
+ element_type:
DataType::Boolean(BooleanType::with_nullable(false)).into(),
+ }),
+ ),
+ ];
+
+ for (name, input, expect) in cases {
+ assert_eq!(
+ serde_json::from_str::<DataType>(input).unwrap(),
+ expect,
+ "test data type deserialize for {name}"
+ )
+ }
}
}