33pub mod ffi;
44pub mod wal_hook;
55
6- use std:: { ffi:: CString , marker :: PhantomData , ops:: Deref , time:: Duration } ;
6+ use std:: { ffi:: CString , ops:: Deref , time:: Duration } ;
77
88pub use crate :: wal_hook:: WalMethodsHook ;
99pub use once_cell:: sync:: Lazy ;
10+ use rusqlite:: ffi:: sqlite3;
11+ use wal_hook:: TransparentMethods ;
1012
1113use self :: {
1214 ffi:: { libsql_wal_methods, libsql_wal_methods_find} ,
@@ -22,40 +24,45 @@ pub fn get_orig_wal_methods() -> anyhow::Result<*mut libsql_wal_methods> {
2224 Ok ( orig)
2325}
2426
25- pub struct Connection < ' a > {
27+ pub struct Connection < W : WalHook > {
2628 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 > ,
2832}
2933
30- impl Deref for Connection < ' _ > {
34+ impl < W : WalHook > Deref for Connection < W > {
3135 type Target = rusqlite:: Connection ;
3236
3337 fn deref ( & self ) -> & Self :: Target {
3438 & self . conn
3539 }
3640}
3741
38- impl < ' a > Connection < ' a > {
42+ impl Connection < TransparentMethods > {
3943 /// returns a dummy, in-memory connection. For testing purposes only
40- pub fn test ( _ : & mut ( ) ) -> Self {
44+ pub fn test ( ) -> Self {
4145 let conn = rusqlite:: Connection :: open_in_memory ( ) . unwrap ( ) ;
4246 Self {
4347 conn,
44- _pth : PhantomData ,
48+ _ctx : Box :: new ( ( ) ) ,
4549 }
4650 }
51+ }
4752
53+ impl < W : WalHook > Connection < W > {
4854 /// 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 (
5056 path : impl AsRef < std:: path:: Path > ,
5157 flags : rusqlite:: OpenFlags ,
5258 // we technically _only_ need to know about W, but requiring a static ref to the wal_hook ensures that
5359 // it has been instanciated and lives for long enough
5460 _wal_hook : & ' static WalMethodsHook < W > ,
55- hook_ctx : & ' a mut W :: Context ,
61+ hook_ctx : W :: Context ,
5662 auto_checkpoint : u32 ,
5763 ) -> Result < Self , rusqlite:: Error > {
5864 let path = path. as_ref ( ) . join ( "data" ) ;
65+ let mut _ctx = Box :: new ( hook_ctx) ;
5966 tracing:: trace!(
6067 "Opening a connection with regular WAL at {}" ,
6168 path. display( )
@@ -75,7 +82,7 @@ impl<'a> Connection<'a> {
7582 flags. bits ( ) ,
7683 std:: ptr:: null_mut ( ) ,
7784 W :: name ( ) . as_ptr ( ) ,
78- hook_ctx as * mut _ as * mut _ ,
85+ _ctx . as_mut ( ) as * mut _ as * mut _ ,
7986 ) ;
8087
8188 if rc == 0 {
@@ -96,9 +103,14 @@ impl<'a> Connection<'a> {
96103 let conn = unsafe { rusqlite:: Connection :: from_handle_owned ( db) ? } ;
97104 conn. busy_timeout ( Duration :: from_millis ( 5000 ) ) ?;
98105
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 ( )
103115 }
104116}
0 commit comments