risingwave_common/types/
map_type.rsuse std::fmt::Formatter;
use anyhow::Context;
use super::*;
#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub struct MapType(Box<(DataType, DataType)>);
impl From<MapType> for DataType {
fn from(value: MapType) -> Self {
DataType::Map(value)
}
}
impl MapType {
pub fn from_kv(key: DataType, value: DataType) -> Self {
Self::check_key_type_valid(&key).unwrap();
Self(Box::new((key, value)))
}
pub fn try_from_kv(key: DataType, value: DataType) -> Result<Self, String> {
Self::check_key_type_valid(&key)?;
Ok(Self(Box::new((key, value))))
}
pub fn try_from_entries(list_entries_type: DataType) -> Result<Self, String> {
match list_entries_type {
DataType::Struct(s) => {
let Some((k, v)) = s.iter().collect_tuple() else {
return Err(format!(
"the underlying struct for map must have exactly two fields, got: {s:?}"
));
};
Self::try_from_kv(k.1.clone(), v.1.clone())
}
_ => Err(format!(
"invalid map entries type, expected struct, got: {list_entries_type}"
)),
}
}
pub fn from_entries(list_entries_type: DataType) -> Self {
Self::try_from_entries(list_entries_type).unwrap()
}
pub fn struct_type_for_map(key_type: DataType, value_type: DataType) -> StructType {
MapType::check_key_type_valid(&key_type).unwrap();
StructType::new(vec![("key", key_type), ("value", value_type)])
}
pub fn key(&self) -> &DataType {
&self.0 .0
}
pub fn value(&self) -> &DataType {
&self.0 .1
}
pub fn into_struct(self) -> DataType {
let (key, value) = *self.0;
DataType::Struct(Self::struct_type_for_map(key, value))
}
pub fn into_list(self) -> DataType {
DataType::List(Box::new(self.into_struct()))
}
pub fn check_key_type_valid(data_type: &DataType) -> Result<(), String> {
let ok = match data_type {
DataType::Int16 | DataType::Int32 | DataType::Int64 => true,
DataType::Varchar => true,
DataType::Boolean
| DataType::Float32
| DataType::Float64
| DataType::Decimal
| DataType::Date
| DataType::Time
| DataType::Timestamp
| DataType::Timestamptz
| DataType::Interval
| DataType::Struct(_)
| DataType::List(_)
| DataType::Bytea
| DataType::Jsonb
| DataType::Serial
| DataType::Int256
| DataType::Map(_) => false,
};
if !ok {
Err(format!("invalid map key type: {data_type}"))
} else {
Ok(())
}
}
}
impl FromStr for MapType {
type Err = anyhow::Error;
fn from_str(s: &str) -> Result<Self, Self::Err> {
if !(s.starts_with("map(") && s.ends_with(')')) {
return Err(anyhow::anyhow!("expect map(...,...)"));
};
if let Some((key, value)) = s[4..s.len() - 1].split(',').collect_tuple() {
let key = key.parse().context("failed to parse map key type")?;
let value = value.parse().context("failed to parse map value type")?;
MapType::try_from_kv(key, value).map_err(|e| anyhow::anyhow!(e))
} else {
Err(anyhow::anyhow!("expect map(...,...)"))
}
}
}
impl std::fmt::Display for MapType {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
write!(f, "map({},{})", self.key(), self.value())
}
}