mirror of
				https://github.com/isar/rusqlite.git
				synced 2025-10-31 22:08:55 +08:00 
			
		
		
		
	Fix vtab::Module lifetime
This commit is contained in:
		
				
					committed by
					
						 Thom Chiovoloni
						Thom Chiovoloni
					
				
			
			
				
	
			
			
			
						parent
						
							e85963852d
						
					
				
				
					commit
					3c6b57fe1b
				
			| @@ -33,8 +33,8 @@ use std::rc::Rc; | |||||||
| use crate::ffi; | use crate::ffi; | ||||||
| use crate::types::{ToSql, ToSqlOutput, Value}; | use crate::types::{ToSql, ToSqlOutput, Value}; | ||||||
| use crate::vtab::{ | use crate::vtab::{ | ||||||
|     eponymous_only_module, Context, IndexConstraintOp, IndexInfo, Module, VTab, VTabConnection, |     eponymous_only_module, Context, IndexConstraintOp, IndexInfo, VTab, VTabConnection, VTabCursor, | ||||||
|     VTabCursor, Values, |     Values, | ||||||
| }; | }; | ||||||
| use crate::{Connection, Result}; | use crate::{Connection, Result}; | ||||||
|  |  | ||||||
| @@ -57,11 +57,7 @@ impl ToSql for Array { | |||||||
| /// `feature = "array"` Register the "rarray" module. | /// `feature = "array"` Register the "rarray" module. | ||||||
| pub fn load_module(conn: &Connection) -> Result<()> { | pub fn load_module(conn: &Connection) -> Result<()> { | ||||||
|     let aux: Option<()> = None; |     let aux: Option<()> = None; | ||||||
|     conn.create_module("rarray", &ARRAY_MODULE, aux) |     conn.create_module("rarray", eponymous_only_module::<ArrayTab>(), aux) | ||||||
| } |  | ||||||
|  |  | ||||||
| lazy_static::lazy_static! { |  | ||||||
|     static ref ARRAY_MODULE: Module<ArrayTab> = eponymous_only_module::<ArrayTab>(1); |  | ||||||
| } | } | ||||||
|  |  | ||||||
| // Column numbers | // Column numbers | ||||||
|   | |||||||
| @@ -30,7 +30,7 @@ use crate::ffi; | |||||||
| use crate::types::Null; | use crate::types::Null; | ||||||
| use crate::vtab::{ | use crate::vtab::{ | ||||||
|     dequote, escape_double_quote, parse_boolean, read_only_module, Context, CreateVTab, IndexInfo, |     dequote, escape_double_quote, parse_boolean, read_only_module, Context, CreateVTab, IndexInfo, | ||||||
|     Module, VTab, VTabConnection, VTabCursor, Values, |     VTab, VTabConnection, VTabCursor, Values, | ||||||
| }; | }; | ||||||
| use crate::{Connection, Error, Result}; | use crate::{Connection, Error, Result}; | ||||||
|  |  | ||||||
| @@ -47,11 +47,7 @@ use crate::{Connection, Error, Result}; | |||||||
| /// ``` | /// ``` | ||||||
| pub fn load_module(conn: &Connection) -> Result<()> { | pub fn load_module(conn: &Connection) -> Result<()> { | ||||||
|     let aux: Option<()> = None; |     let aux: Option<()> = None; | ||||||
|     conn.create_module("csv", &CSV_MODULE, aux) |     conn.create_module("csv", read_only_module::<CSVTab>(), aux) | ||||||
| } |  | ||||||
|  |  | ||||||
| lazy_static::lazy_static! { |  | ||||||
|     static ref CSV_MODULE: Module<CSVTab> = read_only_module::<CSVTab>(1); |  | ||||||
| } | } | ||||||
|  |  | ||||||
| /// An instance of the CSV virtual table | /// An instance of the CSV virtual table | ||||||
|   | |||||||
							
								
								
									
										143
									
								
								src/vtab/mod.rs
									
									
									
									
									
								
							
							
						
						
									
										143
									
								
								src/vtab/mod.rs
									
									
									
									
									
								
							| @@ -60,7 +60,7 @@ use crate::{str_to_cstring, Connection, Error, InnerConnection, Result}; | |||||||
| /// `feature = "vtab"` Virtual table module | /// `feature = "vtab"` Virtual table module | ||||||
| /// | /// | ||||||
| /// (See [SQLite doc](https://sqlite.org/c3ref/module.html)) | /// (See [SQLite doc](https://sqlite.org/c3ref/module.html)) | ||||||
| #[repr(C)] | #[repr(transparent)] | ||||||
| pub struct Module<T: VTab> { | pub struct Module<T: VTab> { | ||||||
|     base: ffi::sqlite3_module, |     base: ffi::sqlite3_module, | ||||||
|     phantom: PhantomData<T>, |     phantom: PhantomData<T>, | ||||||
| @@ -69,47 +69,55 @@ pub struct Module<T: VTab> { | |||||||
| unsafe impl<T: VTab> Send for Module<T> {} | unsafe impl<T: VTab> Send for Module<T> {} | ||||||
| unsafe impl<T: VTab> Sync for Module<T> {} | unsafe impl<T: VTab> Sync for Module<T> {} | ||||||
|  |  | ||||||
| // Used as a trailing initializer for sqlite3_module -- this way we avoid having | union ModuleZeroHack { | ||||||
| // the build fail if buildtime_bindgen is on |     bytes: [u8; std::mem::size_of::<ffi::sqlite3_module>()], | ||||||
| fn zeroed_module() -> ffi::sqlite3_module { |     module: ffi::sqlite3_module, | ||||||
|     // This is safe, as bindgen-generated structs are allowed to be zeroed. |  | ||||||
|     unsafe { std::mem::MaybeUninit::zeroed().assume_init() } |  | ||||||
| } | } | ||||||
|  |  | ||||||
|  | // Used as a trailing initializer for sqlite3_module -- this way we avoid having | ||||||
|  | // the build fail if buildtime_bindgen is on. This is safe, as bindgen-generated | ||||||
|  | // structs are allowed to be zeroed. | ||||||
|  | const ZERO_MODULE: ffi::sqlite3_module = unsafe { | ||||||
|  |     ModuleZeroHack { | ||||||
|  |         bytes: [0u8; std::mem::size_of::<ffi::sqlite3_module>()], | ||||||
|  |     } | ||||||
|  |     .module | ||||||
|  | }; | ||||||
|  |  | ||||||
| /// `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>(version: c_int) -> Module<T> { | pub fn read_only_module<T: CreateVTab>() -> &'static Module<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. | ||||||
|     let ffi_module = ffi::sqlite3_module { |     &Module { | ||||||
|         iVersion: version, |         base: ffi::sqlite3_module { | ||||||
|         xCreate: Some(rust_create::<T>), |             // We don't use V3 | ||||||
|         xConnect: Some(rust_connect::<T>), |             iVersion: 2, // We don't use V2 or V3 features in read_only_module types | ||||||
|         xBestIndex: Some(rust_best_index::<T>), |             xCreate: Some(rust_create::<T>), | ||||||
|         xDisconnect: Some(rust_disconnect::<T>), |             xConnect: Some(rust_connect::<T>), | ||||||
|         xDestroy: Some(rust_destroy::<T>), |             xBestIndex: Some(rust_best_index::<T>), | ||||||
|         xOpen: Some(rust_open::<T>), |             xDisconnect: Some(rust_disconnect::<T>), | ||||||
|         xClose: Some(rust_close::<T::Cursor>), |             xDestroy: Some(rust_destroy::<T>), | ||||||
|         xFilter: Some(rust_filter::<T::Cursor>), |             xOpen: Some(rust_open::<T>), | ||||||
|         xNext: Some(rust_next::<T::Cursor>), |             xClose: Some(rust_close::<T::Cursor>), | ||||||
|         xEof: Some(rust_eof::<T::Cursor>), |             xFilter: Some(rust_filter::<T::Cursor>), | ||||||
|         xColumn: Some(rust_column::<T::Cursor>), |             xNext: Some(rust_next::<T::Cursor>), | ||||||
|         xRowid: Some(rust_rowid::<T::Cursor>), |             xEof: Some(rust_eof::<T::Cursor>), | ||||||
|         xUpdate: None, |             xColumn: Some(rust_column::<T::Cursor>), | ||||||
|         xBegin: None, |             xRowid: Some(rust_rowid::<T::Cursor>), | ||||||
|         xSync: None, |             xUpdate: None, | ||||||
|         xCommit: None, |             xBegin: None, | ||||||
|         xRollback: None, |             xSync: None, | ||||||
|         xFindFunction: None, |             xCommit: None, | ||||||
|         xRename: None, |             xRollback: None, | ||||||
|         xSavepoint: None, |             xFindFunction: None, | ||||||
|         xRelease: None, |             xRename: None, | ||||||
|         xRollbackTo: None, |             xSavepoint: None, | ||||||
|         ..zeroed_module() |             xRelease: None, | ||||||
|     }; |             xRollbackTo: None, | ||||||
|     Module { |             ..ZERO_MODULE | ||||||
|         base: ffi_module, |         }, | ||||||
|         phantom: PhantomData::<T>, |         phantom: PhantomData::<T>, | ||||||
|     } |     } | ||||||
| } | } | ||||||
| @@ -117,38 +125,38 @@ pub fn read_only_module<T: CreateVTab>(version: c_int) -> Module<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>(version: c_int) -> Module<T> { | pub fn eponymous_only_module<T: VTab>() -> &'static Module<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 | ||||||
|     let ffi_module = ffi::sqlite3_module { |     &Module { | ||||||
|         iVersion: version, |         base: ffi::sqlite3_module { | ||||||
|         xCreate: None, |             // We don't use V3 | ||||||
|         xConnect: Some(rust_connect::<T>), |             iVersion: 2, | ||||||
|         xBestIndex: Some(rust_best_index::<T>), |             xCreate: None, | ||||||
|         xDisconnect: Some(rust_disconnect::<T>), |             xConnect: Some(rust_connect::<T>), | ||||||
|         xDestroy: None, |             xBestIndex: Some(rust_best_index::<T>), | ||||||
|         xOpen: Some(rust_open::<T>), |             xDisconnect: Some(rust_disconnect::<T>), | ||||||
|         xClose: Some(rust_close::<T::Cursor>), |             xDestroy: None, | ||||||
|         xFilter: Some(rust_filter::<T::Cursor>), |             xOpen: Some(rust_open::<T>), | ||||||
|         xNext: Some(rust_next::<T::Cursor>), |             xClose: Some(rust_close::<T::Cursor>), | ||||||
|         xEof: Some(rust_eof::<T::Cursor>), |             xFilter: Some(rust_filter::<T::Cursor>), | ||||||
|         xColumn: Some(rust_column::<T::Cursor>), |             xNext: Some(rust_next::<T::Cursor>), | ||||||
|         xRowid: Some(rust_rowid::<T::Cursor>), |             xEof: Some(rust_eof::<T::Cursor>), | ||||||
|         xUpdate: None, |             xColumn: Some(rust_column::<T::Cursor>), | ||||||
|         xBegin: None, |             xRowid: Some(rust_rowid::<T::Cursor>), | ||||||
|         xSync: None, |             xUpdate: None, | ||||||
|         xCommit: None, |             xBegin: None, | ||||||
|         xRollback: None, |             xSync: None, | ||||||
|         xFindFunction: None, |             xCommit: None, | ||||||
|         xRename: None, |             xRollback: None, | ||||||
|         xSavepoint: None, |             xFindFunction: None, | ||||||
|         xRelease: None, |             xRename: None, | ||||||
|         xRollbackTo: None, |             xSavepoint: None, | ||||||
|         ..zeroed_module() |             xRelease: None, | ||||||
|     }; |             xRollbackTo: None, | ||||||
|     Module { |             ..ZERO_MODULE | ||||||
|         base: ffi_module, |         }, | ||||||
|         phantom: PhantomData::<T>, |         phantom: PhantomData::<T>, | ||||||
|     } |     } | ||||||
| } | } | ||||||
| @@ -583,11 +591,12 @@ impl<'a> Iterator for ValueIter<'a> { | |||||||
| impl Connection { | impl Connection { | ||||||
|     /// `feature = "vtab"` Register a virtual table implementation. |     /// `feature = "vtab"` Register a virtual table implementation. | ||||||
|     /// |     /// | ||||||
|     /// Step 3 of [Creating New Virtual Table Implementations](https://sqlite.org/vtab.html#creating_new_virtual_table_implementations). |     /// 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<T: VTab>( | ||||||
|         &self, |         &self, | ||||||
|         module_name: &str, |         module_name: &str, | ||||||
|         module: &Module<T>, |         module: &'static Module<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) | ||||||
| @@ -598,7 +607,7 @@ impl InnerConnection { | |||||||
|     fn create_module<T: VTab>( |     fn create_module<T: VTab>( | ||||||
|         &mut self, |         &mut self, | ||||||
|         module_name: &str, |         module_name: &str, | ||||||
|         module: &Module<T>, |         module: &'static Module<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)?; | ||||||
|   | |||||||
| @@ -9,19 +9,15 @@ use std::os::raw::c_int; | |||||||
| use crate::ffi; | use crate::ffi; | ||||||
| use crate::types::Type; | use crate::types::Type; | ||||||
| use crate::vtab::{ | use crate::vtab::{ | ||||||
|     eponymous_only_module, Context, IndexConstraintOp, IndexInfo, Module, VTab, VTabConnection, |     eponymous_only_module, Context, IndexConstraintOp, IndexInfo, VTab, VTabConnection, VTabCursor, | ||||||
|     VTabCursor, Values, |     Values, | ||||||
| }; | }; | ||||||
| use crate::{Connection, Result}; | use crate::{Connection, Result}; | ||||||
|  |  | ||||||
| /// `feature = "series"` Register the "generate_series" module. | /// `feature = "series"` Register the "generate_series" module. | ||||||
| pub fn load_module(conn: &Connection) -> Result<()> { | pub fn load_module(conn: &Connection) -> Result<()> { | ||||||
|     let aux: Option<()> = None; |     let aux: Option<()> = None; | ||||||
|     conn.create_module("generate_series", &SERIES_MODULE, aux) |     conn.create_module("generate_series", eponymous_only_module::<SeriesTab>(), aux) | ||||||
| } |  | ||||||
|  |  | ||||||
| lazy_static::lazy_static! { |  | ||||||
|     static ref SERIES_MODULE: Module<SeriesTab> = eponymous_only_module::<SeriesTab>(1); |  | ||||||
| } | } | ||||||
|  |  | ||||||
| // Column numbers | // Column numbers | ||||||
|   | |||||||
| @@ -11,7 +11,7 @@ fn test_dummy_module() { | |||||||
|     use rusqlite::{version_number, Connection, Result}; |     use rusqlite::{version_number, Connection, Result}; | ||||||
|     use std::os::raw::c_int; |     use std::os::raw::c_int; | ||||||
|  |  | ||||||
|     let module = eponymous_only_module::<DummyTab>(1); |     let module = eponymous_only_module::<DummyTab>(); | ||||||
|  |  | ||||||
|     #[repr(C)] |     #[repr(C)] | ||||||
|     struct DummyTab { |     struct DummyTab { | ||||||
| @@ -19,7 +19,7 @@ fn test_dummy_module() { | |||||||
|         base: sqlite3_vtab, |         base: sqlite3_vtab, | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     impl VTab for DummyTab { |     unsafe impl VTab for DummyTab { | ||||||
|         type Aux = (); |         type Aux = (); | ||||||
|         type Cursor = DummyTabCursor; |         type Cursor = DummyTabCursor; | ||||||
|  |  | ||||||
| @@ -53,7 +53,7 @@ fn test_dummy_module() { | |||||||
|         row_id: i64, |         row_id: i64, | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     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