reifydb_engine/expression/cast/
temporal.rs1use reifydb_core::value::column::data::ColumnData;
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: &ColumnData, target: Type, lazy_fragment: impl LazyFragment) -> Result<ColumnData> {
24 if let ColumnData::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 source_type = data.get_type();
36 Err(TypeError::UnsupportedCast {
37 from: source_type,
38 to: target,
39 fragment: lazy_fragment.fragment(),
40 }
41 .into())
42 }
43 }
44 } else {
45 let source_type = data.get_type();
46 Err(TypeError::UnsupportedCast {
47 from: source_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<'a>(container: &Utf8Container, lazy_fragment: impl LazyFragment) -> Result<ColumnData> {
59 let mut out = ColumnData::with_capacity($target_type, container.len());
60 for idx in 0..container.len() {
61 if container.is_defined(idx) {
62 let val = &container[idx];
63 let temp_fragment = Fragment::internal(val.as_str());
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.as_str()
89 || source_text.contains(&format!(
90 "\"{}\"",
91 val.as_str()
92 )) {
93 let offset = val
96 .as_str()
97 .find(&**error_text)
98 .unwrap_or(0);
99 e.0.fragment = proper_fragment
100 .sub_fragment(offset, error_text.len());
101 } else {
102 e.0.fragment = proper_fragment.clone();
105 }
106 } else {
107 e.0.fragment = proper_fragment.clone();
110 }
111 }
112
113 Error::from(CastError::InvalidTemporal {
114 fragment: e.0.fragment.clone(),
115 target: $target_type,
116 cause: e.diagnostic(),
117 })
118 })?;
119
120 out.push::<$type>(parsed);
121 } else {
122 out.push_none();
123 }
124 }
125 Ok(out)
126 }
127 };
128}
129
130impl_to_temporal!(to_date, Date, Type::Date, parse_date);
131impl_to_temporal!(to_datetime, DateTime, Type::DateTime, parse_datetime);
132impl_to_temporal!(to_time, Time, Type::Time, parse_time);
133impl_to_temporal!(to_duration, Duration, Type::Duration, parse_duration);