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