• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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