use std::sync::Arc;
use arrow_schema::DataType;
use crate::liquid_array::Date32Field;
#[derive(Debug, Clone, PartialEq, Eq, Hash, serde::Serialize)]
pub struct VariantRequest {
path: Arc<str>,
data_type: Arc<DataType>,
}
impl VariantRequest {
pub fn new(path: impl Into<Arc<str>>, data_type: DataType) -> Self {
Self {
path: path.into(),
data_type: Arc::new(data_type),
}
}
pub fn path(&self) -> &str {
self.path.as_ref()
}
pub fn data_type(&self) -> &DataType {
self.data_type.as_ref()
}
}
#[derive(Debug, Clone, PartialEq, Eq, Hash, serde::Serialize)]
pub enum CacheExpression {
ExtractDate32 {
field: Date32Field,
},
VariantGet {
requests: Arc<[VariantRequest]>,
},
PredicateColumn,
SubstringSearch,
}
impl std::fmt::Display for CacheExpression {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
Self::VariantGet { requests } => {
write!(f, "VariantGet[")?;
let requests = requests
.iter()
.map(|request| format!("{}:{}", request.path(), request.data_type()))
.collect::<Vec<_>>();
write!(f, "{}", requests.join(","))?;
write!(f, "]")
}
Self::ExtractDate32 { field } => {
write!(f, "ExtractDate32:{:?}", field)
}
Self::PredicateColumn => {
write!(f, "PredicateColumn")
}
Self::SubstringSearch => {
write!(f, "SubstringSearch")
}
}
}
}
impl CacheExpression {
pub fn extract_date32(field: Date32Field) -> Self {
Self::ExtractDate32 { field }
}
pub fn variant_get(path: impl Into<Arc<str>>, data_type: DataType) -> Self {
Self::VariantGet {
requests: Arc::from(vec![VariantRequest::new(path, data_type)].into_boxed_slice()),
}
}
pub fn variant_get_many<I, S>(requests: I) -> Self
where
I: IntoIterator<Item = (S, DataType)>,
S: Into<Arc<str>>,
{
let requests: Vec<VariantRequest> = requests
.into_iter()
.map(|(path, data_type)| VariantRequest::new(path.into(), data_type))
.collect();
assert!(
!requests.is_empty(),
"variant_get_many requires at least one path"
);
Self::VariantGet {
requests: Arc::from(requests.into_boxed_slice()),
}
}
pub fn substring_search() -> Self {
Self::SubstringSearch
}
pub fn try_from_date_part_str(value: &str) -> Option<Self> {
let upper = value.to_ascii_uppercase();
let field = match upper.as_str() {
"YEAR" => Date32Field::Year,
"MONTH" => Date32Field::Month,
"DAY" => Date32Field::Day,
"DOW" | "DAYOFWEEK" | "DAY_OF_WEEK" => Date32Field::DayOfWeek,
_ => return None,
};
Some(Self::ExtractDate32 { field })
}
pub fn as_date32_field(&self) -> Option<Date32Field> {
match self {
Self::ExtractDate32 { field } => Some(*field),
Self::VariantGet { .. } | Self::PredicateColumn | Self::SubstringSearch => None,
}
}
pub fn variant_path(&self) -> Option<&str> {
match self {
Self::VariantGet { requests } => requests.first().map(|request| request.path()),
Self::ExtractDate32 { .. } | Self::PredicateColumn | Self::SubstringSearch => None,
}
}
pub fn variant_data_type(&self) -> Option<&DataType> {
match self {
Self::VariantGet { requests } => requests.first().map(|request| request.data_type()),
Self::ExtractDate32 { .. } | Self::PredicateColumn | Self::SubstringSearch => None,
}
}
pub fn variant_requests(&self) -> Option<&[VariantRequest]> {
match self {
Self::VariantGet { requests } => Some(requests.as_ref()),
Self::ExtractDate32 { .. } | Self::PredicateColumn | Self::SubstringSearch => None,
}
}
}