1use 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 iter(&self, num_rows: usize) -> NullableSlice<'_, T> {
51 NullableSlice {
52 indicators: &self.indicators[0..num_rows],
53 values: &self.values[0..num_rows],
54 }
55 }
56
57 pub fn fill_null(&mut self, from: usize, to: usize) {
59 for index in from..to {
60 self.indicators[index] = NULL_DATA;
61 }
62 }
63
64 pub fn writer_n(&mut self, n: usize) -> NullableSliceMut<'_, T> {
66 NullableSliceMut {
67 indicators: &mut self.indicators[0..n],
68 values: &mut self.values[0..n],
69 }
70 }
71}
72
73#[derive(Debug, Clone, Copy)]
76pub struct NullableSlice<'a, T> {
77 indicators: &'a [isize],
78 values: &'a [T],
79}
80
81impl<'a, T> NullableSlice<'a, T> {
82 pub fn is_empty(&self) -> bool {
84 self.values.is_empty()
85 }
86
87 pub fn len(&self) -> usize {
89 self.values.len()
90 }
91
92 pub fn raw_values(&self) -> (&'a [T], &'a [isize]) {
120 (self.values, self.indicators)
121 }
122
123 pub fn get(&self, index: usize) -> Option<&'a T> {
125 if self.indicators[index] == NULL_DATA {
126 None
127 } else {
128 Some(&self.values[index])
129 }
130 }
131}
132
133impl<'a, T> Iterator for NullableSlice<'a, T> {
134 type Item = Option<&'a T>;
135
136 fn next(&mut self) -> Option<Self::Item> {
137 if let Some(&ind) = self.indicators.first() {
138 let item = if ind == NULL_DATA {
139 None
140 } else {
141 Some(&self.values[0])
142 };
143 self.indicators = &self.indicators[1..];
144 self.values = &self.values[1..];
145 Some(item)
146 } else {
147 None
148 }
149 }
150}
151
152unsafe impl<T> CData for ColumnWithIndicator<T>
153where
154 T: Pod,
155{
156 fn cdata_type(&self) -> odbc_sys::CDataType {
157 T::C_DATA_TYPE
158 }
159
160 fn indicator_ptr(&self) -> *const isize {
161 self.indicators.as_ptr()
162 }
163
164 fn value_ptr(&self) -> *const c_void {
165 self.values.as_ptr() as *const c_void
166 }
167
168 fn buffer_length(&self) -> isize {
169 size_of::<T>().try_into().unwrap()
170 }
171}
172
173unsafe impl<T> CDataMut for ColumnWithIndicator<T>
174where
175 T: Pod,
176{
177 fn mut_indicator_ptr(&mut self) -> *mut isize {
178 self.indicators.as_mut_ptr()
179 }
180
181 fn mut_value_ptr(&mut self) -> *mut c_void {
182 self.values.as_mut_ptr() as *mut c_void
183 }
184}
185
186unsafe impl<T> ColumnBuffer for ColumnWithIndicator<T>
187where
188 T: Pod,
189{
190 fn capacity(&self) -> usize {
191 self.indicators.len()
192 }
193
194 fn has_truncated_values(&self, _num_rows: usize) -> Option<Indicator> {
195 None
196 }
197}
198
199unsafe impl<T> Slice for ColumnWithIndicator<T>
200where
201 T: Pod,
202{
203 type Slice<'a> = NullableSlice<'a, T>;
204
205 fn slice(&self, valid_rows: usize) -> NullableSlice<'_, T> {
206 NullableSlice {
207 indicators: &self.indicators[0..valid_rows],
208 values: &self.values[0..valid_rows],
209 }
210 }
211}
212
213unsafe impl<'a, T> BoundInputSlice<'a> for ColumnWithIndicator<T>
214where
215 T: Pod + 'static,
216{
217 type SliceMut = NullableSliceMut<'a, T>;
218
219 unsafe fn as_view_mut(
220 &'a mut self,
221 _parameter_index: u16,
222 _stmt: StatementRef<'a>,
223 ) -> NullableSliceMut<'a, T> {
224 self.writer_n(self.capacity())
225 }
226}
227
228unsafe impl<T> CData for Vec<T>
229where
230 T: Pod,
231{
232 fn cdata_type(&self) -> odbc_sys::CDataType {
233 T::C_DATA_TYPE
234 }
235
236 fn indicator_ptr(&self) -> *const isize {
237 null()
238 }
239
240 fn value_ptr(&self) -> *const c_void {
241 self.as_ptr() as *const c_void
242 }
243
244 fn buffer_length(&self) -> isize {
245 size_of::<T>().try_into().unwrap()
246 }
247}
248
249unsafe impl<T> CDataMut for Vec<T>
250where
251 T: Pod,
252{
253 fn mut_indicator_ptr(&mut self) -> *mut isize {
254 null_mut()
255 }
256
257 fn mut_value_ptr(&mut self) -> *mut c_void {
258 self.as_mut_ptr() as *mut c_void
259 }
260}
261
262unsafe impl<'a, T> BoundInputSlice<'a> for Vec<T>
263where
264 T: Pod + 'static,
265{
266 type SliceMut = &'a mut [T];
267
268 unsafe fn as_view_mut(
269 &'a mut self,
270 _parameter_index: u16,
271 _stmt: StatementRef<'a>,
272 ) -> &'a mut [T] {
273 self.as_mut_slice()
274 }
275}
276
277#[derive(Debug)]
280pub struct NullableSliceMut<'a, T> {
281 indicators: &'a mut [isize],
282 values: &'a mut [T],
283}
284
285impl<T> NullableSliceMut<'_, T> {
286 pub fn is_empty(&self) -> bool {
288 self.values.is_empty()
289 }
290
291 pub fn len(&self) -> usize {
293 self.values.len()
294 }
295
296 pub fn set_cell(&mut self, index: usize, cell: Option<T>) {
298 if let Some(value) = cell {
299 self.indicators[index] = 0;
300 self.values[index] = value;
301 } else {
302 self.indicators[index] = NULL_DATA;
303 }
304 }
305
306 pub fn raw_values(&mut self) -> (&mut [T], &mut [isize]) {
338 (self.values, self.indicators)
339 }
340}
341
342impl<T> NullableSliceMut<'_, T> {
343 pub fn write(&mut self, it: impl Iterator<Item = Option<T>>) {
346 for (index, item) in it.enumerate().take(self.values.len()) {
347 self.set_cell(index, item)
348 }
349 }
350}
351
352impl<T> Resize for ColumnWithIndicator<T>
353where
354 T: Default + Clone,
355{
356 fn resize(&mut self, new_size: usize) {
357 self.values.resize(new_size, T::default());
358 self.indicators.resize(new_size, NULL_DATA);
359 }
360}
361
362#[cfg(test)]
363mod tests {
364 use crate::buffers::Resize;
365
366 use super::ColumnWithIndicator;
367
368 #[test]
369 fn column_with_indicator_is_resize() {
370 let mut column = ColumnWithIndicator::<i32>::new(2);
372 let mut writer = column.writer_n(2);
373 writer.set_cell(0, Some(1));
374 writer.set_cell(1, Some(2));
375
376 column.resize(3);
378
379 let reader = column.iter(3);
381 assert_eq!(reader.get(0), Some(&1));
382 assert_eq!(reader.get(1), Some(&2));
383 assert_eq!(reader.get(2), None);
384 }
385}