1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
use std::cell::RefCell;
use std::rc::Rc;
use mysql as my;
use rdbc;
fn to_rdbc_err(e: &my::error::Error) -> rdbc::Error {
rdbc::Error::General(format!("{:?}", e))
}
pub struct MySQLDriver {}
impl MySQLDriver {
pub fn new() -> Self {
MySQLDriver {}
}
pub fn connect(&self, url: &str) -> rdbc::Result<Rc<RefCell<dyn rdbc::Connection + 'static>>> {
let opts = my::Opts::from_url(&url).expect("DATABASE_URL invalid");
my::Conn::new(opts)
.map_err(|e| to_rdbc_err(&e))
.map(|conn| {
Rc::new(RefCell::new(MySQLConnection { conn })) as Rc<RefCell<dyn rdbc::Connection>>
})
}
}
pub struct MySQLConnection {
conn: my::Conn,
}
impl rdbc::Connection for MySQLConnection {
fn execute_query(&mut self, sql: &str) -> rdbc::Result<Rc<RefCell<dyn rdbc::ResultSet + '_>>> {
self.conn
.query(sql)
.map_err(|e| to_rdbc_err(&e))
.map(|result| {
Rc::new(RefCell::new(MySQLResultSet { result, row: None }))
as Rc<RefCell<dyn rdbc::ResultSet>>
})
}
fn execute_update(&mut self, sql: &str) -> rdbc::Result<usize> {
self.conn
.query(sql)
.map_err(|e| to_rdbc_err(&e))
.map(|result| result.affected_rows() as usize)
}
}
pub struct MySQLResultSet<'a> {
result: my::QueryResult<'a>,
row: Option<my::Result<my::Row>>,
}
impl<'a> rdbc::ResultSet for MySQLResultSet<'a> {
fn next(&mut self) -> bool {
self.row = self.result.next();
self.row.is_some()
}
fn get_i32(&self, i: usize) -> Option<i32> {
match &self.row {
Some(Ok(row)) => row.get(i - 1),
_ => None,
}
}
fn get_string(&self, i: usize) -> Option<String> {
match &self.row {
Some(Ok(row)) => row.get(i - 1),
_ => None,
}
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn execute_query() -> rdbc::Result<()> {
let driver = MySQLDriver::new();
let conn = driver.connect("mysql://root:secret@127.0.0.1:3307")?;
let mut conn = conn.as_ref().borrow_mut();
let rs = conn.execute_query("SELECT 1")?;
let mut rs = rs.borrow_mut();
while rs.next() {
println!("{:?}", rs.get_i32(1))
}
Ok(())
}
}