mirror of
https://github.com/isar/rusqlite.git
synced 2024-11-26 19:41:37 +08:00
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:
parent
30e23cf0a0
commit
702e58f744
@ -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,
|
||||||
|
@ -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),
|
||||||
|
@ -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,
|
||||||
|
@ -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,
|
||||||
|
Loading…
Reference in New Issue
Block a user