2018-07-14 17:01:19 +08:00
|
|
|
//! Ensure Virtual tables can be declared outside `rusqlite` crate.
|
|
|
|
|
|
|
|
#[cfg(feature = "vtab")]
|
|
|
|
extern crate rusqlite;
|
|
|
|
|
|
|
|
#[cfg(feature = "vtab")]
|
|
|
|
#[test]
|
|
|
|
fn test_dummy_module() {
|
2018-07-15 01:21:03 +08:00
|
|
|
use rusqlite::vtab::{
|
2018-07-17 02:17:53 +08:00
|
|
|
eponymous_only_module, sqlite3_vtab, sqlite3_vtab_cursor, Context, IndexInfo, VTab,
|
|
|
|
VTabConnection, VTabCursor, Values,
|
2018-07-15 01:21:03 +08:00
|
|
|
};
|
2018-07-15 22:15:55 +08:00
|
|
|
use rusqlite::{version_number, Connection, Result};
|
2018-07-15 00:47:52 +08:00
|
|
|
use std::os::raw::c_int;
|
|
|
|
|
2018-07-17 02:17:53 +08:00
|
|
|
let module = eponymous_only_module::<DummyTab>(1);
|
2018-07-14 17:01:19 +08:00
|
|
|
|
|
|
|
#[repr(C)]
|
2018-07-15 00:47:52 +08:00
|
|
|
struct DummyTab {
|
|
|
|
/// Base class. Must be first
|
2018-07-15 22:15:55 +08:00
|
|
|
base: sqlite3_vtab,
|
2018-07-15 00:47:52 +08:00
|
|
|
}
|
2018-07-14 17:01:19 +08:00
|
|
|
|
2018-07-15 00:47:52 +08:00
|
|
|
impl VTab for DummyTab {
|
2018-07-14 17:01:19 +08:00
|
|
|
type Aux = ();
|
2018-07-15 00:47:52 +08:00
|
|
|
type Cursor = DummyTabCursor;
|
2018-07-14 17:01:19 +08:00
|
|
|
|
|
|
|
fn connect(
|
|
|
|
_: &mut VTabConnection,
|
|
|
|
_aux: Option<&()>,
|
|
|
|
_args: &[&[u8]],
|
|
|
|
) -> Result<(String, DummyTab)> {
|
|
|
|
let vtab = DummyTab {
|
2018-07-15 22:15:55 +08:00
|
|
|
base: sqlite3_vtab::default(),
|
2018-07-14 17:01:19 +08:00
|
|
|
};
|
|
|
|
Ok(("CREATE TABLE x(value)".to_owned(), vtab))
|
|
|
|
}
|
|
|
|
|
|
|
|
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
|
2018-07-15 22:15:55 +08:00
|
|
|
base: sqlite3_vtab_cursor,
|
2018-07-14 17:01:19 +08:00
|
|
|
/// The rowid
|
|
|
|
row_id: i64,
|
|
|
|
}
|
|
|
|
|
|
|
|
impl VTabCursor for DummyTabCursor {
|
|
|
|
type Table = 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();
|
|
|
|
|
2018-07-15 01:21:03 +08:00
|
|
|
db.create_module::<DummyTab>("dummy", &module, None)
|
|
|
|
.unwrap();
|
2018-07-14 17:01:19 +08:00
|
|
|
|
2018-07-15 22:15:55 +08:00
|
|
|
let version = version_number();
|
2018-07-14 17:28:43 +08:00
|
|
|
if version < 3008012 {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2018-07-14 17:01:19 +08:00
|
|
|
let mut s = db.prepare("SELECT * FROM dummy()").unwrap();
|
|
|
|
|
|
|
|
let dummy = s.query_row(&[], |row| row.get::<_, i32>(0)).unwrap();
|
|
|
|
assert_eq!(1, dummy);
|
|
|
|
}
|