@@ -3,6 +3,7 @@ use std::{
3
3
mem,
4
4
os:: raw:: c_char,
5
5
ptr, str,
6
+ sync:: { Arc , Mutex }
6
7
} ;
7
8
8
9
use super :: { ffi, Appender , Config , Connection , Result } ;
@@ -15,6 +16,7 @@ use crate::{
15
16
pub struct InnerConnection {
16
17
pub db : ffi:: duckdb_database ,
17
18
pub con : ffi:: duckdb_connection ,
19
+ interrupt : Arc < InterruptHandle > ,
18
20
owned : bool ,
19
21
}
20
22
@@ -30,7 +32,9 @@ impl InnerConnection {
30
32
Some ( "connect error" . to_owned ( ) ) ,
31
33
) ) ;
32
34
}
33
- Ok ( InnerConnection { db, con, owned } )
35
+ let interrupt = Arc :: new ( InterruptHandle :: new ( con) ) ;
36
+
37
+ Ok ( InnerConnection { db, con, interrupt, owned } )
34
38
}
35
39
36
40
pub fn open_with_flags ( c_path : & CStr , config : Config ) -> Result < InnerConnection > {
@@ -57,6 +61,7 @@ impl InnerConnection {
57
61
unsafe {
58
62
ffi:: duckdb_disconnect ( & mut self . con ) ;
59
63
self . con = ptr:: null_mut ( ) ;
64
+ self . interrupt . clear ( ) ;
60
65
61
66
if self . owned {
62
67
ffi:: duckdb_close ( & mut self . db ) ;
@@ -106,6 +111,10 @@ impl InnerConnection {
106
111
Ok ( Appender :: new ( conn, c_app) )
107
112
}
108
113
114
+ pub fn get_interrupt_handle ( & self ) -> Arc < InterruptHandle > {
115
+ self . interrupt . clone ( )
116
+ }
117
+
109
118
#[ inline]
110
119
pub fn is_autocommit ( & self ) -> bool {
111
120
true
@@ -126,3 +135,39 @@ impl Drop for InnerConnection {
126
135
}
127
136
}
128
137
}
138
+
139
+ /// A handle that allows interrupting long-running queries.
140
+ pub struct InterruptHandle {
141
+ conn : Mutex < ffi:: duckdb_connection > ,
142
+ }
143
+
144
+ unsafe impl Send for InterruptHandle { }
145
+ unsafe impl Sync for InterruptHandle { }
146
+
147
+ impl InterruptHandle {
148
+ fn new ( conn : ffi:: duckdb_connection ) -> Self {
149
+ Self {
150
+ conn : Mutex :: new ( conn) ,
151
+ }
152
+ }
153
+
154
+ fn clear ( & self ) {
155
+ * ( self . conn . lock ( ) . unwrap ( ) ) = ptr:: null_mut ( ) ;
156
+ }
157
+
158
+ /// Interrupt the query currently running on the connection this handle was
159
+ /// obtained from. The interrupt will cause that query to fail with
160
+ /// `Error::DuckDBFailure`. If the connection was dropped after obtaining
161
+ /// this interrupt handle, calling this method results in a noop.
162
+ ///
163
+ /// See [`crate::Connection::interrupt_handle`] for an example.
164
+ pub fn interrupt ( & self ) {
165
+ let db_handle = self . conn . lock ( ) . unwrap ( ) ;
166
+
167
+ if !db_handle. is_null ( ) {
168
+ unsafe {
169
+ ffi:: duckdb_interrupt ( * db_handle) ;
170
+ }
171
+ }
172
+ }
173
+ }
0 commit comments