1use arrow_array::{
16 Array, ArrayRef, PrimitiveArray, TimestampMicrosecondArray, TimestampMillisecondArray,
17 TimestampNanosecondArray, TimestampSecondArray,
18};
19use arrow_schema::DataType;
20use common_time::Timestamp;
21use common_time::timestamp::TimeUnit;
22use paste::paste;
23use serde::{Deserialize, Serialize};
24
25use crate::prelude::{Scalar, Value, ValueRef};
26use crate::scalars::ScalarRef;
27use crate::types::{
28 TimestampMicrosecondType, TimestampMillisecondType, TimestampNanosecondType,
29 TimestampSecondType, WrapperType,
30};
31use crate::vectors::{
32 TimestampMicrosecondVector, TimestampMillisecondVector, TimestampNanosecondVector,
33 TimestampSecondVector,
34};
35
36macro_rules! define_timestamp_with_unit {
37 ($unit: ident) => {
38 paste! {
39 #[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
40 pub struct [<Timestamp $unit>](pub Timestamp);
41
42 impl [<Timestamp $unit>] {
43 pub fn new(val: i64) -> Self {
44 Self(Timestamp::new(val, TimeUnit::$unit))
45 }
46 }
47
48 impl Default for [<Timestamp $unit>] {
49 fn default() -> Self {
50 Self::new(0)
51 }
52 }
53
54 impl From<[<Timestamp $unit>]> for Value {
55 fn from(t: [<Timestamp $unit>]) -> Value {
56 Value::Timestamp(t.0)
57 }
58 }
59
60 impl From<[<Timestamp $unit>]> for serde_json::Value {
61 fn from(t: [<Timestamp $unit>]) -> Self {
62 t.0.into()
63 }
64 }
65
66 impl From<[<Timestamp $unit>]> for ValueRef<'static> {
67 fn from(t: [<Timestamp $unit>]) -> Self {
68 ValueRef::Timestamp(t.0)
69 }
70 }
71
72 impl Scalar for [<Timestamp $unit>] {
73 type VectorType = [<Timestamp $unit Vector>];
74 type RefType<'a> = [<Timestamp $unit>];
75
76 fn as_scalar_ref(&self) -> Self::RefType<'_> {
77 *self
78 }
79
80 fn upcast_gat<'short, 'long: 'short>(
81 long: Self::RefType<'long>,
82 ) -> Self::RefType<'short> {
83 long
84 }
85 }
86
87 impl<'a> ScalarRef<'a> for [<Timestamp $unit>] {
88 type ScalarType = [<Timestamp $unit>];
89
90 fn to_owned_scalar(&self) -> Self::ScalarType {
91 *self
92 }
93 }
94
95 impl WrapperType for [<Timestamp $unit>] {
96 type LogicalType = [<Timestamp $unit Type>];
97 type Native = i64;
98
99 fn from_native(value: Self::Native) -> Self {
100 Self::new(value)
101 }
102
103 fn into_native(self) -> Self::Native {
104 self.0.into()
105 }
106 }
107
108 impl From<i64> for [<Timestamp $unit>] {
109 fn from(val: i64) -> Self {
110 [<Timestamp $unit>]::from_native(val)
111 }
112 }
113
114 impl From<[<Timestamp $unit>]> for i64{
115 fn from(val: [<Timestamp $unit>]) -> Self {
116 val.0.value()
117 }
118 }
119
120 impl TryFrom<Value> for Option<[<Timestamp $unit>]> {
121 type Error = $crate::error::Error;
122
123 #[inline]
124 fn try_from(from: Value) -> std::result::Result<Self, Self::Error> {
125 match from {
126 Value::Timestamp(v) if v.unit() == TimeUnit::$unit => {
127 Ok(Some([<Timestamp $unit>](v)))
128 },
129 Value::Null => Ok(None),
130 _ => $crate::error::TryFromValueSnafu {
131 reason: format!("{:?} is not a {}", from, stringify!([<Timestamp $unit>])),
132 }
133 .fail(),
134 }
135 }
136 }
137 }
138 };
139}
140
141define_timestamp_with_unit!(Second);
142define_timestamp_with_unit!(Millisecond);
143define_timestamp_with_unit!(Microsecond);
144define_timestamp_with_unit!(Nanosecond);
145
146pub fn timestamp_array_to_primitive(
148 ts_array: &ArrayRef,
149) -> Option<(
150 PrimitiveArray<arrow_array::types::Int64Type>,
151 arrow::datatypes::TimeUnit,
152)> {
153 let DataType::Timestamp(unit, _) = ts_array.data_type() else {
154 return None;
155 };
156
157 let ts_primitive = match unit {
158 arrow_schema::TimeUnit::Second => ts_array
159 .as_any()
160 .downcast_ref::<TimestampSecondArray>()
161 .unwrap()
162 .reinterpret_cast::<arrow_array::types::Int64Type>(),
163 arrow_schema::TimeUnit::Millisecond => ts_array
164 .as_any()
165 .downcast_ref::<TimestampMillisecondArray>()
166 .unwrap()
167 .reinterpret_cast::<arrow_array::types::Int64Type>(),
168 arrow_schema::TimeUnit::Microsecond => ts_array
169 .as_any()
170 .downcast_ref::<TimestampMicrosecondArray>()
171 .unwrap()
172 .reinterpret_cast::<arrow_array::types::Int64Type>(),
173 arrow_schema::TimeUnit::Nanosecond => ts_array
174 .as_any()
175 .downcast_ref::<TimestampNanosecondArray>()
176 .unwrap()
177 .reinterpret_cast::<arrow_array::types::Int64Type>(),
178 };
179 Some((ts_primitive, *unit))
180}
181
182pub fn append_timestamps(ts_array: &ArrayRef, timestamps: &mut Vec<i64>) -> Option<()> {
186 let (values, _) = timestamp_array_to_primitive(ts_array)?;
187 if values.null_count() == 0 {
188 timestamps.extend_from_slice(values.values());
189 } else {
190 timestamps.extend(values.iter().flatten());
191 }
192 Some(())
193}
194
195#[cfg(test)]
196mod tests {
197 use std::sync::Arc;
198
199 use arrow_array::Int64Array;
200 use common_time::timezone::set_default_timezone;
201
202 use super::*;
203
204 #[test]
205 fn test_to_serde_json_value() {
206 set_default_timezone(Some("Asia/Shanghai")).unwrap();
207 let ts = TimestampSecond::new(123);
208 let val = serde_json::Value::from(ts);
209 match val {
210 serde_json::Value::String(s) => {
211 assert_eq!("1970-01-01 08:02:03+0800", s);
212 }
213 _ => unreachable!(),
214 }
215 }
216
217 #[test]
218 fn test_timestamp_scalar() {
219 let ts = TimestampSecond::new(123);
220 assert_eq!(ts, ts.as_scalar_ref());
221 assert_eq!(ts, ts.to_owned_scalar());
222 let ts = TimestampMillisecond::new(123);
223 assert_eq!(ts, ts.as_scalar_ref());
224 assert_eq!(ts, ts.to_owned_scalar());
225 let ts = TimestampMicrosecond::new(123);
226 assert_eq!(ts, ts.as_scalar_ref());
227 assert_eq!(ts, ts.to_owned_scalar());
228 let ts = TimestampNanosecond::new(123);
229 assert_eq!(ts, ts.as_scalar_ref());
230 assert_eq!(ts, ts.to_owned_scalar());
231 }
232
233 #[test]
234 fn test_append_timestamps() {
235 let cases = [
236 vec![Some(i64::MIN), Some(-1), Some(0), Some(i64::MAX)],
237 vec![Some(-1), None, Some(2), None],
238 vec![None, None],
239 vec![],
240 ];
241 for values in cases {
242 let arrays: [ArrayRef; 4] = [
243 Arc::new(TimestampSecondArray::from(values.clone())),
244 Arc::new(TimestampMillisecondArray::from(values.clone())),
245 Arc::new(TimestampMicrosecondArray::from(values.clone())),
246 Arc::new(TimestampNanosecondArray::from(values.clone())),
247 ];
248 let mut expected = vec![42];
249 expected.extend(values.iter().flatten().copied());
250 for array in arrays {
251 for _ in 0..2 {
252 let (primitive, _) = timestamp_array_to_primitive(&array).unwrap();
253 let mut reference = vec![42];
254 reference.extend(primitive.iter().flatten());
255
256 let mut timestamps = vec![42];
257 assert_eq!(append_timestamps(&array, &mut timestamps), Some(()));
258 assert_eq!(timestamps, expected);
259 assert_eq!(timestamps, reference);
260 }
261 }
262 }
263 }
264
265 #[test]
266 fn test_append_timestamps_invalid_array_preserves_prefix() {
267 for values in [vec![], vec![Some(1), None]] {
268 let array: ArrayRef = Arc::new(Int64Array::from(values));
269 let mut timestamps = vec![42, -1];
270 assert_eq!(append_timestamps(&array, &mut timestamps), None);
271 assert_eq!(timestamps, vec![42, -1]);
272 }
273 }
274}