liquid_cache/cache/
expressions.rs1use std::sync::Arc;
4
5use arrow_schema::DataType;
6
7use crate::liquid_array::Date32Field;
8
9#[derive(Debug, Clone, PartialEq, Eq, Hash, serde::Serialize)]
11pub struct VariantRequest {
12 path: Arc<str>,
13 data_type: Arc<DataType>,
14}
15
16impl VariantRequest {
17 pub fn new(path: impl Into<Arc<str>>, data_type: DataType) -> Self {
19 Self {
20 path: path.into(),
21 data_type: Arc::new(data_type),
22 }
23 }
24
25 pub fn path(&self) -> &str {
27 self.path.as_ref()
28 }
29
30 pub fn data_type(&self) -> &DataType {
32 self.data_type.as_ref()
33 }
34}
35
36#[derive(Debug, Clone, PartialEq, Eq, Hash, serde::Serialize)]
38pub enum CacheExpression {
39 ExtractDate32 {
41 field: Date32Field,
43 },
44 VariantGet {
46 requests: Arc<[VariantRequest]>,
48 },
49 PredicateColumn,
51 SubstringSearch,
53}
54
55impl std::fmt::Display for CacheExpression {
56 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
57 match self {
58 Self::VariantGet { requests } => {
59 write!(f, "VariantGet[")?;
60 let requests = requests
61 .iter()
62 .map(|request| format!("{}:{}", request.path(), request.data_type()))
63 .collect::<Vec<_>>();
64 write!(f, "{}", requests.join(","))?;
65 write!(f, "]")
66 }
67 Self::ExtractDate32 { field } => {
68 write!(f, "ExtractDate32:{:?}", field)
69 }
70 Self::PredicateColumn => {
71 write!(f, "PredicateColumn")
72 }
73 Self::SubstringSearch => {
74 write!(f, "SubstringSearch")
75 }
76 }
77 }
78}
79
80impl CacheExpression {
81 pub fn extract_date32(field: Date32Field) -> Self {
83 Self::ExtractDate32 { field }
84 }
85
86 pub fn variant_get(path: impl Into<Arc<str>>, data_type: DataType) -> Self {
88 Self::VariantGet {
89 requests: Arc::from(vec![VariantRequest::new(path, data_type)].into_boxed_slice()),
90 }
91 }
92
93 pub fn variant_get_many<I, S>(requests: I) -> Self
95 where
96 I: IntoIterator<Item = (S, DataType)>,
97 S: Into<Arc<str>>,
98 {
99 let requests: Vec<VariantRequest> = requests
100 .into_iter()
101 .map(|(path, data_type)| VariantRequest::new(path.into(), data_type))
102 .collect();
103 assert!(
104 !requests.is_empty(),
105 "variant_get_many requires at least one path"
106 );
107 Self::VariantGet {
108 requests: Arc::from(requests.into_boxed_slice()),
109 }
110 }
111
112 pub fn substring_search() -> Self {
114 Self::SubstringSearch
115 }
116
117 pub fn try_from_date_part_str(value: &str) -> Option<Self> {
121 let upper = value.to_ascii_uppercase();
122 let field = match upper.as_str() {
123 "YEAR" => Date32Field::Year,
124 "MONTH" => Date32Field::Month,
125 "DAY" => Date32Field::Day,
126 "DOW" | "DAYOFWEEK" | "DAY_OF_WEEK" => Date32Field::DayOfWeek,
127 _ => return None,
128 };
129 Some(Self::ExtractDate32 { field })
130 }
131
132 pub fn as_date32_field(&self) -> Option<Date32Field> {
134 match self {
135 Self::ExtractDate32 { field } => Some(*field),
136 Self::VariantGet { .. } | Self::PredicateColumn | Self::SubstringSearch => None,
137 }
138 }
139
140 pub fn variant_path(&self) -> Option<&str> {
142 match self {
143 Self::VariantGet { requests } => requests.first().map(|request| request.path()),
144 Self::ExtractDate32 { .. } | Self::PredicateColumn | Self::SubstringSearch => None,
145 }
146 }
147
148 pub fn variant_data_type(&self) -> Option<&DataType> {
150 match self {
151 Self::VariantGet { requests } => requests.first().map(|request| request.data_type()),
152 Self::ExtractDate32 { .. } | Self::PredicateColumn | Self::SubstringSearch => None,
153 }
154 }
155
156 pub fn variant_requests(&self) -> Option<&[VariantRequest]> {
158 match self {
159 Self::VariantGet { requests } => Some(requests.as_ref()),
160 Self::ExtractDate32 { .. } | Self::PredicateColumn | Self::SubstringSearch => None,
161 }
162 }
163}