odbc_iter/
value_row.rs

1use crate::row::{Row, TryFromColumn, DefaultConfiguration, TryFromRow, RowConvertError};
2use crate::value::{TryFromValue, Value};
3use std::convert::Infallible;
4use std::error::Error;
5use std::fmt;
6
7/// Row of dynamic nullable column values.
8///
9/// This objects are constructed from row data returned by ODBC library and can be further converted to types implementing `TryFromValueRow`/`TryFromValue` traits.
10pub type ValueRow = Vec<Option<Value>>;
11
12impl TryFromRow<DefaultConfiguration> for ValueRow {
13    type Error = RowConvertError;
14
15    fn try_from_row<'r, 's, 'c, S>(mut row: Row<'r, 's, 'c, S, DefaultConfiguration>) -> Result<Self, Self::Error> {
16        let mut value_row = Vec::with_capacity(row.columns() as usize);
17
18        loop {
19            if let Some(column) = row.shift_column() {
20                let value: Option<Value> = TryFromColumn::try_from_column(column)?;
21                value_row.push(value)
22            } else {
23                return Ok(value_row);
24            }
25        }
26    }
27}
28
29// Note: TryFrom/TryInto cannot be implemented since we need to own the trait
30
31/// This traits allow for conversion of `ValueRow` type used internally by `ResultSet` iterator to any
32/// other type returned as `Item` that implements it.
33///
34/// This trait is implemented for Rust tuple type enabling conversion of rows to tuples of types implementing `TryFromValue`.
35/// Also this trait implementation allows to convert single column rows to types implementing `TryFromValue`.
36///
37/// This trait can be implemented for custom objects. This will enable them to be queried directly from database as `Item` of `ResultSet` iterator.
38pub trait TryFromValueRow: Sized {
39    type Error: Error + 'static;
40    /// Convert from `ValueRow` to other type of value representing table row.
41    fn try_from_value_row(values: ValueRow) -> Result<Self, Self::Error>;
42}
43
44/// Errors that may happen during conversion of `ValueRow` to given type.
45#[derive(Debug)]
46pub enum ValueRowConvertError {
47    UnexpectedNullValue(&'static str),
48    UnexpectedValue,
49    UnexpectedNumberOfColumns { expected: u16, got: usize },
50    ValueConvertError(Box<dyn Error>),
51}
52
53impl fmt::Display for ValueRowConvertError {
54    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
55        match self {
56            ValueRowConvertError::UnexpectedNullValue(t) => {
57                write!(f, "expecting value of type {} but got NULL", t)
58            }
59            ValueRowConvertError::UnexpectedValue => write!(f, "expecting no data (unit) but got a row"),
60            ValueRowConvertError::UnexpectedNumberOfColumns { expected, got } => write!(
61                f,
62                "unexpected number of columns: expected {} but got {}",
63                expected, got
64            ),
65            ValueRowConvertError::ValueConvertError(_) => {
66                write!(f, "failed to convert column value to target type")
67            }
68        }
69    }
70}
71
72impl Error for ValueRowConvertError {
73    fn source(&self) -> Option<&(dyn Error + 'static)> {
74        match self {
75            ValueRowConvertError::UnexpectedNullValue(_)
76            | ValueRowConvertError::UnexpectedValue
77            | ValueRowConvertError::UnexpectedNumberOfColumns { .. } => None,
78            ValueRowConvertError::ValueConvertError(err) => Some(err.as_ref()),
79        }
80    }
81}
82
83/// Allow to retrieve unconverted `ValueRow` as item of `ResultSet` iterator.
84impl TryFromValueRow for ValueRow {
85    type Error = Infallible;
86    fn try_from_value_row(values: ValueRow) -> Result<Self, Self::Error> {
87        Ok(values)
88    }
89}
90
91/// Unit can be used to signal that no rows of data should be produced.
92impl TryFromValueRow for () {
93    type Error = ValueRowConvertError;
94    fn try_from_value_row(_values: ValueRow) -> Result<Self, Self::Error> {
95        Err(ValueRowConvertError::UnexpectedValue)
96    }
97}
98
99/// Convert row with single column to any type implementing `TryFromValue`.
100impl<T> TryFromValueRow for T
101where
102    T: TryFromValue,
103{
104    type Error = ValueRowConvertError;
105    fn try_from_value_row(mut values: ValueRow) -> Result<Self, Self::Error> {
106        if values.len() != 1 {
107            return Err(ValueRowConvertError::UnexpectedNumberOfColumns {
108                expected: 1,
109                got: values.len(),
110            });
111        }
112        values
113            .pop()
114            .ok_or_else(|| ValueRowConvertError::UnexpectedNullValue("Value"))
115            .and_then(|v| {
116                TryFromValue::try_from_value(v)
117                    .map_err(|e| ValueRowConvertError::ValueConvertError(Box::new(e)))
118            })
119    }
120}
121
122/// Errors that my arise when converting rows to tuples.
123#[derive(Debug)]
124pub enum ValueRowConvertTupleError {
125    UnexpectedNumberOfColumns { expected: u16, tuple: &'static str },
126    ValueConvertError(Box<dyn Error>),
127}
128
129impl fmt::Display for ValueRowConvertTupleError {
130    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
131        match self {
132            ValueRowConvertTupleError::UnexpectedNumberOfColumns { expected, tuple } => write!(
133                f,
134                "failed to convert row with {} columns to tuple {}",
135                expected, tuple
136            ),
137            ValueRowConvertTupleError::ValueConvertError(_) => {
138                write!(f, "failed to convert column value to target type")
139            }
140        }
141    }
142}
143
144impl Error for ValueRowConvertTupleError {
145    fn source(&self) -> Option<&(dyn Error + 'static)> {
146        match self {
147            ValueRowConvertTupleError::UnexpectedNumberOfColumns { .. } => None,
148            ValueRowConvertTupleError::ValueConvertError(err) => Some(err.as_ref()),
149        }
150    }
151}
152
153macro_rules! count {
154    () => (0usize);
155    ( $x:tt $($xs:tt)* ) => (1usize + count!($($xs)*));
156}
157
158macro_rules! try_from_tuple {
159    ($(
160        $Tuple:ident {
161            $(($idx:tt) -> $T:ident)+
162        }
163    )+) => {
164        $(
165            impl<$($T: TryFromValue),+> TryFromValueRow for ($($T,)+) {
166                type Error = ValueRowConvertTupleError;
167                fn try_from_value_row(values: ValueRow) -> Result<($($T,)+), Self::Error> {
168                    if values.len() != count!($($T)+) {
169                        return Err(ValueRowConvertTupleError::UnexpectedNumberOfColumns { expected: values.len() as u16, tuple: stringify![($($T,)+)] })
170                    }
171                    let mut values = values.into_iter();
172                    Ok(($({ let x: $T = $T::try_from_value(values.next().unwrap()).map_err(|err| ValueRowConvertTupleError::ValueConvertError(Box::new(err)))?; x},)+))
173                }
174            }
175        )+
176    }
177}
178
179try_from_tuple! {
180    Tuple1 {
181        (0) -> A
182    }
183    Tuple2 {
184        (0) -> A
185        (1) -> B
186    }
187    Tuple3 {
188        (0) -> A
189        (1) -> B
190        (2) -> C
191    }
192    Tuple4 {
193        (0) -> A
194        (1) -> B
195        (2) -> C
196        (3) -> D
197    }
198    Tuple5 {
199        (0) -> A
200        (1) -> B
201        (2) -> C
202        (3) -> D
203        (4) -> E
204    }
205    Tuple6 {
206        (0) -> A
207        (1) -> B
208        (2) -> C
209        (3) -> D
210        (4) -> E
211        (5) -> F
212    }
213    Tuple7 {
214        (0) -> A
215        (1) -> B
216        (2) -> C
217        (3) -> D
218        (4) -> E
219        (5) -> F
220        (6) -> G
221    }
222    Tuple8 {
223        (0) -> A
224        (1) -> B
225        (2) -> C
226        (3) -> D
227        (4) -> E
228        (5) -> F
229        (6) -> G
230        (7) -> H
231    }
232    Tuple9 {
233        (0) -> A
234        (1) -> B
235        (2) -> C
236        (3) -> D
237        (4) -> E
238        (5) -> F
239        (6) -> G
240        (7) -> H
241        (8) -> I
242    }
243    Tuple10 {
244        (0) -> A
245        (1) -> B
246        (2) -> C
247        (3) -> D
248        (4) -> E
249        (5) -> F
250        (6) -> G
251        (7) -> H
252        (8) -> I
253        (9) -> J
254    }
255    Tuple11 {
256        (0) -> A
257        (1) -> B
258        (2) -> C
259        (3) -> D
260        (4) -> E
261        (5) -> F
262        (6) -> G
263        (7) -> H
264        (8) -> I
265        (9) -> J
266        (10) -> K
267    }
268    Tuple12 {
269        (0) -> A
270        (1) -> B
271        (2) -> C
272        (3) -> D
273        (4) -> E
274        (5) -> F
275        (6) -> G
276        (7) -> H
277        (8) -> I
278        (9) -> J
279        (10) -> K
280        (11) -> L
281    }
282    Tuple13 {
283        (0) -> A
284        (1) -> B
285        (2) -> C
286        (3) -> D
287        (4) -> E
288        (5) -> F
289        (6) -> G
290        (7) -> H
291        (8) -> I
292        (9) -> J
293        (10) -> K
294        (11) -> L
295        (13) -> M
296    }
297    Tuple14 {
298        (0) -> A
299        (1) -> B
300        (2) -> C
301        (3) -> D
302        (4) -> E
303        (5) -> F
304        (6) -> G
305        (7) -> H
306        (8) -> I
307        (9) -> J
308        (10) -> K
309        (11) -> L
310        (13) -> M
311        (14) -> N
312    }
313    Tuple15 {
314        (0) -> A
315        (1) -> B
316        (2) -> C
317        (3) -> D
318        (4) -> E
319        (5) -> F
320        (6) -> G
321        (7) -> H
322        (8) -> I
323        (9) -> J
324        (10) -> K
325        (11) -> L
326        (13) -> M
327        (14) -> N
328        (15) -> O
329    }
330    Tuple16 {
331        (0) -> A
332        (1) -> B
333        (2) -> C
334        (3) -> D
335        (4) -> E
336        (5) -> F
337        (6) -> G
338        (7) -> H
339        (8) -> I
340        (9) -> J
341        (10) -> K
342        (11) -> L
343        (13) -> M
344        (14) -> N
345        (15) -> O
346        (16) -> P
347    }
348    Tuple17 {
349        (0) -> A
350        (1) -> B
351        (2) -> C
352        (3) -> D
353        (4) -> E
354        (5) -> F
355        (6) -> G
356        (7) -> H
357        (8) -> I
358        (9) -> J
359        (10) -> K
360        (11) -> L
361        (13) -> M
362        (14) -> N
363        (15) -> O
364        (16) -> P
365        (17) -> Q
366    }
367    Tuple18 {
368        (0) -> A
369        (1) -> B
370        (2) -> C
371        (3) -> D
372        (4) -> E
373        (5) -> F
374        (6) -> G
375        (7) -> H
376        (8) -> I
377        (9) -> J
378        (10) -> K
379        (11) -> L
380        (13) -> M
381        (14) -> N
382        (15) -> O
383        (16) -> P
384        (17) -> Q
385        (18) -> R
386    }
387    Tuple19 {
388        (0) -> A
389        (1) -> B
390        (2) -> C
391        (3) -> D
392        (4) -> E
393        (5) -> F
394        (6) -> G
395        (7) -> H
396        (8) -> I
397        (9) -> J
398        (10) -> K
399        (11) -> L
400        (13) -> M
401        (14) -> N
402        (15) -> O
403        (16) -> P
404        (17) -> Q
405        (18) -> R
406        (19) -> S
407    }
408    Tuple20 {
409        (0) -> A
410        (1) -> B
411        (2) -> C
412        (3) -> D
413        (4) -> E
414        (5) -> F
415        (6) -> G
416        (7) -> H
417        (8) -> I
418        (9) -> J
419        (10) -> K
420        (11) -> L
421        (13) -> M
422        (14) -> N
423        (15) -> O
424        (16) -> P
425        (17) -> Q
426        (18) -> R
427        (19) -> S
428        (20) -> T
429    }
430    Tuple21 {
431        (0) -> A
432        (1) -> B
433        (2) -> C
434        (3) -> D
435        (4) -> E
436        (5) -> F
437        (6) -> G
438        (7) -> H
439        (8) -> I
440        (9) -> J
441        (10) -> K
442        (11) -> L
443        (13) -> M
444        (14) -> N
445        (15) -> O
446        (16) -> P
447        (17) -> Q
448        (18) -> R
449        (19) -> S
450        (20) -> T
451        (21) -> U
452    }
453    Tuple22 {
454        (0) -> A
455        (1) -> B
456        (2) -> C
457        (3) -> D
458        (4) -> E
459        (5) -> F
460        (6) -> G
461        (7) -> H
462        (8) -> I
463        (9) -> J
464        (10) -> K
465        (11) -> L
466        (13) -> M
467        (14) -> N
468        (15) -> O
469        (16) -> P
470        (17) -> Q
471        (18) -> R
472        (19) -> S
473        (20) -> T
474        (21) -> U
475        (22) -> V
476    }
477    Tuple23 {
478        (0) -> A
479        (1) -> B
480        (2) -> C
481        (3) -> D
482        (4) -> E
483        (5) -> F
484        (6) -> G
485        (7) -> H
486        (8) -> I
487        (9) -> J
488        (10) -> K
489        (11) -> L
490        (13) -> M
491        (14) -> N
492        (15) -> O
493        (16) -> P
494        (17) -> Q
495        (18) -> R
496        (19) -> S
497        (20) -> T
498        (21) -> U
499        (22) -> V
500        (23) -> W
501    }
502    Tuple24 {
503        (0) -> A
504        (1) -> B
505        (2) -> C
506        (3) -> D
507        (4) -> E
508        (5) -> F
509        (6) -> G
510        (7) -> H
511        (8) -> I
512        (9) -> J
513        (10) -> K
514        (11) -> L
515        (13) -> M
516        (14) -> N
517        (15) -> O
518        (16) -> P
519        (17) -> Q
520        (18) -> R
521        (19) -> S
522        (20) -> T
523        (21) -> U
524        (22) -> V
525        (23) -> W
526        (24) -> Y
527    }
528}
529
530#[cfg(test)]
531mod tests {
532    #[allow(unused_imports)]
533    use super::*;
534    #[allow(unused_imports)]
535    use crate::Odbc;
536    #[allow(unused_imports)]
537    use assert_matches::assert_matches;
538
539    #[derive(Debug)]
540    struct Foo {
541        val: i64,
542    }
543
544    impl TryFromValueRow for Foo {
545        type Error = Infallible;
546        fn try_from_value_row(mut values: ValueRow) -> Result<Self, Self::Error> {
547            Ok(values
548                .pop()
549                .map(|val| Foo {
550                    val: val.and_then(|v| v.to_i64()).expect("val to be an bigint"),
551                })
552                .expect("value"))
553        }
554    }
555
556    use crate::value::Value;
557
558    #[test]
559    fn test_custom_type() {
560        let test_row: ValueRow = vec![Some(Value::Bigint(42))];
561        let foo: Foo = TryFromValueRow::try_from_value_row(test_row).expect("failed to convert");
562
563        assert_eq!(foo.val, 42);
564    }
565
566    #[test]
567    fn test_single_value() {
568        let test_row: ValueRow = vec![Some(Value::Bigint(42))];
569        let value: Value = TryFromValueRow::try_from_value_row(test_row).expect("failed to convert");
570
571        assert_eq!(value.to_i64().unwrap(), 42);
572    }
573
574    #[test]
575    fn test_single_nullable_value() {
576        let test_row: ValueRow = vec![Some(Value::Bigint(42))];
577        let value: Option<Value> = TryFromValueRow::try_from_value_row(test_row).expect("failed to convert");
578
579        assert!(value.is_some());
580        assert_eq!(value.unwrap().to_i64().unwrap(), 42);
581
582        let test_row: ValueRow = vec![None];
583        let value: Option<Value> = TryFromValueRow::try_from_value_row(test_row).expect("failed to convert");
584
585        assert!(value.is_none());
586    }
587
588    #[test]
589    fn test_value_row() {
590        let test_row: ValueRow = vec![Some(Value::Bigint(42)), Some(Value::Integer(22))];
591        let value: ValueRow = TryFromValueRow::try_from_value_row(test_row).expect("failed to convert");
592
593        assert_eq!(value.len(), 2);
594        assert_eq!(value[0].as_ref().unwrap().to_i64().unwrap(), 42);
595        assert_eq!(value[1].as_ref().unwrap().to_i32().unwrap(), 22);
596    }
597
598    #[test]
599    fn test_single_copy() {
600        let test_row: ValueRow = vec![Some(Value::Bit(true))];
601        let value: bool = TryFromValueRow::try_from_value_row(test_row).expect("failed to convert");
602
603        assert_eq!(value, true);
604
605        let test_row: ValueRow = vec![Some(Value::Bit(true))];
606        let value: Option<bool> = TryFromValueRow::try_from_value_row(test_row).expect("failed to convert");
607
608        assert_eq!(value.unwrap(), true);
609
610        let test_row: ValueRow = vec![None];
611        let value: Option<bool> = TryFromValueRow::try_from_value_row(test_row).expect("failed to convert");
612
613        assert!(value.is_none());
614
615        let test_row: ValueRow = vec![Some(Value::Bigint(42))];
616        let value: i64 = TryFromValueRow::try_from_value_row(test_row).expect("failed to convert");
617
618        assert_eq!(value, 42);
619
620        let test_row: ValueRow = vec![Some(Value::Bigint(42))];
621        let value: Option<i64> = TryFromValueRow::try_from_value_row(test_row).expect("failed to convert");
622
623        assert_eq!(value.unwrap(), 42i64);
624
625        let test_row: ValueRow = vec![None];
626        let value: Option<i64> = TryFromValueRow::try_from_value_row(test_row).expect("failed to convert");
627
628        assert!(value.is_none());
629    }
630
631    #[test]
632    fn test_single_unsigned() {
633        let test_row: ValueRow = vec![Some(Value::Bigint(42))];
634        let value: Option<u64> = TryFromValueRow::try_from_value_row(test_row).expect("failed to convert");
635
636        assert_eq!(value.unwrap(), 42u64);
637    }
638
639    #[test]
640    #[should_panic(expected = "ValueOutOfRange")]
641    fn test_single_unsigned_err() {
642        let test_row: ValueRow = vec![Some(Value::Bigint(-666))];
643        let _value: Option<u64> = TryFromValueRow::try_from_value_row(test_row).expect("failed to convert");
644    }
645
646    #[test]
647    fn test_single_string() {
648        let test_row: ValueRow = vec![Some(Value::String("foo".into()))];
649        let value: String = TryFromValueRow::try_from_value_row(test_row).expect("failed to convert");
650
651        assert_eq!(&value, "foo");
652
653        let test_row: ValueRow = vec![Some(Value::String("foo".into()))];
654        let value: Option<String> = TryFromValueRow::try_from_value_row(test_row).expect("failed to convert");
655
656        assert_eq!(&value.unwrap(), "foo");
657
658        let test_row: ValueRow = vec![None];
659        let value: Option<String> = TryFromValueRow::try_from_value_row(test_row).expect("failed to convert");
660
661        assert!(value.is_none());
662    }
663
664    #[test]
665    #[cfg(feature = "chrono")]
666    fn test_single_date() {
667        use chrono::Datelike;
668        use chrono::NaiveDate;
669
670        let test_row: ValueRow = vec![Some(Value::Date(odbc::SqlDate { year: 2019, month: 4, day: 2 }))];
671        let value: NaiveDate = TryFromValueRow::try_from_value_row(test_row).expect("failed to convert");
672
673        assert_eq!(value.year(), 2019);
674        assert_eq!(value.month(), 4);
675        assert_eq!(value.day(), 2);
676
677        let test_row: ValueRow = vec![Some(Value::Date(odbc::SqlDate { year: 2019, month: 4, day: 2 }))];
678        let value: Option<NaiveDate> = TryFromValueRow::try_from_value_row(test_row).expect("failed to convert");
679
680        assert_eq!(value.unwrap().year(), 2019);
681        assert_eq!(value.unwrap().month(), 4);
682        assert_eq!(value.unwrap().day(), 2);
683
684        let test_row: ValueRow = vec![None];
685        let value: Option<NaiveDate> = TryFromValueRow::try_from_value_row(test_row).expect("failed to convert");
686
687        assert!(value.is_none());
688    }
689
690    #[test]
691    fn test_tuple_value() {
692        let test_row: ValueRow = vec![Some(Value::String("foo".into())), Some(Value::Bigint(42)), Some(Value::Bit(true))];
693        let value: (String, i64, bool) = TryFromValueRow::try_from_value_row(test_row).expect("failed to convert");
694
695        assert_eq!(&value.0, "foo");
696        assert_eq!(value.1, 42);
697        assert_eq!(value.2, true);
698
699        let test_row: ValueRow = vec![Some(Value::String("foo".into())), Some(Value::Bigint(42)), Some(Value::Bit(true))];
700        let value: (Option<String>, i64, Option<bool>) = TryFromValueRow::try_from_value_row(test_row).expect("failed to convert");
701
702        assert_eq!(&value.0.unwrap(), "foo");
703        assert_eq!(value.1, 42);
704        assert_eq!(value.2.unwrap(), true);
705
706        let test_row: ValueRow = vec![None, Some(Value::Bigint(42)), None];
707        let value: (Option<String>, i64, Option<bool>) = TryFromValueRow::try_from_value_row(test_row).expect("failed to convert");
708
709        assert!(&value.0.is_none());
710        assert_eq!(value.1, 42);
711        assert!(value.2.is_none());
712    }
713
714    #[test]
715    fn test_value_row_conversions() {
716        let test_row: ValueRow = vec![Some(Value::Bit(true)), Some(Value::Integer(42)), None];
717        type Test = (Option<bool>, Option<u32>, Option<String>);
718
719        //let (b, u, s): (Option<bool>, Option<u32>, Option<String>) = test_row.try_into().unwrap();
720        let (b, u, s) = Test::try_from_value_row(test_row).unwrap();
721        assert_eq!(b, Some(true));
722        assert_eq!(u, Some(42));
723        assert_eq!(s, None);
724    }
725}