odbc_api_helper/executor/
statement.rs

1use crate::error::OdbcHelperError;
2use crate::TryConvert;
3use either::Either;
4use odbc_api::parameter::InputParameter;
5use std::fmt::Debug;
6
7pub(crate) type EitherBoxParams = Either<Vec<Box<dyn InputParameter>>, ()>;
8
9pub trait StatementInput {
10    type Item: SqlValue;
11
12    fn to_value(self) -> Either<Vec<Self::Item>, ()>;
13    fn to_sql(&self) -> &str;
14
15    fn values(self) -> Result<EitherBoxParams, OdbcHelperError>
16    where
17        Self: Sized,
18    {
19        let params: EitherBoxParams = self.try_convert()?;
20        Ok(params)
21    }
22}
23
24pub trait SqlValue {
25    fn to_value(self) -> Either<Box<dyn InputParameter>, ()>;
26}
27
28#[derive(Debug)]
29pub struct Statement<T: Debug> {
30    /// The SQL query
31    pub sql: String,
32    /// The values for the SQL statement's parameters
33    pub values: Vec<T>,
34}
35
36impl<T> Statement<T>
37where
38    T: SqlValue + Debug,
39{
40    pub fn new<S: Into<String>>(sql: S, values: Vec<T>) -> Self {
41        Statement {
42            sql: sql.into(),
43            values,
44        }
45    }
46}
47
48impl SqlValue for &str {
49    fn to_value(self) -> Either<Box<dyn InputParameter>, ()> {
50        Either::Right(())
51    }
52}
53
54impl SqlValue for String {
55    fn to_value(self) -> Either<Box<dyn InputParameter>, ()> {
56        Either::Right(())
57    }
58}
59
60impl<T> StatementInput for Statement<T>
61where
62    T: SqlValue + Debug,
63{
64    type Item = T;
65
66    fn to_value(self) -> Either<Vec<T>, ()> {
67        Either::Left(self.values)
68    }
69
70    fn to_sql(&self) -> &str {
71        &self.sql
72    }
73}
74
75impl StatementInput for &str {
76    type Item = Self;
77
78    fn to_value(self) -> Either<Vec<Self::Item>, ()> {
79        Either::Right(())
80    }
81
82    fn to_sql(&self) -> &str {
83        self
84    }
85}
86
87impl StatementInput for String {
88    type Item = Self;
89
90    fn to_value(self) -> Either<Vec<Self::Item>, ()> {
91        Either::Right(())
92    }
93
94    fn to_sql(&self) -> &str {
95        self
96    }
97}
98
99/// TryConvert State `StatementInput` trait to `EitherBoxParams`
100/// # Example
101///
102/// ```rust
103/// use either::Either;
104/// use odbc_api::parameter::InputParameter;
105/// use odbc_api_helper::executor::statement::Statement;
106/// use odbc_api_helper::extension::pg::PgValueInput;
107/// use odbc_api_helper::TryConvert;
108///
109/// let statement = Statement::new("select * from empty where name=? and age=?",vec![
110///     PgValueInput::VARCHAR("foo".into()),
111///     PgValueInput::INT2(8)
112/// ]);
113///
114/// let left:Vec<Box<dyn InputParameter>> = statement.try_convert().unwrap().left().unwrap();
115/// assert_eq!(left.len(),2);
116///
117/// let statement = "select * from empty where name=? and age=?";
118///
119/// let right:() = statement.try_convert().unwrap().right().unwrap();///
120/// assert_eq!(right,());
121///
122/// ```
123///
124impl<T: StatementInput> TryConvert<EitherBoxParams> for T {
125    type Error = OdbcHelperError;
126
127    fn try_convert(self) -> Result<EitherBoxParams, Self::Error> {
128        match self.to_value() {
129            Either::Left(values) => {
130                let params: Result<Vec<_>, Self::Error> = values
131                    .into_iter()
132                    .map(|v| v.to_value())
133                    .map(|x| {
134                        x.left().ok_or_else(|| {
135                            OdbcHelperError::SqlParamsError("value not include empty tuple".into())
136                        })
137                    })
138                    .collect();
139                Ok(Either::Left(params?))
140            }
141            Either::Right(values) => Ok(Either::Right(values)),
142        }
143    }
144}