reifydb_engine/function/math/scalar/
round.rs1use reifydb_core::value::column::ColumnData;
5
6use crate::function::{ScalarFunction, ScalarFunctionContext};
7
8pub struct Round;
9
10impl Default for Round {
11 fn default() -> Self {
12 Self {}
13 }
14}
15
16impl Round {
17 pub fn new() -> Self {
18 Self::default()
19 }
20}
21
22impl ScalarFunction for Round {
23 fn scalar(&self, ctx: ScalarFunctionContext) -> crate::Result<ColumnData> {
24 let columns = ctx.columns;
25 let row_count = ctx.row_count;
26
27 if columns.is_empty() {
28 return Ok(ColumnData::utf8(Vec::<String>::new()));
29 }
30
31 let value_column = columns.first().unwrap();
32
33 let precision_column = columns.get(1);
35
36 match value_column.data() {
37 ColumnData::Float4(container) => {
38 let mut result = Vec::with_capacity(row_count);
39
40 for row_idx in 0..row_count {
41 if let Some(&value) = container.get(row_idx) {
42 let precision = if let Some(prec_col) = precision_column {
43 match prec_col.data() {
44 ColumnData::Int4(prec_container) => prec_container
45 .get(row_idx)
46 .copied()
47 .unwrap_or(0),
48 ColumnData::Int1(prec_container) => prec_container
49 .get(row_idx)
50 .map(|&v| v as i32)
51 .unwrap_or(0),
52 ColumnData::Int2(prec_container) => prec_container
53 .get(row_idx)
54 .map(|&v| v as i32)
55 .unwrap_or(0),
56 ColumnData::Int8(prec_container) => prec_container
57 .get(row_idx)
58 .map(|&v| v as i32)
59 .unwrap_or(0),
60 _ => 0,
61 }
62 } else {
63 0
64 };
65
66 let multiplier = 10_f32.powi(precision);
67 let rounded = (value * multiplier).round() / multiplier;
68 result.push(rounded);
69 } else {
70 result.push(0.0);
71 }
72 }
73
74 Ok(ColumnData::float4(result))
75 }
76 ColumnData::Float8(container) => {
77 let mut result = Vec::with_capacity(row_count);
78
79 for row_idx in 0..row_count {
80 if let Some(&value) = container.get(row_idx) {
81 let precision = if let Some(prec_col) = precision_column {
82 match prec_col.data() {
83 ColumnData::Int4(prec_container) => prec_container
84 .get(row_idx)
85 .copied()
86 .unwrap_or(0),
87 ColumnData::Int1(prec_container) => prec_container
88 .get(row_idx)
89 .map(|&v| v as i32)
90 .unwrap_or(0),
91 ColumnData::Int2(prec_container) => prec_container
92 .get(row_idx)
93 .map(|&v| v as i32)
94 .unwrap_or(0),
95 ColumnData::Int8(prec_container) => prec_container
96 .get(row_idx)
97 .map(|&v| v as i32)
98 .unwrap_or(0),
99 _ => 0,
100 }
101 } else {
102 0
103 };
104
105 let multiplier = 10_f64.powi(precision);
106 let rounded = (value * multiplier).round() / multiplier;
107 result.push(rounded);
108 } else {
109 result.push(0.0);
110 }
111 }
112
113 Ok(ColumnData::float8(result))
114 }
115 ColumnData::Int4(container) => {
116 let mut result = Vec::with_capacity(row_count);
117
118 for row_idx in 0..row_count {
119 if let Some(&value) = container.get(row_idx) {
120 result.push(value);
121 } else {
122 result.push(0);
123 }
124 }
125
126 Ok(ColumnData::int4(result))
127 }
128 _ => unimplemented!("Round function currently supports float4, float8, and int4 types"),
129 }
130 }
131}