Skip to content

Commit 19161a8

Browse files
authored
Remove panic from inner connection initialization (#54)
* Remove panic from inner connection initialization * Add clone drop test * In UT, close conn explicitly
1 parent 0dc4c28 commit 19161a8

File tree

3 files changed

+44
-35
lines changed

3 files changed

+44
-35
lines changed

src/inner_connection.rs

Lines changed: 12 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -16,25 +16,19 @@ pub struct InnerConnection {
1616
owned: bool,
1717
}
1818

19-
impl Clone for InnerConnection {
20-
fn clone(&self) -> Self {
21-
unsafe { InnerConnection::new(self.db, false) }
22-
}
23-
}
24-
2519
impl InnerConnection {
26-
#[allow(clippy::mutex_atomic)]
2720
#[inline]
28-
pub unsafe fn new(db: ffi::duckdb_database, owned: bool) -> InnerConnection {
21+
pub unsafe fn new(db: ffi::duckdb_database, owned: bool) -> Result<InnerConnection> {
2922
let mut con: ffi::duckdb_connection = ptr::null_mut();
3023
let r = ffi::duckdb_connect(db, &mut con);
3124
if r != ffi::DuckDBSuccess {
3225
ffi::duckdb_disconnect(&mut con);
33-
let e = Error::DuckDBFailure(ffi::Error::new(r), Some("connect error".to_owned()));
34-
// TODO: fix this
35-
panic!("error {:?}", e);
26+
return Err(Error::DuckDBFailure(
27+
ffi::Error::new(r),
28+
Some("connect error".to_owned()),
29+
));
3630
}
37-
InnerConnection { db, con, owned }
31+
Ok(InnerConnection { db, con, owned })
3832
}
3933

4034
pub fn open_with_flags(c_path: &CStr, config: Config) -> Result<InnerConnection> {
@@ -47,11 +41,10 @@ impl InnerConnection {
4741
ffi::duckdb_free(c_err as *mut c_void);
4842
return Err(Error::DuckDBFailure(ffi::Error::new(r as u32), msg));
4943
}
50-
Ok(InnerConnection::new(db, true))
44+
InnerConnection::new(db, true)
5145
}
5246
}
5347

54-
#[allow(clippy::mutex_atomic)]
5548
pub fn close(&mut self) -> Result<()> {
5649
if self.db.is_null() {
5750
return Ok(());
@@ -71,6 +64,11 @@ impl InnerConnection {
7164
Ok(())
7265
}
7366

67+
/// Creates a new connection to the already-opened database.
68+
pub fn try_clone(&self) -> Result<Self> {
69+
unsafe { InnerConnection::new(self.db, false) }
70+
}
71+
7472
pub fn execute(&mut self, sql: &str) -> Result<()> {
7573
let c_str = CString::new(sql).unwrap();
7674
unsafe {
@@ -106,12 +104,6 @@ impl InnerConnection {
106104
Ok(Appender::new(conn, c_app))
107105
}
108106

109-
#[inline]
110-
#[allow(dead_code)]
111-
pub fn changes(&mut self) -> usize {
112-
panic!("changes: not supported")
113-
}
114-
115107
#[inline]
116108
pub fn is_autocommit(&self) -> bool {
117109
true

src/lib.rs

Lines changed: 31 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -197,16 +197,6 @@ pub struct Connection {
197197

198198
unsafe impl Send for Connection {}
199199

200-
impl Clone for Connection {
201-
/// Open a new db connection
202-
fn clone(&self) -> Self {
203-
Connection {
204-
db: RefCell::new(self.db.borrow().clone()),
205-
path: self.path.clone(),
206-
}
207-
}
208-
}
209-
210200
impl Connection {
211201
/// Open a new connection to a DuckDB database.
212202
///
@@ -510,6 +500,15 @@ impl Connection {
510500
pub fn is_autocommit(&self) -> bool {
511501
self.db.borrow().is_autocommit()
512502
}
503+
504+
/// Creates a new connection to the already-opened database.
505+
pub fn try_clone(&self) -> Result<Self> {
506+
let inner = self.db.borrow().try_clone()?;
507+
Ok(Connection {
508+
db: RefCell::new(inner),
509+
path: self.path.clone(),
510+
})
511+
}
513512
}
514513

515514
impl fmt::Debug for Connection {
@@ -922,12 +921,30 @@ mod test {
922921

923922
#[test]
924923
fn test_clone() -> Result<()> {
925-
let owned_con = checked_memory_handle();
924+
// 1. Drop the cloned connection first. The original connection should still be able to run queries.
925+
{
926+
let owned_con = checked_memory_handle();
927+
{
928+
let cloned_con = owned_con.try_clone().unwrap();
929+
cloned_con.execute_batch("create table test (c1 bigint)")?;
930+
cloned_con.close().unwrap();
931+
}
932+
owned_con.execute_batch("create table test2 (c1 bigint)")?;
933+
owned_con.close().unwrap();
934+
}
935+
936+
// 2. Close the original connection first. The cloned connection should still be able to run queries.
926937
{
927-
let cloned_con = owned_con.clone();
928-
cloned_con.execute_batch("PRAGMA VERSION")?;
938+
let cloned_con = {
939+
let owned_con = checked_memory_handle();
940+
let clone = owned_con.try_clone().unwrap();
941+
owned_con.execute_batch("create table test (c1 bigint)")?;
942+
owned_con.close().unwrap();
943+
clone
944+
};
945+
cloned_con.execute_batch("create table test2 (c1 bigint)")?;
946+
cloned_con.close().unwrap();
929947
}
930-
owned_con.close().unwrap();
931948
Ok(())
932949
}
933950

src/r2d2.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -86,7 +86,7 @@ impl r2d2::ManageConnection for DuckdbConnectionManager {
8686

8787
fn connect(&self) -> Result<Self::Connection, Self::Error> {
8888
let conn = self.connection.lock().unwrap();
89-
Ok(conn.clone())
89+
conn.try_clone()
9090
}
9191

9292
fn is_valid(&self, conn: &mut Self::Connection) -> Result<(), Self::Error> {

0 commit comments

Comments
 (0)