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
64 let temp_fragment = Fragment::internal(val);
65
66 let parsed = $parse_fn(temp_fragment).map_err(|mut e| {
67 let proper_fragment = lazy_fragment.fragment();
68
69 if let Fragment::Internal {
70 text: error_text,
71 } = &e.0.fragment
72 {
73 if let Fragment::Statement {
74 text: source_text,
75 ..
76 } = &proper_fragment
77 {
78 if &**source_text == val
79 || source_text.contains(&format!("\"{}\"", val))
80 {
81 let offset =
82 val.find(&**error_text).unwrap_or(0);
83 e.0.fragment = proper_fragment
84 .sub_fragment(offset, error_text.len());
85 } else {
86 e.0.fragment = proper_fragment.clone();
87 }
88 } else {
89 e.0.fragment = proper_fragment.clone();
90 }
91 }
92
93 Error::from(CastError::InvalidTemporal {
94 fragment: e.0.fragment.clone(),
95 target: $target_type,
96 cause: e.diagnostic(),
97 })
98 })?;
99
100 out.push::<$type>(parsed);
101 } else {
102 out.push_none();
103 }
104 }
105 Ok(out)
106 }
107 };
108}
109
110impl_to_temporal!(to_date, Date, Type::Date, parse_date);
111impl_to_temporal!(to_datetime, DateTime, Type::DateTime, parse_datetime);
112impl_to_temporal!(to_time, Time, Type::Time, parse_time);
113impl_to_temporal!(to_duration, Duration, Type::Duration, parse_duration);