odbc_api/buffers/
column_with_indicator.rs1use super::{ColumnBuffer, Indicator, Resize, Slice};
2use crate::{
3 BoundInputSlice,
4 fixed_sized::{Bit, Pod},
5 handles::{CData, CDataMut, StatementRef},
6};
7use odbc_sys::{Date, NULL_DATA, Time, Timestamp};
8use std::{
9 ffi::c_void,
10 mem::size_of,
11 ptr::{null, null_mut},
12};
13
14pub type OptF64Column = ColumnWithIndicator<f64>;
15pub type OptF32Column = ColumnWithIndicator<f32>;
16pub type OptDateColumn = ColumnWithIndicator<Date>;
17pub type OptTimestampColumn = ColumnWithIndicator<Timestamp>;
18pub type OptTimeColumn = ColumnWithIndicator<Time>;
19pub type OptI8Column = ColumnWithIndicator<i8>;
20pub type OptI16Column = ColumnWithIndicator<i16>;
21pub type OptI32Column = ColumnWithIndicator<i32>;
22pub type OptI64Column = ColumnWithIndicator<i64>;
23pub type OptU8Column = ColumnWithIndicator<u8>;
24pub type OptBitColumn = ColumnWithIndicator<Bit>;
25
26#[derive(Debug)]
28pub struct ColumnWithIndicator<T> {
29 values: Vec<T>,
30 indicators: Vec<isize>,
31}
32
33impl<T> ColumnWithIndicator<T>
34where
35 T: Default + Clone,
36{
37 pub fn new(batch_size: usize) -> Self {
38 Self {
39 values: vec![T::default(); batch_size],
40 indicators: vec![NULL_DATA; batch_size],
41 }
42 }
43
44 pub fn writer_n(&mut self, n: usize) -> NullableSliceMut<'_, T> {
46 NullableSliceMut {
47 indicators: &mut self.indicators[0..n],
48 values: &mut self.values[0..n],
49 }
50 }
51}
52
53#[derive(Debug, Clone, Copy)]
56pub struct NullableSlice<'a, T> {
57 indicators: &'a [isize],
58 values: &'a [T],
59}
60
61impl<'a, T> NullableSlice<'a, T> {
62 pub fn is_empty(&self) -> bool {
64 self.values.is_empty()
65 }
66
67 pub fn len(&self) -> usize {
69 self.values.len()
70 }
71
72 pub fn raw_values(&self) -> (&'a [T], &'a [isize]) {
100 (self.values, self.indicators)
101 }
102
103 pub fn get(&self, index: usize) -> Option<&'a T> {
105 if self.indicators[index] == NULL_DATA {
106 None
107 } else {
108 Some(&self.values[index])
109 }
110 }
111}
112
113impl<'a, T> Iterator for NullableSlice<'a, T> {
114 type Item = Option<&'a T>;
115
116 fn next(&mut self) -> Option<Self::Item> {
117 if let Some(&ind) = self.indicators.first() {
118 let item = if ind == NULL_DATA {
119 None
120 } else {
121 Some(&self.values[0])
122 };
123 self.indicators = &self.indicators[1..];
124 self.values = &self.values[1..];
125 Some(item)
126 } else {
127 None
128 }
129 }
130}
131
132unsafe impl<T> CData for ColumnWithIndicator<T>
133where
134 T: Pod,
135{
136 fn cdata_type(&self) -> odbc_sys::CDataType {
137 T::C_DATA_TYPE
138 }
139
140 fn indicator_ptr(&self) -> *const isize {
141 self.indicators.as_ptr()
142 }
143
144 fn value_ptr(&self) -> *const c_void {
145 self.values.as_ptr() as *const c_void
146 }
147
148 fn buffer_length(&self) -> isize {
149 size_of::<T>().try_into().unwrap()
150 }
151}
152
153unsafe impl<T> CDataMut for ColumnWithIndicator<T>
154where
155 T: Pod,
156{
157 fn mut_indicator_ptr(&mut self) -> *mut isize {
158 self.indicators.as_mut_ptr()
159 }
160
161 fn mut_value_ptr(&mut self) -> *mut c_void {
162 self.values.as_mut_ptr() as *mut c_void
163 }
164}
165
166unsafe impl<T> ColumnBuffer for ColumnWithIndicator<T>
167where
168 T: Pod,
169{
170 fn capacity(&self) -> usize {
171 self.indicators.len()
172 }
173
174 fn has_truncated_values(&self, _num_rows: usize) -> Option<Indicator> {
175 None
176 }
177}
178
179unsafe impl<T> Slice for ColumnWithIndicator<T>
180where
181 T: Pod,
182{
183 type Slice<'a> = NullableSlice<'a, T>;
184
185 fn slice(&self, valid_rows: usize) -> NullableSlice<'_, T> {
186 NullableSlice {
187 indicators: &self.indicators[0..valid_rows],
188 values: &self.values[0..valid_rows],
189 }
190 }
191}
192
193unsafe impl<'a, T> BoundInputSlice<'a> for ColumnWithIndicator<T>
194where
195 T: Pod + 'static,
196{
197 type SliceMut = NullableSliceMut<'a, T>;
198
199 unsafe fn as_view_mut(
200 &'a mut self,
201 _parameter_index: u16,
202 _stmt: StatementRef<'a>,
203 ) -> NullableSliceMut<'a, T> {
204 self.writer_n(self.capacity())
205 }
206}
207
208unsafe impl<T> CData for Vec<T>
209where
210 T: Pod,
211{
212 fn cdata_type(&self) -> odbc_sys::CDataType {
213 T::C_DATA_TYPE
214 }
215
216 fn indicator_ptr(&self) -> *const isize {
217 null()
218 }
219
220 fn value_ptr(&self) -> *const c_void {
221 self.as_ptr() as *const c_void
222 }
223
224 fn buffer_length(&self) -> isize {
225 size_of::<T>().try_into().unwrap()
226 }
227}
228
229unsafe impl<T> CDataMut for Vec<T>
230where
231 T: Pod,
232{
233 fn mut_indicator_ptr(&mut self) -> *mut isize {
234 null_mut()
235 }
236
237 fn mut_value_ptr(&mut self) -> *mut c_void {
238 self.as_mut_ptr() as *mut c_void
239 }
240}
241
242unsafe impl<'a, T> BoundInputSlice<'a> for Vec<T>
243where
244 T: Pod + 'static,
245{
246 type SliceMut = &'a mut [T];
247
248 unsafe fn as_view_mut(
249 &'a mut self,
250 _parameter_index: u16,
251 _stmt: StatementRef<'a>,
252 ) -> &'a mut [T] {
253 self.as_mut_slice()
254 }
255}
256
257#[derive(Debug)]
260pub struct NullableSliceMut<'a, T> {
261 indicators: &'a mut [isize],
262 values: &'a mut [T],
263}
264
265impl<T> NullableSliceMut<'_, T> {
266 pub fn is_empty(&self) -> bool {
268 self.values.is_empty()
269 }
270
271 pub fn len(&self) -> usize {
273 self.values.len()
274 }
275
276 pub fn set_cell(&mut self, index: usize, cell: Option<T>) {
278 if let Some(value) = cell {
279 self.indicators[index] = 0;
280 self.values[index] = value;
281 } else {
282 self.indicators[index] = NULL_DATA;
283 }
284 }
285
286 pub fn raw_values(&mut self) -> (&mut [T], &mut [isize]) {
318 (self.values, self.indicators)
319 }
320}
321
322impl<T> NullableSliceMut<'_, T> {
323 pub fn write(&mut self, it: impl Iterator<Item = Option<T>>) {
326 for (index, item) in it.enumerate().take(self.values.len()) {
327 self.set_cell(index, item)
328 }
329 }
330}
331
332impl<T> Resize for ColumnWithIndicator<T>
333where
334 T: Default + Clone,
335{
336 fn resize(&mut self, new_size: usize) {
337 self.values.resize(new_size, T::default());
338 self.indicators.resize(new_size, NULL_DATA);
339 }
340}
341
342#[cfg(test)]
343mod tests {
344 use crate::buffers::{Resize, Slice};
345
346 use super::ColumnWithIndicator;
347
348 #[test]
349 fn column_with_indicator_is_resize() {
350 let mut column = ColumnWithIndicator::<i32>::new(2);
352 let mut writer = column.writer_n(2);
353 writer.set_cell(0, Some(1));
354 writer.set_cell(1, Some(2));
355
356 column.resize(3);
358
359 let slice = column.slice(3);
361 assert_eq!(slice.get(0), Some(&1));
362 assert_eq!(slice.get(1), Some(&2));
363 assert_eq!(slice.get(2), None);
364 }
365}