diff --git a/rdbc-cli/src/main.rs b/rdbc-cli/src/main.rs index d7279e7..a334d49 100644 --- a/rdbc-cli/src/main.rs +++ b/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; @@ -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, - "postgres" => Rc::new(PostgresDriver::new()) as Rc, - "sqlite" => Rc::new(SqliteDriver::new()) as Rc, + let driver: Box = 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(); @@ -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), } @@ -75,13 +72,10 @@ fn main() -> Result<()> { Ok(()) } -fn execute(conn: Rc>, 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() { diff --git a/rdbc-mysql/src/lib.rs b/rdbc-mysql/src/lib.rs index 88ff9a3..7fd5f0c 100644 --- a/rdbc-mysql/src/lib.rs +++ b/rdbc-mysql/src/lib.rs @@ -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()) } @@ -44,13 +39,10 @@ impl MySQLDriver { } impl rdbc::Driver for MySQLDriver { - fn connect(&self, url: &str) -> rdbc::Result>> { + fn connect(&self, url: &str) -> rdbc::Result> { 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> - }) + let conn = my::Conn::new(opts).map_err(to_rdbc_err)?; + Ok(Box::new(MySQLConnection { conn })) } } @@ -59,21 +51,16 @@ struct MySQLConnection { } impl rdbc::Connection for MySQLConnection { - fn create(&mut self, sql: &str) -> rdbc::Result>> { - Ok(Rc::new(RefCell::new(MySQLStatement { + fn create(&mut self, sql: &str) -> rdbc::Result> { + Ok(Box::new(MySQLStatement { conn: &mut self.conn, sql: sql.to_owned(), - })) as Rc>) + })) } - fn prepare(&mut self, sql: &str) -> rdbc::Result>> { - self.conn - .prepare(&sql) - .and_then(|stmt| { - Ok(Rc::new(RefCell::new(MySQLPreparedStatement { stmt })) - as Rc>) - }) - .map_err(|e| to_rdbc_err(&e)) + fn prepare<'a>(&'a mut self, sql: &str) -> rdbc::Result> { + let stmt = self.conn.prepare(&sql).map_err(to_rdbc_err)?; + Ok(Box::new(MySQLPreparedStatement { stmt })) } } @@ -86,22 +73,17 @@ impl<'a> rdbc::Statement for MySQLStatement<'a> { fn execute_query( &mut self, params: &[rdbc::Value], - ) -> rdbc::Result>> { + ) -> rdbc::Result> { 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> - }) + 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 { 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()) } } @@ -114,20 +96,19 @@ impl<'a> rdbc::Statement for MySQLPreparedStatement<'a> { fn execute_query( &mut self, params: &[rdbc::Value], - ) -> rdbc::Result>> { - self.stmt + ) -> rdbc::Result> { + 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> - }) + .map_err(to_rdbc_err)?; + + Ok(Box::new(MySQLResultSet { result, row: None })) } fn execute_update(&mut self, params: &[rdbc::Value]) -> rdbc::Result { self.stmt .execute(to_my_params(params)) - .map_err(|e| to_rdbc_err(&e)) + .map_err(to_rdbc_err) .map(|result| result.affected_rows()) } } @@ -138,14 +119,14 @@ pub struct MySQLResultSet<'a> { } impl<'a> rdbc::ResultSet for MySQLResultSet<'a> { - fn meta_data(&self) -> rdbc::Result> { + fn meta_data(&self) -> rdbc::Result> { let meta: Vec = 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 { @@ -317,14 +298,9 @@ mod tests { )?; let driver: Arc = 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()); @@ -335,10 +311,8 @@ mod tests { fn execute(sql: &str, values: &Vec) -> rdbc::Result { println!("Executing '{}' with {} params", sql, values.len()); let driver: Arc = 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) } } diff --git a/rdbc-postgres/src/lib.rs b/rdbc-postgres/src/lib.rs index 68ce48f..dd0fbeb 100644 --- a/rdbc-postgres/src/lib.rs +++ b/rdbc-postgres/src/lib.rs @@ -19,10 +19,6 @@ //! } //! ``` -use std::cell::RefCell; -use std::rc::Rc; - -use postgres; use postgres::rows::Rows; use postgres::{Connection, TlsMode}; @@ -30,7 +26,6 @@ use sqlparser::dialect::PostgreSqlDialect; use sqlparser::tokenizer::{Token, Tokenizer, Word}; use postgres::types::Type; -use rdbc; use rdbc::Column; pub struct PostgresDriver {} @@ -42,12 +37,9 @@ impl PostgresDriver { } impl rdbc::Driver for PostgresDriver { - fn connect(&self, url: &str) -> rdbc::Result>> { - 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>) - })? + fn connect(&self, url: &str) -> rdbc::Result> { + let c = postgres::Connection::connect(url, TlsMode::None).map_err(to_rdbc_err)?; + Ok(Box::new(PConnection::new(c))) } } @@ -62,11 +54,11 @@ impl PConnection { } impl rdbc::Connection for PConnection { - fn create(&mut self, sql: &str) -> rdbc::Result>> { + fn create(&mut self, sql: &str) -> rdbc::Result> { self.prepare(sql) } - fn prepare(&mut self, sql: &str) -> rdbc::Result>> { + fn prepare(&mut self, sql: &str) -> rdbc::Result> { // translate SQL, mapping ? into $1 style bound param placeholder let dialect = PostgreSqlDialect {}; let mut tokenizer = Tokenizer::new(&dialect, sql); @@ -92,10 +84,10 @@ impl rdbc::Connection for PConnection { .collect::>() .join(""); - Ok(Rc::new(RefCell::new(PStatement { + Ok(Box::new(PStatement { conn: &self.conn, sql, - })) as Rc>) + })) } } @@ -108,22 +100,20 @@ impl<'a> rdbc::Statement for PStatement<'a> { fn execute_query( &mut self, params: &[rdbc::Value], - ) -> rdbc::Result>> { + ) -> rdbc::Result> { 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> - }) + .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 { @@ -131,7 +121,7 @@ impl<'a> rdbc::Statement for PStatement<'a> { 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) } } @@ -142,8 +132,8 @@ struct PResultSet { } impl rdbc::ResultSet for PResultSet { - fn meta_data(&self) -> rdbc::Result> { - Ok(Rc::new(self.meta.clone())) + fn meta_data(&self) -> rdbc::Result> { + Ok(Box::new(self.meta.clone())) } fn next(&mut self) -> bool { @@ -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)) } @@ -229,13 +219,9 @@ mod tests { )?; let driver: Arc = 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)?); @@ -247,10 +233,8 @@ mod tests { fn execute(sql: &str, values: &Vec) -> rdbc::Result { println!("Executing '{}' with {} params", sql, values.len()); let driver: Arc = 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) } } diff --git a/rdbc-sqlite/src/lib.rs b/rdbc-sqlite/src/lib.rs index f462aa6..69b8bbb 100644 --- a/rdbc-sqlite/src/lib.rs +++ b/rdbc-sqlite/src/lib.rs @@ -20,15 +20,11 @@ //! assert_eq!(Some(123), rs.as_ref().borrow_mut().get_i32(0).unwrap()); //! ``` -use std::cell::RefCell; -use std::rc::Rc; - use fallible_streaming_iterator::FallibleStreamingIterator; -use rdbc; use rusqlite::Rows; /// Convert a Sqlite error into an RDBC error -fn to_rdbc_err(e: &rusqlite::Error) -> rdbc::Error { +fn to_rdbc_err(e: rusqlite::Error) -> rdbc::Error { rdbc::Error::General(format!("{:?}", e)) } @@ -41,12 +37,9 @@ impl SqliteDriver { } impl rdbc::Driver for SqliteDriver { - fn connect(&self, _url: &str) -> rdbc::Result>> { - rusqlite::Connection::open_in_memory() - .map_err(|e| to_rdbc_err(&e)) - .map(|c| { - Ok(Rc::new(RefCell::new(SConnection::new(c))) as Rc>) - })? + fn connect(&self, _url: &str) -> rdbc::Result> { + let c = rusqlite::Connection::open_in_memory().map_err(to_rdbc_err)?; + Ok(Box::new(SConnection::new(c))) } } @@ -61,13 +54,13 @@ impl SConnection { } impl rdbc::Connection for SConnection { - fn create(&mut self, sql: &str) -> rdbc::Result>> { + fn create(&mut self, sql: &str) -> rdbc::Result> { self.prepare(sql) } - fn prepare(&mut self, sql: &str) -> rdbc::Result>> { - let stmt = self.conn.prepare(sql).map_err(|e| to_rdbc_err(&e))?; - Ok(Rc::new(RefCell::new(SStatement { stmt })) as Rc>) + fn prepare(&mut self, sql: &str) -> rdbc::Result> { + let stmt = self.conn.prepare(sql).map_err(to_rdbc_err)?; + Ok(Box::new(SStatement { stmt })) } } @@ -79,11 +72,11 @@ impl<'a> rdbc::Statement for SStatement<'a> { fn execute_query( &mut self, params: &[rdbc::Value], - ) -> rdbc::Result>> { + ) -> rdbc::Result> { let params = to_sqlite_value(params); let params: Vec<&dyn rusqlite::types::ToSql> = params.iter().map(|v| v.as_ref()).collect(); - let rows = self.stmt.query(¶ms).map_err(|e| to_rdbc_err(&e))?; - return Ok(Rc::new(RefCell::new(SResultSet { rows })) as Rc>); + let rows = self.stmt.query(¶ms).map_err(to_rdbc_err)?; + Ok(Box::new(SResultSet { rows })) } fn execute_update(&mut self, params: &[rdbc::Value]) -> rdbc::Result { @@ -92,7 +85,7 @@ impl<'a> rdbc::Statement for SStatement<'a> { return self .stmt .execute(¶ms) - .map_err(|e| to_rdbc_err(&e)) + .map_err(to_rdbc_err) .map(|n| n as u64); } } @@ -102,7 +95,7 @@ struct SResultSet<'stmt> { } impl<'stmt> rdbc::ResultSet for SResultSet<'stmt> { - fn meta_data(&self) -> rdbc::Result> { + fn meta_data(&self) -> rdbc::Result> { let meta: Vec = self .rows .columns() @@ -110,7 +103,7 @@ impl<'stmt> rdbc::ResultSet for SResultSet<'stmt> { .iter() .map(|c| rdbc::Column::new(c.name(), to_rdbc_type(c.decl_type()))) .collect(); - Ok(Rc::new(meta)) + Ok(Box::new(meta)) } fn next(&mut self) -> bool { @@ -122,7 +115,7 @@ impl<'stmt> rdbc::ResultSet for SResultSet<'stmt> { .get() .unwrap() .get(i as usize) - .map_err(|e| to_rdbc_err(&e)) + .map_err(to_rdbc_err) } fn get_i16(&self, i: u64) -> rdbc::Result> { @@ -130,7 +123,7 @@ impl<'stmt> rdbc::ResultSet for SResultSet<'stmt> { .get() .unwrap() .get(i as usize) - .map_err(|e| to_rdbc_err(&e)) + .map_err(to_rdbc_err) } fn get_i32(&self, i: u64) -> rdbc::Result> { @@ -138,7 +131,7 @@ impl<'stmt> rdbc::ResultSet for SResultSet<'stmt> { .get() .unwrap() .get(i as usize) - .map_err(|e| to_rdbc_err(&e)) + .map_err(to_rdbc_err) } fn get_i64(&self, i: u64) -> rdbc::Result> { @@ -146,7 +139,7 @@ impl<'stmt> rdbc::ResultSet for SResultSet<'stmt> { .get() .unwrap() .get(i as usize) - .map_err(|e| to_rdbc_err(&e)) + .map_err(to_rdbc_err) } fn get_f32(&self, _i: u64) -> rdbc::Result> { @@ -158,7 +151,7 @@ impl<'stmt> rdbc::ResultSet for SResultSet<'stmt> { .get() .unwrap() .get(i as usize) - .map_err(|e| to_rdbc_err(&e)) + .map_err(to_rdbc_err) } fn get_string(&self, i: u64) -> rdbc::Result> { @@ -166,7 +159,7 @@ impl<'stmt> rdbc::ResultSet for SResultSet<'stmt> { .get() .unwrap() .get(i as usize) - .map_err(|e| to_rdbc_err(&e)) + .map_err(to_rdbc_err) } fn get_bytes(&self, i: u64) -> rdbc::Result>> { @@ -174,7 +167,7 @@ impl<'stmt> rdbc::ResultSet for SResultSet<'stmt> { .get() .unwrap() .get(i as usize) - .map_err(|e| to_rdbc_err(&e)) + .map_err(to_rdbc_err) } } @@ -207,20 +200,16 @@ mod tests { let driver: Arc = Arc::new(SqliteDriver::new()); let url = ""; let mut conn = driver.connect(url)?; - execute(&mut conn, "DROP TABLE IF EXISTS test", &vec![])?; - execute(&mut conn, "CREATE TABLE test (a INT NOT NULL)", &vec![])?; + execute(&mut *conn, "DROP TABLE IF EXISTS test", &vec![])?; + execute(&mut *conn, "CREATE TABLE test (a INT NOT NULL)", &vec![])?; execute( - &mut conn, + &mut *conn, "INSERT INTO test (a) VALUES (?)", &vec![rdbc::Value::Int32(123)], )?; - 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 stmt = conn.prepare("SELECT a FROM test")?; + let mut rs = stmt.execute_query(&vec![])?; let meta = rs.meta_data()?; assert_eq!(1, meta.num_columns()); @@ -235,14 +224,12 @@ mod tests { } fn execute( - conn: &mut Rc>, + conn: &mut dyn Connection, sql: &str, values: &Vec, ) -> rdbc::Result { println!("Executing '{}' with {} params", sql, values.len()); - let mut conn = conn.as_ref().borrow_mut(); - let stmt = conn.prepare(sql)?; - let mut stmt = stmt.borrow_mut(); + let mut stmt = conn.prepare(sql)?; stmt.execute_update(values) } } diff --git a/rdbc/src/lib.rs b/rdbc/src/lib.rs index 6737410..8e9491e 100644 --- a/rdbc/src/lib.rs +++ b/rdbc/src/lib.rs @@ -21,9 +21,6 @@ //! } //! ``` -use std::cell::RefCell; -use std::rc::Rc; - /// RDBC Error #[derive(Debug)] pub enum Error { @@ -56,21 +53,23 @@ pub type Result = std::result::Result; pub trait Driver: Sync + Send { /// Create a connection to the database. Note that connections are intended to be used /// in a single thread since most database connections are not thread-safe - fn connect(&self, url: &str) -> Result>>; + fn connect(&self, url: &str) -> Result>; } /// Represents a connection to a database pub trait Connection { /// Create a statement for execution - fn create(&mut self, sql: &str) -> Result>>; + fn create(&mut self, sql: &str) -> Result>; + /// Create a prepared statement for execution - fn prepare(&mut self, sql: &str) -> Result>>; + fn prepare(&mut self, sql: &str) -> Result>; } /// Represents an executable statement pub trait Statement { /// Execute a query that is expected to return a result set, such as a `SELECT` statement - fn execute_query(&mut self, params: &[Value]) -> Result>>; + fn execute_query(&mut self, params: &[Value]) -> Result>; + /// Execute a query that is expected to update some rows. fn execute_update(&mut self, params: &[Value]) -> Result; } @@ -78,7 +77,8 @@ pub trait Statement { /// Result set from executing a query against a statement pub trait ResultSet { /// get meta data about this result set - fn meta_data(&self) -> Result>; + fn meta_data(&self) -> Result>; + /// Move the cursor to the next available row if one exists and return true if it does fn next(&mut self) -> bool;