mirror of
https://github.com/isar/rusqlite.git
synced 2025-08-19 12:29:34 +08:00
Ensure Virtual tables can be declared outside rusqlite
crate
Not sure it is the way to go.
This commit is contained in:
127
tests/vtab.rs
Normal file
127
tests/vtab.rs
Normal file
@@ -0,0 +1,127 @@
|
||||
//! Ensure Virtual tables can be declared outside `rusqlite` crate.
|
||||
|
||||
#[cfg(feature = "vtab")]
|
||||
#[macro_use]
|
||||
extern crate rusqlite;
|
||||
extern crate libsqlite3_sys as ffi;
|
||||
|
||||
#[cfg(feature = "vtab")]
|
||||
#[test]
|
||||
fn test_dummy_module() {
|
||||
use ffi;
|
||||
use rusqlite::vtab::{Context, IndexInfo, Module, VTab, VTabConnection, VTabCursor, Values};
|
||||
use rusqlite::{error_from_sqlite_code, Connection, Error, Result};
|
||||
use std::os::raw::{c_char, c_int, c_void};
|
||||
|
||||
eponymous_module!(
|
||||
DUMMY_MODULE,
|
||||
DummyModule,
|
||||
DummyTab,
|
||||
(),
|
||||
DummyTabCursor,
|
||||
None,
|
||||
dummy_connect,
|
||||
dummy_best_index,
|
||||
dummy_disconnect,
|
||||
None,
|
||||
dummy_open,
|
||||
dummy_close,
|
||||
dummy_filter,
|
||||
dummy_next,
|
||||
dummy_eof,
|
||||
dummy_column,
|
||||
dummy_rowid
|
||||
);
|
||||
|
||||
#[repr(C)]
|
||||
struct DummyModule(&'static ffi::sqlite3_module);
|
||||
|
||||
impl Module for DummyModule {
|
||||
type Aux = ();
|
||||
type Table = DummyTab;
|
||||
|
||||
fn as_ptr(&self) -> *const ffi::sqlite3_module {
|
||||
self.0
|
||||
}
|
||||
|
||||
fn connect(
|
||||
_: &mut VTabConnection,
|
||||
_aux: Option<&()>,
|
||||
_args: &[&[u8]],
|
||||
) -> Result<(String, DummyTab)> {
|
||||
let vtab = DummyTab {
|
||||
base: ffi::sqlite3_vtab::default(),
|
||||
};
|
||||
Ok(("CREATE TABLE x(value)".to_owned(), vtab))
|
||||
}
|
||||
}
|
||||
|
||||
#[repr(C)]
|
||||
struct DummyTab {
|
||||
/// Base class. Must be first
|
||||
base: ffi::sqlite3_vtab,
|
||||
}
|
||||
|
||||
impl VTab for DummyTab {
|
||||
type Cursor = DummyTabCursor;
|
||||
|
||||
fn best_index(&self, info: &mut IndexInfo) -> Result<()> {
|
||||
info.set_estimated_cost(1.);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn open(&self) -> Result<DummyTabCursor> {
|
||||
Ok(DummyTabCursor::default())
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Default)]
|
||||
#[repr(C)]
|
||||
struct DummyTabCursor {
|
||||
/// Base class. Must be first
|
||||
base: ffi::sqlite3_vtab_cursor,
|
||||
/// The rowid
|
||||
row_id: i64,
|
||||
}
|
||||
|
||||
impl VTabCursor for DummyTabCursor {
|
||||
type Table = DummyTab;
|
||||
|
||||
fn vtab(&self) -> &DummyTab {
|
||||
unsafe { &*(self.base.pVtab as *const DummyTab) }
|
||||
}
|
||||
fn filter(
|
||||
&mut self,
|
||||
_idx_num: c_int,
|
||||
_idx_str: Option<&str>,
|
||||
_args: &Values,
|
||||
) -> Result<()> {
|
||||
self.row_id = 1;
|
||||
Ok(())
|
||||
}
|
||||
fn next(&mut self) -> Result<()> {
|
||||
self.row_id += 1;
|
||||
Ok(())
|
||||
}
|
||||
fn eof(&self) -> bool {
|
||||
self.row_id > 1
|
||||
}
|
||||
fn column(&self, ctx: &mut Context, _: c_int) -> Result<()> {
|
||||
ctx.set_result(&self.row_id)
|
||||
}
|
||||
fn rowid(&self) -> Result<i64> {
|
||||
Ok(self.row_id)
|
||||
}
|
||||
}
|
||||
|
||||
let db = Connection::open_in_memory().unwrap();
|
||||
|
||||
let module = DummyModule(&DUMMY_MODULE);
|
||||
|
||||
db.create_module("dummy", module, None).unwrap();
|
||||
|
||||
let mut s = db.prepare("SELECT * FROM dummy()").unwrap();
|
||||
|
||||
let dummy = s.query_row(&[], |row| row.get::<_, i32>(0)).unwrap();
|
||||
assert_eq!(1, dummy);
|
||||
}
|
Reference in New Issue
Block a user