Fix non-eponymous virtual table declaration

Ensure that xCreate is different from xConnect for non-eponymous
virtual tables (even when the implementation is the same).
This commit is contained in:
gwenn 2018-05-05 10:33:05 +02:00
parent 30e23cf0a0
commit 702e58f744
4 changed files with 83 additions and 7 deletions

View File

@ -20,11 +20,11 @@ pub fn load_module(conn: &Connection) -> Result<()> {
init_module!(CSV_MODULE, init_module!(CSV_MODULE,
CSVTab, CSVTab,
CSVTabCursor, CSVTabCursor,
Some(csv_connect), csv_create,
csv_connect, csv_connect,
csv_best_index, csv_best_index,
csv_disconnect, csv_disconnect,
Some(csv_disconnect), csv_disconnect,
csv_open, csv_open,
csv_close, csv_close,
csv_filter, csv_filter,

View File

@ -37,7 +37,7 @@ pub fn drop_int_array(conn: &Connection, name: &str) -> Result<()> {
} }
init_module!(INT_ARRAY_MODULE, eponymous_module!(INT_ARRAY_MODULE,
IntArrayVTab, IntArrayVTab,
IntArrayVTabCursor, IntArrayVTabCursor,
Some(int_array_connect), Some(int_array_connect),

View File

@ -46,6 +46,11 @@ pub trait VTab<C: VTabCursor<Self>>: 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.
fn create(db: *mut ffi::sqlite3, aux: *mut c_void, args: &[&[u8]]) -> Result<Self> {
Self::connect(db, aux, args)
}
/// 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.
fn connect(db: *mut ffi::sqlite3, aux: *mut c_void, args: &[&[u8]]) -> Result<Self>; fn connect(db: *mut ffi::sqlite3, aux: *mut c_void, args: &[&[u8]]) -> Result<Self>;
/// Determine the best way to access the virtual table. /// Determine the best way to access the virtual table.
fn best_index(&self, info: &mut IndexInfo) -> Result<()>; fn best_index(&self, info: &mut IndexInfo) -> Result<()>;
@ -335,6 +340,54 @@ unsafe extern "C" fn free_boxed_value<T>(p: *mut c_void) {
#[macro_export] #[macro_export]
macro_rules! init_module { macro_rules! init_module {
($module_name: ident, $vtab: ident, $cursor: ty,
$create: ident, $connect: ident, $best_index: ident,
$disconnect: ident, $destroy: ident,
$open: ident, $close: ident,
$filter: ident, $next: ident, $eof: ident,
$column: ident, $rowid: ident) => {
static $module_name: ffi::sqlite3_module = ffi::sqlite3_module {
iVersion: 1,
xCreate: Some($create),
xConnect: Some($connect),
xBestIndex: Some($best_index),
xDisconnect: Some($disconnect),
xDestroy: Some($destroy),
xOpen: Some($open),
xClose: Some($close),
xFilter: Some($filter),
xNext: Some($next),
xEof: Some($eof),
xColumn: Some($column),
xRowid: Some($rowid),
xUpdate: None, // TODO
xBegin: None,
xSync: None,
xCommit: None,
xRollback: None,
xFindFunction: None,
xRename: None,
xSavepoint: None,
xRelease: None,
xRollbackTo: None,
};
// 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.
create_or_connect!($vtab, $create, create);
common_decl!($vtab, $cursor,
$connect, $best_index,
$disconnect, $destroy,
$open, $close,
$filter, $next, $eof,
$column, $rowid
);
}
} // init_module macro end
#[macro_export]
macro_rules! eponymous_module {
($module_name: ident, $vtab: ident, $cursor: ty, ($module_name: ident, $vtab: ident, $cursor: ty,
$create: expr, $connect: ident, $best_index: ident, $create: expr, $connect: ident, $best_index: ident,
$disconnect: ident, $destroy: expr, $disconnect: ident, $destroy: expr,
@ -369,7 +422,19 @@ static $module_name: ffi::sqlite3_module = ffi::sqlite3_module {
xRollbackTo: None, xRollbackTo: None,
}; };
unsafe extern "C" fn $connect(db: *mut ffi::sqlite3, common_decl!($vtab, $cursor,
$connect, $best_index,
$disconnect, $destroy,
$open, $close,
$filter, $next, $eof,
$column, $rowid
);
}
} // eponymous_module macro end
macro_rules! create_or_connect {
($vtab: ident, $create_or_connect: ident, $vtab_func: ident) => {
unsafe extern "C" fn $create_or_connect(db: *mut ffi::sqlite3,
aux: *mut c_void, aux: *mut c_void,
argc: c_int, argc: c_int,
argv: *const *const c_char, argv: *const *const c_char,
@ -384,7 +449,7 @@ unsafe extern "C" fn $connect(db: *mut ffi::sqlite3,
let vec = args.iter().map(|&cs| { let vec = args.iter().map(|&cs| {
CStr::from_ptr(cs).to_bytes() CStr::from_ptr(cs).to_bytes()
}).collect::<Vec<_>>(); }).collect::<Vec<_>>();
match $vtab::connect(db, aux, &vec[..]) { match $vtab::$vtab_func(db, aux, &vec[..]) {
Ok(vtab) => { Ok(vtab) => {
let boxed_vtab: *mut $vtab = Box::into_raw(Box::new(vtab)); let boxed_vtab: *mut $vtab = Box::into_raw(Box::new(vtab));
*pp_vtab = boxed_vtab as *mut ffi::sqlite3_vtab; *pp_vtab = boxed_vtab as *mut ffi::sqlite3_vtab;
@ -402,6 +467,17 @@ unsafe extern "C" fn $connect(db: *mut ffi::sqlite3,
} }
} }
} }
}
} // create_or_connect macro end
macro_rules! common_decl {
($vtab: ident, $cursor: ty,
$connect: ident, $best_index: ident,
$disconnect: ident, $destroy: expr,
$open: ident, $close: ident,
$filter: ident, $next: ident, $eof: ident,
$column: ident, $rowid: ident) => {
create_or_connect!($vtab, $connect, connect);
unsafe extern "C" fn $best_index(vtab: *mut ffi::sqlite3_vtab, unsafe extern "C" fn $best_index(vtab: *mut ffi::sqlite3_vtab,
info: *mut ffi::sqlite3_index_info) info: *mut ffi::sqlite3_index_info)
-> c_int { -> c_int {
@ -514,7 +590,7 @@ unsafe extern "C" fn $rowid(cursor: *mut ffi::sqlite3_vtab_cursor,
} }
} }
} }
} } // common_decl macro end
/// Virtual table cursors can set an error message by assigning a string to `zErrMsg`. /// Virtual table cursors can set an error message by assigning a string to `zErrMsg`.
pub unsafe fn cursor_error<T>(cursor: *mut ffi::sqlite3_vtab_cursor, pub unsafe fn cursor_error<T>(cursor: *mut ffi::sqlite3_vtab_cursor,

View File

@ -13,7 +13,7 @@ pub fn load_module(conn: &Connection) -> Result<()> {
conn.create_module("generate_series", &SERIES_MODULE, aux) conn.create_module("generate_series", &SERIES_MODULE, aux)
} }
init_module!(SERIES_MODULE, eponymous_module!(SERIES_MODULE,
SeriesTab, SeriesTab,
SeriesTabCursor, SeriesTabCursor,
None, None,