1use std::borrow::Cow::{self, Borrowed, Owned};
13use std::marker::PhantomData;
14use std::marker::Sync;
15use std::os::raw::{c_char, c_int, c_void};
16use std::ptr;
17use std::slice;
18
19use crate::context::set_result;
20use crate::error::error_from_sqlite_code;
21use crate::ffi;
22pub use crate::ffi::{sqlite3_vtab, sqlite3_vtab_cursor};
23use crate::types::{FromSql, FromSqlError, ToSql, ValueRef};
24use crate::{str_to_cstring, Connection, Error, InnerConnection, Result};
25
26pub enum VTabKind {
62    Default,
64    Eponymous,
68    EponymousOnly,
75}
76
77#[repr(transparent)]
81pub struct Module<'vtab, T: VTab<'vtab>> {
82    base: ffi::sqlite3_module,
83    phantom: PhantomData<&'vtab T>,
84}
85
86unsafe impl<'vtab, T: VTab<'vtab>> Send for Module<'vtab, T> {}
87unsafe impl<'vtab, T: VTab<'vtab>> Sync for Module<'vtab, T> {}
88
89union ModuleZeroHack {
90    bytes: [u8; std::mem::size_of::<ffi::sqlite3_module>()],
91    module: ffi::sqlite3_module,
92}
93
94const ZERO_MODULE: ffi::sqlite3_module = unsafe {
98    ModuleZeroHack {
99        bytes: [0_u8; std::mem::size_of::<ffi::sqlite3_module>()],
100    }
101    .module
102};
103
104macro_rules! module {
105    ($lt:lifetime, $vt:ty, $ct:ty, $xc:expr, $xd:expr, $xu:expr) => {
106    #[allow(clippy::needless_update)]
107    &Module {
108        base: ffi::sqlite3_module {
109            iVersion: 2,
111            xCreate: $xc,
112            xConnect: Some(rust_connect::<$vt>),
113            xBestIndex: Some(rust_best_index::<$vt>),
114            xDisconnect: Some(rust_disconnect::<$vt>),
115            xDestroy: $xd,
116            xOpen: Some(rust_open::<$vt>),
117            xClose: Some(rust_close::<$ct>),
118            xFilter: Some(rust_filter::<$ct>),
119            xNext: Some(rust_next::<$ct>),
120            xEof: Some(rust_eof::<$ct>),
121            xColumn: Some(rust_column::<$ct>),
122            xRowid: Some(rust_rowid::<$ct>), xUpdate: $xu,
124            xBegin: None,
125            xSync: None,
126            xCommit: None,
127            xRollback: None,
128            xFindFunction: None,
129            xRename: None,
130            xSavepoint: None,
131            xRelease: None,
132            xRollbackTo: None,
133            ..ZERO_MODULE
134        },
135        phantom: PhantomData::<&$lt $vt>,
136    }
137    };
138}
139
140#[must_use]
144pub fn update_module<'vtab, T: UpdateVTab<'vtab>>() -> &'static Module<'vtab, T> {
145    match T::KIND {
146        VTabKind::EponymousOnly => {
147            module!('vtab, T, T::Cursor, None, None, Some(rust_update::<T>))
148        }
149        VTabKind::Eponymous => {
150            module!('vtab, T, T::Cursor, Some(rust_connect::<T>), Some(rust_disconnect::<T>), Some(rust_update::<T>))
151        }
152        _ => {
153            module!('vtab, T, T::Cursor, Some(rust_create::<T>), Some(rust_destroy::<T>), Some(rust_update::<T>))
154        }
155    }
156}
157
158#[must_use]
162pub fn read_only_module<'vtab, T: CreateVTab<'vtab>>() -> &'static Module<'vtab, T> {
163    match T::KIND {
164        VTabKind::EponymousOnly => eponymous_only_module(),
165        VTabKind::Eponymous => {
166            module!('vtab, T, T::Cursor, Some(rust_connect::<T>), Some(rust_disconnect::<T>), None)
169        }
170        _ => {
171            module!('vtab, T, T::Cursor, Some(rust_create::<T>), Some(rust_destroy::<T>), None)
174        }
175    }
176}
177
178#[must_use]
182pub fn eponymous_only_module<'vtab, T: VTab<'vtab>>() -> &'static Module<'vtab, T> {
183    module!('vtab, T, T::Cursor, None, None, None)
185}
186
187#[repr(i32)]
189#[non_exhaustive]
190#[derive(Debug, Clone, Copy, Eq, PartialEq)]
191pub enum VTabConfig {
192    ConstraintSupport = 1,
194    Innocuous = 2,
196    DirectOnly = 3,
198}
199
200pub struct VTabConnection(*mut ffi::sqlite3);
202
203impl VTabConnection {
204    pub fn config(&mut self, config: VTabConfig) -> Result<()> {
206        crate::error::check(unsafe { ffi::sqlite3_vtab_config(self.0, config as c_int) })
207    }
208
209    pub unsafe fn handle(&mut self) -> *mut ffi::sqlite3 {
225        self.0
226    }
227}
228
229pub unsafe trait VTab<'vtab>: Sized {
247    type Aux;
249    type Cursor: VTabCursor;
251
252    fn connect(
256        db: &mut VTabConnection,
257        aux: Option<&Self::Aux>,
258        args: &[&[u8]],
259    ) -> Result<(String, Self)>;
260
261    fn best_index(&self, info: &mut IndexInfo) -> Result<()>;
264
265    fn open(&'vtab mut self) -> Result<Self::Cursor>;
268}
269
270pub trait CreateVTab<'vtab>: VTab<'vtab> {
274    const KIND: VTabKind;
278    fn create(
286        db: &mut VTabConnection,
287        aux: Option<&Self::Aux>,
288        args: &[&[u8]],
289    ) -> Result<(String, Self)> {
290        Self::connect(db, aux, args)
291    }
292
293    fn destroy(&self) -> Result<()> {
299        Ok(())
300    }
301}
302
303pub trait UpdateVTab<'vtab>: CreateVTab<'vtab> {
307    fn delete(&mut self, arg: ValueRef<'_>) -> Result<()>;
309    fn insert(&mut self, args: &Values<'_>) -> Result<i64>;
315    fn update(&mut self, args: &Values<'_>) -> Result<()>;
318}
319
320#[derive(Debug, Eq, PartialEq)]
323#[allow(non_snake_case, non_camel_case_types, missing_docs)]
324#[allow(clippy::upper_case_acronyms)]
325pub enum IndexConstraintOp {
326    SQLITE_INDEX_CONSTRAINT_EQ,
327    SQLITE_INDEX_CONSTRAINT_GT,
328    SQLITE_INDEX_CONSTRAINT_LE,
329    SQLITE_INDEX_CONSTRAINT_LT,
330    SQLITE_INDEX_CONSTRAINT_GE,
331    SQLITE_INDEX_CONSTRAINT_MATCH,
332    SQLITE_INDEX_CONSTRAINT_LIKE,         SQLITE_INDEX_CONSTRAINT_GLOB,         SQLITE_INDEX_CONSTRAINT_REGEXP,       SQLITE_INDEX_CONSTRAINT_NE,           SQLITE_INDEX_CONSTRAINT_ISNOT,        SQLITE_INDEX_CONSTRAINT_ISNOTNULL,    SQLITE_INDEX_CONSTRAINT_ISNULL,       SQLITE_INDEX_CONSTRAINT_IS,           SQLITE_INDEX_CONSTRAINT_LIMIT,        SQLITE_INDEX_CONSTRAINT_OFFSET,       SQLITE_INDEX_CONSTRAINT_FUNCTION(u8), }
344
345impl From<u8> for IndexConstraintOp {
346    fn from(code: u8) -> IndexConstraintOp {
347        match code {
348            2 => IndexConstraintOp::SQLITE_INDEX_CONSTRAINT_EQ,
349            4 => IndexConstraintOp::SQLITE_INDEX_CONSTRAINT_GT,
350            8 => IndexConstraintOp::SQLITE_INDEX_CONSTRAINT_LE,
351            16 => IndexConstraintOp::SQLITE_INDEX_CONSTRAINT_LT,
352            32 => IndexConstraintOp::SQLITE_INDEX_CONSTRAINT_GE,
353            64 => IndexConstraintOp::SQLITE_INDEX_CONSTRAINT_MATCH,
354            65 => IndexConstraintOp::SQLITE_INDEX_CONSTRAINT_LIKE,
355            66 => IndexConstraintOp::SQLITE_INDEX_CONSTRAINT_GLOB,
356            67 => IndexConstraintOp::SQLITE_INDEX_CONSTRAINT_REGEXP,
357            68 => IndexConstraintOp::SQLITE_INDEX_CONSTRAINT_NE,
358            69 => IndexConstraintOp::SQLITE_INDEX_CONSTRAINT_ISNOT,
359            70 => IndexConstraintOp::SQLITE_INDEX_CONSTRAINT_ISNOTNULL,
360            71 => IndexConstraintOp::SQLITE_INDEX_CONSTRAINT_ISNULL,
361            72 => IndexConstraintOp::SQLITE_INDEX_CONSTRAINT_IS,
362            73 => IndexConstraintOp::SQLITE_INDEX_CONSTRAINT_LIMIT,
363            74 => IndexConstraintOp::SQLITE_INDEX_CONSTRAINT_OFFSET,
364            v => IndexConstraintOp::SQLITE_INDEX_CONSTRAINT_FUNCTION(v),
365        }
366    }
367}
368
369bitflags::bitflags! {
370    #[repr(C)]
373    pub struct IndexFlags: ::std::os::raw::c_int {
374        const NONE     = 0;
376        const SQLITE_INDEX_SCAN_UNIQUE  = ffi::SQLITE_INDEX_SCAN_UNIQUE;
378    }
379}
380
381#[derive(Debug)]
386pub struct IndexInfo(*mut ffi::sqlite3_index_info);
387
388impl IndexInfo {
389    #[inline]
391    pub fn constraints_and_usages(&mut self) -> IndexConstraintAndUsageIter<'_> {
392        let constraints =
393            unsafe { slice::from_raw_parts((*self.0).aConstraint, (*self.0).nConstraint as usize) };
394        let constraint_usages = unsafe {
395            slice::from_raw_parts_mut((*self.0).aConstraintUsage, (*self.0).nConstraint as usize)
396        };
397        IndexConstraintAndUsageIter {
398            iter: constraints.iter().zip(constraint_usages.iter_mut()),
399        }
400    }
401
402    #[inline]
404    #[must_use]
405    pub fn constraints(&self) -> IndexConstraintIter<'_> {
406        let constraints =
407            unsafe { slice::from_raw_parts((*self.0).aConstraint, (*self.0).nConstraint as usize) };
408        IndexConstraintIter {
409            iter: constraints.iter(),
410        }
411    }
412
413    #[inline]
415    #[must_use]
416    pub fn order_bys(&self) -> OrderByIter<'_> {
417        let order_bys =
418            unsafe { slice::from_raw_parts((*self.0).aOrderBy, (*self.0).nOrderBy as usize) };
419        OrderByIter {
420            iter: order_bys.iter(),
421        }
422    }
423
424    #[inline]
426    #[must_use]
427    pub fn num_of_order_by(&self) -> usize {
428        unsafe { (*self.0).nOrderBy as usize }
429    }
430
431    #[inline]
433    pub fn constraint_usage(&mut self, constraint_idx: usize) -> IndexConstraintUsage<'_> {
434        let constraint_usages = unsafe {
435            slice::from_raw_parts_mut((*self.0).aConstraintUsage, (*self.0).nConstraint as usize)
436        };
437        IndexConstraintUsage(&mut constraint_usages[constraint_idx])
438    }
439
440    #[inline]
442    pub fn set_idx_num(&mut self, idx_num: c_int) {
443        unsafe {
444            (*self.0).idxNum = idx_num;
445        }
446    }
447
448    pub fn set_idx_str(&mut self, idx_str: &str) {
450        unsafe {
451            (*self.0).idxStr = alloc(idx_str);
452            (*self.0).needToFreeIdxStr = 1;
453        }
454    }
455
456    #[inline]
458    pub fn set_order_by_consumed(&mut self, order_by_consumed: bool) {
459        unsafe {
460            (*self.0).orderByConsumed = order_by_consumed as c_int;
461        }
462    }
463
464    #[inline]
466    pub fn set_estimated_cost(&mut self, estimated_ost: f64) {
467        unsafe {
468            (*self.0).estimatedCost = estimated_ost;
469        }
470    }
471
472    #[inline]
474    pub fn set_estimated_rows(&mut self, estimated_rows: i64) {
475        unsafe {
476            (*self.0).estimatedRows = estimated_rows;
477        }
478    }
479
480    #[inline]
482    pub fn set_idx_flags(&mut self, flags: IndexFlags) {
483        unsafe { (*self.0).idxFlags = flags.bits() };
484    }
485
486    #[inline]
488    pub fn col_used(&self) -> u64 {
489        unsafe { (*self.0).colUsed }
490    }
491
492    #[cfg(feature = "modern_sqlite")] #[cfg_attr(docsrs, doc(cfg(feature = "modern_sqlite")))]
495    pub fn collation(&self, constraint_idx: usize) -> Result<&str> {
496        use std::ffi::CStr;
497        let idx = constraint_idx as c_int;
498        let collation = unsafe { ffi::sqlite3_vtab_collation(self.0, idx) };
499        if collation.is_null() {
500            return Err(Error::SqliteFailure(
501                ffi::Error::new(ffi::SQLITE_MISUSE),
502                Some(format!("{constraint_idx} is out of range")),
503            ));
504        }
505        Ok(unsafe { CStr::from_ptr(collation) }.to_str()?)
506    }
507
508    }
531
532pub struct IndexConstraintAndUsageIter<'a> {
534    iter: std::iter::Zip<
535        slice::Iter<'a, ffi::sqlite3_index_constraint>,
536        slice::IterMut<'a, ffi::sqlite3_index_constraint_usage>,
537    >,
538}
539
540impl<'a> Iterator for IndexConstraintAndUsageIter<'a> {
541    type Item = (IndexConstraint<'a>, IndexConstraintUsage<'a>);
542
543    #[inline]
544    fn next(&mut self) -> Option<(IndexConstraint<'a>, IndexConstraintUsage<'a>)> {
545        self.iter
546            .next()
547            .map(|raw| (IndexConstraint(raw.0), IndexConstraintUsage(raw.1)))
548    }
549
550    #[inline]
551    fn size_hint(&self) -> (usize, Option<usize>) {
552        self.iter.size_hint()
553    }
554}
555
556pub struct IndexConstraintIter<'a> {
558    iter: slice::Iter<'a, ffi::sqlite3_index_constraint>,
559}
560
561impl<'a> Iterator for IndexConstraintIter<'a> {
562    type Item = IndexConstraint<'a>;
563
564    #[inline]
565    fn next(&mut self) -> Option<IndexConstraint<'a>> {
566        self.iter.next().map(IndexConstraint)
567    }
568
569    #[inline]
570    fn size_hint(&self) -> (usize, Option<usize>) {
571        self.iter.size_hint()
572    }
573}
574
575pub struct IndexConstraint<'a>(&'a ffi::sqlite3_index_constraint);
577
578impl IndexConstraint<'_> {
579    #[inline]
581    #[must_use]
582    pub fn column(&self) -> c_int {
583        self.0.iColumn
584    }
585
586    #[inline]
588    #[must_use]
589    pub fn operator(&self) -> IndexConstraintOp {
590        IndexConstraintOp::from(self.0.op)
591    }
592
593    #[inline]
595    #[must_use]
596    pub fn is_usable(&self) -> bool {
597        self.0.usable != 0
598    }
599}
600
601pub struct IndexConstraintUsage<'a>(&'a mut ffi::sqlite3_index_constraint_usage);
604
605impl IndexConstraintUsage<'_> {
606    #[inline]
609    pub fn set_argv_index(&mut self, argv_index: c_int) {
610        self.0.argvIndex = argv_index;
611    }
612
613    #[inline]
615    pub fn set_omit(&mut self, omit: bool) {
616        self.0.omit = omit as std::os::raw::c_uchar;
617    }
618}
619
620pub struct OrderByIter<'a> {
622    iter: slice::Iter<'a, ffi::sqlite3_index_orderby>,
623}
624
625impl<'a> Iterator for OrderByIter<'a> {
626    type Item = OrderBy<'a>;
627
628    #[inline]
629    fn next(&mut self) -> Option<OrderBy<'a>> {
630        self.iter.next().map(OrderBy)
631    }
632
633    #[inline]
634    fn size_hint(&self) -> (usize, Option<usize>) {
635        self.iter.size_hint()
636    }
637}
638
639pub struct OrderBy<'a>(&'a ffi::sqlite3_index_orderby);
641
642impl OrderBy<'_> {
643    #[inline]
645    #[must_use]
646    pub fn column(&self) -> c_int {
647        self.0.iColumn
648    }
649
650    #[inline]
652    #[must_use]
653    pub fn is_order_by_desc(&self) -> bool {
654        self.0.desc != 0
655    }
656}
657
658pub unsafe trait VTabCursor: Sized {
674    fn filter(&mut self, idx_num: c_int, idx_str: Option<&str>, args: &Values<'_>) -> Result<()>;
677    fn next(&mut self) -> Result<()>;
680    fn eof(&self) -> bool;
684    fn column(&self, ctx: &mut Context, i: c_int) -> Result<()>;
689    fn rowid(&self) -> Result<i64>;
692}
693
694pub struct Context(*mut ffi::sqlite3_context);
697
698impl Context {
699    #[inline]
701    pub fn set_result<T: ToSql>(&mut self, value: &T) -> Result<()> {
702        let t = value.to_sql()?;
703        unsafe { set_result(self.0, &t) };
704        Ok(())
705    }
706
707    }
709
710pub struct Values<'a> {
713    args: &'a [*mut ffi::sqlite3_value],
714}
715
716impl Values<'_> {
717    #[inline]
719    #[must_use]
720    pub fn len(&self) -> usize {
721        self.args.len()
722    }
723
724    #[inline]
726    #[must_use]
727    pub fn is_empty(&self) -> bool {
728        self.args.is_empty()
729    }
730
731    pub fn get<T: FromSql>(&self, idx: usize) -> Result<T> {
733        let arg = self.args[idx];
734        let value = unsafe { ValueRef::from_value(arg) };
735        FromSql::column_result(value).map_err(|err| match err {
736            FromSqlError::InvalidType => Error::InvalidFilterParameterType(idx, value.data_type()),
737            FromSqlError::Other(err) => {
738                Error::FromSqlConversionFailure(idx, value.data_type(), err)
739            }
740            FromSqlError::InvalidBlobSize { .. } => {
741                Error::FromSqlConversionFailure(idx, value.data_type(), Box::new(err))
742            }
743            FromSqlError::OutOfRange(i) => Error::IntegralValueOutOfRange(idx, i),
744        })
745    }
746
747    #[cfg(feature = "array")]
750    #[cfg_attr(docsrs, doc(cfg(feature = "array")))]
751    fn get_array(&self, idx: usize) -> Option<array::Array> {
752        use crate::types::Value;
753        let arg = self.args[idx];
754        let ptr = unsafe { ffi::sqlite3_value_pointer(arg, array::ARRAY_TYPE) };
755        if ptr.is_null() {
756            None
757        } else {
758            Some(unsafe {
759                let rc = array::Array::from_raw(ptr as *const Vec<Value>);
760                let array = rc.clone();
761                let _ = array::Array::into_raw(rc); array
763            })
764        }
765    }
766
767    #[inline]
769    #[must_use]
770    pub fn iter(&self) -> ValueIter<'_> {
771        ValueIter {
772            iter: self.args.iter(),
773        }
774    }
775    }
777
778impl<'a> IntoIterator for &'a Values<'a> {
779    type IntoIter = ValueIter<'a>;
780    type Item = ValueRef<'a>;
781
782    #[inline]
783    fn into_iter(self) -> ValueIter<'a> {
784        self.iter()
785    }
786}
787
788pub struct ValueIter<'a> {
790    iter: slice::Iter<'a, *mut ffi::sqlite3_value>,
791}
792
793impl<'a> Iterator for ValueIter<'a> {
794    type Item = ValueRef<'a>;
795
796    #[inline]
797    fn next(&mut self) -> Option<ValueRef<'a>> {
798        self.iter
799            .next()
800            .map(|&raw| unsafe { ValueRef::from_value(raw) })
801    }
802
803    #[inline]
804    fn size_hint(&self) -> (usize, Option<usize>) {
805        self.iter.size_hint()
806    }
807}
808
809impl Connection {
810    #[inline]
815    pub fn create_module<'vtab, T: VTab<'vtab>>(
816        &self,
817        module_name: &str,
818        module: &'static Module<'vtab, T>,
819        aux: Option<T::Aux>,
820    ) -> Result<()> {
821        self.db.borrow_mut().create_module(module_name, module, aux)
822    }
823}
824
825impl InnerConnection {
826    fn create_module<'vtab, T: VTab<'vtab>>(
827        &mut self,
828        module_name: &str,
829        module: &'static Module<'vtab, T>,
830        aux: Option<T::Aux>,
831    ) -> Result<()> {
832        use crate::version;
833        if version::version_number() < 3_009_000 && module.base.xCreate.is_none() {
834            return Err(Error::ModuleError(format!(
835                "Eponymous-only virtual table not supported by SQLite version {}",
836                version::version()
837            )));
838        }
839        let c_name = str_to_cstring(module_name)?;
840        let r = match aux {
841            Some(aux) => {
842                let boxed_aux: *mut T::Aux = Box::into_raw(Box::new(aux));
843                unsafe {
844                    ffi::sqlite3_create_module_v2(
845                        self.db(),
846                        c_name.as_ptr(),
847                        &module.base,
848                        boxed_aux.cast::<c_void>(),
849                        Some(free_boxed_value::<T::Aux>),
850                    )
851                }
852            }
853            None => unsafe {
854                ffi::sqlite3_create_module_v2(
855                    self.db(),
856                    c_name.as_ptr(),
857                    &module.base,
858                    ptr::null_mut(),
859                    None,
860                )
861            },
862        };
863        self.decode_result(r)
864    }
865}
866
867#[must_use]
870pub fn escape_double_quote(identifier: &str) -> Cow<'_, str> {
871    if identifier.contains('"') {
872        Owned(identifier.replace('"', "\"\""))
874    } else {
875        Borrowed(identifier)
876    }
877}
878#[must_use]
880pub fn dequote(s: &str) -> &str {
881    if s.len() < 2 {
882        return s;
883    }
884    match s.bytes().next() {
885        Some(b) if b == b'"' || b == b'\'' => match s.bytes().rev().next() {
886            Some(e) if e == b => &s[1..s.len() - 1], _ => s,
888        },
889        _ => s,
890    }
891}
892#[must_use]
898pub fn parse_boolean(s: &str) -> Option<bool> {
899    if s.eq_ignore_ascii_case("yes")
900        || s.eq_ignore_ascii_case("on")
901        || s.eq_ignore_ascii_case("true")
902        || s.eq("1")
903    {
904        Some(true)
905    } else if s.eq_ignore_ascii_case("no")
906        || s.eq_ignore_ascii_case("off")
907        || s.eq_ignore_ascii_case("false")
908        || s.eq("0")
909    {
910        Some(false)
911    } else {
912        None
913    }
914}
915
916pub fn parameter(c_slice: &[u8]) -> Result<(&str, &str)> {
918    let arg = std::str::from_utf8(c_slice)?.trim();
919    let mut split = arg.split('=');
920    if let Some(key) = split.next() {
921        if let Some(value) = split.next() {
922            let param = key.trim();
923            let value = dequote(value);
924            return Ok((param, value));
925        }
926    }
927    Err(Error::ModuleError(format!("illegal argument: '{arg}'")))
928}
929
930unsafe extern "C" fn free_boxed_value<T>(p: *mut c_void) {
932    drop(Box::from_raw(p.cast::<T>()));
933}
934
935unsafe extern "C" fn rust_create<'vtab, T>(
936    db: *mut ffi::sqlite3,
937    aux: *mut c_void,
938    argc: c_int,
939    argv: *const *const c_char,
940    pp_vtab: *mut *mut ffi::sqlite3_vtab,
941    err_msg: *mut *mut c_char,
942) -> c_int
943where
944    T: CreateVTab<'vtab>,
945{
946    use std::ffi::CStr;
947
948    let mut conn = VTabConnection(db);
949    let aux = aux.cast::<T::Aux>();
950    let args = slice::from_raw_parts(argv, argc as usize);
951    let vec = args
952        .iter()
953        .map(|&cs| CStr::from_ptr(cs).to_bytes()) .collect::<Vec<_>>();
955    match T::create(&mut conn, aux.as_ref(), &vec[..]) {
956        Ok((sql, vtab)) => match std::ffi::CString::new(sql) {
957            Ok(c_sql) => {
958                let rc = ffi::sqlite3_declare_vtab(db, c_sql.as_ptr());
959                if rc == ffi::SQLITE_OK {
960                    let boxed_vtab: *mut T = Box::into_raw(Box::new(vtab));
961                    *pp_vtab = boxed_vtab.cast::<ffi::sqlite3_vtab>();
962                    ffi::SQLITE_OK
963                } else {
964                    let err = error_from_sqlite_code(rc, None);
965                    *err_msg = alloc(&err.to_string());
966                    rc
967                }
968            }
969            Err(err) => {
970                *err_msg = alloc(&err.to_string());
971                ffi::SQLITE_ERROR
972            }
973        },
974        Err(Error::SqliteFailure(err, s)) => {
975            if let Some(s) = s {
976                *err_msg = alloc(&s);
977            }
978            err.extended_code
979        }
980        Err(err) => {
981            *err_msg = alloc(&err.to_string());
982            ffi::SQLITE_ERROR
983        }
984    }
985}
986
987unsafe extern "C" fn rust_connect<'vtab, T>(
988    db: *mut ffi::sqlite3,
989    aux: *mut c_void,
990    argc: c_int,
991    argv: *const *const c_char,
992    pp_vtab: *mut *mut ffi::sqlite3_vtab,
993    err_msg: *mut *mut c_char,
994) -> c_int
995where
996    T: VTab<'vtab>,
997{
998    use std::ffi::CStr;
999
1000    let mut conn = VTabConnection(db);
1001    let aux = aux.cast::<T::Aux>();
1002    let args = slice::from_raw_parts(argv, argc as usize);
1003    let vec = args
1004        .iter()
1005        .map(|&cs| CStr::from_ptr(cs).to_bytes()) .collect::<Vec<_>>();
1007    match T::connect(&mut conn, aux.as_ref(), &vec[..]) {
1008        Ok((sql, vtab)) => match std::ffi::CString::new(sql) {
1009            Ok(c_sql) => {
1010                let rc = ffi::sqlite3_declare_vtab(db, c_sql.as_ptr());
1011                if rc == ffi::SQLITE_OK {
1012                    let boxed_vtab: *mut T = Box::into_raw(Box::new(vtab));
1013                    *pp_vtab = boxed_vtab.cast::<ffi::sqlite3_vtab>();
1014                    ffi::SQLITE_OK
1015                } else {
1016                    let err = error_from_sqlite_code(rc, None);
1017                    *err_msg = alloc(&err.to_string());
1018                    rc
1019                }
1020            }
1021            Err(err) => {
1022                *err_msg = alloc(&err.to_string());
1023                ffi::SQLITE_ERROR
1024            }
1025        },
1026        Err(Error::SqliteFailure(err, s)) => {
1027            if let Some(s) = s {
1028                *err_msg = alloc(&s);
1029            }
1030            err.extended_code
1031        }
1032        Err(err) => {
1033            *err_msg = alloc(&err.to_string());
1034            ffi::SQLITE_ERROR
1035        }
1036    }
1037}
1038
1039unsafe extern "C" fn rust_best_index<'vtab, T>(
1040    vtab: *mut ffi::sqlite3_vtab,
1041    info: *mut ffi::sqlite3_index_info,
1042) -> c_int
1043where
1044    T: VTab<'vtab>,
1045{
1046    let vt = vtab.cast::<T>();
1047    let mut idx_info = IndexInfo(info);
1048    match (*vt).best_index(&mut idx_info) {
1049        Ok(_) => ffi::SQLITE_OK,
1050        Err(Error::SqliteFailure(err, s)) => {
1051            if let Some(err_msg) = s {
1052                set_err_msg(vtab, &err_msg);
1053            }
1054            err.extended_code
1055        }
1056        Err(err) => {
1057            set_err_msg(vtab, &err.to_string());
1058            ffi::SQLITE_ERROR
1059        }
1060    }
1061}
1062
1063unsafe extern "C" fn rust_disconnect<'vtab, T>(vtab: *mut ffi::sqlite3_vtab) -> c_int
1064where
1065    T: VTab<'vtab>,
1066{
1067    if vtab.is_null() {
1068        return ffi::SQLITE_OK;
1069    }
1070    let vtab = vtab.cast::<T>();
1071    drop(Box::from_raw(vtab));
1072    ffi::SQLITE_OK
1073}
1074
1075unsafe extern "C" fn rust_destroy<'vtab, T>(vtab: *mut ffi::sqlite3_vtab) -> c_int
1076where
1077    T: CreateVTab<'vtab>,
1078{
1079    if vtab.is_null() {
1080        return ffi::SQLITE_OK;
1081    }
1082    let vt = vtab.cast::<T>();
1083    match (*vt).destroy() {
1084        Ok(_) => {
1085            drop(Box::from_raw(vt));
1086            ffi::SQLITE_OK
1087        }
1088        Err(Error::SqliteFailure(err, s)) => {
1089            if let Some(err_msg) = s {
1090                set_err_msg(vtab, &err_msg);
1091            }
1092            err.extended_code
1093        }
1094        Err(err) => {
1095            set_err_msg(vtab, &err.to_string());
1096            ffi::SQLITE_ERROR
1097        }
1098    }
1099}
1100
1101unsafe extern "C" fn rust_open<'vtab, T: 'vtab>(
1102    vtab: *mut ffi::sqlite3_vtab,
1103    pp_cursor: *mut *mut ffi::sqlite3_vtab_cursor,
1104) -> c_int
1105where
1106    T: VTab<'vtab>,
1107{
1108    let vt = vtab.cast::<T>();
1109    match (*vt).open() {
1110        Ok(cursor) => {
1111            let boxed_cursor: *mut T::Cursor = Box::into_raw(Box::new(cursor));
1112            *pp_cursor = boxed_cursor.cast::<ffi::sqlite3_vtab_cursor>();
1113            ffi::SQLITE_OK
1114        }
1115        Err(Error::SqliteFailure(err, s)) => {
1116            if let Some(err_msg) = s {
1117                set_err_msg(vtab, &err_msg);
1118            }
1119            err.extended_code
1120        }
1121        Err(err) => {
1122            set_err_msg(vtab, &err.to_string());
1123            ffi::SQLITE_ERROR
1124        }
1125    }
1126}
1127
1128unsafe extern "C" fn rust_close<C>(cursor: *mut ffi::sqlite3_vtab_cursor) -> c_int
1129where
1130    C: VTabCursor,
1131{
1132    let cr = cursor.cast::<C>();
1133    drop(Box::from_raw(cr));
1134    ffi::SQLITE_OK
1135}
1136
1137unsafe extern "C" fn rust_filter<C>(
1138    cursor: *mut ffi::sqlite3_vtab_cursor,
1139    idx_num: c_int,
1140    idx_str: *const c_char,
1141    argc: c_int,
1142    argv: *mut *mut ffi::sqlite3_value,
1143) -> c_int
1144where
1145    C: VTabCursor,
1146{
1147    use std::ffi::CStr;
1148    use std::str;
1149    let idx_name = if idx_str.is_null() {
1150        None
1151    } else {
1152        let c_slice = CStr::from_ptr(idx_str).to_bytes();
1153        Some(str::from_utf8_unchecked(c_slice))
1154    };
1155    let args = slice::from_raw_parts_mut(argv, argc as usize);
1156    let values = Values { args };
1157    let cr = cursor as *mut C;
1158    cursor_error(cursor, (*cr).filter(idx_num, idx_name, &values))
1159}
1160
1161unsafe extern "C" fn rust_next<C>(cursor: *mut ffi::sqlite3_vtab_cursor) -> c_int
1162where
1163    C: VTabCursor,
1164{
1165    let cr = cursor as *mut C;
1166    cursor_error(cursor, (*cr).next())
1167}
1168
1169unsafe extern "C" fn rust_eof<C>(cursor: *mut ffi::sqlite3_vtab_cursor) -> c_int
1170where
1171    C: VTabCursor,
1172{
1173    let cr = cursor.cast::<C>();
1174    (*cr).eof() as c_int
1175}
1176
1177unsafe extern "C" fn rust_column<C>(
1178    cursor: *mut ffi::sqlite3_vtab_cursor,
1179    ctx: *mut ffi::sqlite3_context,
1180    i: c_int,
1181) -> c_int
1182where
1183    C: VTabCursor,
1184{
1185    let cr = cursor.cast::<C>();
1186    let mut ctxt = Context(ctx);
1187    result_error(ctx, (*cr).column(&mut ctxt, i))
1188}
1189
1190unsafe extern "C" fn rust_rowid<C>(
1191    cursor: *mut ffi::sqlite3_vtab_cursor,
1192    p_rowid: *mut ffi::sqlite3_int64,
1193) -> c_int
1194where
1195    C: VTabCursor,
1196{
1197    let cr = cursor.cast::<C>();
1198    match (*cr).rowid() {
1199        Ok(rowid) => {
1200            *p_rowid = rowid;
1201            ffi::SQLITE_OK
1202        }
1203        err => cursor_error(cursor, err),
1204    }
1205}
1206
1207unsafe extern "C" fn rust_update<'vtab, T: 'vtab>(
1208    vtab: *mut ffi::sqlite3_vtab,
1209    argc: c_int,
1210    argv: *mut *mut ffi::sqlite3_value,
1211    p_rowid: *mut ffi::sqlite3_int64,
1212) -> c_int
1213where
1214    T: UpdateVTab<'vtab>,
1215{
1216    assert!(argc >= 1);
1217    let args = slice::from_raw_parts_mut(argv, argc as usize);
1218    let vt = vtab.cast::<T>();
1219    let r = if args.len() == 1 {
1220        (*vt).delete(ValueRef::from_value(args[0]))
1221    } else if ffi::sqlite3_value_type(args[0]) == ffi::SQLITE_NULL {
1222        let values = Values { args };
1224        match (*vt).insert(&values) {
1225            Ok(rowid) => {
1226                *p_rowid = rowid;
1227                Ok(())
1228            }
1229            Err(e) => Err(e),
1230        }
1231    } else {
1232        let values = Values { args };
1233        (*vt).update(&values)
1234    };
1235    match r {
1236        Ok(_) => ffi::SQLITE_OK,
1237        Err(Error::SqliteFailure(err, s)) => {
1238            if let Some(err_msg) = s {
1239                set_err_msg(vtab, &err_msg);
1240            }
1241            err.extended_code
1242        }
1243        Err(err) => {
1244            set_err_msg(vtab, &err.to_string());
1245            ffi::SQLITE_ERROR
1246        }
1247    }
1248}
1249
1250#[cold]
1253unsafe fn cursor_error<T>(cursor: *mut ffi::sqlite3_vtab_cursor, result: Result<T>) -> c_int {
1254    match result {
1255        Ok(_) => ffi::SQLITE_OK,
1256        Err(Error::SqliteFailure(err, s)) => {
1257            if let Some(err_msg) = s {
1258                set_err_msg((*cursor).pVtab, &err_msg);
1259            }
1260            err.extended_code
1261        }
1262        Err(err) => {
1263            set_err_msg((*cursor).pVtab, &err.to_string());
1264            ffi::SQLITE_ERROR
1265        }
1266    }
1267}
1268
1269#[cold]
1272unsafe fn set_err_msg(vtab: *mut ffi::sqlite3_vtab, err_msg: &str) {
1273    if !(*vtab).zErrMsg.is_null() {
1274        ffi::sqlite3_free((*vtab).zErrMsg.cast::<c_void>());
1275    }
1276    (*vtab).zErrMsg = alloc(err_msg);
1277}
1278
1279#[cold]
1282unsafe fn result_error<T>(ctx: *mut ffi::sqlite3_context, result: Result<T>) -> c_int {
1283    match result {
1284        Ok(_) => ffi::SQLITE_OK,
1285        Err(Error::SqliteFailure(err, s)) => {
1286            match err.extended_code {
1287                ffi::SQLITE_TOOBIG => {
1288                    ffi::sqlite3_result_error_toobig(ctx);
1289                }
1290                ffi::SQLITE_NOMEM => {
1291                    ffi::sqlite3_result_error_nomem(ctx);
1292                }
1293                code => {
1294                    ffi::sqlite3_result_error_code(ctx, code);
1295                    if let Some(Ok(cstr)) = s.map(|s| str_to_cstring(&s)) {
1296                        ffi::sqlite3_result_error(ctx, cstr.as_ptr(), -1);
1297                    }
1298                }
1299            };
1300            err.extended_code
1301        }
1302        Err(err) => {
1303            ffi::sqlite3_result_error_code(ctx, ffi::SQLITE_ERROR);
1304            if let Ok(cstr) = str_to_cstring(&err.to_string()) {
1305                ffi::sqlite3_result_error(ctx, cstr.as_ptr(), -1);
1306            }
1307            ffi::SQLITE_ERROR
1308        }
1309    }
1310}
1311
1312fn alloc(s: &str) -> *mut c_char {
1315    crate::util::SqliteMallocString::from_str(s).into_raw()
1316}
1317
1318#[cfg(feature = "array")]
1319#[cfg_attr(docsrs, doc(cfg(feature = "array")))]
1320pub mod array;
1321#[cfg(feature = "csvtab")]
1322#[cfg_attr(docsrs, doc(cfg(feature = "csvtab")))]
1323pub mod csvtab;
1324#[cfg(feature = "series")]
1325#[cfg_attr(docsrs, doc(cfg(feature = "series")))]
1326pub mod series; #[cfg(all(test, feature = "modern_sqlite"))]
1328mod vtablog;
1329
1330#[cfg(test)]
1331mod test {
1332    #[test]
1333    fn test_dequote() {
1334        assert_eq!("", super::dequote(""));
1335        assert_eq!("'", super::dequote("'"));
1336        assert_eq!("\"", super::dequote("\""));
1337        assert_eq!("'\"", super::dequote("'\""));
1338        assert_eq!("", super::dequote("''"));
1339        assert_eq!("", super::dequote("\"\""));
1340        assert_eq!("x", super::dequote("'x'"));
1341        assert_eq!("x", super::dequote("\"x\""));
1342        assert_eq!("x", super::dequote("x"));
1343    }
1344    #[test]
1345    fn test_parse_boolean() {
1346        assert_eq!(None, super::parse_boolean(""));
1347        assert_eq!(Some(true), super::parse_boolean("1"));
1348        assert_eq!(Some(true), super::parse_boolean("yes"));
1349        assert_eq!(Some(true), super::parse_boolean("on"));
1350        assert_eq!(Some(true), super::parse_boolean("true"));
1351        assert_eq!(Some(false), super::parse_boolean("0"));
1352        assert_eq!(Some(false), super::parse_boolean("no"));
1353        assert_eq!(Some(false), super::parse_boolean("off"));
1354        assert_eq!(Some(false), super::parse_boolean("false"));
1355    }
1356}