Skip to main content

rusqlite/vtab/
mod.rs

1//! Create virtual tables.
2//!
3//! Follow these steps to create your own virtual table:
4//! 1. Write implementation of [`VTab`] and [`VTabCursor`] traits.
5//! 2. Create an instance of the [`Module`] structure specialized for [`VTab`]
6//!    impl. from step 1.
7//! 3. Register your [`Module`] structure using [`Connection::create_module`].
8//! 4. Run a `CREATE VIRTUAL TABLE` command that specifies the new module in the
9//!    `USING` clause.
10//!
11//! (See [SQLite doc](http://sqlite.org/vtab.html))
12use std::borrow::Cow::{self, Borrowed, Owned};
13use std::ffi::{CStr, c_char, c_int, c_uint, c_void};
14use std::marker::PhantomData;
15use std::ops::Deref;
16use std::ptr;
17use std::slice;
18
19use crate::ffi::{sqlite3_context, sqlite3_free, sqlite3_value};
20
21use crate::context::set_result;
22use crate::error::{check, error_from_sqlite_code, to_sqlite_error};
23use crate::ffi;
24pub use crate::ffi::{sqlite3_vtab, sqlite3_vtab_cursor};
25use crate::types::{FromSql, FromSqlError, ToSql, ValueRef};
26use crate::util::{alloc, free_boxed_value, from_raw_parts, from_raw_parts_mut};
27use crate::{Connection, Error, InnerConnection, Name, Result, str_to_cstring};
28
29// let conn: Connection = ...;
30// let mod: Module = ...; // VTab builder
31// conn.create_module("module", mod);
32//
33// conn.execute("CREATE VIRTUAL TABLE foo USING module(...)");
34// \-> Module::xcreate
35//  |-> let vtab: VTab = ...; // on the heap
36//  \-> conn.declare_vtab("CREATE TABLE foo (...)");
37// conn = Connection::open(...);
38// \-> Module::xconnect
39//  |-> let vtab: VTab = ...; // on the heap
40//  \-> conn.declare_vtab("CREATE TABLE foo (...)");
41//
42// conn.close();
43// \-> vtab.xdisconnect
44// conn.execute("DROP TABLE foo");
45// \-> vtab.xDestroy
46//
47// let stmt = conn.prepare("SELECT ... FROM foo WHERE ...");
48// \-> vtab.xbestindex
49// stmt.query().next();
50// \-> vtab.xopen
51//  |-> let cursor: VTabCursor = ...; // on the heap
52//  |-> cursor.xfilter or xnext
53//  |-> cursor.xeof
54//  \-> if not eof { cursor.column or xrowid } else { cursor.xclose }
55//
56
57// db: *mut ffi::sqlite3 => VTabConnection
58// module: *const ffi::sqlite3_module => Module
59// aux: *mut c_void => Module::Aux
60// ffi::sqlite3_vtab => VTab
61// ffi::sqlite3_vtab_cursor => VTabCursor
62
63/// Virtual table kind
64pub enum VTabKind {
65    /// Non-eponymous
66    Default,
67    /// [`create`](CreateVTab::create) == [`connect`](VTab::connect)
68    ///
69    /// See [SQLite doc](https://sqlite.org/vtab.html#eponymous_virtual_tables)
70    Eponymous,
71    /// No [`create`](CreateVTab::create) / [`destroy`](CreateVTab::destroy) or
72    /// not used
73    ///
74    /// SQLite >= 3.9.0
75    ///
76    /// See [SQLite doc](https://sqlite.org/vtab.html#eponymous_only_virtual_tables)
77    EponymousOnly,
78}
79
80/// Virtual table module
81///
82/// (See [SQLite doc](https://sqlite.org/c3ref/module.html))
83#[repr(transparent)]
84pub struct Module<'vtab, T: VTab<'vtab>> {
85    base: ffi::sqlite3_module,
86    phantom: PhantomData<&'vtab T>,
87}
88
89union ModuleZeroHack {
90    bytes: [u8; size_of::<ffi::sqlite3_module>()],
91    module: ffi::sqlite3_module,
92}
93
94// Used as a trailing initializer for sqlite3_module -- this way we avoid having
95// the build fail if buildtime_bindgen is on. This is safe, as bindgen-generated
96// structs are allowed to be zeroed.
97const ZERO_MODULE: ffi::sqlite3_module = unsafe {
98    ModuleZeroHack {
99        bytes: [0_u8; size_of::<ffi::sqlite3_module>()],
100    }
101    .module
102};
103
104impl<'vtab, T: VTab<'vtab>> Module<'vtab, T> {
105    /// Create an eponymous only virtual table implementation.
106    ///
107    /// Step 2 of [Creating New Virtual Table Implementations](https://sqlite.org/vtab.html#creating_new_virtual_table_implementations).
108    #[must_use]
109    pub const fn eponymous_only_module() -> Self {
110        //  For eponymous-only virtual tables, the xCreate method is NULL
111        Module {
112            base: ffi::sqlite3_module {
113                // We don't use methods provided by versions > 1
114                iVersion: 1,
115                xCreate: None,
116                xConnect: Some(rust_connect::<T>),
117                xBestIndex: Some(rust_best_index::<T>),
118                xDisconnect: Some(rust_disconnect::<T>),
119                xDestroy: None,
120                xOpen: Some(rust_open::<T>),
121                xClose: Some(rust_close::<T::Cursor>),
122                xFilter: Some(rust_filter::<T::Cursor>),
123                xNext: Some(rust_next::<T::Cursor>),
124                xEof: Some(rust_eof::<T::Cursor>),
125                xColumn: Some(rust_column::<T::Cursor>),
126                xRowid: Some(rust_rowid::<T::Cursor>),
127                xUpdate: None,
128                xBegin: None,
129                xSync: None,
130                xCommit: None,
131                xRollback: None,
132                xFindFunction: None,
133                xRename: None,
134                ..ZERO_MODULE
135            },
136            phantom: PhantomData::<&'vtab T>,
137        }
138    }
139
140    /// Create a read-only virtual table implementation.
141    ///
142    /// Step 2 of [Creating New Virtual Table Implementations](https://sqlite.org/vtab.html#creating_new_virtual_table_implementations).
143    #[must_use]
144    pub const fn read_only_module() -> Self
145    where
146        T: CreateVTab<'vtab>,
147    {
148        let mut module = Self::eponymous_only_module();
149        match T::KIND {
150            VTabKind::EponymousOnly => module,
151            VTabKind::Eponymous => {
152                // A virtual table is eponymous if its xCreate method is the exact same function
153                // as the xConnect method
154                module.base.xCreate = module.base.xConnect;
155                module.base.xDestroy = module.base.xDisconnect;
156                module
157            }
158            _ => {
159                // The xConnect and xCreate methods may do the same thing, but they must be
160                // different so that the virtual table is not an eponymous virtual table.
161                module.base.xCreate = Some(rust_create::<T>);
162                module.base.xDestroy = Some(rust_destroy::<T>);
163                module
164            }
165        }
166    }
167
168    /// Create a modifiable virtual table implementation.
169    ///
170    /// Step 2 of [Creating New Virtual Table Implementations](https://sqlite.org/vtab.html#creating_new_virtual_table_implementations).
171    #[must_use]
172    pub const fn update_module() -> Self
173    where
174        T: UpdateVTab<'vtab>,
175    {
176        let mut module = Self::read_only_module();
177        module.base.xUpdate = Some(rust_update::<T>);
178        module
179    }
180
181    /// Create a modifiable virtual table implementation with support for transactions.
182    ///
183    /// Step 2 of [Creating New Virtual Table Implementations](https://sqlite.org/vtab.html#creating_new_virtual_table_implementations).
184    #[must_use]
185    pub const fn update_module_with_tx() -> Self
186    where
187        T: TransactionVTab<'vtab>,
188    {
189        let mut module = Self::update_module();
190        module.base.xBegin = Some(rust_begin::<T>);
191        module.base.xSync = Some(rust_sync::<T>);
192        module.base.xCommit = Some(rust_commit::<T>);
193        module.base.xRollback = Some(rust_rollback::<T>);
194        module
195    }
196
197    /// No `xRowid`
198    #[must_use]
199    pub const fn without_rowid(mut self) -> Self {
200        self.base.xRowid = None;
201        self
202    }
203
204    /// No `xSync`
205    #[must_use]
206    pub const fn without_sync(mut self) -> Self
207    where
208        T: TransactionVTab<'vtab>,
209    {
210        self.base.xSync = None;
211        self
212    }
213}
214
215/// Virtual table configuration options
216#[repr(i32)]
217#[non_exhaustive]
218#[derive(Debug, Clone, Copy, Eq, PartialEq)]
219pub enum VTabConfig {
220    /// Equivalent to `SQLITE_VTAB_CONSTRAINT_SUPPORT`
221    ConstraintSupport = 1,
222    /// Equivalent to `SQLITE_VTAB_INNOCUOUS`
223    Innocuous = 2,
224    /// Equivalent to `SQLITE_VTAB_DIRECTONLY`
225    DirectOnly = 3,
226    /// Equivalent to `SQLITE_VTAB_USES_ALL_SCHEMAS`
227    UsesAllSchemas = 4,
228}
229
230/// `feature = "vtab"`
231pub struct VTabConnection(*mut ffi::sqlite3);
232
233impl VTabConnection {
234    /// Configure various facets of the virtual table interface
235    pub fn config(&mut self, config: VTabConfig) -> Result<()> {
236        check(unsafe { ffi::sqlite3_vtab_config(self.0, config as c_int) })
237    }
238
239    /// Get access to the underlying SQLite database connection handle.
240    ///
241    /// # Warning
242    ///
243    /// You should not need to use this function. If you do need to, please
244    /// [open an issue on the rusqlite repository](https://github.com/rusqlite/rusqlite/issues) and describe
245    /// your use case.
246    ///
247    /// # Safety
248    ///
249    /// This function is unsafe because it gives you raw access
250    /// to the SQLite connection, and what you do with it could impact the
251    /// safety of this `Connection`.
252    pub unsafe fn handle(&mut self) -> *mut ffi::sqlite3 {
253        self.0
254    }
255}
256
257/// Eponymous-only virtual table instance trait.
258///
259/// # Safety
260///
261/// The first item in a struct implementing `VTab` must be
262/// `rusqlite::sqlite3_vtab`, and the struct must be `#[repr(C)]`.
263///
264/// ```rust,ignore
265/// #[repr(C)]
266/// struct MyTab {
267///    /// Base class. Must be first
268///    base: rusqlite::vtab::sqlite3_vtab,
269///    /* Virtual table implementations will typically add additional fields */
270/// }
271/// ```
272///
273/// (See [SQLite doc](https://sqlite.org/c3ref/vtab.html))
274pub unsafe trait VTab<'vtab>: Sized {
275    /// Client data passed to [`Connection::create_module`].
276    type Aux: Send + Sync + 'static;
277    /// Specific cursor implementation
278    type Cursor: VTabCursor;
279
280    /// Establish a new connection to an existing virtual table.
281    ///
282    /// (See [SQLite doc](https://sqlite.org/vtab.html#the_xconnect_method))
283    fn connect(
284        db: &mut VTabConnection,
285        aux: Option<&Self::Aux>,
286        module_name: &[u8],
287        database_name: &[u8],
288        table_name: &[u8],
289        args: &[&[u8]],
290    ) -> Result<(Cow<'static, CStr>, Self)>;
291
292    /// Determine the best way to access the virtual table.
293    /// (See [SQLite doc](https://sqlite.org/vtab.html#the_xbestindex_method))
294    /// Returning `Ok(false)` means unusable / `SQLITE_CONSTRAINT`.
295    fn best_index(&self, info: &mut IndexInfo) -> Result<bool>;
296
297    /// Create a new cursor used for accessing a virtual table.
298    /// (See [SQLite doc](https://sqlite.org/vtab.html#the_xopen_method))
299    fn open(&'vtab mut self) -> Result<Self::Cursor>;
300}
301
302/// Read-only virtual table instance trait.
303///
304/// (See [SQLite doc](https://sqlite.org/c3ref/vtab.html))
305pub trait CreateVTab<'vtab>: VTab<'vtab> {
306    /// For [`EponymousOnly`](VTabKind::EponymousOnly),
307    /// [`create`](CreateVTab::create) and [`destroy`](CreateVTab::destroy) are
308    /// not called
309    const KIND: VTabKind;
310    /// Create a new instance of a virtual table in response to a CREATE VIRTUAL
311    /// TABLE statement. The `db` parameter is a pointer to the SQLite
312    /// database connection that is executing the CREATE VIRTUAL TABLE
313    /// statement.
314    ///
315    /// Call [`connect`](VTab::connect) by default.
316    /// (See [SQLite doc](https://sqlite.org/vtab.html#the_xcreate_method))
317    fn create(
318        db: &mut VTabConnection,
319        aux: Option<&Self::Aux>,
320        module_name: &[u8],
321        database_name: &[u8],
322        table_name: &[u8],
323        args: &[&[u8]],
324    ) -> Result<(Cow<'static, CStr>, Self)> {
325        Self::connect(db, aux, module_name, database_name, table_name, args)
326    }
327
328    /// Destroy the underlying table implementation. This method undoes the work
329    /// of [`create`](CreateVTab::create).
330    ///
331    /// Do nothing by default.
332    /// (See [SQLite doc](https://sqlite.org/vtab.html#the_xdestroy_method))
333    fn destroy(&self) -> Result<()> {
334        Ok(())
335    }
336}
337
338/// Writable virtual table instance trait.
339///
340/// (See [SQLite doc](https://sqlite.org/vtab.html#xupdate))
341pub trait UpdateVTab<'vtab>: CreateVTab<'vtab> {
342    /// Delete rowid or PK
343    fn delete(&mut self, arg: ValueRef<'_>) -> Result<()>;
344    /// Insert: `args[0] == NULL: old rowid or PK, args[1]: new rowid or PK,
345    /// args[2]: ...`
346    ///
347    /// Return the new rowid.
348    // TODO Make the distinction between argv[1] == NULL and argv[1] != NULL ?
349    fn insert(&mut self, args: &Inserts<'_>) -> Result<i64>;
350    /// Update: `args[0] != NULL: old rowid or PK, args[1]: new row id or PK,
351    /// args[2]: ...`
352    fn update(&mut self, args: &Updates<'_>) -> Result<()>;
353}
354
355/// Writable virtual table instance with transaction support trait.
356///
357/// See [SQLite doc](https://sqlite.org/vtab.html#the_xbegin_method)
358pub trait TransactionVTab<'vtab>: UpdateVTab<'vtab> {
359    /// Start a new transaction
360    fn begin(&mut self) -> Result<()> {
361        Ok(())
362    }
363    /// Begin two-phase commit
364    fn sync(&mut self) -> Result<()> {
365        Ok(())
366    }
367    /// Commit the current transaction
368    fn commit(&mut self) -> Result<()> {
369        Ok(())
370    }
371    /// Abandon the current transaction
372    fn rollback(&mut self) -> Result<()> {
373        Ok(())
374    }
375}
376
377/// Index constraint operator.
378/// See [Virtual Table Constraint Operator Codes](https://sqlite.org/c3ref/c_index_constraint_eq.html) for details.
379#[derive(Debug, Eq, PartialEq)]
380#[allow(missing_docs)]
381#[expect(non_camel_case_types)]
382pub enum IndexConstraintOp {
383    SQLITE_INDEX_CONSTRAINT_EQ,
384    SQLITE_INDEX_CONSTRAINT_GT,
385    SQLITE_INDEX_CONSTRAINT_LE,
386    SQLITE_INDEX_CONSTRAINT_LT,
387    SQLITE_INDEX_CONSTRAINT_GE,
388    SQLITE_INDEX_CONSTRAINT_MATCH,
389    SQLITE_INDEX_CONSTRAINT_LIKE,         // 3.10.0
390    SQLITE_INDEX_CONSTRAINT_GLOB,         // 3.10.0
391    SQLITE_INDEX_CONSTRAINT_REGEXP,       // 3.10.0
392    SQLITE_INDEX_CONSTRAINT_NE,           // 3.21.0
393    SQLITE_INDEX_CONSTRAINT_ISNOT,        // 3.21.0
394    SQLITE_INDEX_CONSTRAINT_ISNOTNULL,    // 3.21.0
395    SQLITE_INDEX_CONSTRAINT_ISNULL,       // 3.21.0
396    SQLITE_INDEX_CONSTRAINT_IS,           // 3.21.0
397    SQLITE_INDEX_CONSTRAINT_LIMIT,        // 3.38.0
398    SQLITE_INDEX_CONSTRAINT_OFFSET,       // 3.38.0
399    SQLITE_INDEX_CONSTRAINT_FUNCTION(u8), // 3.25.0
400}
401
402impl From<u8> for IndexConstraintOp {
403    fn from(code: u8) -> Self {
404        match code {
405            2 => Self::SQLITE_INDEX_CONSTRAINT_EQ,
406            4 => Self::SQLITE_INDEX_CONSTRAINT_GT,
407            8 => Self::SQLITE_INDEX_CONSTRAINT_LE,
408            16 => Self::SQLITE_INDEX_CONSTRAINT_LT,
409            32 => Self::SQLITE_INDEX_CONSTRAINT_GE,
410            64 => Self::SQLITE_INDEX_CONSTRAINT_MATCH,
411            65 => Self::SQLITE_INDEX_CONSTRAINT_LIKE,
412            66 => Self::SQLITE_INDEX_CONSTRAINT_GLOB,
413            67 => Self::SQLITE_INDEX_CONSTRAINT_REGEXP,
414            68 => Self::SQLITE_INDEX_CONSTRAINT_NE,
415            69 => Self::SQLITE_INDEX_CONSTRAINT_ISNOT,
416            70 => Self::SQLITE_INDEX_CONSTRAINT_ISNOTNULL,
417            71 => Self::SQLITE_INDEX_CONSTRAINT_ISNULL,
418            72 => Self::SQLITE_INDEX_CONSTRAINT_IS,
419            73 => Self::SQLITE_INDEX_CONSTRAINT_LIMIT,
420            74 => Self::SQLITE_INDEX_CONSTRAINT_OFFSET,
421            v => Self::SQLITE_INDEX_CONSTRAINT_FUNCTION(v),
422        }
423    }
424}
425
426bitflags::bitflags! {
427    /// Virtual table scan flags
428    /// See [Function Flags](https://sqlite.org/c3ref/c_index_scan_unique.html) for details.
429    #[repr(C)]
430    #[derive(Copy, Clone, Debug)]
431    pub struct IndexFlags: c_int {
432        /// Default
433        const NONE     = 0;
434        /// Scan visits at most 1 row.
435        const SQLITE_INDEX_SCAN_UNIQUE  = ffi::SQLITE_INDEX_SCAN_UNIQUE;
436        /// Display idxNum as hex in EXPLAIN QUERY PLAN
437        const SQLITE_INDEX_SCAN_HEX  = 0x0000_0002; // 3.47.0
438    }
439}
440
441/// Pass information into and receive the reply from the
442/// [`VTab::best_index`] method.
443///
444/// (See [SQLite doc](http://sqlite.org/c3ref/index_info.html))
445#[derive(Debug)]
446pub struct IndexInfo(*mut ffi::sqlite3_index_info);
447
448impl IndexInfo {
449    /// Iterate on index constraint and its associated usage.
450    #[inline]
451    pub fn constraints_and_usages(&mut self) -> IndexConstraintAndUsageIter<'_> {
452        let constraints = unsafe { from_raw_parts((*self.0).aConstraint, (*self.0).nConstraint) };
453        let constraint_usages =
454            unsafe { from_raw_parts_mut((*self.0).aConstraintUsage, (*self.0).nConstraint) };
455        IndexConstraintAndUsageIter {
456            iter: constraints.iter().zip(constraint_usages.iter_mut()),
457        }
458    }
459
460    /// Record WHERE clause constraints.
461    #[inline]
462    #[must_use]
463    pub fn constraints(&self) -> IndexConstraintIter<'_> {
464        let constraints = unsafe { from_raw_parts((*self.0).aConstraint, (*self.0).nConstraint) };
465        IndexConstraintIter {
466            iter: constraints.iter(),
467        }
468    }
469
470    /// Information about the ORDER BY clause.
471    #[inline]
472    #[must_use]
473    pub fn order_bys(&self) -> OrderByIter<'_> {
474        let order_bys = unsafe { from_raw_parts((*self.0).aOrderBy, (*self.0).nOrderBy) };
475        OrderByIter {
476            iter: order_bys.iter(),
477        }
478    }
479
480    /// Number of terms in the ORDER BY clause
481    #[inline]
482    #[must_use]
483    pub fn num_of_order_by(&self) -> usize {
484        unsafe { (*self.0).nOrderBy as usize }
485    }
486
487    /// Information about what parameters to pass to [`VTabCursor::filter`].
488    #[inline]
489    pub fn constraint_usage(&mut self, constraint_idx: usize) -> IndexConstraintUsage<'_> {
490        let constraint_usages =
491            unsafe { from_raw_parts_mut((*self.0).aConstraintUsage, (*self.0).nConstraint) };
492        IndexConstraintUsage(&mut constraint_usages[constraint_idx])
493    }
494
495    /// Number used to identify the index
496    #[inline]
497    pub fn set_idx_num(&mut self, idx_num: c_int) {
498        unsafe {
499            (*self.0).idxNum = idx_num;
500        }
501    }
502
503    /// String used to identify the index
504    pub fn set_idx_str(&mut self, idx_str: &str) {
505        unsafe {
506            if (*self.0).needToFreeIdxStr == 1 {
507                sqlite3_free((*self.0).idxStr.cast());
508            }
509            (*self.0).idxStr = alloc(idx_str);
510            (*self.0).needToFreeIdxStr = 1;
511        }
512    }
513
514    /// String used to identify the index
515    pub fn set_idx_cstr(&mut self, idx_str: &'static CStr) {
516        unsafe {
517            if (*self.0).needToFreeIdxStr == 1 {
518                sqlite3_free((*self.0).idxStr.cast());
519            }
520            (*self.0).idxStr = idx_str.as_ptr().cast_mut();
521            (*self.0).needToFreeIdxStr = 0;
522        }
523    }
524
525    /// True if output is already ordered
526    #[inline]
527    pub fn set_order_by_consumed(&mut self, order_by_consumed: bool) {
528        unsafe {
529            (*self.0).orderByConsumed = c_int::from(order_by_consumed);
530        }
531    }
532
533    /// Estimated cost of using this index
534    #[inline]
535    pub fn set_estimated_cost(&mut self, estimated_ost: f64) {
536        unsafe {
537            (*self.0).estimatedCost = estimated_ost;
538        }
539    }
540
541    /// Estimated number of rows returned.
542    #[inline]
543    pub fn set_estimated_rows(&mut self, estimated_rows: i64) {
544        unsafe {
545            (*self.0).estimatedRows = estimated_rows;
546        }
547    }
548
549    /// Mask of `SQLITE_INDEX_SCAN_*` flags.
550    #[inline]
551    pub fn set_idx_flags(&mut self, flags: IndexFlags) {
552        unsafe { (*self.0).idxFlags = flags.bits() };
553    }
554
555    /// Mask of columns used by statement
556    #[inline]
557    #[must_use]
558    pub fn col_used(&self) -> u64 {
559        unsafe { (*self.0).colUsed }
560    }
561
562    /// Determine the collation for a virtual table constraint
563    pub fn collation(&self, constraint_idx: usize) -> Result<&str> {
564        let idx = constraint_idx as c_int;
565        let collation = unsafe { ffi::sqlite3_vtab_collation(self.0, idx) };
566        if collation.is_null() {
567            return Err(err!(ffi::SQLITE_MISUSE, "{constraint_idx} is out of range"));
568        }
569        Ok(unsafe { CStr::from_ptr(collation) }.to_str()?)
570    }
571
572    /// Determine if a virtual table query is DISTINCT
573    #[must_use]
574    pub fn distinct(&self) -> DistinctMode {
575        match unsafe { ffi::sqlite3_vtab_distinct(self.0) } {
576            0 => DistinctMode::Ordered,
577            1 => DistinctMode::Grouped,
578            2 => DistinctMode::Distinct,
579            3 => DistinctMode::DistinctOrdered,
580            _ => DistinctMode::Ordered,
581        }
582    }
583
584    /// Constraint value
585    pub fn rhs_value(&self, constraint_idx: usize) -> Result<Option<ValueRef<'_>>> {
586        let idx = constraint_idx as c_int;
587        let mut p_value: *mut sqlite3_value = ptr::null_mut();
588        let rc = unsafe { ffi::sqlite3_vtab_rhs_value(self.0, idx, &raw mut p_value) };
589        if rc == ffi::SQLITE_NOTFOUND {
590            return Ok(None);
591        }
592        check(rc)?;
593        assert!(!p_value.is_null());
594        Ok(Some(unsafe { ValueRef::from_value(p_value) }))
595    }
596
597    /// Identify IN constraints
598    pub fn is_in_constraint(&self, constraint_idx: usize) -> Result<bool> {
599        self.check_constraint_index(constraint_idx)?;
600        let idx = constraint_idx as c_int;
601        Ok(unsafe { ffi::sqlite3_vtab_in(self.0, idx, -1) != 0 })
602    }
603
604    /// Handle IN constraints
605    pub fn set_in_constraint(&mut self, constraint_idx: usize, filter_all: bool) -> Result<bool> {
606        self.check_constraint_index(constraint_idx)?;
607        let idx = constraint_idx as c_int;
608        Ok(unsafe { ffi::sqlite3_vtab_in(self.0, idx, c_int::from(filter_all)) != 0 })
609    }
610
611    fn check_constraint_index(&self, idx: usize) -> Result<()> {
612        if idx >= unsafe { (*self.0).nConstraint } as usize {
613            return Err(err!(ffi::SQLITE_MISUSE, "{idx} is out of range"));
614        }
615        Ok(())
616    }
617}
618
619/// Determine if a virtual table query is DISTINCT
620#[non_exhaustive]
621#[derive(Debug, Eq, PartialEq)]
622pub enum DistinctMode {
623    /// This is the default expectation.
624    Ordered,
625    /// This mode is used when the query planner is doing a GROUP BY.
626    Grouped,
627    /// This mode is used for a DISTINCT query.
628    Distinct,
629    /// This mode is used for queries that have both DISTINCT and ORDER BY clauses.
630    DistinctOrdered,
631}
632
633/// Iterate on index constraint and its associated usage.
634pub struct IndexConstraintAndUsageIter<'a> {
635    iter: std::iter::Zip<
636        slice::Iter<'a, ffi::sqlite3_index_constraint>,
637        slice::IterMut<'a, ffi::sqlite3_index_constraint_usage>,
638    >,
639}
640
641impl<'a> Iterator for IndexConstraintAndUsageIter<'a> {
642    type Item = (IndexConstraint<'a>, IndexConstraintUsage<'a>);
643
644    #[inline]
645    fn next(&mut self) -> Option<(IndexConstraint<'a>, IndexConstraintUsage<'a>)> {
646        self.iter
647            .next()
648            .map(|raw| (IndexConstraint(raw.0), IndexConstraintUsage(raw.1)))
649    }
650
651    #[inline]
652    fn size_hint(&self) -> (usize, Option<usize>) {
653        self.iter.size_hint()
654    }
655}
656
657/// `feature = "vtab"`
658pub struct IndexConstraintIter<'a> {
659    iter: slice::Iter<'a, ffi::sqlite3_index_constraint>,
660}
661
662impl<'a> Iterator for IndexConstraintIter<'a> {
663    type Item = IndexConstraint<'a>;
664
665    #[inline]
666    fn next(&mut self) -> Option<IndexConstraint<'a>> {
667        self.iter.next().map(IndexConstraint)
668    }
669
670    #[inline]
671    fn size_hint(&self) -> (usize, Option<usize>) {
672        self.iter.size_hint()
673    }
674}
675
676/// WHERE clause constraint.
677pub struct IndexConstraint<'a>(&'a ffi::sqlite3_index_constraint);
678
679impl IndexConstraint<'_> {
680    /// Column constrained.  -1 for ROWID
681    #[inline]
682    #[must_use]
683    pub fn column(&self) -> c_int {
684        self.0.iColumn
685    }
686
687    /// Constraint operator
688    #[inline]
689    #[must_use]
690    pub fn operator(&self) -> IndexConstraintOp {
691        IndexConstraintOp::from(self.0.op)
692    }
693
694    /// True if this constraint is usable
695    #[inline]
696    #[must_use]
697    pub fn is_usable(&self) -> bool {
698        self.0.usable != 0
699    }
700}
701
702/// Information about what parameters to pass to
703/// [`VTabCursor::filter`].
704pub struct IndexConstraintUsage<'a>(&'a mut ffi::sqlite3_index_constraint_usage);
705
706impl IndexConstraintUsage<'_> {
707    /// if `argv_index` > 0, constraint is part of argv to
708    /// [`VTabCursor::filter`]
709    #[inline]
710    pub fn set_argv_index(&mut self, argv_index: c_int) {
711        self.0.argvIndex = argv_index;
712    }
713
714    /// if `omit`, do not code a test for this constraint
715    #[inline]
716    pub fn set_omit(&mut self, omit: bool) {
717        self.0.omit = std::ffi::c_uchar::from(omit);
718    }
719}
720
721/// `feature = "vtab"`
722pub struct OrderByIter<'a> {
723    iter: slice::Iter<'a, ffi::sqlite3_index_orderby>,
724}
725
726impl<'a> Iterator for OrderByIter<'a> {
727    type Item = OrderBy<'a>;
728
729    #[inline]
730    fn next(&mut self) -> Option<OrderBy<'a>> {
731        self.iter.next().map(OrderBy)
732    }
733
734    #[inline]
735    fn size_hint(&self) -> (usize, Option<usize>) {
736        self.iter.size_hint()
737    }
738}
739
740/// A column of the ORDER BY clause.
741pub struct OrderBy<'a>(&'a ffi::sqlite3_index_orderby);
742
743impl OrderBy<'_> {
744    /// Column number
745    #[inline]
746    #[must_use]
747    pub fn column(&self) -> c_int {
748        self.0.iColumn
749    }
750
751    /// True for DESC.  False for ASC.
752    #[inline]
753    #[must_use]
754    pub fn is_order_by_desc(&self) -> bool {
755        self.0.desc != 0
756    }
757}
758
759/// Virtual table cursor trait.
760///
761/// # Safety
762///
763/// Implementations must be like:
764/// ```rust,ignore
765/// #[repr(C)]
766/// struct MyTabCursor {
767///    /// Base class. Must be first
768///    base: rusqlite::vtab::sqlite3_vtab_cursor,
769///    /* Virtual table implementations will typically add additional fields */
770/// }
771/// ```
772///
773/// (See [SQLite doc](https://sqlite.org/c3ref/vtab_cursor.html))
774pub unsafe trait VTabCursor: Sized {
775    /// Begin a search of a virtual table.
776    /// (See [SQLite doc](https://sqlite.org/vtab.html#the_xfilter_method))
777    fn filter(&mut self, idx_num: c_int, idx_str: Option<&str>, args: &Filters<'_>) -> Result<()>;
778    /// Advance cursor to the next row of a result set initiated by
779    /// [`filter`](VTabCursor::filter). (See [SQLite doc](https://sqlite.org/vtab.html#the_xnext_method))
780    fn next(&mut self) -> Result<()>;
781    /// Must return `false` if the cursor currently points to a valid row of
782    /// data, or `true` otherwise.
783    /// (See [SQLite doc](https://sqlite.org/vtab.html#the_xeof_method))
784    fn eof(&self) -> bool;
785    /// Find the value for the `i`-th column of the current row.
786    /// `i` is zero-based so the first column is numbered 0.
787    /// May return its result back to SQLite using one of the specified `ctx`.
788    /// (See [SQLite doc](https://sqlite.org/vtab.html#the_xcolumn_method))
789    fn column(&self, ctx: &mut Context, i: c_int) -> Result<()>;
790    /// Return the rowid of row that the cursor is currently pointing at.
791    /// (See [SQLite doc](https://sqlite.org/vtab.html#the_xrowid_method))
792    fn rowid(&self) -> Result<i64>;
793}
794
795/// Context is used by [`VTabCursor::column`] to specify the
796/// cell value.
797pub struct Context(*mut sqlite3_context);
798
799impl Context {
800    /// Set current cell value
801    #[inline]
802    pub fn set_result<T: ToSql>(&mut self, value: T) -> Result<()> {
803        let t = value.to_sql()?;
804        unsafe { set_result(self.0, &[], t) }
805    }
806
807    /// Determine if column access is for UPDATE
808    #[inline]
809    #[must_use]
810    pub fn no_change(&self) -> bool {
811        unsafe { ffi::sqlite3_vtab_nochange(self.0) != 0 }
812    }
813
814    /// Get the db connection handle via [sqlite3_context_db_handle](https://www.sqlite.org/c3ref/context_db_handle.html)
815    ///
816    /// # Safety
817    ///
818    /// This function is unsafe because improper use may impact the Connection.
819    pub unsafe fn get_connection(&self) -> Result<ConnectionRef<'_>> {
820        Ok(ConnectionRef {
821            conn: unsafe {
822                let handle = ffi::sqlite3_context_db_handle(self.0);
823                Connection::from_handle(handle)?
824            },
825            phantom: PhantomData,
826        })
827    }
828}
829
830/// A reference to a connection handle with a lifetime bound to context.
831pub struct ConnectionRef<'ctx> {
832    // comes from Connection::from_handle(sqlite3_context_db_handle(...))
833    // and is non-owning
834    conn: Connection,
835    phantom: PhantomData<&'ctx Context>,
836}
837
838impl Deref for ConnectionRef<'_> {
839    type Target = Connection;
840
841    #[inline]
842    fn deref(&self) -> &Connection {
843        &self.conn
844    }
845}
846
847/// Wrapper to [`VTabCursor::filter`] arguments, the values
848/// requested by [`VTab::best_index`].
849pub struct Filters<'a> {
850    values: Values<'a>,
851}
852impl<'a> Deref for Filters<'a> {
853    type Target = Values<'a>;
854
855    fn deref(&self) -> &Self::Target {
856        &self.values
857    }
858}
859impl Filters<'_> {
860    /// Find all elements on the right-hand side of an IN constraint
861    pub fn in_values(&self, idx: usize) -> Result<InValues<'_>> {
862        let list = self.args[idx];
863        Ok(InValues {
864            list,
865            phantom: PhantomData,
866            first: true,
867        })
868    }
869}
870
871/// IN values
872pub struct InValues<'a> {
873    list: *mut sqlite3_value,
874    phantom: PhantomData<Filters<'a>>,
875    first: bool,
876}
877impl<'a> fallible_iterator::FallibleIterator for InValues<'a> {
878    type Error = Error;
879    type Item = ValueRef<'a>;
880
881    fn next(&mut self) -> Result<Option<Self::Item>> {
882        let mut val: *mut sqlite3_value = ptr::null_mut();
883        let rc = unsafe {
884            if self.first {
885                self.first = false;
886                ffi::sqlite3_vtab_in_first(self.list, &raw mut val)
887            } else {
888                ffi::sqlite3_vtab_in_next(self.list, &raw mut val)
889            }
890        };
891        match rc {
892            ffi::SQLITE_OK => Ok(Some(unsafe { ValueRef::from_value(val) })),
893            ffi::SQLITE_DONE => Ok(None),
894            _ => Err(error_from_sqlite_code(rc, None)),
895        }
896    }
897}
898
899/// Wrapper to [`ffi::sqlite3_value`]s
900pub struct Values<'a> {
901    args: &'a [*mut sqlite3_value],
902}
903
904impl Values<'_> {
905    /// Returns the number of values.
906    #[inline]
907    #[must_use]
908    pub fn len(&self) -> usize {
909        self.args.len()
910    }
911
912    /// Returns `true` if there is no value.
913    #[inline]
914    #[must_use]
915    pub fn is_empty(&self) -> bool {
916        self.args.is_empty()
917    }
918
919    /// Returns value at `idx`
920    pub fn get<T: FromSql>(&self, idx: usize) -> Result<T> {
921        let arg = self.args[idx];
922        let value = unsafe { ValueRef::from_value(arg) };
923        FromSql::column_result(value).map_err(|err| match err {
924            FromSqlError::InvalidType => Error::InvalidFilterParameterType(idx, value.data_type()),
925            FromSqlError::Other(err) => {
926                Error::FromSqlConversionFailure(idx, value.data_type(), err)
927            }
928            FromSqlError::InvalidBlobSize { .. } => {
929                Error::FromSqlConversionFailure(idx, value.data_type(), Box::new(err))
930            }
931            FromSqlError::OutOfRange(i) => Error::IntegralValueOutOfRange(idx, i),
932            FromSqlError::Utf8Error(err) => Error::Utf8Error(idx, err),
933        })
934    }
935
936    /// Returns the subtype of value at `idx`.
937    ///
938    /// # Failure
939    ///
940    /// Will panic if `idx` is greater than or equal to
941    /// [`self.len()`](Values::len).
942    #[inline]
943    #[must_use]
944    pub fn get_subtype(&self, idx: usize) -> c_uint {
945        let arg = self.args[idx];
946        unsafe { ffi::sqlite3_value_subtype(arg) }
947    }
948
949    /// Return raw pointer at `idx`
950    /// # Safety
951    /// This function is unsafe because it uses raw pointer and cast
952    // `sqlite3_value_type` returns `SQLITE_NULL` for pointer.
953    // So it seems not possible to enhance `ValueRef::from_value`.
954    #[cfg(feature = "pointer")]
955    #[must_use]
956    pub unsafe fn get_pointer<'a, T: 'static>(
957        &self,
958        idx: usize,
959        ptr_type: &'static CStr,
960    ) -> Option<&'a T> {
961        let arg = self.args[idx];
962        debug_assert_eq!(unsafe { ffi::sqlite3_value_type(arg) }, ffi::SQLITE_NULL);
963        unsafe {
964            ffi::sqlite3_value_pointer(arg, ptr_type.as_ptr())
965                .cast::<T>()
966                .as_ref()
967        }
968    }
969
970    /// Turns `Values` into an iterator.
971    #[inline]
972    #[must_use]
973    pub fn iter(&self) -> ValueIter<'_> {
974        ValueIter {
975            iter: self.args.iter(),
976        }
977    }
978}
979
980impl<'a> IntoIterator for &'a Values<'a> {
981    type IntoIter = ValueIter<'a>;
982    type Item = ValueRef<'a>;
983
984    #[inline]
985    fn into_iter(self) -> ValueIter<'a> {
986        self.iter()
987    }
988}
989
990/// [`Values`] iterator.
991pub struct ValueIter<'a> {
992    iter: slice::Iter<'a, *mut sqlite3_value>,
993}
994
995impl<'a> Iterator for ValueIter<'a> {
996    type Item = ValueRef<'a>;
997
998    #[inline]
999    fn next(&mut self) -> Option<ValueRef<'a>> {
1000        self.iter
1001            .next()
1002            .map(|&raw| unsafe { ValueRef::from_value(raw) })
1003    }
1004
1005    #[inline]
1006    fn size_hint(&self) -> (usize, Option<usize>) {
1007        self.iter.size_hint()
1008    }
1009}
1010
1011/// Wrapper to [`UpdateVTab::insert`] arguments
1012pub struct Inserts<'a> {
1013    values: Values<'a>,
1014}
1015impl<'a> Deref for Inserts<'a> {
1016    type Target = Values<'a>;
1017
1018    fn deref(&self) -> &Self::Target {
1019        &self.values
1020    }
1021}
1022impl Inserts<'_> {
1023    /// Determine the virtual table conflict policy
1024    ///
1025    /// # Safety
1026    /// This function is unsafe because it uses raw pointer
1027    #[must_use]
1028    pub unsafe fn on_conflict(&self, db: *mut ffi::sqlite3) -> ConflictMode {
1029        ConflictMode::from(unsafe { ffi::sqlite3_vtab_on_conflict(db) })
1030    }
1031}
1032
1033/// Wrapper to [`UpdateVTab::update`] arguments
1034pub struct Updates<'a> {
1035    values: Values<'a>,
1036}
1037impl<'a> Deref for Updates<'a> {
1038    type Target = Values<'a>;
1039
1040    fn deref(&self) -> &Self::Target {
1041        &self.values
1042    }
1043}
1044impl Updates<'_> {
1045    /// Returns `true` if and only
1046    /// - if the column corresponding to `idx` is unchanged by the UPDATE operation that the [`UpdateVTab::update`] method call was invoked to implement
1047    /// - and if and the prior [`VTabCursor::column`] method call that was invoked to extract the value for that column returned without setting a result.
1048    #[inline]
1049    #[must_use]
1050    pub fn no_change(&self, idx: usize) -> bool {
1051        unsafe { ffi::sqlite3_value_nochange(self.values.args[idx]) != 0 }
1052    }
1053
1054    /// Determine the virtual table conflict policy
1055    ///
1056    /// # Safety
1057    /// This function is unsafe because it uses raw pointer
1058    #[must_use]
1059    pub unsafe fn on_conflict(&self, db: *mut ffi::sqlite3) -> ConflictMode {
1060        ConflictMode::from(unsafe { ffi::sqlite3_vtab_on_conflict(db) })
1061    }
1062}
1063
1064/// Conflict resolution modes
1065#[non_exhaustive]
1066#[derive(Debug, Eq, PartialEq)]
1067pub enum ConflictMode {
1068    /// `SQLITE_ROLLBACK`
1069    Rollback,
1070    /// `SQLITE_IGNORE`
1071    Ignore,
1072    /// `SQLITE_FAIL`
1073    Fail,
1074    /// `SQLITE_ABORT`
1075    Abort,
1076    /// `SQLITE_REPLACE`
1077    Replace,
1078}
1079impl From<c_int> for ConflictMode {
1080    fn from(value: c_int) -> Self {
1081        match value {
1082            ffi::SQLITE_ROLLBACK => ConflictMode::Rollback,
1083            ffi::SQLITE_IGNORE => ConflictMode::Ignore,
1084            ffi::SQLITE_FAIL => ConflictMode::Fail,
1085            ffi::SQLITE_ABORT => ConflictMode::Abort,
1086            ffi::SQLITE_REPLACE => ConflictMode::Replace,
1087            _ => unreachable!("sqlite3_vtab_on_conflict returned invalid value"),
1088        }
1089    }
1090}
1091
1092impl Connection {
1093    /// Register a virtual table implementation.
1094    ///
1095    /// Step 3 of [Creating New Virtual Table
1096    /// Implementations](https://sqlite.org/vtab.html#creating_new_virtual_table_implementations).
1097    #[inline]
1098    pub fn create_module<'vtab, T: VTab<'vtab>, M: Name>(
1099        &self,
1100        module_name: M,
1101        module: &'static Module<'vtab, T>,
1102        aux: Option<T::Aux>,
1103    ) -> Result<()> {
1104        self.db.borrow_mut().create_module(module_name, module, aux)
1105    }
1106}
1107
1108impl InnerConnection {
1109    fn create_module<'vtab, T: VTab<'vtab>, M: Name>(
1110        &mut self,
1111        module_name: M,
1112        module: &'static Module<'vtab, T>,
1113        aux: Option<T::Aux>,
1114    ) -> Result<()> {
1115        use crate::version;
1116        if version::version_number() < 3_009_000 && module.base.xCreate.is_none() {
1117            return Err(Error::ModuleError(format!(
1118                "Eponymous-only virtual table not supported by SQLite version {}",
1119                version::version()
1120            )));
1121        }
1122        let c_name = module_name.as_cstr()?;
1123        let r = match aux {
1124            Some(aux) => {
1125                let boxed_aux: *mut T::Aux = Box::into_raw(Box::new(aux));
1126                unsafe {
1127                    ffi::sqlite3_create_module_v2(
1128                        self.db(),
1129                        c_name.as_ptr(),
1130                        &raw const module.base,
1131                        boxed_aux.cast::<c_void>(),
1132                        Some(free_boxed_value::<T::Aux>),
1133                    )
1134                }
1135            }
1136            None => unsafe {
1137                ffi::sqlite3_create_module_v2(
1138                    self.db(),
1139                    c_name.as_ptr(),
1140                    &raw const module.base,
1141                    ptr::null_mut(),
1142                    None,
1143                )
1144            },
1145        };
1146        self.decode_result(r)
1147    }
1148}
1149
1150/// Escape double-quote (`"`) character occurrences by
1151/// doubling them (`""`).
1152#[must_use]
1153pub fn escape_double_quote(identifier: &str) -> Cow<'_, str> {
1154    if identifier.contains('"') {
1155        // escape quote by doubling them
1156        Owned(identifier.replace('"', "\"\""))
1157    } else {
1158        Borrowed(identifier)
1159    }
1160}
1161/// Dequote string
1162#[must_use]
1163pub fn dequote(mut s: &str) -> Cow<'_, str> {
1164    let mut chars = s.chars();
1165    let (Some(first), Some(last)) = (chars.next(), chars.next_back()) else {
1166        return Borrowed(s);
1167    };
1168    if (first == '"' || first == '\'' || first == '`' || first == '[')
1169        && (last == first || first == '[' && last == ']')
1170    {
1171        s = chars.as_str();
1172        if first != '[' && s.contains(first) {
1173            // handle inner escaped quote(s)
1174            let mut owned = String::with_capacity(s.len());
1175            let mut escaped = false;
1176            for c in s.chars() {
1177                if c == first {
1178                    if !escaped {
1179                        escaped = true;
1180                        continue;
1181                    }
1182                    escaped = false;
1183                } else if escaped {
1184                    // not properly escaped
1185                    return Borrowed(s);
1186                }
1187                owned.push(c);
1188            }
1189            if !escaped {
1190                return Owned(owned);
1191            }
1192        }
1193    }
1194    Borrowed(s)
1195}
1196/// The boolean can be one of:
1197/// ```text
1198/// 1 yes true on
1199/// 0 no false off
1200/// ```
1201#[must_use]
1202pub fn parse_boolean(s: &str) -> Option<bool> {
1203    if s.eq_ignore_ascii_case("yes")
1204        || s.eq_ignore_ascii_case("on")
1205        || s.eq_ignore_ascii_case("true")
1206        || s.eq("1")
1207    {
1208        Some(true)
1209    } else if s.eq_ignore_ascii_case("no")
1210        || s.eq_ignore_ascii_case("off")
1211        || s.eq_ignore_ascii_case("false")
1212        || s.eq("0")
1213    {
1214        Some(false)
1215    } else {
1216        None
1217    }
1218}
1219
1220/// `<param_name>=['"`[]?<param_value>['"`]]?` => `(<param_name>, <param_value>)`
1221pub fn parameter(c_slice: &[u8]) -> Result<(&str, Cow<'_, str>)> {
1222    let arg = std::str::from_utf8(c_slice)?.trim();
1223    match arg.split_once('=') {
1224        Some((key, value)) => {
1225            let param = key.trim();
1226            let value = dequote(value.trim());
1227            Ok((param, value))
1228        }
1229        _ => Err(Error::ModuleError(format!("illegal argument: '{arg}'"))),
1230    }
1231}
1232
1233unsafe extern "C" fn rust_create<'vtab, T>(
1234    db: *mut ffi::sqlite3,
1235    aux: *mut c_void,
1236    argc: c_int,
1237    argv: *const *const c_char,
1238    pp_vtab: *mut *mut sqlite3_vtab,
1239    err_msg: *mut *mut c_char,
1240) -> c_int
1241where
1242    T: CreateVTab<'vtab>,
1243{
1244    let mut conn = VTabConnection(db);
1245    let aux = aux.cast::<T::Aux>();
1246    unsafe {
1247        let args = from_raw_parts(argv, argc);
1248        let vec = args
1249            .iter()
1250            .map(|&cs| CStr::from_ptr(cs).to_bytes()) // FIXME .to_str() -> Result<&str, Utf8Error>
1251            .collect::<Vec<_>>();
1252        match T::create(&mut conn, aux.as_ref(), vec[0], vec[1], vec[2], &vec[3..]) {
1253            Ok((sql, vtab)) => {
1254                let rc = ffi::sqlite3_declare_vtab(db, sql.as_ptr());
1255                if rc == ffi::SQLITE_OK {
1256                    let boxed_vtab: *mut T = Box::into_raw(Box::new(vtab));
1257                    *pp_vtab = boxed_vtab.cast::<sqlite3_vtab>();
1258                    ffi::SQLITE_OK
1259                } else {
1260                    let err = error_from_sqlite_code(rc, None);
1261                    to_sqlite_error(&err, err_msg)
1262                }
1263            }
1264            Err(err) => to_sqlite_error(&err, err_msg),
1265        }
1266    }
1267}
1268
1269unsafe extern "C" fn rust_connect<'vtab, T>(
1270    db: *mut ffi::sqlite3,
1271    aux: *mut c_void,
1272    argc: c_int,
1273    argv: *const *const c_char,
1274    pp_vtab: *mut *mut sqlite3_vtab,
1275    err_msg: *mut *mut c_char,
1276) -> c_int
1277where
1278    T: VTab<'vtab>,
1279{
1280    let mut conn = VTabConnection(db);
1281    let aux = aux.cast::<T::Aux>();
1282    unsafe {
1283        let args = from_raw_parts(argv, argc);
1284        let vec = args
1285            .iter()
1286            .map(|&cs| CStr::from_ptr(cs).to_bytes()) // FIXME .to_str() -> Result<&str, Utf8Error>
1287            .collect::<Vec<_>>();
1288        match T::connect(&mut conn, aux.as_ref(), vec[0], vec[1], vec[2], &vec[3..]) {
1289            Ok((sql, vtab)) => {
1290                let rc = ffi::sqlite3_declare_vtab(db, sql.as_ptr());
1291                if rc == ffi::SQLITE_OK {
1292                    let boxed_vtab: *mut T = Box::into_raw(Box::new(vtab));
1293                    *pp_vtab = boxed_vtab.cast::<sqlite3_vtab>();
1294                    ffi::SQLITE_OK
1295                } else {
1296                    let err = error_from_sqlite_code(rc, None);
1297                    to_sqlite_error(&err, err_msg)
1298                }
1299            }
1300            Err(err) => to_sqlite_error(&err, err_msg),
1301        }
1302    }
1303}
1304
1305unsafe extern "C" fn rust_best_index<'vtab, T>(
1306    vtab: *mut sqlite3_vtab,
1307    info: *mut ffi::sqlite3_index_info,
1308) -> c_int
1309where
1310    T: VTab<'vtab>,
1311{
1312    let vt = vtab.cast::<T>();
1313    let mut idx_info = IndexInfo(info);
1314    unsafe {
1315        match (*vt).best_index(&mut idx_info) {
1316            Ok(true) => ffi::SQLITE_OK,
1317            Ok(false) => ffi::SQLITE_CONSTRAINT,
1318            err => vtab_error(vtab, err),
1319        }
1320    }
1321}
1322
1323unsafe extern "C" fn rust_disconnect<'vtab, T>(vtab: *mut sqlite3_vtab) -> c_int
1324where
1325    T: VTab<'vtab>,
1326{
1327    if vtab.is_null() {
1328        return ffi::SQLITE_OK;
1329    }
1330    let vtab = vtab.cast::<T>();
1331    drop(unsafe { Box::from_raw(vtab) });
1332    ffi::SQLITE_OK
1333}
1334
1335unsafe extern "C" fn rust_destroy<'vtab, T>(vtab: *mut sqlite3_vtab) -> c_int
1336where
1337    T: CreateVTab<'vtab>,
1338{
1339    if vtab.is_null() {
1340        return ffi::SQLITE_OK;
1341    }
1342    let vt = vtab.cast::<T>();
1343    unsafe {
1344        match (*vt).destroy() {
1345            Ok(()) => {
1346                drop(Box::from_raw(vt));
1347                ffi::SQLITE_OK
1348            }
1349            err => vtab_error(vtab, err),
1350        }
1351    }
1352}
1353
1354unsafe extern "C" fn rust_open<'vtab, T>(
1355    vtab: *mut sqlite3_vtab,
1356    pp_cursor: *mut *mut sqlite3_vtab_cursor,
1357) -> c_int
1358where
1359    T: VTab<'vtab> + 'vtab,
1360{
1361    let vt = vtab.cast::<T>();
1362    unsafe {
1363        match (*vt).open() {
1364            Ok(cursor) => {
1365                let boxed_cursor: *mut T::Cursor = Box::into_raw(Box::new(cursor));
1366                *pp_cursor = boxed_cursor.cast::<sqlite3_vtab_cursor>();
1367                ffi::SQLITE_OK
1368            }
1369            err => vtab_error(vtab, err),
1370        }
1371    }
1372}
1373
1374unsafe extern "C" fn rust_close<C>(cursor: *mut sqlite3_vtab_cursor) -> c_int
1375where
1376    C: VTabCursor,
1377{
1378    let cr = cursor.cast::<C>();
1379    drop(unsafe { Box::from_raw(cr) });
1380    ffi::SQLITE_OK
1381}
1382
1383unsafe extern "C" fn rust_filter<C>(
1384    cursor: *mut sqlite3_vtab_cursor,
1385    idx_num: c_int,
1386    idx_str: *const c_char,
1387    argc: c_int,
1388    argv: *mut *mut sqlite3_value,
1389) -> c_int
1390where
1391    C: VTabCursor,
1392{
1393    use std::str;
1394    unsafe {
1395        let idx_name = if idx_str.is_null() {
1396            None
1397        } else {
1398            let c_slice = CStr::from_ptr(idx_str).to_bytes();
1399            Some(str::from_utf8_unchecked(c_slice))
1400        };
1401        let args = from_raw_parts_mut(argv, argc);
1402        let values = Values { args };
1403        let cr = cursor.cast::<C>();
1404        cursor_error(cursor, (*cr).filter(idx_num, idx_name, &Filters { values }))
1405    }
1406}
1407
1408unsafe extern "C" fn rust_next<C>(cursor: *mut sqlite3_vtab_cursor) -> c_int
1409where
1410    C: VTabCursor,
1411{
1412    let cr = cursor.cast::<C>();
1413    unsafe { cursor_error(cursor, (*cr).next()) }
1414}
1415
1416unsafe extern "C" fn rust_eof<C>(cursor: *mut sqlite3_vtab_cursor) -> c_int
1417where
1418    C: VTabCursor,
1419{
1420    let cr = cursor.cast::<C>();
1421    unsafe { c_int::from((*cr).eof()) }
1422}
1423
1424unsafe extern "C" fn rust_column<C>(
1425    cursor: *mut sqlite3_vtab_cursor,
1426    ctx: *mut sqlite3_context,
1427    i: c_int,
1428) -> c_int
1429where
1430    C: VTabCursor,
1431{
1432    let cr = cursor.cast::<C>();
1433    let mut ctxt = Context(ctx);
1434    unsafe { result_error(ctx, (*cr).column(&mut ctxt, i)) }
1435}
1436
1437unsafe extern "C" fn rust_rowid<C>(
1438    cursor: *mut sqlite3_vtab_cursor,
1439    p_rowid: *mut ffi::sqlite3_int64,
1440) -> c_int
1441where
1442    C: VTabCursor,
1443{
1444    let cr = cursor.cast::<C>();
1445    unsafe {
1446        match (*cr).rowid() {
1447            Ok(rowid) => {
1448                *p_rowid = rowid;
1449                ffi::SQLITE_OK
1450            }
1451            err => cursor_error(cursor, err),
1452        }
1453    }
1454}
1455
1456unsafe extern "C" fn rust_update<'vtab, T>(
1457    vtab: *mut sqlite3_vtab,
1458    argc: c_int,
1459    argv: *mut *mut sqlite3_value,
1460    p_rowid: *mut ffi::sqlite3_int64,
1461) -> c_int
1462where
1463    T: UpdateVTab<'vtab> + 'vtab,
1464{
1465    assert!(argc >= 1);
1466    let vt = vtab.cast::<T>();
1467    unsafe {
1468        let args = from_raw_parts_mut(argv, argc);
1469        let r = if args.len() == 1 {
1470            (*vt).delete(ValueRef::from_value(args[0]))
1471        } else if ffi::sqlite3_value_type(args[0]) == ffi::SQLITE_NULL {
1472            // TODO Make the distinction between argv[1] == NULL and argv[1] != NULL ?
1473            let values = Values { args };
1474            match (*vt).insert(&Inserts { values }) {
1475                Ok(rowid) => {
1476                    *p_rowid = rowid;
1477                    Ok(())
1478                }
1479                Err(e) => Err(e),
1480            }
1481        } else {
1482            let values = Values { args };
1483            (*vt).update(&Updates { values })
1484        };
1485        vtab_error(vtab, r)
1486    }
1487}
1488
1489unsafe extern "C" fn rust_begin<'vtab, T>(vtab: *mut sqlite3_vtab) -> c_int
1490where
1491    T: TransactionVTab<'vtab>,
1492{
1493    let vt = vtab.cast::<T>();
1494    unsafe { vtab_error(vtab, (*vt).begin()) }
1495}
1496unsafe extern "C" fn rust_sync<'vtab, T>(vtab: *mut sqlite3_vtab) -> c_int
1497where
1498    T: TransactionVTab<'vtab>,
1499{
1500    let vt = vtab.cast::<T>();
1501    unsafe { vtab_error(vtab, (*vt).sync()) }
1502}
1503unsafe extern "C" fn rust_commit<'vtab, T>(vtab: *mut sqlite3_vtab) -> c_int
1504where
1505    T: TransactionVTab<'vtab>,
1506{
1507    let vt = vtab.cast::<T>();
1508    unsafe { vtab_error(vtab, (*vt).commit()) }
1509}
1510unsafe extern "C" fn rust_rollback<'vtab, T>(vtab: *mut sqlite3_vtab) -> c_int
1511where
1512    T: TransactionVTab<'vtab>,
1513{
1514    let vt = vtab.cast::<T>();
1515    unsafe { vtab_error(vtab, (*vt).rollback()) }
1516}
1517
1518/// Virtual table cursors can set an error message by assigning a string to
1519/// `zErrMsg`.
1520unsafe fn cursor_error<T>(cursor: *mut sqlite3_vtab_cursor, result: Result<T>) -> c_int {
1521    unsafe { vtab_error((*cursor).pVtab, result) }
1522}
1523
1524/// Virtual tables can set an error message by assigning a string to
1525/// `zErrMsg`.
1526unsafe fn vtab_error<T>(vtab: *mut sqlite3_vtab, result: Result<T>) -> c_int {
1527    unsafe {
1528        match result {
1529            Ok(_) => ffi::SQLITE_OK,
1530            Err(Error::SqliteFailure(err, s)) => {
1531                if let Some(err_msg) = s {
1532                    set_err_msg(vtab, &err_msg);
1533                }
1534                err.extended_code
1535            }
1536            Err(err) => {
1537                set_err_msg(vtab, &err.to_string());
1538                ffi::SQLITE_ERROR
1539            }
1540        }
1541    }
1542}
1543
1544/// Virtual tables methods can set an error message by assigning a string to
1545/// `zErrMsg`.
1546#[cold]
1547unsafe fn set_err_msg(vtab: *mut sqlite3_vtab, err_msg: &str) {
1548    unsafe {
1549        if !(*vtab).zErrMsg.is_null() {
1550            sqlite3_free((*vtab).zErrMsg.cast::<c_void>());
1551        }
1552        (*vtab).zErrMsg = alloc(err_msg);
1553    }
1554}
1555
1556/// To raise an error, the `column` method should use this method to set the
1557/// error message and return the error code.
1558#[cold]
1559unsafe fn result_error<T>(ctx: *mut sqlite3_context, result: Result<T>) -> c_int {
1560    unsafe {
1561        match result {
1562            Ok(_) => ffi::SQLITE_OK,
1563            Err(Error::SqliteFailure(err, s)) => {
1564                match err.extended_code {
1565                    ffi::SQLITE_TOOBIG => {
1566                        ffi::sqlite3_result_error_toobig(ctx);
1567                    }
1568                    ffi::SQLITE_NOMEM => {
1569                        ffi::sqlite3_result_error_nomem(ctx);
1570                    }
1571                    code => {
1572                        ffi::sqlite3_result_error_code(ctx, code);
1573                        if let Some(Ok(cstr)) = s.map(|s| str_to_cstring(&s)) {
1574                            ffi::sqlite3_result_error(ctx, cstr.as_ptr(), -1);
1575                        }
1576                    }
1577                }
1578                err.extended_code
1579            }
1580            Err(err) => {
1581                ffi::sqlite3_result_error_code(ctx, ffi::SQLITE_ERROR);
1582                if let Ok(cstr) = str_to_cstring(&err.to_string()) {
1583                    ffi::sqlite3_result_error(ctx, cstr.as_ptr(), -1);
1584                }
1585                ffi::SQLITE_ERROR
1586            }
1587        }
1588    }
1589}
1590
1591#[cfg(feature = "array")]
1592pub mod array;
1593#[cfg(feature = "csvtab")]
1594pub mod csvtab;
1595#[cfg(feature = "series")]
1596pub mod series; // SQLite >= 3.9.0
1597#[cfg(all(test, not(miri)))]
1598mod vtablog;
1599
1600#[cfg(test)]
1601mod test {
1602    use std::borrow::Cow;
1603
1604    #[cfg(all(target_family = "wasm", target_os = "unknown"))]
1605    use wasm_bindgen_test::wasm_bindgen_test as test;
1606
1607    #[test]
1608    fn test_dequote() {
1609        assert_eq!("", super::dequote(""));
1610        assert_eq!("'", super::dequote("'"));
1611        assert_eq!("\"", super::dequote("\""));
1612
1613        assert_eq!("'\"", super::dequote("'\""));
1614
1615        assert_eq!("", super::dequote("''"));
1616        assert_eq!("", super::dequote("\"\""));
1617        assert_eq!("", super::dequote("``"));
1618        assert_eq!("", super::dequote("[]"));
1619
1620        assert_eq!("x", super::dequote("'x'"));
1621        assert_eq!("x", super::dequote("\"x\""));
1622        assert_eq!("x", super::dequote("x"));
1623        assert_eq!("x", super::dequote("`x`"));
1624        assert_eq!("x", super::dequote("[x]"));
1625
1626        assert_eq!("x'", super::dequote("'x'''"));
1627        assert_eq!("x`", super::dequote("`x```"));
1628
1629        assert_eq!("x'", super::dequote("'x''"));
1630        assert_eq!("x`", super::dequote("`x``"));
1631    }
1632    #[test]
1633    fn test_parse_boolean() {
1634        assert_eq!(None, super::parse_boolean(""));
1635        assert_eq!(Some(true), super::parse_boolean("1"));
1636        assert_eq!(Some(true), super::parse_boolean("yes"));
1637        assert_eq!(Some(true), super::parse_boolean("on"));
1638        assert_eq!(Some(true), super::parse_boolean("true"));
1639        assert_eq!(Some(false), super::parse_boolean("0"));
1640        assert_eq!(Some(false), super::parse_boolean("no"));
1641        assert_eq!(Some(false), super::parse_boolean("off"));
1642        assert_eq!(Some(false), super::parse_boolean("false"));
1643    }
1644    #[test]
1645    fn test_parse_parameters() {
1646        assert_eq!(
1647            Ok(("key", Cow::Borrowed("value"))),
1648            super::parameter(b"key='value'")
1649        );
1650        assert_eq!(
1651            Ok(("key", Cow::Borrowed("foo=bar"))),
1652            super::parameter(b"key='foo=bar'")
1653        );
1654    }
1655
1656    #[cfg(all(feature = "functions", not(miri)))]
1657    #[test]
1658    fn test_values_get_subtype() -> crate::Result<()> {
1659        use std::ffi::{CStr, c_int, c_uint};
1660        use std::sync::atomic::{AtomicU32, Ordering};
1661
1662        use crate::ffi;
1663        use crate::functions::{FunctionFlags, SqlFnArg, SubType};
1664        use crate::types::Value;
1665        use crate::vtab::{
1666            Context, CreateVTab, Filters, IndexConstraintOp, IndexInfo, Inserts, Module,
1667            UpdateVTab, Updates, VTab, VTabConnection, VTabCursor, VTabKind,
1668        };
1669        use crate::{Connection, Result};
1670
1671        static FILTER_SUBTYPE: AtomicU32 = AtomicU32::new(0);
1672        static INSERT_SUBTYPE: AtomicU32 = AtomicU32::new(0);
1673
1674        fn set_subtype(ctx: &crate::functions::Context<'_>) -> Result<(SqlFnArg, SubType)> {
1675            let value = ctx.get_arg(0);
1676            let sub_type = ctx.get::<c_uint>(1)?;
1677            Ok((value, Some(sub_type)))
1678        }
1679
1680        #[repr(C)]
1681        struct SubTypeVTab {
1682            base: ffi::sqlite3_vtab,
1683        }
1684        #[repr(C)]
1685        struct SubTypeVTabCursor {
1686            base: ffi::sqlite3_vtab_cursor,
1687        }
1688
1689        unsafe impl<'vtab> VTab<'vtab> for SubTypeVTab {
1690            type Aux = ();
1691            type Cursor = SubTypeVTabCursor;
1692
1693            fn connect(
1694                _db: &mut VTabConnection,
1695                _aux: Option<&Self::Aux>,
1696                _module_name: &[u8],
1697                _database_name: &[u8],
1698                _table_name: &[u8],
1699                _args: &[&[u8]],
1700            ) -> Result<(Cow<'static, CStr>, Self)> {
1701                Ok((
1702                    Cow::Borrowed(c"CREATE TABLE x(value BLOB)"),
1703                    Self {
1704                        base: ffi::sqlite3_vtab::default(),
1705                    },
1706                ))
1707            }
1708
1709            fn best_index(&self, info: &mut IndexInfo) -> Result<bool> {
1710                let mut argv_index = 1;
1711                let mut usable_constraints = Vec::new();
1712                for (i, constraint) in info.constraints().enumerate() {
1713                    if constraint.is_usable()
1714                        && constraint.operator() == IndexConstraintOp::SQLITE_INDEX_CONSTRAINT_EQ
1715                    {
1716                        usable_constraints.push(i);
1717                    }
1718                }
1719                for i in usable_constraints {
1720                    let mut usage = info.constraint_usage(i);
1721                    usage.set_argv_index(argv_index);
1722                    usage.set_omit(true);
1723                    argv_index += 1;
1724                }
1725                info.set_estimated_cost(1.0);
1726                Ok(true)
1727            }
1728
1729            fn open(&'vtab mut self) -> Result<Self::Cursor> {
1730                Ok(SubTypeVTabCursor {
1731                    base: ffi::sqlite3_vtab_cursor::default(),
1732                })
1733            }
1734        }
1735
1736        impl CreateVTab<'_> for SubTypeVTab {
1737            const KIND: VTabKind = VTabKind::Default;
1738        }
1739
1740        impl UpdateVTab<'_> for SubTypeVTab {
1741            fn delete(&mut self, _arg: crate::types::ValueRef<'_>) -> Result<()> {
1742                Ok(())
1743            }
1744
1745            fn insert(&mut self, args: &Inserts<'_>) -> Result<i64> {
1746                // args[0]: old rowid (NULL for new rows)
1747                // args[1]: new rowid
1748                // args[2]: first column value
1749                INSERT_SUBTYPE.store(args.get_subtype(2), Ordering::SeqCst);
1750                Ok(0)
1751            }
1752
1753            fn update(&mut self, _args: &Updates<'_>) -> Result<()> {
1754                Ok(())
1755            }
1756        }
1757
1758        unsafe impl VTabCursor for SubTypeVTabCursor {
1759            fn filter(
1760                &mut self,
1761                _idx_num: c_int,
1762                _idx_str: Option<&str>,
1763                args: &Filters<'_>,
1764            ) -> Result<()> {
1765                FILTER_SUBTYPE.store(args.get_subtype(0), Ordering::SeqCst);
1766                Ok(())
1767            }
1768
1769            fn next(&mut self) -> Result<()> {
1770                Ok(())
1771            }
1772
1773            fn eof(&self) -> bool {
1774                true
1775            }
1776
1777            fn column(&self, ctx: &mut Context, _i: c_int) -> Result<()> {
1778                ctx.set_result(Value::Null)
1779            }
1780
1781            fn rowid(&self) -> Result<i64> {
1782                Ok(0)
1783            }
1784        }
1785
1786        let db = Connection::open_in_memory()?;
1787        db.create_scalar_function(
1788            c"set_subtype",
1789            2,
1790            FunctionFlags::SQLITE_UTF8 | FunctionFlags::SQLITE_RESULT_SUBTYPE,
1791            set_subtype,
1792        )?;
1793        const MODULE: Module<SubTypeVTab> = Module::update_module();
1794        db.create_module(c"subtype_vtab", &MODULE, None)?;
1795
1796        db.execute("CREATE VIRTUAL TABLE st USING subtype_vtab()", [])?;
1797
1798        FILTER_SUBTYPE.store(0, Ordering::SeqCst);
1799        INSERT_SUBTYPE.store(0, Ordering::SeqCst);
1800
1801        // Test filter callback can read subtype from scalar function result.
1802        let _: Result<String> = db.query_row(
1803            "SELECT value FROM st WHERE value = set_subtype('a', 223)",
1804            [],
1805            |row| row.get(0),
1806        );
1807        assert_eq!(FILTER_SUBTYPE.load(Ordering::SeqCst), 223);
1808
1809        // Test insert callback can read subtype from scalar function result.
1810        // Use a BLOB literal as input so the value remains a BLOB when inserted.
1811        db.execute(
1812            "INSERT INTO st(rowid, value) VALUES (1, set_subtype(X'62', 225))",
1813            [],
1814        )?;
1815        assert_eq!(INSERT_SUBTYPE.load(Ordering::SeqCst), 225);
1816
1817        Ok(())
1818    }
1819}