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