Skip to main content

reifydb_engine/expression/cast/
any.rs

1// SPDX-License-Identifier: AGPL-3.0-or-later
2// Copyright (c) 2025 ReifyDB
3
4use reifydb_core::value::column::data::ColumnData;
5use reifydb_type::{error::TypeError, fragment::LazyFragment, value::r#type::Type};
6
7use super::cast_column_data;
8use crate::{Result, expression::context::EvalContext};
9
10pub fn from_any(
11	ctx: &EvalContext,
12	data: &ColumnData,
13	target: Type,
14	lazy_fragment: impl LazyFragment + Clone,
15) -> Result<ColumnData> {
16	let any_container = match data {
17		ColumnData::Any(container) => container,
18		_ => {
19			return Err(TypeError::UnsupportedCast {
20				from: data.get_type(),
21				to: target,
22				fragment: lazy_fragment.fragment(),
23			}
24			.into());
25		}
26	};
27
28	if any_container.is_empty() {
29		return Ok(ColumnData::with_capacity(target.clone(), 0));
30	}
31
32	// First pass: validate all values can be cast to target type
33	// We need to check all values before actually casting any
34	let mut temp_results = Vec::with_capacity(any_container.len());
35
36	for i in 0..any_container.len() {
37		if !any_container.is_defined(i) {
38			// Undefined values can be cast to any type
39			temp_results.push(None);
40			continue;
41		}
42
43		let value = &*any_container.data()[i];
44
45		// Try to cast this single value to validate it can be done
46		let single_column = ColumnData::from(value.clone());
47		match cast_column_data(ctx, &single_column, target.clone(), lazy_fragment.clone()) {
48			Ok(result) => temp_results.push(Some(result)),
49			Err(e) => {
50				// If any value fails to cast, the entire operation fails
51				return Err(e);
52			}
53		}
54	}
55
56	// Second pass: build the result container
57	// All values validated successfully, now we can build the result
58	let mut result = ColumnData::with_capacity(target, any_container.len());
59
60	for temp_result in temp_results {
61		match temp_result {
62			None => {
63				// This was an undefined value
64				result.push_none();
65			}
66			Some(casted_column) => {
67				// Extract the single value from the casted column and add to result
68				// We know each casted_column has exactly one value
69				match &casted_column {
70					ColumnData::Bool(c) => {
71						if c.is_defined(0) {
72							result.push::<bool>(c.get(0).unwrap());
73						} else {
74							result.push_none();
75						}
76					}
77					ColumnData::Int1(c) => {
78						if c.is_defined(0) {
79							result.push::<i8>(*c.get(0).unwrap());
80						} else {
81							result.push_none();
82						}
83					}
84					ColumnData::Int2(c) => {
85						if c.is_defined(0) {
86							result.push::<i16>(*c.get(0).unwrap());
87						} else {
88							result.push_none();
89						}
90					}
91					ColumnData::Int4(c) => {
92						if c.is_defined(0) {
93							result.push::<i32>(*c.get(0).unwrap());
94						} else {
95							result.push_none();
96						}
97					}
98					ColumnData::Int8(c) => {
99						if c.is_defined(0) {
100							result.push::<i64>(*c.get(0).unwrap());
101						} else {
102							result.push_none();
103						}
104					}
105					ColumnData::Int16(c) => {
106						if c.is_defined(0) {
107							result.push::<i128>(*c.get(0).unwrap());
108						} else {
109							result.push_none();
110						}
111					}
112					ColumnData::Uint1(c) => {
113						if c.is_defined(0) {
114							result.push::<u8>(*c.get(0).unwrap());
115						} else {
116							result.push_none();
117						}
118					}
119					ColumnData::Uint2(c) => {
120						if c.is_defined(0) {
121							result.push::<u16>(*c.get(0).unwrap());
122						} else {
123							result.push_none();
124						}
125					}
126					ColumnData::Uint4(c) => {
127						if c.is_defined(0) {
128							result.push::<u32>(*c.get(0).unwrap());
129						} else {
130							result.push_none();
131						}
132					}
133					ColumnData::Uint8(c) => {
134						if c.is_defined(0) {
135							result.push::<u64>(*c.get(0).unwrap());
136						} else {
137							result.push_none();
138						}
139					}
140					ColumnData::Uint16(c) => {
141						if c.is_defined(0) {
142							result.push::<u128>(*c.get(0).unwrap());
143						} else {
144							result.push_none();
145						}
146					}
147					ColumnData::Float4(c) => {
148						if c.is_defined(0) {
149							result.push::<f32>(*c.get(0).unwrap());
150						} else {
151							result.push_none();
152						}
153					}
154					ColumnData::Float8(c) => {
155						if c.is_defined(0) {
156							result.push::<f64>(*c.get(0).unwrap());
157						} else {
158							result.push_none();
159						}
160					}
161					ColumnData::Utf8 {
162						container: c,
163						..
164					} => {
165						if c.is_defined(0) {
166							result.push::<String>(c.get(0).unwrap().clone());
167						} else {
168							result.push_none();
169						}
170					}
171					ColumnData::Blob {
172						container: c,
173						..
174					} => {
175						if c.is_defined(0) {
176							result.push(c.get(0).unwrap().clone());
177						} else {
178							result.push_none();
179						}
180					}
181					ColumnData::Date(c) => {
182						if c.is_defined(0) {
183							result.push(*c.get(0).unwrap());
184						} else {
185							result.push_none();
186						}
187					}
188					ColumnData::DateTime(c) => {
189						if c.is_defined(0) {
190							result.push(*c.get(0).unwrap());
191						} else {
192							result.push_none();
193						}
194					}
195					ColumnData::Time(c) => {
196						if c.is_defined(0) {
197							result.push(*c.get(0).unwrap());
198						} else {
199							result.push_none();
200						}
201					}
202					ColumnData::Duration(c) => {
203						if c.is_defined(0) {
204							result.push(*c.get(0).unwrap());
205						} else {
206							result.push_none();
207						}
208					}
209					ColumnData::IdentityId(c) => {
210						if c.is_defined(0) {
211							result.push(*c.get(0).unwrap());
212						} else {
213							result.push_none();
214						}
215					}
216					ColumnData::Uuid4(c) => {
217						if c.is_defined(0) {
218							result.push(*c.get(0).unwrap());
219						} else {
220							result.push_none();
221						}
222					}
223					ColumnData::Uuid7(c) => {
224						if c.is_defined(0) {
225							result.push(*c.get(0).unwrap());
226						} else {
227							result.push_none();
228						}
229					}
230					ColumnData::Int {
231						container: c,
232						..
233					} => {
234						if c.is_defined(0) {
235							result.push(c.get(0).unwrap().clone());
236						} else {
237							result.push_none();
238						}
239					}
240					ColumnData::Uint {
241						container: c,
242						..
243					} => {
244						if c.is_defined(0) {
245							result.push(c.get(0).unwrap().clone());
246						} else {
247							result.push_none();
248						}
249					}
250					ColumnData::Decimal {
251						container: c,
252						..
253					} => {
254						if c.is_defined(0) {
255							result.push(c.get(0).unwrap().clone());
256						} else {
257							result.push_none();
258						}
259					}
260					ColumnData::DictionaryId(c) => {
261						if c.is_defined(0) {
262							result.push(c.get(0).unwrap().clone());
263						} else {
264							result.push_none();
265						}
266					}
267					ColumnData::Any(_) => {
268						// This shouldn't happen as we're casting FROM Any
269						unreachable!("Casting from Any should not produce Any")
270					}
271					ColumnData::Option {
272						..
273					} => {
274						let value = casted_column.get_value(0);
275						result.push_value(value);
276					}
277				}
278			}
279		}
280	}
281
282	Ok(result)
283}