Skip to content

Commit

Permalink
Use Box instead of Rc/RefCell
Browse files Browse the repository at this point in the history
  • Loading branch information
95th committed Dec 28, 2019
1 parent e634f75 commit 131b0b7
Show file tree
Hide file tree
Showing 5 changed files with 100 additions and 161 deletions.
24 changes: 9 additions & 15 deletions rdbc-cli/src/main.rs
@@ -1,6 +1,3 @@
use std::cell::RefCell;
use std::rc::Rc;

use clap::{crate_version, App, Arg};
use rustyline::Editor;

Expand Down Expand Up @@ -33,14 +30,14 @@ fn main() -> Result<()> {
let url = matches.value_of("connection-url").unwrap();
println!("Connecting to {} driver with url: {}", driver, url);

let driver = match driver {
"mysql" => Rc::new(MySQLDriver::new()) as Rc<dyn rdbc::Driver>,
"postgres" => Rc::new(PostgresDriver::new()) as Rc<dyn rdbc::Driver>,
"sqlite" => Rc::new(SqliteDriver::new()) as Rc<dyn rdbc::Driver>,
let driver: Box<dyn rdbc::Driver> = match driver {
"mysql" => Box::new(MySQLDriver::new()),
"postgres" => Box::new(PostgresDriver::new()),
"sqlite" => Box::new(SqliteDriver::new()),
_ => panic!("Invalid driver"),
};

let conn = driver.connect(url).unwrap();
let mut conn = driver.connect(url).unwrap();

let mut rl = Editor::<()>::new();
rl.load_history(".history").ok();
Expand All @@ -53,7 +50,7 @@ fn main() -> Result<()> {
query.push_str(line.trim_end());
rl.add_history_entry(query.clone());

match execute(conn.clone(), &query) {
match execute(&mut *conn, &query) {
Ok(_) => {}
Err(e) => println!("Error: {:?}", e),
}
Expand All @@ -75,13 +72,10 @@ fn main() -> Result<()> {
Ok(())
}

fn execute(conn: Rc<RefCell<dyn Connection>>, sql: &str) -> Result<()> {
fn execute(conn: &mut dyn Connection, sql: &str) -> Result<()> {
println!("Executing {}", sql);
let mut conn = conn.borrow_mut();
let stmt = conn.create(sql)?;
let mut stmt = stmt.borrow_mut();
let rs = stmt.execute_query(&vec![])?;
let mut rs = rs.borrow_mut();
let mut stmt = conn.create(sql)?;
let mut rs = stmt.execute_query(&vec![])?;
let meta = rs.meta_data()?;

for i in 0..meta.num_columns() {
Expand Down
82 changes: 28 additions & 54 deletions rdbc-mysql/src/lib.rs
Expand Up @@ -19,19 +19,14 @@
//! }
//! ```

use std::cell::RefCell;
use std::rc::Rc;

use mysql as my;
use mysql_common::constants::ColumnType;

use rdbc;

use sqlparser::dialect::MySqlDialect;
use sqlparser::tokenizer::{Token, Tokenizer, Word};

/// Convert a MySQL error into an RDBC error
fn to_rdbc_err(e: &my::error::Error) -> rdbc::Error {
fn to_rdbc_err(e: my::error::Error) -> rdbc::Error {
rdbc::Error::General(e.to_string())
}

Expand All @@ -44,13 +39,10 @@ impl MySQLDriver {
}

impl rdbc::Driver for MySQLDriver {
fn connect(&self, url: &str) -> rdbc::Result<Rc<RefCell<dyn rdbc::Connection + 'static>>> {
fn connect(&self, url: &str) -> rdbc::Result<Box<dyn rdbc::Connection>> {
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>>
})
let conn = my::Conn::new(opts).map_err(to_rdbc_err)?;
Ok(Box::new(MySQLConnection { conn }))
}
}

Expand All @@ -59,21 +51,16 @@ struct MySQLConnection {
}

impl rdbc::Connection for MySQLConnection {
fn create(&mut self, sql: &str) -> rdbc::Result<Rc<RefCell<dyn rdbc::Statement + '_>>> {
Ok(Rc::new(RefCell::new(MySQLStatement {
fn create(&mut self, sql: &str) -> rdbc::Result<Box<dyn rdbc::Statement + '_>> {
Ok(Box::new(MySQLStatement {
conn: &mut self.conn,
sql: sql.to_owned(),
})) as Rc<RefCell<dyn rdbc::Statement>>)
}))
}

fn prepare(&mut self, sql: &str) -> rdbc::Result<Rc<RefCell<dyn rdbc::Statement + '_>>> {
self.conn
.prepare(&sql)
.and_then(|stmt| {
Ok(Rc::new(RefCell::new(MySQLPreparedStatement { stmt }))
as Rc<RefCell<dyn rdbc::Statement>>)
})
.map_err(|e| to_rdbc_err(&e))
fn prepare<'a>(&'a mut self, sql: &str) -> rdbc::Result<Box<dyn rdbc::Statement + '_>> {
let stmt = self.conn.prepare(&sql).map_err(to_rdbc_err)?;
Ok(Box::new(MySQLPreparedStatement { stmt }))
}
}

Expand All @@ -86,22 +73,17 @@ impl<'a> rdbc::Statement for MySQLStatement<'a> {
fn execute_query(
&mut self,
params: &[rdbc::Value],
) -> rdbc::Result<Rc<RefCell<dyn rdbc::ResultSet + '_>>> {
) -> rdbc::Result<Box<dyn rdbc::ResultSet + '_>> {
let sql = rewrite(&self.sql, params)?;
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>>
})
let result = self.conn.query(&sql).map_err(to_rdbc_err)?;
Ok(Box::new(MySQLResultSet { result, row: None }))
}

