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