1use tiberius::Row;
4
5use crate::error::{MssqlError, MssqlResult};
6
7pub trait MssqlRow {
9 fn get_value<'a, T>(&'a self, column: &str) -> MssqlResult<T>
11 where
12 T: tiberius::FromSql<'a>;
13
14 fn get_opt<'a, T>(&'a self, column: &str) -> MssqlResult<Option<T>>
16 where
17 T: tiberius::FromSql<'a>;
18
19 fn try_get_by_index<'a, T>(&'a self, index: usize) -> Option<T>
21 where
22 T: tiberius::FromSql<'a>;
23}
24
25impl MssqlRow for Row {
26 fn get_value<'a, T>(&'a self, column: &str) -> MssqlResult<T>
27 where
28 T: tiberius::FromSql<'a>,
29 {
30 self.try_get(column)
31 .map_err(|e| {
32 MssqlError::deserialization(format!("failed to get column '{}': {}", column, e))
33 })?
34 .ok_or_else(|| MssqlError::deserialization(format!("column '{}' is null", column)))
35 }
36
37 fn get_opt<'a, T>(&'a self, column: &str) -> MssqlResult<Option<T>>
38 where
39 T: tiberius::FromSql<'a>,
40 {
41 self.try_get(column).map_err(|e| {
42 MssqlError::deserialization(format!("failed to get column '{}': {}", column, e))
43 })
44 }
45
46 fn try_get_by_index<'a, T>(&'a self, index: usize) -> Option<T>
47 where
48 T: tiberius::FromSql<'a>,
49 {
50 self.get(index)
51 }
52}
53
54pub trait FromMssqlRow: Sized {
56 fn from_row(row: &Row) -> MssqlResult<Self>;
58}
59
60#[macro_export]
71macro_rules! impl_from_mssql_row {
72 ($type:ident { $($field:ident : $field_type:ty),* $(,)? }) => {
73 impl $crate::row::FromMssqlRow for $type {
74 fn from_row(row: &tiberius::Row) -> $crate::error::MssqlResult<Self> {
75 use $crate::row::MssqlRow;
76 Ok(Self {
77 $(
78 $field: row.get_value(stringify!($field))?,
79 )*
80 })
81 }
82 }
83 };
84}
85
86#[cfg(test)]
87mod tests {
88 }