3
3
pub mod ffi;
4
4
pub mod wal_hook;
5
5
6
- use std:: { ffi:: CString , marker :: PhantomData , ops:: Deref , time:: Duration } ;
6
+ use std:: { ffi:: CString , ops:: Deref , time:: Duration } ;
7
7
8
8
pub use crate :: wal_hook:: WalMethodsHook ;
9
9
pub use once_cell:: sync:: Lazy ;
10
+ use rusqlite:: ffi:: sqlite3;
11
+ use wal_hook:: TransparentMethods ;
10
12
11
13
use self :: {
12
14
ffi:: { libsql_wal_methods, libsql_wal_methods_find} ,
@@ -22,40 +24,45 @@ pub fn get_orig_wal_methods() -> anyhow::Result<*mut libsql_wal_methods> {
22
24
Ok ( orig)
23
25
}
24
26
25
- pub struct Connection < ' a > {
27
+ pub struct Connection < W : WalHook > {
26
28
conn : rusqlite:: Connection ,
27
- _pth : PhantomData < & ' a mut ( ) > ,
29
+ // Safety: _ctx MUST be dropped after the connection, because the connection has a pointer
30
+ // This pointer MUST NOT move out of the connection
31
+ _ctx : Box < W :: Context > ,
28
32
}
29
33
30
- impl Deref for Connection < ' _ > {
34
+ impl < W : WalHook > Deref for Connection < W > {
31
35
type Target = rusqlite:: Connection ;
32
36
33
37
fn deref ( & self ) -> & Self :: Target {
34
38
& self . conn
35
39
}
36
40
}
37
41
38
- impl < ' a > Connection < ' a > {
42
+ impl Connection < TransparentMethods > {
39
43
/// returns a dummy, in-memory connection. For testing purposes only
40
- pub fn test ( _ : & mut ( ) ) -> Self {
44
+ pub fn test ( ) -> Self {
41
45
let conn = rusqlite:: Connection :: open_in_memory ( ) . unwrap ( ) ;
42
46
Self {
43
47
conn,
44
- _pth : PhantomData ,
48
+ _ctx : Box :: new ( ( ) ) ,
45
49
}
46
50
}
51
+ }
47
52
53
+ impl < W : WalHook > Connection < W > {
48
54
/// Opens a database with the regular wal methods in the directory pointed to by path
49
- pub fn open < W : WalHook > (
55
+ pub fn open (
50
56
path : impl AsRef < std:: path:: Path > ,
51
57
flags : rusqlite:: OpenFlags ,
52
58
// we technically _only_ need to know about W, but requiring a static ref to the wal_hook ensures that
53
59
// it has been instanciated and lives for long enough
54
60
_wal_hook : & ' static WalMethodsHook < W > ,
55
- hook_ctx : & ' a mut W :: Context ,
61
+ hook_ctx : W :: Context ,
56
62
auto_checkpoint : u32 ,
57
63
) -> Result < Self , rusqlite:: Error > {
58
64
let path = path. as_ref ( ) . join ( "data" ) ;
65
+ let mut _ctx = Box :: new ( hook_ctx) ;
59
66
tracing:: trace!(
60
67
"Opening a connection with regular WAL at {}" ,
61
68
path. display( )
@@ -75,7 +82,7 @@ impl<'a> Connection<'a> {
75
82
flags. bits ( ) ,
76
83
std:: ptr:: null_mut ( ) ,
77
84
W :: name ( ) . as_ptr ( ) ,
78
- hook_ctx as * mut _ as * mut _ ,
85
+ _ctx . as_mut ( ) as * mut _ as * mut _ ,
79
86
) ;
80
87
81
88
if rc == 0 {
@@ -96,9 +103,14 @@ impl<'a> Connection<'a> {
96
103
let conn = unsafe { rusqlite:: Connection :: from_handle_owned ( db) ? } ;
97
104
conn. busy_timeout ( Duration :: from_millis ( 5000 ) ) ?;
98
105
99
- Ok ( Connection {
100
- conn,
101
- _pth : PhantomData ,
102
- } )
106
+ Ok ( Connection { conn, _ctx } )
107
+ }
108
+
109
+ /// Returns the raw sqlite handle
110
+ ///
111
+ /// # Safety
112
+ /// The caller is responsible for the returned pointer.
113
+ pub unsafe fn handle ( & mut self ) -> * mut sqlite3 {
114
+ self . conn . handle ( )
103
115
}
104
116
}
0 commit comments