fn execute_update(&mut self, params: &[rdbc::Value]) -> rdbc::Result<u64> {
let sql = rewrite(&self.sql, params)?;
self.conn
.query(&sql)
.map_err(|e| to_rdbc_err(&e))
.map_err(to_rdbc_err)
.map(|result| result.affected_rows())
}
}
Expand All @@ -114,20 +96,19 @@ impl<'a> rdbc::Statement for MySQLPreparedStatement<'a> {
fn execute_query(
&mut self,
params: &[rdbc::Value],
) -> rdbc::Result<Rc<RefCell<dyn rdbc::ResultSet + '_>>> {
self.stmt
) -> rdbc::Result<Box<dyn rdbc::ResultSet + '_>> {
let result = self
.stmt
.execute(to_my_params(params))
.map_err(|e| to_rdbc_err(&e))
.map(|result| {
Rc::new(RefCell::new(MySQLResultSet { result, row: None }))
as Rc<RefCell<dyn rdbc::ResultSet>>
})
.map_err(to_rdbc_err)?;

Ok(Box::new(MySQLResultSet { result, row: None }))
}

fn execute_update(&mut self, params: &[rdbc::Value]) -> rdbc::Result<u64> {
self.stmt
.execute(to_my_params(params))
.map_err(|e| to_rdbc_err(&e))
.map_err(to_rdbc_err)
.map(|result| result.affected_rows())
}
}
Expand All @@ -138,14 +119,14 @@ pub struct MySQLResultSet<'a> {
}

