mirror of
				https://github.com/isar/rusqlite.git
				synced 2025-10-31 13:58:55 +08:00 
			
		
		
		
	VTabCursor lifetime should be bound to VTab lifetime
```c
struct sqlite3_vtab_cursor {
  sqlite3_vtab *pVtab;      /* Virtual table of this cursor */
```
It seems that we need to introduce a lifetime on `VTab` trait
to express such constraint:
https://users.rust-lang.org/t/associated-type-with-lifetime-bound/7256
But there may be another/new way to do it.
			
			
This commit is contained in:
		| @@ -27,6 +27,7 @@ | ||||
| //! ``` | ||||
|  | ||||
| use std::default::Default; | ||||
| use std::marker::PhantomData; | ||||
| use std::os::raw::{c_char, c_int, c_void}; | ||||
| use std::rc::Rc; | ||||
|  | ||||
| @@ -72,9 +73,9 @@ struct ArrayTab { | ||||
|     base: ffi::sqlite3_vtab, | ||||
| } | ||||
|  | ||||
| unsafe impl VTab for ArrayTab { | ||||
| unsafe impl<'vtab> VTab<'vtab> for ArrayTab { | ||||
|     type Aux = (); | ||||
|     type Cursor = ArrayTabCursor; | ||||
|     type Cursor = ArrayTabCursor<'vtab>; | ||||
|  | ||||
|     fn connect( | ||||
|         _: &mut VTabConnection, | ||||
| @@ -118,28 +119,30 @@ unsafe impl VTab for ArrayTab { | ||||
|         Ok(()) | ||||
|     } | ||||
|  | ||||
|     fn open(&self) -> Result<ArrayTabCursor> { | ||||
|     fn open(&'vtab self) -> Result<ArrayTabCursor<'vtab>> { | ||||
|         Ok(ArrayTabCursor::new()) | ||||
|     } | ||||
| } | ||||
|  | ||||
| /// A cursor for the Array virtual table | ||||
| #[repr(C)] | ||||
| struct ArrayTabCursor { | ||||
| struct ArrayTabCursor<'vtab> { | ||||
|     /// Base class. Must be first | ||||
|     base: ffi::sqlite3_vtab_cursor, | ||||
|     /// The rowid | ||||
|     row_id: i64, | ||||
|     /// Pointer to the array of values ("pointer") | ||||
|     ptr: Option<Array>, | ||||
|     phantom: PhantomData<&'vtab ArrayTab>, | ||||
| } | ||||
|  | ||||
| impl ArrayTabCursor { | ||||
|     fn new() -> ArrayTabCursor { | ||||
| impl ArrayTabCursor<'_> { | ||||
|     fn new<'vtab>() -> ArrayTabCursor<'vtab> { | ||||
|         ArrayTabCursor { | ||||
|             base: ffi::sqlite3_vtab_cursor::default(), | ||||
|             row_id: 0, | ||||
|             ptr: None, | ||||
|             phantom: PhantomData, | ||||
|         } | ||||
|     } | ||||
|  | ||||
| @@ -150,7 +153,7 @@ impl ArrayTabCursor { | ||||
|         } | ||||
|     } | ||||
| } | ||||
| unsafe impl VTabCursor for ArrayTabCursor { | ||||
| unsafe impl VTabCursor for ArrayTabCursor<'_> { | ||||
|     fn filter(&mut self, idx_num: c_int, _idx_str: Option<&str>, args: &Values<'_>) -> Result<()> { | ||||
|         if idx_num > 0 { | ||||
|             self.ptr = args.get_array(0)?; | ||||
|   | ||||
| @@ -22,6 +22,7 @@ | ||||
| //! } | ||||
| //! ``` | ||||
| use std::fs::File; | ||||
| use std::marker::PhantomData; | ||||
| use std::os::raw::c_int; | ||||
| use std::path::Path; | ||||
| use std::str; | ||||
| @@ -95,9 +96,9 @@ impl CSVTab { | ||||
|     } | ||||
| } | ||||
|  | ||||
| unsafe impl VTab for CSVTab { | ||||
| unsafe impl<'vtab> VTab<'vtab> for CSVTab { | ||||
|     type Aux = (); | ||||
|     type Cursor = CSVTabCursor; | ||||
|     type Cursor = CSVTabCursor<'vtab>; | ||||
|  | ||||
|     fn connect( | ||||
|         _: &mut VTabConnection, | ||||
| @@ -258,16 +259,16 @@ unsafe impl VTab for CSVTab { | ||||
|         Ok(()) | ||||
|     } | ||||
|  | ||||
|     fn open(&self) -> Result<CSVTabCursor> { | ||||
|     fn open(&'vtab self) -> Result<CSVTabCursor<'vtab>> { | ||||
|         Ok(CSVTabCursor::new(self.reader()?)) | ||||
|     } | ||||
| } | ||||
|  | ||||
| impl CreateVTab for CSVTab {} | ||||
| impl CreateVTab<'_> for CSVTab {} | ||||
|  | ||||
| /// A cursor for the CSV virtual table | ||||
| #[repr(C)] | ||||
| struct CSVTabCursor { | ||||
| struct CSVTabCursor<'vtab> { | ||||
|     /// Base class. Must be first | ||||
|     base: ffi::sqlite3_vtab_cursor, | ||||
|     /// The CSV reader object | ||||
| @@ -277,16 +278,18 @@ struct CSVTabCursor { | ||||
|     /// Values of the current row | ||||
|     cols: csv::StringRecord, | ||||
|     eof: bool, | ||||
|     phantom: PhantomData<&'vtab CSVTab>, | ||||
| } | ||||
|  | ||||
| impl CSVTabCursor { | ||||
|     fn new(reader: csv::Reader<File>) -> CSVTabCursor { | ||||
| impl CSVTabCursor<'_> { | ||||
|     fn new<'vtab>(reader: csv::Reader<File>) -> CSVTabCursor<'vtab> { | ||||
|         CSVTabCursor { | ||||
|             base: ffi::sqlite3_vtab_cursor::default(), | ||||
|             reader, | ||||
|             row_number: 0, | ||||
|             cols: csv::StringRecord::new(), | ||||
|             eof: false, | ||||
|             phantom: PhantomData, | ||||
|         } | ||||
|     } | ||||
|  | ||||
| @@ -296,7 +299,7 @@ impl CSVTabCursor { | ||||
|     } | ||||
| } | ||||
|  | ||||
| unsafe impl VTabCursor for CSVTabCursor { | ||||
| unsafe impl VTabCursor for CSVTabCursor<'_> { | ||||
|     // Only a full table scan is supported.  So `filter` simply rewinds to | ||||
|     // the beginning. | ||||
|     fn filter( | ||||
|   | ||||
| @@ -61,13 +61,13 @@ use crate::{str_to_cstring, Connection, Error, InnerConnection, Result}; | ||||
| /// | ||||
| /// (See [SQLite doc](https://sqlite.org/c3ref/module.html)) | ||||
| #[repr(transparent)] | ||||
| pub struct Module<T: VTab> { | ||||
| pub struct Module<'vtab, T: VTab<'vtab>> { | ||||
|     base: ffi::sqlite3_module, | ||||
|     phantom: PhantomData<T>, | ||||
|     phantom: PhantomData<&'vtab T>, | ||||
| } | ||||
|  | ||||
| unsafe impl<T: VTab> Send for Module<T> {} | ||||
| unsafe impl<T: VTab> Sync for Module<T> {} | ||||
| unsafe impl<'vtab, T: VTab<'vtab>> Send for Module<'vtab, T> {} | ||||
| unsafe impl<'vtab, T: VTab<'vtab>> Sync for Module<'vtab, T> {} | ||||
|  | ||||
| union ModuleZeroHack { | ||||
|     bytes: [u8; std::mem::size_of::<ffi::sqlite3_module>()], | ||||
| @@ -87,7 +87,7 @@ const ZERO_MODULE: ffi::sqlite3_module = unsafe { | ||||
| /// `feature = "vtab"` Create a read-only virtual table implementation. | ||||
| /// | ||||
| /// Step 2 of [Creating New Virtual Table Implementations](https://sqlite.org/vtab.html#creating_new_virtual_table_implementations). | ||||
| pub fn read_only_module<T: CreateVTab>() -> &'static Module<T> { | ||||
| pub fn read_only_module<'vtab, T: CreateVTab<'vtab>>() -> &'static Module<'vtab, T> { | ||||
|     // The xConnect and xCreate methods do the same thing, but they must be | ||||
|     // different so that the virtual table is not an eponymous virtual table. | ||||
|     &Module { | ||||
| @@ -118,14 +118,14 @@ pub fn read_only_module<T: CreateVTab>() -> &'static Module<T> { | ||||
|             xRollbackTo: None, | ||||
|             ..ZERO_MODULE | ||||
|         }, | ||||
|         phantom: PhantomData::<T>, | ||||
|         phantom: PhantomData::<&'vtab T>, | ||||
|     } | ||||
| } | ||||
|  | ||||
| /// `feature = "vtab"` Create an eponymous only virtual table implementation. | ||||
| /// | ||||
| /// Step 2 of [Creating New Virtual Table Implementations](https://sqlite.org/vtab.html#creating_new_virtual_table_implementations). | ||||
| pub fn eponymous_only_module<T: VTab>() -> &'static Module<T> { | ||||
| pub fn eponymous_only_module<'vtab, T: VTab<'vtab>>() -> &'static Module<'vtab, T> { | ||||
|     // A virtual table is eponymous if its xCreate method is the exact same function | ||||
|     // as the xConnect method For eponymous-only virtual tables, the xCreate | ||||
|     // method is NULL | ||||
| @@ -157,7 +157,7 @@ pub fn eponymous_only_module<T: VTab>() -> &'static Module<T> { | ||||
|             xRollbackTo: None, | ||||
|             ..ZERO_MODULE | ||||
|         }, | ||||
|         phantom: PhantomData::<T>, | ||||
|         phantom: PhantomData::<&'vtab T>, | ||||
|     } | ||||
| } | ||||
|  | ||||
| @@ -204,7 +204,7 @@ impl VTabConnection { | ||||
| /// ``` | ||||
| /// | ||||
| /// (See [SQLite doc](https://sqlite.org/c3ref/vtab.html)) | ||||
| pub unsafe trait VTab: Sized { | ||||
| pub unsafe trait VTab<'vtab>: Sized { | ||||
|     /// Client data passed to `Connection::create_module`. | ||||
|     type Aux; | ||||
|     /// Specific cursor implementation | ||||
| @@ -225,13 +225,13 @@ pub unsafe trait VTab: Sized { | ||||
|  | ||||
|     /// Create a new cursor used for accessing a virtual table. | ||||
|     /// (See [SQLite doc](https://sqlite.org/vtab.html#the_xopen_method)) | ||||
|     fn open(&self) -> Result<Self::Cursor>; | ||||
|     fn open(&'vtab self) -> Result<Self::Cursor>; | ||||
| } | ||||
|  | ||||
| /// `feature = "vtab"` Non-eponymous virtual table instance trait. | ||||
| /// | ||||
| /// (See [SQLite doc](https://sqlite.org/c3ref/vtab.html)) | ||||
| pub trait CreateVTab: VTab { | ||||
| pub trait CreateVTab<'vtab>: VTab<'vtab> { | ||||
|     /// Create a new instance of a virtual table in response to a CREATE VIRTUAL | ||||
|     /// TABLE statement. The `db` parameter is a pointer to the SQLite | ||||
|     /// database connection that is executing the CREATE VIRTUAL TABLE | ||||
| @@ -607,10 +607,10 @@ impl Connection { | ||||
|     /// | ||||
|     /// Step 3 of [Creating New Virtual Table | ||||
|     /// Implementations](https://sqlite.org/vtab.html#creating_new_virtual_table_implementations). | ||||
|     pub fn create_module<T: VTab>( | ||||
|     pub fn create_module<'vtab, T: VTab<'vtab>>( | ||||
|         &self, | ||||
|         module_name: &str, | ||||
|         module: &'static Module<T>, | ||||
|         module: &'static Module<'vtab, T>, | ||||
|         aux: Option<T::Aux>, | ||||
|     ) -> Result<()> { | ||||
|         self.db.borrow_mut().create_module(module_name, module, aux) | ||||
| @@ -618,10 +618,10 @@ impl Connection { | ||||
| } | ||||
|  | ||||
| impl InnerConnection { | ||||
|     fn create_module<T: VTab>( | ||||
|     fn create_module<'vtab, T: VTab<'vtab>>( | ||||
|         &mut self, | ||||
|         module_name: &str, | ||||
|         module: &'static Module<T>, | ||||
|         module: &'static Module<'vtab, T>, | ||||
|         aux: Option<T::Aux>, | ||||
|     ) -> Result<()> { | ||||
|         let c_name = str_to_cstring(module_name)?; | ||||
| @@ -703,7 +703,7 @@ unsafe extern "C" fn free_boxed_value<T>(p: *mut c_void) { | ||||
|     let _: Box<T> = Box::from_raw(p as *mut T); | ||||
| } | ||||
|  | ||||
| unsafe extern "C" fn rust_create<T>( | ||||
| unsafe extern "C" fn rust_create<'vtab, T>( | ||||
|     db: *mut ffi::sqlite3, | ||||
|     aux: *mut c_void, | ||||
|     argc: c_int, | ||||
| @@ -712,7 +712,7 @@ unsafe extern "C" fn rust_create<T>( | ||||
|     err_msg: *mut *mut c_char, | ||||
| ) -> c_int | ||||
| where | ||||
|     T: CreateVTab, | ||||
|     T: CreateVTab<'vtab>, | ||||
| { | ||||
|     use std::ffi::CStr; | ||||
|  | ||||
| @@ -755,7 +755,7 @@ where | ||||
|     } | ||||
| } | ||||
|  | ||||
| unsafe extern "C" fn rust_connect<T>( | ||||
| unsafe extern "C" fn rust_connect<'vtab, T>( | ||||
|     db: *mut ffi::sqlite3, | ||||
|     aux: *mut c_void, | ||||
|     argc: c_int, | ||||
| @@ -764,7 +764,7 @@ unsafe extern "C" fn rust_connect<T>( | ||||
|     err_msg: *mut *mut c_char, | ||||
| ) -> c_int | ||||
| where | ||||
|     T: VTab, | ||||
|     T: VTab<'vtab>, | ||||
| { | ||||
|     use std::ffi::CStr; | ||||
|  | ||||
| @@ -807,12 +807,12 @@ where | ||||
|     } | ||||
| } | ||||
|  | ||||
| unsafe extern "C" fn rust_best_index<T>( | ||||
| unsafe extern "C" fn rust_best_index<'vtab, T>( | ||||
|     vtab: *mut ffi::sqlite3_vtab, | ||||
|     info: *mut ffi::sqlite3_index_info, | ||||
| ) -> c_int | ||||
| where | ||||
|     T: VTab, | ||||
|     T: VTab<'vtab>, | ||||
| { | ||||
|     let vt = vtab as *mut T; | ||||
|     let mut idx_info = IndexInfo(info); | ||||
| @@ -831,9 +831,9 @@ where | ||||
|     } | ||||
| } | ||||
|  | ||||
| unsafe extern "C" fn rust_disconnect<T>(vtab: *mut ffi::sqlite3_vtab) -> c_int | ||||
| unsafe extern "C" fn rust_disconnect<'vtab, T>(vtab: *mut ffi::sqlite3_vtab) -> c_int | ||||
| where | ||||
|     T: VTab, | ||||
|     T: VTab<'vtab>, | ||||
| { | ||||
|     if vtab.is_null() { | ||||
|         return ffi::SQLITE_OK; | ||||
| @@ -843,9 +843,9 @@ where | ||||
|     ffi::SQLITE_OK | ||||
| } | ||||
|  | ||||
| unsafe extern "C" fn rust_destroy<T>(vtab: *mut ffi::sqlite3_vtab) -> c_int | ||||
| unsafe extern "C" fn rust_destroy<'vtab, T>(vtab: *mut ffi::sqlite3_vtab) -> c_int | ||||
| where | ||||
|     T: CreateVTab, | ||||
|     T: CreateVTab<'vtab>, | ||||
| { | ||||
|     if vtab.is_null() { | ||||
|         return ffi::SQLITE_OK; | ||||
| @@ -869,12 +869,12 @@ where | ||||
|     } | ||||
| } | ||||
|  | ||||
| unsafe extern "C" fn rust_open<T>( | ||||
| unsafe extern "C" fn rust_open<'vtab, T: 'vtab>( | ||||
|     vtab: *mut ffi::sqlite3_vtab, | ||||
|     pp_cursor: *mut *mut ffi::sqlite3_vtab_cursor, | ||||
| ) -> c_int | ||||
| where | ||||
|     T: VTab, | ||||
|     T: VTab<'vtab>, | ||||
| { | ||||
|     let vt = vtab as *mut T; | ||||
|     match (*vt).open() { | ||||
|   | ||||
| @@ -4,6 +4,7 @@ | ||||
| //! "function"](http://www.sqlite.org/cgi/src/finfo?name=ext/misc/series.c): | ||||
| //! https://www.sqlite.org/series.html | ||||
| use std::default::Default; | ||||
| use std::marker::PhantomData; | ||||
| use std::os::raw::c_int; | ||||
|  | ||||
| use crate::ffi; | ||||
| @@ -49,9 +50,9 @@ struct SeriesTab { | ||||
|     base: ffi::sqlite3_vtab, | ||||
| } | ||||
|  | ||||
| unsafe impl VTab for SeriesTab { | ||||
| unsafe impl<'vtab> VTab<'vtab> for SeriesTab { | ||||
|     type Aux = (); | ||||
|     type Cursor = SeriesTabCursor; | ||||
|     type Cursor = SeriesTabCursor<'vtab>; | ||||
|  | ||||
|     fn connect( | ||||
|         _: &mut VTabConnection, | ||||
| @@ -151,15 +152,14 @@ unsafe impl VTab for SeriesTab { | ||||
|         Ok(()) | ||||
|     } | ||||
|  | ||||
|     fn open(&self) -> Result<SeriesTabCursor> { | ||||
|     fn open(&'vtab self) -> Result<SeriesTabCursor<'vtab>> { | ||||
|         Ok(SeriesTabCursor::new()) | ||||
|     } | ||||
| } | ||||
|  | ||||
| /// A cursor for the Series virtual table | ||||
| #[derive(Default)] | ||||
| #[repr(C)] | ||||
| struct SeriesTabCursor { | ||||
| struct SeriesTabCursor<'vtab> { | ||||
|     /// Base class. Must be first | ||||
|     base: ffi::sqlite3_vtab_cursor, | ||||
|     /// True to count down rather than up | ||||
| @@ -174,14 +174,24 @@ struct SeriesTabCursor { | ||||
|     max_value: i64, | ||||
|     /// Increment ("step") | ||||
|     step: i64, | ||||
|     phantom: PhantomData<&'vtab SeriesTab>, | ||||
| } | ||||
|  | ||||
| impl SeriesTabCursor { | ||||
|     fn new() -> SeriesTabCursor { | ||||
|         SeriesTabCursor::default() | ||||
| impl SeriesTabCursor<'_> { | ||||
|     fn new<'vtab>() -> SeriesTabCursor<'vtab> { | ||||
|         SeriesTabCursor { | ||||
|             base: ffi::sqlite3_vtab_cursor::default(), | ||||
|             is_desc: false, | ||||
|             row_id: 0, | ||||
|             value: 0, | ||||
|             min_value: 0, | ||||
|             max_value: 0, | ||||
|             step: 0, | ||||
|             phantom: PhantomData, | ||||
|         } | ||||
|     } | ||||
| } | ||||
| unsafe impl VTabCursor for SeriesTabCursor { | ||||
| unsafe impl VTabCursor for SeriesTabCursor<'_> { | ||||
|     fn filter(&mut self, idx_num: c_int, _idx_str: Option<&str>, args: &Values<'_>) -> Result<()> { | ||||
|         let idx_num = QueryPlanFlags::from_bits_truncate(idx_num); | ||||
|         let mut i = 0; | ||||
|   | ||||
| @@ -9,6 +9,7 @@ fn test_dummy_module() { | ||||
|         VTabConnection, VTabCursor, Values, | ||||
|     }; | ||||
|     use rusqlite::{version_number, Connection, Result}; | ||||
|     use std::marker::PhantomData; | ||||
|     use std::os::raw::c_int; | ||||
|  | ||||
|     let module = eponymous_only_module::<DummyTab>(); | ||||
| @@ -19,9 +20,9 @@ fn test_dummy_module() { | ||||
|         base: sqlite3_vtab, | ||||
|     } | ||||
|  | ||||
|     unsafe impl VTab for DummyTab { | ||||
|     unsafe impl<'vtab> VTab<'vtab> for DummyTab { | ||||
|         type Aux = (); | ||||
|         type Cursor = DummyTabCursor; | ||||
|         type Cursor = DummyTabCursor<'vtab>; | ||||
|  | ||||
|         fn connect( | ||||
|             _: &mut VTabConnection, | ||||
| @@ -39,21 +40,22 @@ fn test_dummy_module() { | ||||
|             Ok(()) | ||||
|         } | ||||
|  | ||||
|         fn open(&self) -> Result<DummyTabCursor> { | ||||
|         fn open(&'vtab self) -> Result<DummyTabCursor<'vtab>> { | ||||
|             Ok(DummyTabCursor::default()) | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     #[derive(Default)] | ||||
|     #[repr(C)] | ||||
|     struct DummyTabCursor { | ||||
|     struct DummyTabCursor<'vtab> { | ||||
|         /// Base class. Must be first | ||||
|         base: sqlite3_vtab_cursor, | ||||
|         /// The rowid | ||||
|         row_id: i64, | ||||
|         phantom: PhantomData<&'vtab DummyTab>, | ||||
|     } | ||||
|  | ||||
|     unsafe impl VTabCursor for DummyTabCursor { | ||||
|     unsafe impl VTabCursor for DummyTabCursor<'_> { | ||||
|         fn filter( | ||||
|             &mut self, | ||||
|             _idx_num: c_int, | ||||
|   | ||||
		Reference in New Issue
	
	Block a user