reifydb_engine/expression/arith/
div.rs1use reifydb_core::value::column::{Column, data::ColumnData, push::Push};
5use reifydb_type::{
6 error::diagnostic::operator::div_cannot_be_applied_to_incompatible_types,
7 fragment::LazyFragment,
8 return_error,
9 value::{
10 container::number::NumberContainer,
11 is::IsNumber,
12 number::{promote::Promote, safe::div::SafeDiv},
13 r#type::{Type, get::GetType},
14 },
15};
16
17use crate::expression::context::EvalContext;
18
19pub(crate) fn div_columns(
20 ctx: &EvalContext,
21 left: &Column,
22 right: &Column,
23 fragment: impl LazyFragment + Copy,
24) -> crate::Result<Column> {
25 crate::expression::option::binary_op_unwrap_option(left, right, fragment.fragment(), |left, right| {
26 let target = Type::promote(left.get_type(), right.get_type());
27
28 dispatch_arith!(
29 &left.data(), &right.data();
30 fixed: div_numeric, arb: div_numeric_clone (ctx, target, fragment);
31
32 _ => return_error!(div_cannot_be_applied_to_incompatible_types(
33 fragment.fragment(),
34 left.get_type(),
35 right.get_type(),
36 )),
37 )
38 })
39}
40
41fn div_numeric<'a, L, R>(
42 ctx: &EvalContext,
43 l: &NumberContainer<L>,
44 r: &NumberContainer<R>,
45 target: Type,
46 fragment: impl LazyFragment + Copy,
47) -> crate::Result<Column>
48where
49 L: GetType + Promote<R> + IsNumber,
50 R: GetType + IsNumber,
51 <L as Promote<R>>::Output: IsNumber,
52 <L as Promote<R>>::Output: SafeDiv,
53 ColumnData: Push<<L as Promote<R>>::Output>,
54{
55 debug_assert_eq!(l.len(), r.len());
56
57 let mut data = ColumnData::with_capacity(target, l.len());
58 let l_data = l.data();
59 let r_data = r.data();
60 for i in 0..l.len() {
61 if let Some(value) = ctx.div(&l_data[i], &r_data[i], fragment)? {
62 data.push(value);
63 } else {
64 data.push_none()
65 }
66 }
67 Ok(Column {
68 name: fragment.fragment(),
69 data,
70 })
71}
72
73fn div_numeric_clone<'a, L, R>(
74 ctx: &EvalContext,
75 l: &NumberContainer<L>,
76 r: &NumberContainer<R>,
77 target: Type,
78 fragment: impl LazyFragment + Copy,
79) -> crate::Result<Column>
80where
81 L: Clone + GetType + Promote<R> + IsNumber,
82 R: Clone + GetType + IsNumber,
83 <L as Promote<R>>::Output: IsNumber,
84 <L as Promote<R>>::Output: SafeDiv,
85 ColumnData: Push<<L as Promote<R>>::Output>,
86{
87 debug_assert_eq!(l.len(), r.len());
88
89 let mut data = ColumnData::with_capacity(target, l.len());
90 let l_data = l.data();
91 let r_data = r.data();
92 for i in 0..l.len() {
93 let l_clone = l_data[i].clone();
94 let r_clone = r_data[i].clone();
95 if let Some(value) = ctx.div(&l_clone, &r_clone, fragment)? {
96 data.push(value);
97 } else {
98 data.push_none()
99 }
100 }
101 Ok(Column {
102 name: fragment.fragment(),
103 data,
104 })
105}