impl<'a> rdbc::ResultSet for MySQLResultSet<'a> {
fn meta_data(&self) -> rdbc::Result<Rc<dyn rdbc::ResultSetMetaData>> {
fn meta_data(&self) -> rdbc::Result<Box<dyn rdbc::ResultSetMetaData>> {
let meta: Vec<rdbc::Column> = self
.result
.columns_ref()
.iter()
.map(|c| rdbc::Column::new(&c.name_str(), to_rdbc_type(&c.column_type())))
.collect();
Ok(Rc::new(meta))
Ok(Box::new(meta))
}

fn next(&mut self) -> bool {
Expand Down Expand Up @@ -317,14 +298,9 @@ mod tests {
)?;

let driver: Arc<dyn rdbc::Driver> = Arc::new(MySQLDriver::new());
let conn = driver.connect("mysql://root:secret@127.0.0.1:3307/mysql")?;
let mut conn = conn.as_ref().borrow_mut();
let stmt = conn.prepare("SELECT a FROM test")?;
let mut stmt = stmt.borrow_mut();
let rs = stmt.execute_query(&vec![])?;

let mut rs = rs.as_ref().borrow_mut();

let mut conn = driver.connect("mysql://root:secret@127.0.0.1:3307/mysql")?;
let mut stmt = conn.prepare("SELECT a FROM test")?;
let mut rs = stmt.execute_query(&vec![])?;
assert!(rs.next());
assert_eq!(Some(123), rs.get_i32(0)?);
assert!(!rs.next());
Expand All @@ -335,10 +311,8 @@ mod tests {
fn execute(sql: &str, values: &Vec<rdbc::Value>) -> rdbc::Result<u64> {
println!("Executing '{}' with {} params", sql, values.len());
let driver: Arc<dyn rdbc::Driver> = Arc::new(MySQLDriver::new());
let conn = driver.connect("mysql://root:secret@127.0.0.1:3307/mysql")?;
let mut conn = conn.as_ref().borrow_mut();
let stmt = conn.create(sql)?;
let mut stmt = stmt.borrow_mut();
let mut conn = driver.connect("mysql://root:secret@127.0.0.1:3307/mysql")?;
let mut stmt = conn.create(sql)?;
stmt.execute_update(values)
}
}
70 changes: 27 additions & 43 deletions rdbc-postgres/src/lib.rs
Expand Up @@ -19,18 +19,13 @@
//! }
//! ```

use std::cell::RefCell;
use std::rc::Rc;

use postgres;
use postgres::rows::Rows;
use postgres::{Connection, TlsMode};

use sqlparser::dialect::PostgreSqlDialect;
use sqlparser::tokenizer::{Token, Tokenizer, Word};

use postgres::types::Type;
use rdbc;
use rdbc::Column;

pub struct PostgresDriver {}
Expand All @@ -42,12 +37,9 @@ impl PostgresDriver {
}

impl rdbc::Driver for PostgresDriver {
fn connect(&self, url: &str) -> rdbc::Result<Rc<RefCell<dyn rdbc::Connection + 'static>>> {
postgres::Connection::connect(url, TlsMode::None)
.map_err(|e| to_rdbc_err(&e))
.map(|c| {
Ok(Rc::new(RefCell::new(PConnection::new(c))) as Rc<RefCell<dyn rdbc::Connection>>)
})?
fn connect(&self, url: &str) -> rdbc::Result<Box<dyn rdbc::Connection>> {
let c = postgres::Connection::connect(url, TlsMode::None).map_err(to_rdbc_err)?;
Ok(Box::new(PConnection::new(c)))
}
}

Expand All @@ -62,11 +54,11 @@ impl PConnection {
}

impl rdbc::Connection for PConnection {
fn create(&mut self, sql: &str) -> rdbc::Result<Rc<RefCell<dyn rdbc::Statement + '_>>> {
fn create(&mut self, sql: &str) -> rdbc::Result<Box<dyn rdbc::Statement + '_>> {
self.prepare(sql)
}

fn prepare(&mut self, sql: &str) -> rdbc::Result<Rc<RefCell<dyn rdbc::Statement + '_>>> {
fn prepare(&mut self, sql: &str) -> rdbc::Result<Box<dyn rdbc::Statement + '_>> {
// translate SQL, mapping ? into $1 style bound param placeholder
let dialect = PostgreSqlDialect {};
let mut tokenizer = Tokenizer::new(&dialect, sql);
Expand All @@ -92,10 +84,10 @@ impl rdbc::Connection for PConnection {
.collect::<Vec<String>>()
.join("");

Ok(Rc::new(RefCell::new(PStatement {
Ok(Box::new(PStatement {
conn: &self.conn,
sql,
})) as Rc<RefCell<dyn rdbc::Statement>>)
}))
}
}

Expand All @@ -108,30 +100,28 @@ impl<'a> rdbc::Statement for PStatement<'a> {
fn execute_query(
&mut self,
params: &[rdbc::Value],
) -> rdbc::Result<Rc<RefCell<dyn rdbc::ResultSet + '_>>> {
) -> rdbc::Result<Box<dyn rdbc::ResultSet + '_>> {
let params = to_postgres_value(params);
let params: Vec<&dyn postgres::types::ToSql> = params.iter().map(|v| v.as_ref()).collect();
self.conn
let rows = self
.conn
.query(&self.sql, params.as_slice())
.map_err(|e| to_rdbc_err(&e))
.map(|rows| {
let meta = rows
.columns()
.iter()
.map(|c| rdbc::Column::new(c.name(), to_rdbc_type(c.type_())))
.collect();

Rc::new(RefCell::new(PResultSet { meta, i: 0, rows }))
as Rc<RefCell<dyn rdbc::ResultSet>>
})
.map_err(to_rdbc_err)?;
let meta = rows
.columns()
.iter()
.map(|c| rdbc::Column::new(c.name(), to_rdbc_type(c.type_())))
.collect();

Ok(Box::new(PResultSet { meta, i: 0, rows }))
}

fn execute_update(&mut self, params: &[rdbc::Value]) -> rdbc::Result<u64> {
let params = to_postgres_value(params);
let params: Vec<&dyn postgres::types::ToSql> = params.iter().map(|v| v.as_ref()).collect();
self.conn
.execute(&self.sql, params.as_slice())
.map_err(|e| to_rdbc_err(&e))
.map_err(to_rdbc_err)
}
}

