odbc_api_helper/extension/
odbc.rs

1use crate::executor::database::Options;
2use crate::{Convert, TryConvert};
3use bytes::BytesMut;
4use odbc_api::buffers::{AnySlice, BufferDescription, BufferKind};
5use odbc_api::sys::{Date, Time, Timestamp, NULL_DATA};
6use odbc_api::DataType;
7use std::cmp::min;
8
9#[derive(Debug, Clone)]
10pub struct OdbcColumn {
11    pub name: String,
12    pub data_type: DataType,
13    pub nullable: bool,
14}
15
16impl OdbcColumn {
17    pub fn new(name: String, data_type: DataType, nullable: bool) -> Self {
18        Self {
19            name,
20            data_type,
21            nullable,
22        }
23    }
24}
25
26impl TryConvert<BufferDescription> for (&OdbcColumn, &Options) {
27    type Error = String;
28
29    fn try_convert(self) -> Result<BufferDescription, Self::Error> {
30        let c = self.0;
31        let option = self.1;
32        let mut description = BufferDescription {
33            nullable: c.nullable,
34            kind: BufferKind::from_data_type(c.data_type)
35                .ok_or_else(|| format!("covert DataType:{:?} to BufferKind error", c.data_type))?,
36        };
37
38        // When use `BufferKind::from_data_type` get result with `BufferKind::Text`
39        // It's maybe caused panic,it need use `Option.max_str_len` to readjust size.
40        // Link: <https://github.com/pacman82/odbc-api/issues/268>
41        match description.kind {
42            // TODO Notice: The kind of `BufferKind::Text` mix up varchar or text type
43            // Need to distinguish between text type or varchar type
44            BufferKind::Text { max_str_len } => {
45                description.kind = BufferKind::Text {
46                    max_str_len: min(max_str_len, option.max_str_len),
47                };
48            }
49            BufferKind::WText { max_str_len } => {
50                description.kind = BufferKind::WText {
51                    max_str_len: min(max_str_len, option.max_str_len),
52                };
53            }
54            BufferKind::Binary { length } => {
55                description.kind = BufferKind::Binary {
56                    length: min(length, option.max_binary_len),
57                }
58            }
59            _ => {}
60        }
61
62        Ok(description)
63    }
64}
65
66#[derive(Debug)]
67pub struct OdbcColumnItem {
68    pub odbc_type: OdbcColumnType,
69    pub value: Option<BytesMut>,
70}
71
72#[derive(Debug)]
73pub enum OdbcColumnType {
74    Text,
75    WText,
76    Binary,
77    Date,
78    Time,
79    Timestamp,
80    F64,
81    F32,
82    I8,
83    I16,
84    I32,
85    I64,
86    U8,
87    Bit,
88}
89
90impl ToString for OdbcColumnItem {
91    fn to_string(&self) -> String {
92        format!("{:?}", self)
93    }
94}
95
96impl Convert<Vec<OdbcColumnItem>> for AnySlice<'_> {
97    fn convert(self) -> Vec<OdbcColumnItem> {
98        match self {
99            AnySlice::Text(view) => {
100                let mut buffer = Vec::with_capacity(view.len());
101                for v in view.iter() {
102                    if let Some(x) = v {
103                        buffer.push(OdbcColumnItem {
104                            odbc_type: OdbcColumnType::Text,
105                            value: Some(BytesMut::from(x)),
106                        });
107                    } else {
108                        buffer.push(OdbcColumnItem {
109                            odbc_type: OdbcColumnType::Text,
110                            value: None,
111                        })
112                    }
113                }
114                buffer
115            }
116            AnySlice::WText(view) => {
117                let mut buffer = Vec::with_capacity(view.len());
118                for v in view.iter() {
119                    if let Some(x) = v {
120                        buffer.push(OdbcColumnItem {
121                            odbc_type: OdbcColumnType::WText,
122                            value: Some(BytesMut::from(x.to_string().unwrap().as_bytes())),
123                        });
124                    } else {
125                        buffer.push(OdbcColumnItem {
126                            odbc_type: OdbcColumnType::WText,
127                            value: None,
128                        })
129                    }
130                }
131                buffer
132            }
133            AnySlice::Binary(view) => {
134                let mut buffer = vec![];
135                for value in view.iter() {
136                    if let Some(bytes) = value {
137                        buffer.push(OdbcColumnItem {
138                            odbc_type: OdbcColumnType::Binary,
139                            value: Some(BytesMut::from(bytes)),
140                        })
141                    } else {
142                        buffer.push(OdbcColumnItem {
143                            odbc_type: OdbcColumnType::Binary,
144                            value: None,
145                        })
146                    }
147                }
148                buffer
149            }
150            AnySlice::Date(view) => {
151                let mut buffer = vec![];
152                for value in view.iter() {
153                    let val = value.try_convert().unwrap();
154                    buffer.push(OdbcColumnItem {
155                        odbc_type: OdbcColumnType::Date,
156                        value: Some(BytesMut::from(val.to_string().as_bytes())),
157                    })
158                }
159                buffer
160            }
161            AnySlice::Timestamp(view) => {
162                let mut buffer = vec![];
163                for value in view.iter() {
164                    let val: time::PrimitiveDateTime = value.try_convert().unwrap();
165                    buffer.push(OdbcColumnItem {
166                        odbc_type: OdbcColumnType::Timestamp,
167                        value: Some(BytesMut::from(val.to_string().as_bytes())),
168                    })
169                }
170                buffer
171            }
172            AnySlice::Time(view) => {
173                let mut buffer = vec![];
174                for value in view.iter() {
175                    let val = value.try_convert().unwrap();
176                    buffer.push(OdbcColumnItem {
177                        odbc_type: OdbcColumnType::Time,
178                        value: Some(BytesMut::from(val.to_string().as_bytes())),
179                    })
180                }
181                buffer
182            }
183            AnySlice::I32(view) => {
184                let mut buffer = vec![];
185                for value in view.iter() {
186                    buffer.push(OdbcColumnItem {
187                        odbc_type: OdbcColumnType::I32,
188                        value: Some(BytesMut::from(value.to_string().as_bytes())),
189                    })
190                }
191                buffer
192            }
193            AnySlice::Bit(view) => {
194                let mut buffer = vec![];
195                for value in view.iter() {
196                    buffer.push(OdbcColumnItem {
197                        odbc_type: OdbcColumnType::Bit,
198                        value: Some(BytesMut::from(value.as_bool().to_string().as_bytes())),
199                    })
200                }
201                buffer
202            }
203
204            AnySlice::F64(view) => {
205                let mut buffer = vec![];
206                for value in view.iter() {
207                    buffer.push(OdbcColumnItem {
208                        odbc_type: OdbcColumnType::F64,
209                        value: Some(BytesMut::from(value.to_string().as_bytes())),
210                    })
211                }
212                buffer
213            }
214            AnySlice::F32(view) => {
215                let mut buffer = vec![];
216                for value in view.iter() {
217                    buffer.push(OdbcColumnItem {
218                        odbc_type: OdbcColumnType::F32,
219                        value: Some(BytesMut::from(value.to_string().as_bytes())),
220                    })
221                }
222                buffer
223            }
224            AnySlice::I8(view) => {
225                let mut buffer = vec![];
226                for value in view.iter() {
227                    buffer.push(OdbcColumnItem {
228                        odbc_type: OdbcColumnType::I8,
229                        value: Some(BytesMut::from(value.to_string().as_bytes())),
230                    })
231                }
232                buffer
233            }
234            AnySlice::I16(view) => {
235                let mut buffer = vec![];
236                for value in view.iter() {
237                    buffer.push(OdbcColumnItem {
238                        odbc_type: OdbcColumnType::I16,
239                        value: Some(BytesMut::from(value.to_string().as_bytes())),
240                    })
241                }
242                buffer
243            }
244            AnySlice::I64(view) => {
245                let mut buffer = vec![];
246                for value in view.iter() {
247                    buffer.push(OdbcColumnItem {
248                        odbc_type: OdbcColumnType::I64,
249                        value: Some(BytesMut::from(value.to_string().as_bytes())),
250                    })
251                }
252                buffer
253            }
254            AnySlice::U8(view) => {
255                let mut buffer = vec![];
256
257                for value in view.iter() {
258                    buffer.push(OdbcColumnItem {
259                        odbc_type: OdbcColumnType::U8,
260                        value: Some(BytesMut::from(vec![*value].as_slice())),
261                    })
262                }
263                buffer
264            }
265            AnySlice::NullableDate(view) => {
266                let (values, indicators) = view.raw_values();
267                let values = values.to_vec();
268
269                values
270                    .iter()
271                    .enumerate()
272                    .map(|(index, value)| {
273                        if indicators[index] != NULL_DATA {
274                            let val = value.try_convert().unwrap();
275                            OdbcColumnItem {
276                                odbc_type: OdbcColumnType::Date,
277                                value: Some(BytesMut::from(val.to_string().as_bytes())),
278                            }
279                        } else {
280                            OdbcColumnItem {
281                                odbc_type: OdbcColumnType::Date,
282                                value: None,
283                            }
284                        }
285                    })
286                    .collect()
287            }
288            AnySlice::NullableTime(view) => {
289                let (values, indicators) = view.raw_values();
290                let values = values.to_vec();
291
292                values
293                    .iter()
294                    .enumerate()
295                    .map(|(index, value)| {
296                        if indicators[index] != NULL_DATA {
297                            let val = value.try_convert().unwrap();
298                            OdbcColumnItem {
299                                odbc_type: OdbcColumnType::Time,
300                                value: Some(BytesMut::from(val.to_string().as_bytes())),
301                            }
302                        } else {
303                            OdbcColumnItem {
304                                odbc_type: OdbcColumnType::Time,
305                                value: None,
306                            }
307                        }
308                    })
309                    .collect()
310            }
311            AnySlice::NullableTimestamp(view) => {
312                let (values, indicators) = view.raw_values();
313                let values = values.to_vec();
314
315                values
316                    .iter()
317                    .enumerate()
318                    .map(|(index, value)| {
319                        if indicators[index] != NULL_DATA {
320                            let val: time::PrimitiveDateTime = value.try_convert().unwrap();
321                            OdbcColumnItem {
322                                odbc_type: OdbcColumnType::Timestamp,
323                                value: Some(BytesMut::from(val.to_string().as_bytes())),
324                            }
325                        } else {
326                            OdbcColumnItem {
327                                odbc_type: OdbcColumnType::Timestamp,
328                                value: None,
329                            }
330                        }
331                    })
332                    .collect()
333            }
334            AnySlice::NullableF64(view) => {
335                let (values, indicators) = view.raw_values();
336                let values = values.to_vec();
337
338                values
339                    .iter()
340                    .enumerate()
341                    .map(|(index, value)| {
342                        if indicators[index] != NULL_DATA {
343                            OdbcColumnItem {
344                                odbc_type: OdbcColumnType::F64,
345                                value: Some(BytesMut::from(value.to_string().as_bytes())),
346                            }
347                        } else {
348                            OdbcColumnItem {
349                                odbc_type: OdbcColumnType::F64,
350                                value: None,
351                            }
352                        }
353                    })
354                    .collect()
355            }
356            AnySlice::NullableF32(view) => {
357                let (values, indicators) = view.raw_values();
358                let values = values.to_vec();
359
360                values
361                    .iter()
362                    .enumerate()
363                    .map(|(index, value)| {
364                        if indicators[index] != NULL_DATA {
365                            OdbcColumnItem {
366                                odbc_type: OdbcColumnType::F32,
367                                value: Some(BytesMut::from(value.to_string().as_bytes())),
368                            }
369                        } else {
370                            OdbcColumnItem {
371                                odbc_type: OdbcColumnType::F32,
372                                value: None,
373                            }
374                        }
375                    })
376                    .collect()
377            }
378            AnySlice::NullableI8(view) => {
379                let (values, indicators) = view.raw_values();
380                let values = values.to_vec();
381
382                values
383                    .iter()
384                    .enumerate()
385                    .map(|(index, value)| {
386                        if indicators[index] != NULL_DATA {
387                            OdbcColumnItem {
388                                odbc_type: OdbcColumnType::I8,
389                                value: Some(BytesMut::from(value.to_string().as_bytes())),
390                            }
391                        } else {
392                            OdbcColumnItem {
393                                odbc_type: OdbcColumnType::I8,
394                                value: None,
395                            }
396                        }
397                    })
398                    .collect()
399            }
400            AnySlice::NullableI16(view) => {
401                let (values, indicators) = view.raw_values();
402                let values = values.to_vec();
403
404                values
405                    .iter()
406                    .enumerate()
407                    .map(|(index, value)| {
408                        if indicators[index] != NULL_DATA {
409                            OdbcColumnItem {
410                                odbc_type: OdbcColumnType::I16,
411                                value: Some(BytesMut::from(value.to_string().as_bytes())),
412                            }
413                        } else {
414                            OdbcColumnItem {
415                                odbc_type: OdbcColumnType::I16,
416                                value: None,
417                            }
418                        }
419                    })
420                    .collect()
421            }
422            AnySlice::NullableI32(view) => {
423                let (values, indicators) = view.raw_values();
424                let values = values.to_vec();
425
426                values
427                    .iter()
428                    .enumerate()
429                    .map(|(index, value)| {
430                        if indicators[index] != NULL_DATA {
431                            OdbcColumnItem {
432                                odbc_type: OdbcColumnType::I32,
433                                value: Some(BytesMut::from(value.to_string().as_bytes())),
434                            }
435                        } else {
436                            OdbcColumnItem {
437                                odbc_type: OdbcColumnType::I32,
438                                value: None,
439                            }
440                        }
441                    })
442                    .collect()
443            }
444            AnySlice::NullableI64(view) => {
445                let (values, indicators) = view.raw_values();
446                let values = values.to_vec();
447
448                values
449                    .iter()
450                    .enumerate()
451                    .map(|(index, value)| {
452                        if indicators[index] != NULL_DATA {
453                            OdbcColumnItem {
454                                odbc_type: OdbcColumnType::I64,
455                                value: Some(BytesMut::from(value.to_string().as_bytes())),
456                            }
457                        } else {
458                            OdbcColumnItem {
459                                odbc_type: OdbcColumnType::I64,
460                                value: None,
461                            }
462                        }
463                    })
464                    .collect()
465            }
466            AnySlice::NullableU8(view) => {
467                let (values, indicators) = view.raw_values();
468                let values = values.to_vec();
469
470                values
471                    .iter()
472                    .enumerate()
473                    .map(|(index, value)| {
474                        if indicators[index] != NULL_DATA {
475                            OdbcColumnItem {
476                                odbc_type: OdbcColumnType::U8,
477                                value: Some(BytesMut::from(vec![*value].as_slice())),
478                            }
479                        } else {
480                            OdbcColumnItem {
481                                odbc_type: OdbcColumnType::U8,
482                                value: None,
483                            }
484                        }
485                    })
486                    .collect()
487            }
488            AnySlice::NullableBit(view) => {
489                let (values, indicators) = view.raw_values();
490                let values = values.to_vec();
491
492                values
493                    .iter()
494                    .enumerate()
495                    .map(|(index, value)| {
496                        if indicators[index] != NULL_DATA {
497                            OdbcColumnItem {
498                                odbc_type: OdbcColumnType::Bit,
499                                value: Some(BytesMut::from(value.as_bool().to_string().as_bytes())),
500                            }
501                        } else {
502                            OdbcColumnItem {
503                                odbc_type: OdbcColumnType::Bit,
504                                value: None,
505                            }
506                        }
507                    })
508                    .collect()
509            }
510        }
511    }
512}
513
514/// Convert `odbc_api::sys::Date` to `time::Date`
515///
516/// # Example
517///
518/// ```rust
519/// # use time::{Date, macros::date};
520/// # use odbc_api::sys::Date as OdbcDate;
521/// use odbc_api_helper::TryConvert;
522///
523/// let odbc_data = OdbcDate{year: 2020,month: 1,day: 1};
524/// assert_eq!(date!(2020 - 01 - 01), odbc_data.try_convert().unwrap());
525///
526/// let odbc_data = OdbcDate{year: 2022,month: 12,day: 31};
527/// assert_eq!(date!(2022 - 12 - 31), odbc_data.try_convert().unwrap());
528///
529/// ```
530impl TryConvert<time::Date> for Date {
531    type Error = time::Error;
532
533    fn try_convert(self) -> Result<time::Date, Self::Error> {
534        Ok(time::Date::from_calendar_date(
535            self.year as i32,
536            time::Month::try_from(self.month as u8)?,
537            self.day as u8,
538        )?)
539    }
540}
541
542/// Convert `odbc_api::sys::Time` to `time::Time`
543///
544/// # Example
545///
546/// ```rust
547/// # use time::{Date, macros::time};
548/// # use odbc_api::sys::Time as OdbcTime;
549/// use odbc_api_helper::TryConvert;
550///
551/// let odbc_time = OdbcTime { hour: 3,minute: 1,second: 1 };
552/// assert_eq!(time!(03 : 01: 01), odbc_time.try_convert().unwrap());
553///
554/// let odbc_time = OdbcTime { hour: 19,minute: 31,second: 59 };
555/// assert_eq!(time!(19 : 31 : 59), odbc_time.try_convert().unwrap());
556///
557/// ```
558impl TryConvert<time::Time> for Time {
559    type Error = time::Error;
560    fn try_convert(self) -> Result<time::Time, Self::Error> {
561        Ok(time::Time::from_hms(
562            self.hour as u8,
563            self.minute as u8,
564            self.second as u8,
565        )?)
566    }
567}
568
569impl TryConvert<time::Time> for (Time, u32) {
570    type Error = time::Error;
571    fn try_convert(self) -> Result<time::Time, Self::Error> {
572        let time = self.0;
573        let nanosecond = self.1;
574
575        Ok(time::Time::from_hms_nano(
576            time.hour as u8,
577            time.minute as u8,
578            time.second as u8,
579            nanosecond,
580        )?)
581    }
582}
583
584impl TryConvert<(time::Date, time::Time)> for Timestamp {
585    type Error = time::Error;
586
587    fn try_convert(self) -> Result<(time::Date, time::Time), Self::Error> {
588        let date = Date {
589            year: self.year,
590            month: self.month,
591            day: self.day,
592        }
593        .try_convert()?;
594        let time = Time {
595            hour: self.hour,
596            minute: self.minute,
597            second: self.second,
598        };
599        let nanosecond = self.fraction as u32;
600        let time = (time, nanosecond).try_convert()?;
601        Ok((date, time))
602    }
603}
604
605impl TryConvert<time::PrimitiveDateTime> for Timestamp {
606    type Error = time::Error;
607
608    fn try_convert(self) -> Result<time::PrimitiveDateTime, Self::Error> {
609        let (date, time) = self.try_convert()?;
610        Ok(time::PrimitiveDateTime::new(date, time))
611    }
612}