odbc_api/buffers/
column_with_indicator.rs1use super::{ColumnBuffer, Indicator, Resize, Slice};
2use crate::{
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
72#[derive(Debug, Clone, Copy)]
75pub struct NullableSlice<'a, T> {
76 indicators: &'a [isize],
77 values: &'a [T],
78}
79
80impl<'a, T> NullableSlice<'a, T> {
81 pub fn is_empty(&self) -> bool {
83 self.values.is_empty()
84 }
85
86 pub fn len(&self) -> usize {
88 self.values.len()
89 }
90
91 pub fn raw_values(&self) -> (&'a [T], &'a [isize]) {
119 (self.values, self.indicators)
120 }
121
122 pub fn get(&self, index: usize) -> Option<&'a T> {
124 if self.indicators[index] == NULL_DATA {
125 None
126 } else {
127 Some(&self.values[index])
128 }
129 }
130}
131
132impl<'a, T> Iterator for NullableSlice<'a, T> {
133 type Item = Option<&'a T>;
134
135 fn next(&mut self) -> Option<Self::Item> {
136 if let Some(&ind) = self.indicators.first() {
137 let item = if ind == NULL_DATA {
138 None
139 } else {
140 Some(&self.values[0])
141 };
142 self.indicators = &self.indicators[1..];
143 self.values = &self.values[1..];
144 Some(item)
145 } else {
146 None
147 }
148 }
149}
150
151unsafe impl<T> CData for ColumnWithIndicator<T>
152where
153 T: Pod,
154{
155 fn cdata_type(&self) -> odbc_sys::CDataType {
156 T::C_DATA_TYPE
157 }
158
159 fn indicator_ptr(&self) -> *const isize {
160 self.indicators.as_ptr()
161 }
162
163 fn value_ptr(&self) -> *const c_void {
164 self.values.as_ptr() as *const c_void
165 }
166
167 fn buffer_length(&self) -> isize {
168 size_of::<T>().try_into().unwrap()
169 }
170}
171
172unsafe impl<T> CDataMut for ColumnWithIndicator<T>
173where
174 T: Pod,
175{
176 fn mut_indicator_ptr(&mut self) -> *mut isize {
177 self.indicators.as_mut_ptr()
178 }
179
180 fn mut_value_ptr(&mut self) -> *mut c_void {
181 self.values.as_mut_ptr() as *mut c_void
182 }
183}
184
185unsafe impl<T> ColumnBuffer for ColumnWithIndicator<T>
186where
187 T: Pod,
188{
189 fn capacity(&self) -> usize {
190 self.indicators.len()
191 }
192
193 fn has_truncated_values(&self, _num_rows: usize) -> Option<Indicator> {
194 None
195 }
196}
197
198unsafe impl<T> Slice for ColumnWithIndicator<T>
199where
200 T: Pod,
201{
202 type Slice<'a> = NullableSlice<'a, T>;
203
204 fn slice(&self, valid_rows: usize) -> NullableSlice<'_, T> {
205 NullableSlice {
206 indicators: &self.indicators[0..valid_rows],
207 values: &self.values[0..valid_rows],
208 }
209 }
210}
211
212unsafe impl<T> CData for Vec<T>
213where
214 T: Pod,
215{
216 fn cdata_type(&self) -> odbc_sys::CDataType {
217 T::C_DATA_TYPE
218 }
219
220 fn indicator_ptr(&self) -> *const isize {
221 null()
222 }
223
224 fn value_ptr(&self) -> *const c_void {
225 self.as_ptr() as *const c_void
226 }
227
228 fn buffer_length(&self) -> isize {
229 size_of::<T>().try_into().unwrap()
230 }
231}
232
233unsafe impl<T> CDataMut for Vec<T>
234where
235 T: Pod,
236{
237 fn mut_indicator_ptr(&mut self) -> *mut isize {
238 null_mut()
239 }
240
241 fn mut_value_ptr(&mut self) -> *mut c_void {
242 self.as_mut_ptr() as *mut c_void
243 }
244}
245
246#[derive(Debug)]
249pub struct NullableSliceMut<'a, T> {
250 indicators: &'a mut [isize],
251 values: &'a mut [T],
252}
253
254impl<T> NullableSliceMut<'_, T> {
255 pub fn is_empty(&self) -> bool {
257 self.values.is_empty()
258 }
259
260 pub fn len(&self) -> usize {
262 self.values.len()
263 }
264
265 pub fn set_cell(&mut self, index: usize, cell: Option<T>) {
267 if let Some(value) = cell {
268 self.indicators[index] = 0;
269 self.values[index] = value;
270 } else {
271 self.indicators[index] = NULL_DATA;
272 }
273 }
274
275 pub fn raw_values(&mut self) -> (&mut [T], &mut [isize]) {
307 (self.values, self.indicators)
308 }
309}
310
311impl<T> NullableSliceMut<'_, T> {
312 pub fn write(&mut self, it: impl Iterator<Item = Option<T>>) {
315 for (index, item) in it.enumerate().take(self.values.len()) {
316 self.set_cell(index, item)
317 }
318 }
319}
320
321impl<T> Resize for ColumnWithIndicator<T>
322where
323 T: Default + Clone,
324{
325 fn resize(&mut self, new_size: usize) {
326 self.values.resize(new_size, T::default());
327 self.indicators.resize(new_size, NULL_DATA);
328 }
329}
330
331#[cfg(test)]
332mod tests {
333 use crate::buffers::Resize;
334
335 use super::ColumnWithIndicator;
336
337 #[test]
338 fn column_with_indicator_is_resize() {
339 let mut column = ColumnWithIndicator::<i32>::new(2);
341 let mut writer = column.writer_n(2);
342 writer.set_cell(0, Some(1));
343 writer.set_cell(1, Some(2));
344
345 column.resize(3);
347
348 let reader = column.iter(3);
350 assert_eq!(reader.get(0), Some(&1));
351 assert_eq!(reader.get(1), Some(&2));
352 assert_eq!(reader.get(2), None);
353 }
354}