//! Ensure Virtual tables can be declared outside `rusqlite` crate. #[cfg(feature = "vtab")] #[test] fn test_dummy_module() -> rusqlite::Result<()> { use rusqlite::vtab::{ eponymous_only_module, sqlite3_vtab, sqlite3_vtab_cursor, Context, IndexInfo, VTab, VTabConnection, VTabCursor, Values, }; use rusqlite::{version_number, Connection, Result}; use std::marker::PhantomData; use std::os::raw::c_int; let module = eponymous_only_module::(); #[repr(C)] struct DummyTab { /// Base class. Must be first base: sqlite3_vtab, } unsafe impl<'vtab> VTab<'vtab> for DummyTab { type Aux = (); type Cursor = DummyTabCursor<'vtab>; fn connect( _: &mut VTabConnection, _aux: Option<&()>, _args: &[&[u8]], ) -> Result<(String, DummyTab)> { let vtab = DummyTab { base: sqlite3_vtab::default(), }; Ok(("CREATE TABLE x(value)".to_owned(), vtab)) } fn best_index(&self, info: &mut IndexInfo) -> Result<()> { info.set_estimated_cost(1.); Ok(()) } fn open(&'vtab self) -> Result> { Ok(DummyTabCursor::default()) } } #[derive(Default)] #[repr(C)] struct DummyTabCursor<'vtab> { /// Base class. Must be first base: sqlite3_vtab_cursor, /// The rowid row_id: i64, phantom: PhantomData<&'vtab DummyTab>, } unsafe impl VTabCursor for DummyTabCursor<'_> { 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 { Ok(self.row_id) } } let db = Connection::open_in_memory()?; db.create_module::("dummy", module, None)?; let version = version_number(); if version < 3_008_012 { return Ok(()); } let mut s = db.prepare("SELECT * FROM dummy()")?; let dummy = s.query_row([], |row| row.get::<_, i32>(0))?; assert_eq!(1, dummy); Ok(()) }