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