Skip to main content

reifydb_engine/expression/cast/
any.rs

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