mirror of
https://github.com/isar/rusqlite.git
synced 2024-11-25 02:21:37 +08:00
Fix vtab::Module lifetime
This commit is contained in:
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,
|
||||||
|
Loading…
Reference in New Issue
Block a user