1 //! Ensure Virtual tables can be declared outside `rusqlite` crate.
2
3 #[cfg(feature = "vtab")]
4 #[test]
test_dummy_module() -> rusqlite::Result<()>5 fn test_dummy_module() -> rusqlite::Result<()> {
6 use rusqlite::vtab::{
7 eponymous_only_module, sqlite3_vtab, sqlite3_vtab_cursor, Context, IndexInfo, VTab,
8 VTabConnection, VTabCursor, Values,
9 };
10 use rusqlite::{version_number, Connection, Result};
11 use std::marker::PhantomData;
12 use std::os::raw::c_int;
13
14 let module = eponymous_only_module::<DummyTab>();
15
16 #[repr(C)]
17 struct DummyTab {
18 /// Base class. Must be first
19 base: sqlite3_vtab,
20 }
21
22 unsafe impl<'vtab> VTab<'vtab> for DummyTab {
23 type Aux = ();
24 type Cursor = DummyTabCursor<'vtab>;
25
26 fn connect(
27 _: &mut VTabConnection,
28 _aux: Option<&()>,
29 _args: &[&[u8]],
30 ) -> Result<(String, DummyTab)> {
31 let vtab = DummyTab {
32 base: sqlite3_vtab::default(),
33 };
34 Ok(("CREATE TABLE x(value)".to_owned(), vtab))
35 }
36
37 fn best_index(&self, info: &mut IndexInfo) -> Result<()> {
38 info.set_estimated_cost(1.);
39 Ok(())
40 }
41
42 fn open(&'vtab mut self) -> Result<DummyTabCursor<'vtab>> {
43 Ok(DummyTabCursor::default())
44 }
45 }
46
47 #[derive(Default)]
48 #[repr(C)]
49 struct DummyTabCursor<'vtab> {
50 /// Base class. Must be first
51 base: sqlite3_vtab_cursor,
52 /// The rowid
53 row_id: i64,
54 phantom: PhantomData<&'vtab DummyTab>,
55 }
56
57 unsafe impl VTabCursor for DummyTabCursor<'_> {
58 fn filter(
59 &mut self,
60 _idx_num: c_int,
61 _idx_str: Option<&str>,
62 _args: &Values<'_>,
63 ) -> Result<()> {
64 self.row_id = 1;
65 Ok(())
66 }
67
68 fn next(&mut self) -> Result<()> {
69 self.row_id += 1;
70 Ok(())
71 }
72
73 fn eof(&self) -> bool {
74 self.row_id > 1
75 }
76
77 fn column(&self, ctx: &mut Context, _: c_int) -> Result<()> {
78 ctx.set_result(&self.row_id)
79 }
80
81 fn rowid(&self) -> Result<i64> {
82 Ok(self.row_id)
83 }
84 }
85
86 let db = Connection::open_in_memory()?;
87
88 db.create_module::<DummyTab>("dummy", module, None)?;
89
90 let version = version_number();
91 if version < 3_009_000 {
92 return Ok(());
93 }
94
95 let mut s = db.prepare("SELECT * FROM dummy()")?;
96
97 let dummy = s.query_row([], |row| row.get::<_, i32>(0))?;
98 assert_eq!(1, dummy);
99 Ok(())
100 }
101