Skip to content

Commit f1d2610

Browse files
committed
fix(sqlite): hold a reference to the connection in SqliteRow
fixes #1419
1 parent 7ff6620 commit f1d2610

File tree

6 files changed

+45
-10
lines changed

6 files changed

+45
-10
lines changed

sqlx-core/src/sqlite/connection/executor.rs

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -152,7 +152,7 @@ impl<'c> Executor<'c> for &'c mut SqliteConnection {
152152

153153
Either::Right(()) => {
154154
let (row, weak_values_ref) = SqliteRow::current(
155-
&stmt,
155+
stmt.to_ref(conn.to_ref()),
156156
columns,
157157
column_names
158158
);
@@ -216,8 +216,11 @@ impl<'c> Executor<'c> for &'c mut SqliteConnection {
216216
Either::Left(_) => (),
217217

218218
Either::Right(()) => {
219-
let (row, weak_values_ref) =
220-
SqliteRow::current(stmt, columns, column_names);
219+
let (row, weak_values_ref) = SqliteRow::current(
220+
stmt.to_ref(self.handle.to_ref()),
221+
columns,
222+
column_names,
223+
);
221224

222225
*last_row_values = Some(weak_values_ref);
223226

sqlx-core/src/sqlite/connection/handle.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ pub(crate) struct ConnectionHandle(Arc<HandleInner>);
1515
/// or `sqlite3_reset()`.
1616
///
1717
/// Note that this does *not* actually give access to the database handle!
18+
#[derive(Clone, Debug)]
1819
pub(crate) struct ConnectionHandleRef(Arc<HandleInner>);
1920

2021
// Wrapper for `*mut sqlite3` which finalizes the handle on-drop.

sqlx-core/src/sqlite/connection/mod.rs

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -104,8 +104,7 @@ impl Connection for SqliteConnection {
104104

105105
impl Drop for SqliteConnection {
106106
fn drop(&mut self) {
107-
// before the connection handle is dropped,
108-
// we must explicitly drop the statements as the drop-order in a struct is undefined
107+
// explicitly drop statements before the connection handle is dropped
109108
self.statements.clear();
110109
self.statement.take();
111110
}

sqlx-core/src/sqlite/row.rs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ use crate::column::ColumnIndex;
1111
use crate::error::Error;
1212
use crate::ext::ustr::UStr;
1313
use crate::row::Row;
14-
use crate::sqlite::statement::StatementHandle;
14+
use crate::sqlite::statement::{StatementHandle, StatementHandleRef};
1515
use crate::sqlite::{Sqlite, SqliteColumn, SqliteValue, SqliteValueRef};
1616

1717
/// Implementation of [`Row`] for SQLite.
@@ -23,7 +23,7 @@ pub struct SqliteRow {
2323
// IF the user drops the Row before iterating the stream (so
2424
// nearly all of our internal stream iterators), the executor moves on; otherwise,
2525
// it actually inflates this row with a list of owned sqlite3 values.
26-
pub(crate) statement: Arc<StatementHandle>,
26+
pub(crate) statement: StatementHandleRef,
2727

2828
pub(crate) values: Arc<AtomicPtr<SqliteValue>>,
2929
pub(crate) num_values: usize,
@@ -48,7 +48,7 @@ impl SqliteRow {
4848
// returns a weak reference to an atomic list where the executor should inflate if its going
4949
// to increment the statement with [step]
5050
pub(crate) fn current(
51-
statement: &Arc<StatementHandle>,
51+
statement: StatementHandleRef,
5252
columns: &Arc<Vec<SqliteColumn>>,
5353
column_names: &Arc<HashMap<UStr, usize>>,
5454
) -> (Self, Weak<AtomicPtr<SqliteValue>>) {
@@ -57,7 +57,7 @@ impl SqliteRow {
5757
let size = statement.column_count();
5858

5959
let row = Self {
60-
statement: Arc::clone(statement),
60+
statement,
6161
values,
6262
num_values: size,
6363
columns: Arc::clone(columns),

sqlx-core/src/sqlite/statement/handle.rs

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,12 +20,25 @@ use libsqlite3_sys::{
2020
};
2121

2222
use crate::error::{BoxDynError, Error};
23+
use crate::sqlite::connection::ConnectionHandleRef;
2324
use crate::sqlite::type_info::DataType;
2425
use crate::sqlite::{SqliteError, SqliteTypeInfo};
26+
use std::ops::Deref;
27+
use std::sync::Arc;
2528

2629
#[derive(Debug)]
2730
pub(crate) struct StatementHandle(NonNull<sqlite3_stmt>);
2831

32+
// wrapper for `Arc<StatementHandle>` which also holds a reference to the `ConnectionHandle`
33+
#[derive(Clone, Debug)]
34+
pub(crate) struct StatementHandleRef {
35+
// NOTE: the ordering of fields here determines the drop order:
36+
// https://doc.rust-lang.org/reference/destructors.html#destructors
37+
// the statement *must* be dropped before the connection
38+
statement: Arc<StatementHandle>,
39+
connection: ConnectionHandleRef,
40+
}
41+
2942
// access to SQLite3 statement handles are safe to send and share between threads
3043
// as long as the `sqlite3_step` call is serialized.
3144

@@ -292,7 +305,18 @@ impl StatementHandle {
292305
pub(crate) fn clear_bindings(&self) {
293306
unsafe { sqlite3_clear_bindings(self.0.as_ptr()) };
294307
}
308+
309+
pub(crate) fn to_ref(
310+
self: &Arc<StatementHandle>,
311+
conn: ConnectionHandleRef,
312+
) -> StatementHandleRef {
313+
StatementHandleRef {
314+
statement: Arc::clone(self),
315+
connection: conn,
316+
}
317+
}
295318
}
319+
296320
impl Drop for StatementHandle {
297321
fn drop(&mut self) {
298322
// SAFETY: we have exclusive access to the `StatementHandle` here
@@ -311,3 +335,11 @@ impl Drop for StatementHandle {
311335
}
312336
}
313337
}
338+
339+
impl Deref for StatementHandleRef {
340+
type Target = StatementHandle;
341+
342+
fn deref(&self) -> &Self::Target {
343+
&self.statement
344+
}
345+
}

sqlx-core/src/sqlite/statement/mod.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ mod handle;
1212
mod r#virtual;
1313
mod worker;
1414

15-
pub(crate) use handle::StatementHandle;
15+
pub(crate) use handle::{StatementHandle, StatementHandleRef};
1616
pub(crate) use r#virtual::VirtualStatement;
1717
pub(crate) use worker::StatementWorker;
1818

0 commit comments

Comments
 (0)