Skip to main content

reifydb_engine/expression/
prefix.rs

1// SPDX-License-Identifier: AGPL-3.0-or-later
2// Copyright (c) 2025 ReifyDB
3
4use reifydb_core::{
5	error::diagnostic::engine::frame_error,
6	value::column::{Column, data::ColumnData},
7};
8use reifydb_function::registry::Functions;
9use reifydb_rql::expression::{PrefixExpression, PrefixOperator};
10use reifydb_runtime::clock::Clock;
11use reifydb_type::{
12	err,
13	error::diagnostic::{
14		operator,
15		operator::{
16			not_can_not_applied_to_number, not_can_not_applied_to_temporal, not_can_not_applied_to_uuid,
17		},
18	},
19	value::{decimal::Decimal, int::Int, uint::Uint},
20};
21
22use crate::expression::context::EvalContext;
23
24pub(crate) fn prefix_eval(
25	ctx: &EvalContext,
26	prefix: &PrefixExpression,
27	functions: &Functions,
28	clock: &Clock,
29) -> crate::Result<Column> {
30	let inner_ctx = EvalContext {
31		target: None,
32		columns: ctx.columns.clone(),
33		row_count: ctx.row_count,
34		take: ctx.take,
35		params: ctx.params,
36		symbol_table: ctx.symbol_table,
37		is_aggregate_context: ctx.is_aggregate_context,
38		functions: ctx.functions,
39		clock: ctx.clock,
40		arena: None,
41	};
42	let column = super::eval::evaluate(&inner_ctx, &prefix.expression, functions, clock)?;
43
44	crate::expression::option::unary_op_unwrap_option(&column, |column| match column.data() {
45		ColumnData::Bool(container) => match prefix.operator {
46			PrefixOperator::Not(_) => {
47				let mut result = Vec::with_capacity(container.data().len());
48				for (idx, val) in container.data().iter().enumerate() {
49					if container.is_defined(idx) {
50						result.push(!val);
51					} else {
52						result.push(false);
53					}
54				}
55
56				let new_data = ColumnData::bool(result);
57				Ok(column.with_new_data(new_data))
58			}
59			_ => err!(frame_error("Cannot apply arithmetic prefix operator to bool".to_string())),
60		},
61
62		ColumnData::Float4(container) => {
63			let mut result = Vec::with_capacity(container.data().len());
64			for (idx, val) in container.data().iter().enumerate() {
65				if container.is_defined(idx) {
66					result.push(match prefix.operator {
67						PrefixOperator::Minus(_) => -*val,
68						PrefixOperator::Plus(_) => *val,
69						PrefixOperator::Not(_) => {
70							return err!(not_can_not_applied_to_number(
71								prefix.full_fragment_owned()
72							));
73						}
74					});
75				} else {
76					result.push(0.0f32);
77				}
78			}
79			let new_data = ColumnData::float4(result);
80			Ok(column.with_new_data(new_data))
81		}
82
83		ColumnData::Float8(container) => {
84			let mut result = Vec::with_capacity(container.data().len());
85			for (idx, val) in container.data().iter().enumerate() {
86				if container.is_defined(idx) {
87					result.push(match prefix.operator {
88						PrefixOperator::Minus(_) => -*val,
89						PrefixOperator::Plus(_) => *val,
90						PrefixOperator::Not(_) => {
91							return err!(not_can_not_applied_to_number(
92								prefix.full_fragment_owned()
93							));
94						}
95					});
96				} else {
97					result.push(0.0f64);
98				}
99			}
100			let new_data = ColumnData::float8(result);
101			Ok(column.with_new_data(new_data))
102		}
103
104		ColumnData::Int1(container) => {
105			let mut result = Vec::with_capacity(container.data().len());
106			for (idx, val) in container.data().iter().enumerate() {
107				if container.is_defined(idx) {
108					result.push(match prefix.operator {
109						PrefixOperator::Minus(_) => -*val,
110						PrefixOperator::Plus(_) => *val,
111						PrefixOperator::Not(_) => {
112							return err!(not_can_not_applied_to_number(
113								prefix.full_fragment_owned()
114							));
115						}
116					});
117				} else {
118					result.push(0);
119				}
120			}
121			let new_data = ColumnData::int1(result);
122			Ok(column.with_new_data(new_data))
123		}
124
125		ColumnData::Int2(container) => {
126			let mut result = Vec::with_capacity(container.data().len());
127			for (idx, val) in container.data().iter().enumerate() {
128				if container.is_defined(idx) {
129					result.push(match prefix.operator {
130						PrefixOperator::Minus(_) => -*val,
131						PrefixOperator::Plus(_) => *val,
132						PrefixOperator::Not(_) => {
133							return err!(not_can_not_applied_to_number(
134								prefix.full_fragment_owned()
135							));
136						}
137					});
138				} else {
139					result.push(0);
140				}
141			}
142			let new_data = ColumnData::int2(result);
143			Ok(column.with_new_data(new_data))
144		}
145
146		ColumnData::Int4(container) => {
147			let mut result = Vec::with_capacity(container.data().len());
148			for (idx, val) in container.data().iter().enumerate() {
149				if container.is_defined(idx) {
150					result.push(match prefix.operator {
151						PrefixOperator::Minus(_) => -*val,
152						PrefixOperator::Plus(_) => *val,
153						PrefixOperator::Not(_) => {
154							return err!(not_can_not_applied_to_number(
155								prefix.full_fragment_owned()
156							));
157						}
158					});
159				} else {
160					result.push(0);
161				}
162			}
163			let new_data = ColumnData::int4(result);
164			Ok(column.with_new_data(new_data))
165		}
166
167		ColumnData::Int8(container) => {
168			let mut result = Vec::with_capacity(container.data().len());
169			for (idx, val) in container.data().iter().enumerate() {
170				if container.is_defined(idx) {
171					result.push(match prefix.operator {
172						PrefixOperator::Minus(_) => -*val,
173						PrefixOperator::Plus(_) => *val,
174						PrefixOperator::Not(_) => {
175							return err!(not_can_not_applied_to_number(
176								prefix.full_fragment_owned()
177							));
178						}
179					});
180				} else {
181					result.push(0);
182				}
183			}
184			let new_data = ColumnData::int8(result);
185			Ok(column.with_new_data(new_data))
186		}
187
188		ColumnData::Int16(container) => {
189			let mut result = Vec::with_capacity(container.data().len());
190			for (idx, val) in container.data().iter().enumerate() {
191				if container.is_defined(idx) {
192					result.push(match prefix.operator {
193						PrefixOperator::Minus(_) => -*val,
194						PrefixOperator::Plus(_) => *val,
195						PrefixOperator::Not(_) => {
196							return err!(not_can_not_applied_to_number(
197								prefix.full_fragment_owned()
198							));
199						}
200					});
201				} else {
202					result.push(0);
203				}
204			}
205			let new_data = ColumnData::int16(result);
206			Ok(column.with_new_data(new_data))
207		}
208
209		ColumnData::Utf8 {
210			container: _,
211			..
212		} => match prefix.operator {
213			PrefixOperator::Not(_) => {
214				err!(operator::not_can_not_applied_to_text(prefix.full_fragment_owned()))
215			}
216			_ => err!(frame_error("Cannot apply arithmetic prefix operator to text".to_string())),
217		},
218
219		ColumnData::Uint1(container) => {
220			let mut result = Vec::with_capacity(container.data().len());
221			for val in container.data().iter() {
222				let signed = *val as i8;
223				result.push(match prefix.operator {
224					PrefixOperator::Minus(_) => -signed,
225					PrefixOperator::Plus(_) => signed,
226					PrefixOperator::Not(_) => {
227						return err!(not_can_not_applied_to_number(
228							prefix.full_fragment_owned()
229						));
230					}
231				});
232			}
233			let new_data = ColumnData::int1(result);
234			Ok(column.with_new_data(new_data))
235		}
236
237		ColumnData::Uint2(container) => {
238			let mut result = Vec::with_capacity(container.data().len());
239			for val in container.data().iter() {
240				let signed = *val as i16;
241				result.push(match prefix.operator {
242					PrefixOperator::Minus(_) => -signed,
243					PrefixOperator::Plus(_) => signed,
244					PrefixOperator::Not(_) => {
245						return err!(not_can_not_applied_to_number(
246							prefix.full_fragment_owned()
247						));
248					}
249				});
250			}
251			let new_data = ColumnData::int2(result);
252			Ok(column.with_new_data(new_data))
253		}
254
255		ColumnData::Uint4(container) => {
256			let mut result = Vec::with_capacity(container.data().len());
257			for val in container.data().iter() {
258				let signed = *val as i32;
259				result.push(match prefix.operator {
260					PrefixOperator::Minus(_) => -signed,
261					PrefixOperator::Plus(_) => signed,
262					PrefixOperator::Not(_) => {
263						return err!(not_can_not_applied_to_number(
264							prefix.full_fragment_owned()
265						));
266					}
267				});
268			}
269			let new_data = ColumnData::int4(result);
270			Ok(column.with_new_data(new_data))
271		}
272
273		ColumnData::Uint8(container) => {
274			let mut result = Vec::with_capacity(container.data().len());
275			for val in container.data().iter() {
276				let signed = *val as i64;
277				result.push(match prefix.operator {
278					PrefixOperator::Minus(_) => -signed,
279					PrefixOperator::Plus(_) => signed,
280					PrefixOperator::Not(_) => {
281						return err!(not_can_not_applied_to_number(
282							prefix.full_fragment_owned()
283						));
284					}
285				});
286			}
287			let new_data = ColumnData::int8(result);
288			Ok(column.with_new_data(new_data))
289		}
290		ColumnData::Uint16(container) => {
291			let mut result = Vec::with_capacity(container.data().len());
292			for val in container.data().iter() {
293				let signed = *val as i128;
294				result.push(match prefix.operator {
295					PrefixOperator::Minus(_) => -signed,
296					PrefixOperator::Plus(_) => signed,
297					PrefixOperator::Not(_) => {
298						return err!(not_can_not_applied_to_number(
299							prefix.full_fragment_owned()
300						));
301					}
302				});
303			}
304			let new_data = ColumnData::int16(result);
305			Ok(column.with_new_data(new_data))
306		}
307		ColumnData::Date(_) => match prefix.operator {
308			PrefixOperator::Not(_) => {
309				err!(not_can_not_applied_to_temporal(prefix.full_fragment_owned()))
310			}
311			_ => unimplemented!(),
312		},
313		ColumnData::DateTime(_) => match prefix.operator {
314			PrefixOperator::Not(_) => {
315				err!(not_can_not_applied_to_temporal(prefix.full_fragment_owned()))
316			}
317			_ => unimplemented!(),
318		},
319		ColumnData::Time(_) => match prefix.operator {
320			PrefixOperator::Not(_) => {
321				err!(not_can_not_applied_to_temporal(prefix.full_fragment_owned()))
322			}
323			_ => unimplemented!(),
324		},
325		ColumnData::Duration(_) => match prefix.operator {
326			PrefixOperator::Not(_) => {
327				err!(not_can_not_applied_to_temporal(prefix.full_fragment_owned()))
328			}
329			_ => unimplemented!(),
330		},
331		ColumnData::IdentityId(_) => match prefix.operator {
332			PrefixOperator::Not(_) => {
333				err!(not_can_not_applied_to_uuid(prefix.full_fragment_owned()))
334			}
335			_ => unimplemented!(),
336		},
337		ColumnData::Uuid4(_) => match prefix.operator {
338			PrefixOperator::Not(_) => {
339				err!(not_can_not_applied_to_uuid(prefix.full_fragment_owned()))
340			}
341			_ => unimplemented!(),
342		},
343		ColumnData::Uuid7(_) => match prefix.operator {
344			PrefixOperator::Not(_) => {
345				err!(not_can_not_applied_to_uuid(prefix.full_fragment_owned()))
346			}
347			_ => unimplemented!(),
348		},
349		ColumnData::Blob {
350			container: _,
351			..
352		} => match prefix.operator {
353			PrefixOperator::Not(_) => {
354				err!(frame_error("Cannot apply NOT operator to BLOB".to_string()))
355			}
356			_ => err!(frame_error("Cannot apply arithmetic prefix operator to BLOB".to_string())),
357		},
358		ColumnData::Int {
359			container,
360			..
361		} => {
362			let mut result = Vec::with_capacity(container.data().len());
363			for (idx, val) in container.data().iter().enumerate() {
364				if container.is_defined(idx) {
365					result.push(match prefix.operator {
366						PrefixOperator::Minus(_) => Int(-val.0.clone()),
367						PrefixOperator::Plus(_) => val.clone(),
368						PrefixOperator::Not(_) => {
369							return err!(not_can_not_applied_to_number(
370								prefix.full_fragment_owned()
371							));
372						}
373					});
374				} else {
375					result.push(Int::zero());
376				}
377			}
378			let new_data = ColumnData::int(result);
379			Ok(column.with_new_data(new_data))
380		}
381		ColumnData::Uint {
382			container,
383			..
384		} => match prefix.operator {
385			PrefixOperator::Minus(_) => {
386				let mut result = Vec::with_capacity(container.data().len());
387				for (idx, val) in container.data().iter().enumerate() {
388					if container.is_defined(idx) {
389						let negated = -val.0.clone();
390						result.push(Int::from(negated));
391					} else {
392						result.push(Int::zero());
393					}
394				}
395				let new_data = ColumnData::int(result);
396				Ok(column.with_new_data(new_data))
397			}
398			PrefixOperator::Plus(_) => {
399				let mut result = Vec::with_capacity(container.data().len());
400				for (idx, val) in container.data().iter().enumerate() {
401					if container.is_defined(idx) {
402						result.push(val.clone());
403					} else {
404						result.push(Uint::zero());
405					}
406				}
407				let new_data = ColumnData::uint(result);
408				Ok(column.with_new_data(new_data))
409			}
410			PrefixOperator::Not(_) => {
411				err!(not_can_not_applied_to_number(prefix.full_fragment_owned()))
412			}
413		},
414		ColumnData::Decimal {
415			container,
416			..
417		} => {
418			let mut result = Vec::with_capacity(container.data().len());
419			for (idx, val) in container.data().iter().enumerate() {
420				if container.is_defined(idx) {
421					result.push(match prefix.operator {
422						PrefixOperator::Minus(_) => val.clone().negate(),
423						PrefixOperator::Plus(_) => val.clone(),
424						PrefixOperator::Not(_) => {
425							return err!(not_can_not_applied_to_number(
426								prefix.full_fragment_owned()
427							));
428						}
429					});
430				} else {
431					result.push(Decimal::from(0));
432				}
433			}
434			let new_data = ColumnData::decimal(result);
435			Ok(column.with_new_data(new_data))
436		}
437		ColumnData::DictionaryId(_) => match prefix.operator {
438			PrefixOperator::Not(_) => {
439				err!(frame_error("Cannot apply NOT operator to DictionaryId type".to_string()))
440			}
441			_ => err!(frame_error(
442				"Cannot apply arithmetic prefix operator to DictionaryId type".to_string()
443			)),
444		},
445		ColumnData::Any(_) => match prefix.operator {
446			PrefixOperator::Not(_) => {
447				err!(frame_error("Cannot apply NOT operator to Any type".to_string()))
448			}
449			_ => err!(frame_error("Cannot apply arithmetic prefix operator to Any type".to_string())),
450		},
451		ColumnData::Option {
452			..
453		} => unreachable!("nested Option after unwrap"),
454	})
455}