proof_of_sql/base/arrow/
column_arrow_conversions.rsuse crate::base::{
database::{ColumnField, ColumnType},
math::decimal::Precision,
};
use alloc::sync::Arc;
use arrow::datatypes::{DataType, Field, TimeUnit as ArrowTimeUnit};
use proof_of_sql_parser::posql_time::{PoSQLTimeUnit, PoSQLTimeZone};
impl From<&ColumnType> for DataType {
fn from(column_type: &ColumnType) -> Self {
match column_type {
ColumnType::Boolean => DataType::Boolean,
ColumnType::TinyInt => DataType::Int8,
ColumnType::SmallInt => DataType::Int16,
ColumnType::Int => DataType::Int32,
ColumnType::BigInt => DataType::Int64,
ColumnType::Int128 => DataType::Decimal128(38, 0),
ColumnType::Decimal75(precision, scale) => {
DataType::Decimal256(precision.value(), *scale)
}
ColumnType::VarChar => DataType::Utf8,
ColumnType::Scalar => unimplemented!("Cannot convert Scalar type to arrow type"),
ColumnType::TimestampTZ(timeunit, timezone) => {
let arrow_timezone = Some(Arc::from(timezone.to_string()));
let arrow_timeunit = match timeunit {
PoSQLTimeUnit::Second => ArrowTimeUnit::Second,
PoSQLTimeUnit::Millisecond => ArrowTimeUnit::Millisecond,
PoSQLTimeUnit::Microsecond => ArrowTimeUnit::Microsecond,
PoSQLTimeUnit::Nanosecond => ArrowTimeUnit::Nanosecond,
};
DataType::Timestamp(arrow_timeunit, arrow_timezone)
}
}
}
}
impl TryFrom<DataType> for ColumnType {
type Error = String;
fn try_from(data_type: DataType) -> Result<Self, Self::Error> {
match data_type {
DataType::Boolean => Ok(ColumnType::Boolean),
DataType::Int8 => Ok(ColumnType::TinyInt),
DataType::Int16 => Ok(ColumnType::SmallInt),
DataType::Int32 => Ok(ColumnType::Int),
DataType::Int64 => Ok(ColumnType::BigInt),
DataType::Decimal128(38, 0) => Ok(ColumnType::Int128),
DataType::Decimal256(precision, scale) if precision <= 75 => {
Ok(ColumnType::Decimal75(Precision::new(precision)?, scale))
}
DataType::Timestamp(time_unit, timezone_option) => {
let posql_time_unit = match time_unit {
ArrowTimeUnit::Second => PoSQLTimeUnit::Second,
ArrowTimeUnit::Millisecond => PoSQLTimeUnit::Millisecond,
ArrowTimeUnit::Microsecond => PoSQLTimeUnit::Microsecond,
ArrowTimeUnit::Nanosecond => PoSQLTimeUnit::Nanosecond,
};
Ok(ColumnType::TimestampTZ(
posql_time_unit,
PoSQLTimeZone::try_from(&timezone_option)?,
))
}
DataType::Utf8 => Ok(ColumnType::VarChar),
_ => Err(format!("Unsupported arrow data type {data_type:?}")),
}
}
}
impl From<&ColumnField> for Field {
fn from(column_field: &ColumnField) -> Self {
Field::new(
column_field.name().name(),
(&column_field.data_type()).into(),
false,
)
}
}