reifydb_sdk/operator/
view_column.rs1use postcard::from_bytes;
5use reifydb_abi::data::column::ColumnTypeCode;
6use reifydb_type::value::decimal::Decimal;
7
8use crate::operator::change::{BorrowedColumn, BorrowedColumns};
9
10#[derive(Clone, Copy)]
11pub struct ColumnView<'a> {
12 inner: BorrowedColumn<'a>,
13}
14
15impl<'a> ColumnView<'a> {
16 pub(crate) fn new(inner: BorrowedColumn<'a>) -> Self {
17 Self {
18 inner,
19 }
20 }
21
22 pub fn name(&self) -> &'a str {
23 self.inner.name()
24 }
25
26 pub fn type_code(&self) -> ColumnTypeCode {
27 self.inner.type_code()
28 }
29
30 pub fn len(&self) -> usize {
31 self.inner.row_count()
32 }
33
34 pub fn is_empty(&self) -> bool {
35 self.len() == 0
36 }
37
38 pub fn raw(&self) -> BorrowedColumn<'a> {
39 self.inner
40 }
41
42 pub fn defined_bitvec(&self) -> Option<&'a [u8]> {
43 let bv = self.inner.defined_bitvec();
44 if bv.is_empty() {
45 None
46 } else {
47 Some(bv)
48 }
49 }
50
51 pub fn is_defined(&self, index: usize) -> bool {
52 match self.defined_bitvec() {
53 None => true,
54 Some(bv) => match bv.get(index / 8) {
55 Some(byte) => (byte >> (index % 8)) & 1 == 1,
56 None => false,
57 },
58 }
59 }
60
61 pub fn u8(&self) -> Option<&'a [u8]> {
62 if self.type_code() != ColumnTypeCode::Uint1 {
63 return None;
64 }
65 unsafe { self.inner.as_slice::<u8>() }
66 }
67
68 pub fn u16(&self) -> Option<&'a [u16]> {
69 if self.type_code() != ColumnTypeCode::Uint2 {
70 return None;
71 }
72 unsafe { self.inner.as_slice::<u16>() }
73 }
74
75 pub fn u32(&self) -> Option<&'a [u32]> {
76 if self.type_code() != ColumnTypeCode::Uint4 {
77 return None;
78 }
79 unsafe { self.inner.as_slice::<u32>() }
80 }
81
82 pub fn u64(&self) -> Option<&'a [u64]> {
83 if self.type_code() != ColumnTypeCode::Uint8 {
84 return None;
85 }
86 unsafe { self.inner.as_slice::<u64>() }
87 }
88
89 pub fn u128(&self) -> Option<&'a [u128]> {
90 if self.type_code() != ColumnTypeCode::Uint16 {
91 return None;
92 }
93 unsafe { self.inner.as_slice::<u128>() }
94 }
95
96 pub fn i8(&self) -> Option<&'a [i8]> {
97 if self.type_code() != ColumnTypeCode::Int1 {
98 return None;
99 }
100 unsafe { self.inner.as_slice::<i8>() }
101 }
102
103 pub fn i16(&self) -> Option<&'a [i16]> {
104 if self.type_code() != ColumnTypeCode::Int2 {
105 return None;
106 }
107 unsafe { self.inner.as_slice::<i16>() }
108 }
109
110 pub fn i32(&self) -> Option<&'a [i32]> {
111 if self.type_code() != ColumnTypeCode::Int4 {
112 return None;
113 }
114 unsafe { self.inner.as_slice::<i32>() }
115 }
116
117 pub fn i64(&self) -> Option<&'a [i64]> {
118 if self.type_code() != ColumnTypeCode::Int8 {
119 return None;
120 }
121 unsafe { self.inner.as_slice::<i64>() }
122 }
123
124 pub fn i128(&self) -> Option<&'a [i128]> {
125 if self.type_code() != ColumnTypeCode::Int16 {
126 return None;
127 }
128 unsafe { self.inner.as_slice::<i128>() }
129 }
130
131 pub fn f32(&self) -> Option<&'a [f32]> {
132 if self.type_code() != ColumnTypeCode::Float4 {
133 return None;
134 }
135 unsafe { self.inner.as_slice::<f32>() }
136 }
137
138 pub fn f64(&self) -> Option<&'a [f64]> {
139 if self.type_code() != ColumnTypeCode::Float8 {
140 return None;
141 }
142 unsafe { self.inner.as_slice::<f64>() }
143 }
144
145 pub fn bool_iter(&self) -> Option<BoolIter<'a>> {
146 if self.type_code() != ColumnTypeCode::Bool {
147 return None;
148 }
149 Some(BoolIter {
150 data: self.inner.data_bytes(),
151 row_count: self.inner.row_count(),
152 index: 0,
153 })
154 }
155
156 pub fn utf8_iter(&self) -> Option<impl Iterator<Item = &'a str> + 'a> {
157 if self.type_code() != ColumnTypeCode::Utf8 {
158 return None;
159 }
160 Some(self.inner.iter_str())
161 }
162
163 pub fn blob_iter(&self) -> Option<impl Iterator<Item = &'a [u8]> + 'a> {
164 if self.type_code() != ColumnTypeCode::Blob {
165 return None;
166 }
167 Some(self.inner.iter_bytes())
168 }
169
170 pub fn decimal_iter(&self) -> Option<impl Iterator<Item = Option<Decimal>> + 'a> {
171 if self.type_code() != ColumnTypeCode::Decimal {
172 return None;
173 }
174 let data = self.inner.data_bytes();
175 let offsets = self.inner.offsets();
176 let row_count = self.inner.row_count();
177 Some(DecimalIter {
178 data,
179 offsets,
180 row_count,
181 index: 0,
182 })
183 }
184
185 pub fn to_u64_vec(&self) -> Option<Vec<u64>> {
186 match self.type_code() {
187 ColumnTypeCode::Uint8 => self.u64().map(|s| s.to_vec()),
188 ColumnTypeCode::Uint4 => self.u32().map(|s| s.iter().map(|v| u64::from(*v)).collect()),
189 ColumnTypeCode::Uint2 => self.u16().map(|s| s.iter().map(|v| u64::from(*v)).collect()),
190 ColumnTypeCode::Uint1 => self.u8().map(|s| s.iter().map(|v| u64::from(*v)).collect()),
191 _ => None,
192 }
193 }
194
195 pub fn to_i64_vec(&self) -> Option<Vec<i64>> {
196 match self.type_code() {
197 ColumnTypeCode::Int8 => self.i64().map(|s| s.to_vec()),
198 ColumnTypeCode::Int4 => self.i32().map(|s| s.iter().map(|v| i64::from(*v)).collect()),
199 ColumnTypeCode::Int2 => self.i16().map(|s| s.iter().map(|v| i64::from(*v)).collect()),
200 ColumnTypeCode::Int1 => self.i8().map(|s| s.iter().map(|v| i64::from(*v)).collect()),
201 _ => None,
202 }
203 }
204
205 pub fn to_f64_vec(&self) -> Option<Vec<f64>> {
206 match self.type_code() {
207 ColumnTypeCode::Float8 => self.f64().map(|s| s.to_vec()),
208 ColumnTypeCode::Float4 => self.f32().map(|s| s.iter().map(|v| f64::from(*v)).collect()),
209 _ => None,
210 }
211 }
212}
213
214pub struct BoolIter<'a> {
215 data: &'a [u8],
216 row_count: usize,
217 index: usize,
218}
219
220impl<'a> Iterator for BoolIter<'a> {
221 type Item = bool;
222
223 fn next(&mut self) -> Option<bool> {
224 if self.index >= self.row_count {
225 return None;
226 }
227 let byte = *self.data.get(self.index / 8)?;
228 let bit = (byte >> (self.index % 8)) & 1 == 1;
229 self.index += 1;
230 Some(bit)
231 }
232
233 fn size_hint(&self) -> (usize, Option<usize>) {
234 let remaining = self.row_count - self.index;
235 (remaining, Some(remaining))
236 }
237}
238
239impl<'a> ExactSizeIterator for BoolIter<'a> {}
240
241pub struct DecimalIter<'a> {
242 data: &'a [u8],
243 offsets: &'a [u64],
244 row_count: usize,
245 index: usize,
246}
247
248impl<'a> Iterator for DecimalIter<'a> {
249 type Item = Option<Decimal>;
250
251 fn next(&mut self) -> Option<Option<Decimal>> {
252 if self.index >= self.row_count {
253 return None;
254 }
255 let i = self.index;
256 self.index += 1;
257 if i + 1 >= self.offsets.len() {
258 return Some(None);
259 }
260 let start = self.offsets[i] as usize;
261 let end = self.offsets[i + 1] as usize;
262 if end > self.data.len() || start > end {
263 return Some(None);
264 }
265 Some(from_bytes::<Decimal>(&self.data[start..end]).ok())
266 }
267
268 fn size_hint(&self) -> (usize, Option<usize>) {
269 let remaining = self.row_count - self.index;
270 (remaining, Some(remaining))
271 }
272}
273
274impl<'a> ExactSizeIterator for DecimalIter<'a> {}
275
276impl<'a> BorrowedColumns<'a> {
277 pub fn column_view(&self, name: &str) -> Option<ColumnView<'a>> {
278 self.column(name).map(ColumnView::new)
279 }
280
281 pub fn column_view_at(&self, index: usize) -> Option<ColumnView<'a>> {
282 self.columns().nth(index).map(ColumnView::new)
283 }
284
285 pub fn column_views(&self) -> impl Iterator<Item = ColumnView<'a>> + 'a {
286 self.columns().map(ColumnView::new)
287 }
288}