1use super::{
2 BinColumn, BinColumnSlice, BinColumnSliceMut, BufferDesc, ColumnBuffer, ColumnarBuffer,
3 Indicator, NullableSlice, NullableSliceMut, Resize, Slice, TextColumn, TextColumnSlice,
4 TextColumnSliceMut, column_with_indicator::ColumnWithIndicator,
5};
6
7use crate::{
8 BoundInputSlice, Error,
9 fixed_sized::Pod,
10 handles::{CData, CDataMut, StatementRef},
11};
12
13use std::{any::Any, collections::HashSet, ffi::c_void};
14
15pub type ColumnarDynBuffer = ColumnarBuffer<BoxColumnBuffer>;
20
21impl ColumnarDynBuffer {
22 pub fn from_descs(capacity: usize, descs: impl IntoIterator<Item = BufferDesc>) -> Self {
24 let mut column_index = 0;
25 let columns = descs
26 .into_iter()
27 .map(move |desc| {
28 let buffer = desc.column_buffer(capacity);
29 column_index += 1;
30 (column_index, buffer)
31 })
32 .collect();
33 unsafe { ColumnarBuffer::new_unchecked(capacity, columns) }
34 }
35
36 pub fn try_from_descs(
41 capacity: usize,
42 descs: impl IntoIterator<Item = BufferDesc>,
43 ) -> Result<Self, Error> {
44 let mut column_index = 0;
45 let columns = descs
46 .into_iter()
47 .map(move |desc| {
48 let buffer = desc
49 .try_column_buffer(capacity)
50 .map_err(|source| source.add_context(column_index))?;
51 column_index += 1;
52 Ok::<_, Error>((column_index, buffer))
53 })
54 .collect::<Result<_, _>>()?;
55 Ok(unsafe { ColumnarBuffer::new_unchecked(capacity, columns) })
56 }
57
58 pub fn from_descs_and_indices(
63 max_rows: usize,
64 description: impl Iterator<Item = (u16, BufferDesc)>,
65 ) -> Self {
66 let columns: Vec<_> = description
67 .map(|(col_index, buffer_desc)| (col_index, buffer_desc.column_buffer(max_rows)))
68 .collect();
69
70 let mut indices = HashSet::new();
72 if columns
73 .iter()
74 .any(move |&(col_index, _)| !indices.insert(col_index))
75 {
76 panic!("Column indices must be unique.")
77 }
78
79 ColumnarBuffer::new(columns)
80 }
81}
82
83pub type BoxColumnBuffer = Box<dyn AnyColumnBuffer>;
87
88pub trait AnyColumnBuffer: ColumnBuffer + Resize + Any + Send {}
97
98impl<T> AnyColumnBuffer for T where T: ColumnBuffer + Resize + Any + Send {}
99
100unsafe impl CData for BoxColumnBuffer {
101 fn cdata_type(&self) -> odbc_sys::CDataType {
102 self.as_ref().cdata_type()
103 }
104
105 fn indicator_ptr(&self) -> *const isize {
106 self.as_ref().indicator_ptr()
107 }
108
109 fn value_ptr(&self) -> *const c_void {
110 self.as_ref().value_ptr()
111 }
112
113 fn buffer_length(&self) -> isize {
114 self.as_ref().buffer_length()
115 }
116}
117
118unsafe impl CDataMut for BoxColumnBuffer {
119 fn mut_indicator_ptr(&mut self) -> *mut isize {
120 self.as_mut().mut_indicator_ptr()
121 }
122
123 fn mut_value_ptr(&mut self) -> *mut c_void {
124 self.as_mut().mut_value_ptr()
125 }
126}
127
128unsafe impl ColumnBuffer for BoxColumnBuffer {
129 fn capacity(&self) -> usize {
130 self.as_ref().capacity()
131 }
132
133 fn has_truncated_values(&self, num_rows: usize) -> Option<Indicator> {
134 self.as_ref().has_truncated_values(num_rows)
135 }
136}
137
138unsafe impl Slice for BoxColumnBuffer {
139 type Slice<'a> = AnyColumnBufferSlice<'a>;
140
141 fn slice(&self, valid_rows: usize) -> AnyColumnBufferSlice<'_> {
142 AnyColumnBufferSlice {
143 buffer: self,
144 valid_rows,
145 }
146 }
147}
148
149#[derive(Clone, Copy)]
152pub struct AnyColumnBufferSlice<'a> {
153 buffer: &'a BoxColumnBuffer,
154 valid_rows: usize,
155}
156
157impl<'a> AnyColumnBufferSlice<'a> {
158 pub fn of<T>(self) -> Option<T::Slice<'a>>
165 where
166 T: Slice + 'static,
167 {
168 let buffer: &dyn Any = self.buffer.as_ref();
169 let buffer = buffer.downcast_ref::<T>()?;
170 Some(T::slice(buffer, self.valid_rows))
171 }
172
173 pub fn as_text(self) -> Option<TextColumnSlice<'a, u8>> {
179 self.of::<TextColumn<u8>>()
180 }
181
182 pub fn as_wide_text(self) -> Option<TextColumnSlice<'a, u16>> {
188 self.of::<TextColumn<u16>>()
189 }
190
191 pub fn as_binary(self) -> Option<BinColumnSlice<'a>> {
196 self.of::<BinColumn>()
197 }
198
199 pub fn as_slice<T>(self) -> Option<&'a [T]>
201 where
202 T: Pod,
203 {
204 self.of::<Vec<T>>()
205 }
206
207 pub fn as_nullable_slice<T>(self) -> Option<NullableSlice<'a, T>>
209 where
210 T: Pod,
211 {
212 self.of::<ColumnWithIndicator<T>>()
213 }
214}
215
216unsafe impl<'a> BoundInputSlice<'a> for BoxColumnBuffer {
217 type SliceMut = BoxColumBufferRefMut<'a>;
218
219 unsafe fn as_view_mut(
220 &'a mut self,
221 parameter_index: u16,
222 stmt: StatementRef<'a>,
223 ) -> BoxColumBufferRefMut<'a> {
224 BoxColumBufferRefMut {
225 buffer: self,
226 parameter_index,
227 stmt,
228 }
229 }
230}
231
232pub struct BoxColumBufferRefMut<'a> {
238 buffer: &'a mut BoxColumnBuffer,
241 parameter_index: u16,
244 stmt: StatementRef<'a>,
248}
249
250impl<'a> BoxColumBufferRefMut<'a> {
251 pub fn of<T>(self) -> Option<T::SliceMut>
253 where
254 T: BoundInputSlice<'a> + 'static,
255 {
256 let buffer: &mut dyn Any = self.buffer.as_mut();
257 let buffer = buffer.downcast_mut::<T>()?;
258 let view_mut = unsafe { buffer.as_view_mut(self.parameter_index, self.stmt) };
259 Some(view_mut)
260 }
261
262 pub fn as_wide_text(self) -> Option<TextColumnSliceMut<'a, u16>> {
268 self.of::<TextColumn<u16>>()
269 }
270
271 pub fn as_text(self) -> Option<TextColumnSliceMut<'a, u8>> {
277 self.of::<TextColumn<u8>>()
278 }
279
280 pub fn as_binary(self) -> Option<BinColumnSliceMut<'a>> {
285 self.of::<BinColumn>()
286 }
287
288 pub fn as_slice<T>(self) -> Option<&'a mut [T]>
289 where
290 T: Pod,
291 {
292 self.of::<Vec<T>>()
293 }
294
295 pub fn as_nullable_slice<T>(self) -> Option<NullableSliceMut<'a, T>>
296 where
297 T: Pod,
298 {
299 self.of::<ColumnWithIndicator<T>>()
300 }
301}
302
303impl Resize for BoxColumnBuffer {
304 fn resize(&mut self, new_capacity: usize) {
305 self.as_mut().resize(new_capacity);
306 }
307}
308
309#[cfg(test)]
310mod tests {
311 use super::{BoxColumnBuffer, BufferDesc, ColumnarDynBuffer, Slice};
312
313 #[test]
314 #[should_panic(expected = "Column indices must be unique.")]
315 fn assert_unique_column_indices() {
316 let bd = BufferDesc::I32 { nullable: false };
317 ColumnarDynBuffer::from_descs_and_indices(1, [(1, bd), (2, bd), (1, bd)].iter().cloned());
318 }
319
320 #[test]
321 fn box_column_buffer_is_resize() {
322 let mut buffer: BoxColumnBuffer = Box::new(vec![1i32, 2]);
324
325 buffer.resize(4);
327
328 assert_eq!(buffer.slice(4).as_slice(), Some([1i32, 2, 0, 0].as_slice()));
331 assert_eq!(buffer.capacity(), 4);
333 }
334
335 #[test]
336 fn slice_should_only_contain_part_of_the_buffer() {
337 let buffer: BoxColumnBuffer = Box::new(vec![1i32, 2, 3]);
338 let view = buffer.slice(2);
339 assert_eq!(Some([1, 2].as_slice()), view.as_slice::<i32>());
340 }
341
342 #[test]
343 fn slice_should_be_none_if_types_mismatch() {
344 let buffer: BoxColumnBuffer = Box::new(vec![1i32, 2, 3]);
345 let view = buffer.slice(3);
346 assert_eq!(None, view.as_slice::<i16>());
347 }
348
349 #[test]
350 fn nullable_slice_should_be_none_if_buffer_is_non_nullable() {
351 let buffer: BoxColumnBuffer = Box::new(vec![1i32, 2, 3]);
352 let view = buffer.slice(3);
353 assert!(view.as_nullable_slice::<i32>().is_none());
354 }
355}