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