derive_sql/proxy/
mysql.rs

1use super::*;
2
3#[cfg(feature="compatibility_v0_10")]
4mod conn; 
5#[cfg(feature="compatibility_v0_10")]
6pub use conn::Conn;
7#[cfg(feature="compatibility_v0_10")]
8mod log; 
9#[cfg(feature="compatibility_v0_10")]
10pub use log::Log;
11
12#[cfg(feature="compatibility_v0_10")]
13/// Generic trait exposing methods used for interaction with SQLite
14/// in `DeriveMysql` macro implementation.
15pub trait MysqlTrait {
16  fn query_drop<Q>(&mut self, query: Q) -> Result<()>
17  where Q: AsRef<str>;
18
19  fn query_first<T, Q>(&mut self, query: Q) -> Result<Option<T>>
20  where Q: AsRef<str>,
21        T: ::mysql::prelude::FromRow;
22
23  fn query_map<T, F, Q, U>(&mut self, query: Q, f: F) -> Result<Vec<U>>
24  where Q: AsRef<str>,
25        T: ::mysql::prelude::FromRow,
26        F: FnMut(T) -> U;
27
28  fn exec_drop<Q, P>(&mut self, query: Q, params: P) -> Result<()>
29  where Q: AsRef<str>,
30        P: Into<::mysql::Params>;
31}
32
33#[cfg(feature="compatibility_v0_10")]
34pub struct MysqlProxy<T>
35where T: ::mysql::prelude::Queryable,
36{
37  conn: T
38}
39
40#[cfg(feature="compatibility_v0_10")]
41impl<T> From<T> for MysqlProxy<T>
42where T: ::mysql::prelude::Queryable,
43{
44  fn from(conn: T) -> Self {
45    MysqlProxy { conn }
46  }
47}
48
49#[cfg(feature="compatibility_v0_10")]
50impl<T> traits::ExecuteTrait for MysqlProxy<T>
51where T: ::mysql::prelude::Queryable,
52{
53  fn execute_with_params<P>(&mut self, query: &str, params: P) -> Result<()>
54  where P: traits::Params
55  {
56    let params = params.as_vec_params()?
57    .into_iter()
58    .map(|p| std::convert::TryInto::<::mysql::Value>::try_into(p))
59    .collect::<Result<Vec<::mysql::Value>>>()?;
60    self.conn.exec_drop(query, params)?;
61    Ok(())
62  }
63}
64
65pub struct Row {
66  row: ::mysql::Row,
67}
68
69impl ::mysql::prelude::FromRow for Row {
70  fn from_row_opt(row: ::mysql::Row) -> std::result::Result<Row, ::mysql::FromRowError> {
71    Ok(Row { row } )
72  }
73}
74
75impl traits::Row for Row {
76  fn get_value(&self, i: usize) -> Option<Result<traits::Value>> { 
77    let v: Option<core::result::Result<::mysql::Value, _>> = self.row.get_opt(i);
78    if let Some(Ok(v)) = v {
79      let v: Result<traits::Value> = v.try_into();
80      Some(v)
81
82    } else if let Some(Err(e)) = v {
83      Some(Err(e.into()))
84      
85    } else {
86      None
87    }
88  }
89}
90
91/*
92struct MyValue {
93  value: ::mysql::Value,
94}
95
96impl std::convert::From<::mysql::Value> for MyValue {
97  fn from(value: ::mysql::Value) -> Self { 
98    MyValue { value }
99  }
100}
101
102impl<T> traits::RefTryInto<T> for MyValue
103where T: ::mysql::prelude::FromValue,
104{
105  fn try_into(&self) -> Result<T> {
106    Ok(::mysql::prelude::FromValue::from_value_opt(self.value.clone())?)
107  }
108}
109*/
110
111/*
112impl<T> std::convert::TryFrom<&Value> for T
113where T: ::mysql::prelude::FromValue
114{
115  type Error = Error;
116  fn try_from(value: &Value) -> Result<Self> {
117    Ok(::mysql::prelude::FromValue::from_value_opt(value.value.clone())?)
118  }
119}
120*/
121
122/*
123impl traits::Row2<MyValue> for Row
124{
125  fn get<T>(&self, i: usize) -> Option<Result<T>>
126  where MyValue: traits::RefTryInto<T>, // T: for<'a> std::convert::TryFrom<&'a Value, Error=Error>
127  {
128    let value: Option<::mysql::Value> = self.row.get(i);
129    let value: Option<MyValue> = value.map(|v| v.into());
130    value.map(|v| traits::RefTryInto::try_into(&v) )
131  }
132}
133*/
134
135
136#[cfg(feature="compatibility_v0_10")]
137impl<T> traits::QueryTrait<Row> for MysqlProxy<T>
138where T: ::mysql::prelude::Queryable,
139{
140  fn query_row(&mut self, query: &str) -> Result<Vec<Row>> {
141    Ok( self.conn.query_map(query, |r: Row| r )? )
142  }
143}
144
145/// Define a trait that provide a transaction. This is required to allow
146/// `::mysql::Conn` and `::mysql::PoolConn` to both provide the same
147/// `start_transaction` interface.
148trait Transaction {
149  fn start_transaction(&mut self, tx_opts: ::mysql::TxOpts) -> Result<::mysql::Transaction>;
150}
151
152impl Transaction for ::mysql::Conn {
153  fn start_transaction(&mut self, tx_opts: ::mysql::TxOpts) -> Result<::mysql::Transaction> {
154    Ok(self.start_transaction(tx_opts)?)
155  }
156}
157
158impl Transaction for ::mysql::PooledConn {
159  fn start_transaction(&mut self, tx_opts: ::mysql::TxOpts) -> Result<::mysql::Transaction> {
160    Ok(self.start_transaction(tx_opts)?)
161  }
162}
163
164impl<T> traits::Connection<Row> for T
165where T: ::mysql::prelude::Queryable + Transaction,
166{
167  fn flavor(&self) -> traits::Flavor { traits::Flavor::MySQL }
168
169  fn execute_with_params<S, P>(&mut self, query: S, params: &P) -> Result<()>
170  where S: std::convert::AsRef<str>,
171        P: traits::Params,
172  {
173    let params = params.as_vec_params()?
174    .into_iter()
175    .map(|p| std::convert::TryInto::<::mysql::Value>::try_into(p))
176    .collect::<Result<Vec<::mysql::Value>>>()?;
177    self.exec_drop(query, params)?;
178    Ok(())
179  }
180
181  fn execute_with_params_iterator<'a, S, I, P>(&mut self, query: S, params_iter: I) -> Result<()>
182  where S: std::convert::AsRef<str>,
183        P: traits::Params + 'a,
184        I: core::iter::IntoIterator<Item = &'a P>
185  {
186    use ::mysql::prelude::Queryable;
187    let params_arr = params_iter
188      .into_iter()
189      .map(|params| 
190        params.as_vec_params()?.into_iter()
191        .map(|p| std::convert::TryInto::<::mysql::Value>::try_into(p))
192        .collect::<Result<Vec<::mysql::Value>>>()
193      )
194      .collect::<Result<Vec<Vec<::mysql::Value>>>>()?;
195
196    let mut conn = self.start_transaction(::mysql::TxOpts::default())?;
197    let statement = conn.prep(query)?;
198    conn.exec_batch(statement, params_arr.into_iter())?;
199    conn.commit()?;
200    Ok(())
201  }
202
203/*
204  fn execute_with_params_rows<S, P>(&mut self, query: S, params: &P) -> Result<Vec<Row>>
205  where S: std::convert::AsRef<str>,
206        P: traits::Params,
207  {
208    let params = params.as_vec_params()?
209    .into_iter()
210    .map(|p| std::convert::TryInto::<::mysql::Value>::try_into(p))
211    .collect::<Result<Vec<::mysql::Value>>>()?;
212    Ok( self.exec_map(query, params, |r: Row| r)? )
213  }
214  */
215
216  fn query<S>(&mut self, query: S) -> Result<Vec<Row>>
217  where S: std::convert::AsRef<str>
218  {
219    Ok( self.query_map(query, |r: Row| r)? )
220  }
221}
222
223#[cfg(test)]
224mod tests {
225  use super::*;
226
227  #[test]
228  fn test_connection() -> Result<()> {
229    let mut conn = ::mysql::Conn::new(
230      ::mysql::Opts::from_url("mysql://test@localhost/simpledb").unwrap()
231    )?;
232
233    proxy_test::run_connection(&mut conn)?;
234
235    use ::mysql::prelude::Queryable;
236    let r: Vec<String> = conn.query_map("SELECT name FROM mytable_proxy_conn", |r: String| r)?;
237    assert!(r[0].eq("my name"));
238
239    Ok(())
240  }
241
242  #[test]
243  fn test_run_with_date() -> Result<()> {
244    let mut conn = ::mysql::Conn::new(
245      ::mysql::Opts::from_url("mysql://test@localhost/simpledb").unwrap()
246    )?;
247    proxy_test::run_with_date(&mut conn)?;
248    Ok(())
249  }
250}
251