in crates/iceberg/src/arrow/value.rs [203:425]
fn primitive(&mut self, p: &PrimitiveType, partner: &ArrayRef) -> Result<Vec<Option<Literal>>> {
match p {
PrimitiveType::Boolean => {
let array = partner
.as_any()
.downcast_ref::<BooleanArray>()
.ok_or_else(|| {
Error::new(ErrorKind::DataInvalid, "The partner is not a boolean array")
})?;
Ok(array.iter().map(|v| v.map(Literal::bool)).collect())
}
PrimitiveType::Int => {
let array = partner
.as_any()
.downcast_ref::<Int32Array>()
.ok_or_else(|| {
Error::new(ErrorKind::DataInvalid, "The partner is not a int32 array")
})?;
Ok(array.iter().map(|v| v.map(Literal::int)).collect())
}
PrimitiveType::Long => {
let array = partner
.as_any()
.downcast_ref::<Int64Array>()
.ok_or_else(|| {
Error::new(ErrorKind::DataInvalid, "The partner is not a int64 array")
})?;
Ok(array.iter().map(|v| v.map(Literal::long)).collect())
}
PrimitiveType::Float => {
let array = partner
.as_any()
.downcast_ref::<Float32Array>()
.ok_or_else(|| {
Error::new(ErrorKind::DataInvalid, "The partner is not a float32 array")
})?;
Ok(array.iter().map(|v| v.map(Literal::float)).collect())
}
PrimitiveType::Double => {
let array = partner
.as_any()
.downcast_ref::<Float64Array>()
.ok_or_else(|| {
Error::new(ErrorKind::DataInvalid, "The partner is not a float64 array")
})?;
Ok(array.iter().map(|v| v.map(Literal::double)).collect())
}
PrimitiveType::Decimal { precision, scale } => {
let array = partner
.as_any()
.downcast_ref::<Decimal128Array>()
.ok_or_else(|| {
Error::new(
ErrorKind::DataInvalid,
"The partner is not a decimal128 array",
)
})?;
if let DataType::Decimal128(arrow_precision, arrow_scale) = array.data_type() {
if *arrow_precision as u32 != *precision || *arrow_scale as u32 != *scale {
return Err(Error::new(
ErrorKind::DataInvalid,
format!(
"The precision or scale ({},{}) of arrow decimal128 array is not compatitable with iceberg decimal type ({},{})",
arrow_precision, arrow_scale, precision, scale
),
));
}
}
Ok(array.iter().map(|v| v.map(Literal::decimal)).collect())
}
PrimitiveType::Date => {
let array = partner
.as_any()
.downcast_ref::<Date32Array>()
.ok_or_else(|| {
Error::new(ErrorKind::DataInvalid, "The partner is not a date32 array")
})?;
Ok(array.iter().map(|v| v.map(Literal::date)).collect())
}
PrimitiveType::Time => {
let array = partner
.as_any()
.downcast_ref::<Time64MicrosecondArray>()
.ok_or_else(|| {
Error::new(ErrorKind::DataInvalid, "The partner is not a time64 array")
})?;
Ok(array.iter().map(|v| v.map(Literal::time)).collect())
}
PrimitiveType::Timestamp => {
let array = partner
.as_any()
.downcast_ref::<TimestampMicrosecondArray>()
.ok_or_else(|| {
Error::new(
ErrorKind::DataInvalid,
"The partner is not a timestamp array",
)
})?;
Ok(array.iter().map(|v| v.map(Literal::timestamp)).collect())
}
PrimitiveType::Timestamptz => {
let array = partner
.as_any()
.downcast_ref::<TimestampMicrosecondArray>()
.ok_or_else(|| {
Error::new(
ErrorKind::DataInvalid,
"The partner is not a timestamptz array",
)
})?;
Ok(array.iter().map(|v| v.map(Literal::timestamptz)).collect())
}
PrimitiveType::TimestampNs => {
let array = partner
.as_any()
.downcast_ref::<TimestampNanosecondArray>()
.ok_or_else(|| {
Error::new(
ErrorKind::DataInvalid,
"The partner is not a timestamp_ns array",
)
})?;
Ok(array
.iter()
.map(|v| v.map(Literal::timestamp_nano))
.collect())
}
PrimitiveType::TimestamptzNs => {
let array = partner
.as_any()
.downcast_ref::<TimestampNanosecondArray>()
.ok_or_else(|| {
Error::new(
ErrorKind::DataInvalid,
"The partner is not a timestamptz_ns array",
)
})?;
Ok(array
.iter()
.map(|v| v.map(Literal::timestamptz_nano))
.collect())
}
PrimitiveType::String => {
if let Some(array) = partner.as_any().downcast_ref::<LargeStringArray>() {
Ok(array.iter().map(|v| v.map(Literal::string)).collect())
} else if let Some(array) = partner.as_any().downcast_ref::<StringArray>() {
Ok(array.iter().map(|v| v.map(Literal::string)).collect())
} else {
return Err(Error::new(
ErrorKind::DataInvalid,
"The partner is not a string array",
));
}
}
PrimitiveType::Uuid => {
if let Some(array) = partner.as_any().downcast_ref::<FixedSizeBinaryArray>() {
if array.value_length() != 16 {
return Err(Error::new(
ErrorKind::DataInvalid,
"The partner is not a uuid array",
));
}
Ok(array
.iter()
.map(|v| {
v.map(|v| {
Ok(Literal::uuid(Uuid::from_bytes(v.try_into().map_err(
|_| {
Error::new(
ErrorKind::DataInvalid,
"Failed to convert binary to uuid",
)
},
)?)))
})
.transpose()
})
.collect::<Result<Vec<_>>>()?)
} else {
Err(Error::new(
ErrorKind::DataInvalid,
"The partner is not a uuid array",
))
}
}
PrimitiveType::Fixed(len) => {
let array = partner
.as_any()
.downcast_ref::<FixedSizeBinaryArray>()
.ok_or_else(|| {
Error::new(ErrorKind::DataInvalid, "The partner is not a fixed array")
})?;
if array.value_length() != *len as i32 {
return Err(Error::new(
ErrorKind::DataInvalid,
"The length of fixed size binary array is not compatitable with iceberg fixed type",
));
}
Ok(array
.iter()
.map(|v| v.map(|v| Literal::fixed(v.iter().cloned())))
.collect())
}
PrimitiveType::Binary => {
if let Some(array) = partner.as_any().downcast_ref::<LargeBinaryArray>() {
Ok(array
.iter()
.map(|v| v.map(|v| Literal::binary(v.to_vec())))
.collect())
} else if let Some(array) = partner.as_any().downcast_ref::<BinaryArray>() {
Ok(array
.iter()
.map(|v| v.map(|v| Literal::binary(v.to_vec())))
.collect())
} else {
return Err(Error::new(
ErrorKind::DataInvalid,
"The partner is not a binary array",
));
}
}
}
}