Expand All @@ -142,8 +132,8 @@ struct PResultSet {
}

impl rdbc::ResultSet for PResultSet {
fn meta_data(&self) -> rdbc::Result<Rc<dyn rdbc::ResultSetMetaData>> {
Ok(Rc::new(self.meta.clone()))
fn meta_data(&self) -> rdbc::Result<Box<dyn rdbc::ResultSetMetaData>> {
Ok(Box::new(self.meta.clone()))
}

fn next(&mut self) -> bool {
Expand Down Expand Up @@ -189,7 +179,7 @@ impl rdbc::ResultSet for PResultSet {
}

/// Convert a Postgres error into an RDBC error
fn to_rdbc_err(e: &postgres::error::Error) -> rdbc::Error {
fn to_rdbc_err(e: postgres::error::Error) -> rdbc::Error {
rdbc::Error::General(format!("{:?}", e))
}

Expand Down Expand Up @@ -229,13 +219,9 @@ mod tests {
)?;

let driver: Arc<dyn rdbc::Driver> = Arc::new(PostgresDriver::new());
let conn = driver.connect("postgres://rdbc:secret@127.0.0.1:5433")?;
let mut conn = conn.as_ref().borrow_mut();
let stmt = conn.prepare("SELECT a FROM test")?;
let mut stmt = stmt.borrow_mut();
let rs = stmt.execute_query(&vec![])?;

let mut rs = rs.as_ref().borrow_mut();
let mut conn = driver.connect("postgres://rdbc:secret@127.0.0.1:5433")?;
let mut stmt = conn.prepare("SELECT a FROM test")?;
let mut rs = stmt.execute_query(&vec![])?;

assert!(rs.next());
assert_eq!(Some(123), rs.get_i32(0)?);
Expand All @@ -247,10 +233,8 @@ mod tests {
fn execute(sql: &str, values: &Vec<rdbc::Value>) -> rdbc::Result<u64> {
println!("Executing '{}' with {} params", sql, values.len());
let driver: Arc<dyn rdbc::Driver> = Arc::new(PostgresDriver::new());
let conn = driver.connect("postgres://rdbc:secret@127.0.0.1:5433")?;
let mut conn = conn.as_ref().borrow_mut();
let stmt = conn.prepare(sql)?;
let mut stmt = stmt.borrow_mut();
let mut conn = driver.connect("postgres://rdbc:secret@127.0.0.1:5433")?;
let mut stmt = conn.prepare(sql)?;
stmt.execute_update(values)
}
}

0 comments on commit 131b0b7

Please sign in to comment.