reifydb_engine/expression/cast/
temporal.rs1use reifydb_core::value::column::buffer::ColumnBuffer;
5use reifydb_type::{
6 error::{Error, TypeError},
7 fragment::{Fragment, LazyFragment},
8 value::{
9 container::utf8::Utf8Container,
10 date::Date,
11 datetime::DateTime,
12 duration::Duration,
13 temporal::parse::{
14 date::parse_date, datetime::parse_datetime, duration::parse_duration, time::parse_time,
15 },
16 time::Time,
17 r#type::Type,
18 },
19};
20
21use crate::{Result, error::CastError};
22
23pub fn to_temporal(data: &ColumnBuffer, target: Type, lazy_fragment: impl LazyFragment) -> Result<ColumnBuffer> {
24 if let ColumnBuffer::Utf8 {
25 container,
26 ..
27 } = data
28 {
29 match target {
30 Type::Date => to_date(container, lazy_fragment),
31 Type::DateTime => to_datetime(container, lazy_fragment),
32 Type::Time => to_time(container, lazy_fragment),
33 Type::Duration => to_duration(container, lazy_fragment),
34 _ => {
35 let shape_type = data.get_type();
36 Err(TypeError::UnsupportedCast {
37 from: shape_type,
38 to: target,
39 fragment: lazy_fragment.fragment(),
40 }
41 .into())
42 }
43 }
44 } else {
45 let shape_type = data.get_type();
46 Err(TypeError::UnsupportedCast {
47 from: shape_type,
48 to: target,
49 fragment: lazy_fragment.fragment(),
50 }
51 .into())
52 }
53}
54
55macro_rules! impl_to_temporal {
56 ($fn_name:ident, $type:ty, $target_type:expr, $parse_fn:expr) => {
57 #[inline]
58 fn $fn_name(container: &Utf8Container, lazy_fragment: impl LazyFragment) -> Result<ColumnBuffer> {
59 let mut out = ColumnBuffer::with_capacity($target_type, container.len());
60 for idx in 0..container.len() {
61 if container.is_defined(idx) {
62 let val = container.get(idx).unwrap();
63 let temp_fragment = Fragment::internal(val);
66
67 let parsed = $parse_fn(temp_fragment).map_err(|mut e| {
68 let proper_fragment = lazy_fragment.fragment();
70
71 if let Fragment::Internal {
74 text: error_text,
75 } = &e.0.fragment
76 {
77 if let Fragment::Statement {
81 text: source_text,
82 ..
83 } = &proper_fragment
84 {
85 if &**source_text == val
89 || source_text.contains(&format!("\"{}\"", val))
90 {
91 let offset =
94 val.find(&**error_text).unwrap_or(0);
95 e.0.fragment = proper_fragment
96 .sub_fragment(offset, error_text.len());
97 } else {
98 e.0.fragment = proper_fragment.clone();
101 }
102 } else {
103 e.0.fragment = proper_fragment.clone();
106 }
107 }
108
109 Error::from(CastError::InvalidTemporal {
110 fragment: e.0.fragment.clone(),
111 target: $target_type,
112 cause: e.diagnostic(),
113 })
114 })?;
115
116 out.push::<$type>(parsed);
117 } else {
118 out.push_none();
119 }
120 }
121 Ok(out)
122 }
123 };
124}
125
126impl_to_temporal!(to_date, Date, Type::Date, parse_date);
127impl_to_temporal!(to_datetime, DateTime, Type::DateTime, parse_datetime);
128impl_to_temporal!(to_time, Time, Type::Time, parse_time);
129impl_to_temporal!(to_duration, Duration, Type::Duration, parse_duration);