Refactoring

Introduce VTab::destroy.
Let implementation specify the iVersion.
Rename simple_module into read_only_module.
This commit is contained in:
gwenn 2018-07-16 20:17:53 +02:00
parent 849dbda5e8
commit 669663304e
5 changed files with 53 additions and 13 deletions

View File

@ -36,7 +36,7 @@ pub fn load_module(conn: &Connection) -> Result<()> {
} }
lazy_static! { lazy_static! {
static ref ARRAY_MODULE: Module<ArrayTab> = eponymous_only_module::<ArrayTab>(); static ref ARRAY_MODULE: Module<ArrayTab> = eponymous_only_module::<ArrayTab>(1);
} }
// Column numbers // Column numbers

View File

@ -11,8 +11,8 @@ use std::str;
use ffi; use ffi;
use types::Null; use types::Null;
use vtab::{ use vtab::{
dequote, escape_double_quote, parse_boolean, simple_module, Context, IndexInfo, Module, VTab, dequote, escape_double_quote, parse_boolean, read_only_module, Context, IndexInfo, Module,
VTabConnection, VTabCursor, Values, VTab, VTabConnection, VTabCursor, Values,
}; };
use {Connection, Error, Result}; use {Connection, Error, Result};
@ -33,7 +33,7 @@ pub fn load_module(conn: &Connection) -> Result<()> {
} }
lazy_static! { lazy_static! {
static ref CSV_MODULE: Module<CSVTab> = simple_module::<CSVTab>(); 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

View File

@ -70,16 +70,16 @@ unsafe impl<T: VTab> Sync for Module<T> {}
/// Create a read-only virtual table implementation. /// 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 simple_module<T: VTab>() -> Module<T> { pub fn read_only_module<T: VTab>(version: c_int) -> 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 { let ffi_module = ffi::sqlite3_module {
iVersion: 1, iVersion: version,
xCreate: Some(rust_create::<T>), xCreate: Some(rust_create::<T>),
xConnect: Some(rust_connect::<T>), xConnect: Some(rust_connect::<T>),
xBestIndex: Some(rust_best_index::<T>), xBestIndex: Some(rust_best_index::<T>),
xDisconnect: Some(rust_disconnect::<T>), xDisconnect: Some(rust_disconnect::<T>),
xDestroy: Some(rust_disconnect::<T>), // TODO Validate: no rust_destroy xDestroy: Some(rust_destroy::<T>),
xOpen: Some(rust_open::<T>), xOpen: Some(rust_open::<T>),
xClose: Some(rust_close::<T::Cursor>), xClose: Some(rust_close::<T::Cursor>),
xFilter: Some(rust_filter::<T::Cursor>), xFilter: Some(rust_filter::<T::Cursor>),
@ -107,11 +107,11 @@ pub fn simple_module<T: VTab>() -> Module<T> {
/// Create an eponymous only virtual table implementation. /// 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>() -> Module<T> { pub fn eponymous_only_module<T: VTab>(version: c_int) -> Module<T> {
// A virtual table is eponymous if its xCreate method is the exact same function as the xConnect method // 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 // For eponymous-only virtual tables, the xCreate method is NULL
let ffi_module = ffi::sqlite3_module { let ffi_module = ffi::sqlite3_module {
iVersion: 1, iVersion: version,
xCreate: None, xCreate: None,
xConnect: Some(rust_connect::<T>), xConnect: Some(rust_connect::<T>),
xBestIndex: Some(rust_best_index::<T>), xBestIndex: Some(rust_best_index::<T>),
@ -177,6 +177,8 @@ pub trait VTab: Sized {
/// Create a new instance of a virtual table in response to a CREATE VIRTUAL TABLE statement. /// 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 `db` parameter is a pointer to the SQLite database connection that is executing
/// the CREATE VIRTUAL TABLE statement. /// the CREATE VIRTUAL TABLE statement.
///
/// Unused by eponymous virtual table. Call `connect` by default.
/// (See [SQLite doc](https://sqlite.org/vtab.html#the_xcreate_method)) /// (See [SQLite doc](https://sqlite.org/vtab.html#the_xcreate_method))
fn create( fn create(
db: &mut VTabConnection, db: &mut VTabConnection,
@ -186,10 +188,17 @@ pub trait VTab: Sized {
Self::connect(db, aux, args) Self::connect(db, aux, args)
} }
// TODO Validate: no destroy /// Destroy the underlying table implementation. This method undoes the work of `create`.
///
/// Unused by eponymous virtual table. Do nothing by default.
/// (See [SQLite doc](https://sqlite.org/vtab.html#the_xdestroy_method))
fn destroy(&self) -> Result<()> {
Ok(())
}
/// Similar to `create`. The difference is that `connect` is called to establish a new connection /// Similar to `create`. The difference is that `connect` is called to establish a new connection
/// to an _existing_ virtual table whereas `create` is called to create a new virtual table from scratch. /// to an _existing_ virtual table whereas `create` is called to create a new virtual table from scratch.
///
/// (See [SQLite doc](https://sqlite.org/vtab.html#the_xconnect_method)) /// (See [SQLite doc](https://sqlite.org/vtab.html#the_xconnect_method))
fn connect( fn connect(
db: &mut VTabConnection, db: &mut VTabConnection,
@ -717,11 +726,41 @@ unsafe extern "C" fn rust_disconnect<T>(vtab: *mut ffi::sqlite3_vtab) -> c_int
where where
T: VTab, T: VTab,
{ {
if vtab.is_null() {
return ffi::SQLITE_OK;
}
let vtab = vtab as *mut T; let vtab = vtab as *mut T;
let _: Box<T> = Box::from_raw(vtab); let _: Box<T> = Box::from_raw(vtab);
ffi::SQLITE_OK ffi::SQLITE_OK
} }
unsafe extern "C" fn rust_destroy<T>(vtab: *mut ffi::sqlite3_vtab) -> c_int
where
T: VTab,
{
use std::error::Error as StdError;
if vtab.is_null() {
return ffi::SQLITE_OK;
}
let vt = vtab as *mut T;
match (*vt).destroy() {
Ok(_) => {
let _: Box<T> = Box::from_raw(vt);
ffi::SQLITE_OK
}
Err(Error::SqliteFailure(err, s)) => {
if let Some(err_msg) = s {
set_err_msg(vtab, &err_msg);
}
err.extended_code
}
Err(err) => {
set_err_msg(vtab, err.description());
ffi::SQLITE_ERROR
}
}
}
unsafe extern "C" fn rust_open<T>( unsafe extern "C" fn rust_open<T>(
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,

View File

@ -19,7 +19,7 @@ pub fn load_module(conn: &Connection) -> Result<()> {
} }
lazy_static! { lazy_static! {
static ref SERIES_MODULE: Module<SeriesTab> = eponymous_only_module::<SeriesTab>(); static ref SERIES_MODULE: Module<SeriesTab> = eponymous_only_module::<SeriesTab>(1);
} }
// Column numbers // Column numbers

View File

@ -7,12 +7,13 @@ extern crate rusqlite;
#[test] #[test]
fn test_dummy_module() { fn test_dummy_module() {
use rusqlite::vtab::{ use rusqlite::vtab::{
eponymous_only_module, sqlite3_vtab, sqlite3_vtab_cursor, Context, IndexInfo, VTab, VTabConnection, VTabCursor, Values, eponymous_only_module, sqlite3_vtab, sqlite3_vtab_cursor, Context, IndexInfo, VTab,
VTabConnection, VTabCursor, Values,
}; };
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>(); let module = eponymous_only_module::<DummyTab>(1);
#[repr(C)] #[repr(C)]
struct DummyTab { struct DummyTab {