odbc_api/buffers/
column_with_indicator.rs1use crate::{
2 buffers::Resize,
3 fixed_sized::{Bit, Pod},
4 handles::{CData, CDataMut},
5};
6use odbc_sys::{Date, NULL_DATA, Time, Timestamp};
7use std::{
8 ffi::c_void,
9 mem::size_of,
10 ptr::{null, null_mut},
11};
12
13pub type OptF64Column = ColumnWithIndicator<f64>;
14pub type OptF32Column = ColumnWithIndicator<f32>;
15pub type OptDateColumn = ColumnWithIndicator<Date>;
16pub type OptTimestampColumn = ColumnWithIndicator<Timestamp>;
17pub type OptTimeColumn = ColumnWithIndicator<Time>;
18pub type OptI8Column = ColumnWithIndicator<i8>;
19pub type OptI16Column = ColumnWithIndicator<i16>;
20pub type OptI32Column = ColumnWithIndicator<i32>;
21pub type OptI64Column = ColumnWithIndicator<i64>;
22pub type OptU8Column = ColumnWithIndicator<u8>;
23pub type OptBitColumn = ColumnWithIndicator<Bit>;
24
25#[derive(Debug)]
27pub struct ColumnWithIndicator<T> {
28 values: Vec<T>,
29 indicators: Vec<isize>,
30}
31
32impl<T> ColumnWithIndicator<T>
33where
34 T: Default + Clone,
35{
36 pub fn new(batch_size: usize) -> Self {
37 Self {
38 values: vec![T::default(); batch_size],
39 indicators: vec![NULL_DATA; batch_size],
40 }
41 }
42
43 pub fn iter(&self, num_rows: usize) -> NullableSlice<'_, T> {
50 NullableSlice {
51 indicators: &self.indicators[0..num_rows],
52 values: &self.values[0..num_rows],
53 }
54 }
55
56 pub fn fill_null(&mut self, from: usize, to: usize) {
58 for index in from..to {
59 self.indicators[index] = NULL_DATA;
60 }
61 }
62
63 pub fn writer_n(&mut self, n: usize) -> NullableSliceMut<'_, T> {
65 NullableSliceMut {
66 indicators: &mut self.indicators[0..n],
67 values: &mut self.values[0..n],
68 }
69 }
70
71 pub fn capacity(&self) -> usize {
73 self.indicators.len()
74 }
75}
76
77#[derive(Debug, Clone, Copy)]
80pub struct NullableSlice<'a, T> {
81 indicators: &'a [isize],
82 values: &'a [T],
83}
84
85impl<'a, T> NullableSlice<'a, T> {
86 pub fn is_empty(&self) -> bool {
88 self.values.is_empty()
89 }
90
91 pub fn len(&self) -> usize {
93 self.values.len()
94 }
95
96 pub fn raw_values(&self) -> (&'a [T], &'a [isize]) {
124 (self.values, self.indicators)
125 }
126
127 pub fn get(&self, index: usize) -> Option<&'a T> {
129 if self.indicators[index] == NULL_DATA {
130 None
131 } else {
132 Some(&self.values[index])
133 }
134 }
135}
136
137impl<'a, T> Iterator for NullableSlice<'a, T> {
138 type Item = Option<&'a T>;
139
140 fn next(&mut self) -> Option<Self::Item> {
141 if let Some(&ind) = self.indicators.first() {
142 let item = if ind == NULL_DATA {
143 None
144 } else {
145 Some(&self.values[0])
146 };
147 self.indicators = &self.indicators[1..];
148 self.values = &self.values[1..];
149 Some(item)
150 } else {
151 None
152 }
153 }
154}
155
156unsafe impl<T> CData for ColumnWithIndicator<T>
157where
158 T: Pod,
159{
160 fn cdata_type(&self) -> odbc_sys::CDataType {
161 T::C_DATA_TYPE
162 }
163
164 fn indicator_ptr(&self) -> *const isize {
165 self.indicators.as_ptr()
166 }
167
168 fn value_ptr(&self) -> *const c_void {
169 self.values.as_ptr() as *const c_void
170 }
171
172 fn buffer_length(&self) -> isize {
173 size_of::<T>().try_into().unwrap()
174 }
175}
176
177unsafe impl<T> CDataMut for ColumnWithIndicator<T>
178where
179 T: Pod,
180{
181 fn mut_indicator_ptr(&mut self) -> *mut isize {
182 self.indicators.as_mut_ptr()
183 }
184
185 fn mut_value_ptr(&mut self) -> *mut c_void {
186 self.values.as_mut_ptr() as *mut c_void
187 }
188}
189
190unsafe impl<T> CData for Vec<T>
191where
192 T: Pod,
193{
194 fn cdata_type(&self) -> odbc_sys::CDataType {
195 T::C_DATA_TYPE
196 }
197
198 fn indicator_ptr(&self) -> *const isize {
199 null()
200 }
201
202 fn value_ptr(&self) -> *const c_void {
203 self.as_ptr() as *const c_void
204 }
205
206 fn buffer_length(&self) -> isize {
207 size_of::<T>().try_into().unwrap()
208 }
209}
210
211unsafe impl<T> CDataMut for Vec<T>
212where
213 T: Pod,
214{
215 fn mut_indicator_ptr(&mut self) -> *mut isize {
216 null_mut()
217 }
218
219 fn mut_value_ptr(&mut self) -> *mut c_void {
220 self.as_mut_ptr() as *mut c_void
221 }
222}
223
224#[derive(Debug)]
227pub struct NullableSliceMut<'a, T> {
228 indicators: &'a mut [isize],
229 values: &'a mut [T],
230}
231
232impl<T> NullableSliceMut<'_, T> {
233 pub fn is_empty(&self) -> bool {
235 self.values.is_empty()
236 }
237
238 pub fn len(&self) -> usize {
240 self.values.len()
241 }
242
243 pub fn set_cell(&mut self, index: usize, cell: Option<T>) {
245 if let Some(value) = cell {
246 self.indicators[index] = 0;
247 self.values[index] = value;
248 } else {
249 self.indicators[index] = NULL_DATA;
250 }
251 }
252
253 pub fn raw_values(&mut self) -> (&mut [T], &mut [isize]) {
285 (self.values, self.indicators)
286 }
287}
288
289impl<T> NullableSliceMut<'_, T> {
290 pub fn write(&mut self, it: impl Iterator<Item = Option<T>>) {
293 for (index, item) in it.enumerate().take(self.values.len()) {
294 self.set_cell(index, item)
295 }
296 }
297}
298
299impl<T> Resize for ColumnWithIndicator<T>
300where
301 T: Default + Clone,
302{
303 fn resize(&mut self, new_size: usize) {
304 self.values.resize(new_size, T::default());
305 self.indicators.resize(new_size, NULL_DATA);
306 }
307}
308
309#[cfg(test)]
310mod tests {
311 use crate::buffers::Resize;
312
313 use super::ColumnWithIndicator;
314
315 #[test]
316 fn column_with_indicator_is_resize() {
317 let mut column = ColumnWithIndicator::<i32>::new(2);
319 let mut writer = column.writer_n(2);
320 writer.set_cell(0, Some(1));
321 writer.set_cell(1, Some(2));
322
323 column.resize(3);
325
326 let reader = column.iter(3);
328 assert_eq!(reader.get(0), Some(&1));
329 assert_eq!(reader.get(1), Some(&2));
330 assert_eq!(reader.get(2), None);
331 }
332}