mirror of
https://github.com/isar/rusqlite.git
synced 2025-11-01 14:28:55 +08:00
Add some missing wrappers (#1139)
* Add some missing wrappers: sqlite3_value_subtype sqlite3_result_subtype sqlite3_changes64 sqlite3_db_readonly sqlite3_txn_state sqlite3_stmt_isexplain sqlite3_vtab_config sqlite3_index_info.idxFlags sqlite3_index_info.colUsed sqlite3_index_info.idxStr sqlite3_vtab_collation * Mark series VTab as innocuous and csv as direct only
This commit is contained in:
@@ -31,7 +31,7 @@ use crate::ffi;
|
||||
use crate::types::Null;
|
||||
use crate::vtab::{
|
||||
dequote, escape_double_quote, parse_boolean, read_only_module, Context, CreateVTab, IndexInfo,
|
||||
VTab, VTabConnection, VTabCursor, Values,
|
||||
VTab, VTabConfig, VTabConnection, VTabCursor, Values,
|
||||
};
|
||||
use crate::{Connection, Error, Result};
|
||||
|
||||
@@ -101,7 +101,7 @@ unsafe impl<'vtab> VTab<'vtab> for CsvTab {
|
||||
type Cursor = CsvTabCursor<'vtab>;
|
||||
|
||||
fn connect(
|
||||
_: &mut VTabConnection,
|
||||
db: &mut VTabConnection,
|
||||
_aux: Option<&()>,
|
||||
args: &[&[u8]],
|
||||
) -> Result<(String, CsvTab)> {
|
||||
@@ -249,7 +249,7 @@ unsafe impl<'vtab> VTab<'vtab> for CsvTab {
|
||||
}
|
||||
schema = Some(sql);
|
||||
}
|
||||
|
||||
db.config(VTabConfig::DirectOnly)?;
|
||||
Ok((schema.unwrap(), vtab))
|
||||
}
|
||||
|
||||
|
||||
104
src/vtab/mod.rs
104
src/vtab/mod.rs
@@ -165,13 +165,32 @@ pub fn eponymous_only_module<'vtab, T: VTab<'vtab>>() -> &'static Module<'vtab,
|
||||
}
|
||||
}
|
||||
|
||||
/// Virtual table configuration options
|
||||
#[repr(i32)]
|
||||
#[non_exhaustive]
|
||||
#[cfg(feature = "modern_sqlite")] // 3.7.7
|
||||
#[derive(Debug, Clone, Copy, PartialEq)]
|
||||
pub enum VTabConfig {
|
||||
/// Equivalent to SQLITE_VTAB_CONSTRAINT_SUPPORT
|
||||
ConstraintSupport = 1,
|
||||
/// Equivalent to SQLITE_VTAB_INNOCUOUS
|
||||
Innocuous = 2,
|
||||
/// Equivalent to SQLITE_VTAB_DIRECTONLY
|
||||
DirectOnly = 3,
|
||||
}
|
||||
|
||||
/// `feature = "vtab"`
|
||||
pub struct VTabConnection(*mut ffi::sqlite3);
|
||||
|
||||
impl VTabConnection {
|
||||
// TODO sqlite3_vtab_config (http://sqlite.org/c3ref/vtab_config.html)
|
||||
/// Configure various facets of the virtual table interface
|
||||
#[cfg(feature = "modern_sqlite")] // 3.7.7
|
||||
#[cfg_attr(docsrs, doc(cfg(feature = "modern_sqlite")))]
|
||||
pub fn config(&mut self, config: VTabConfig) -> Result<()> {
|
||||
crate::error::check(unsafe { ffi::sqlite3_vtab_config(self.0, config as c_int) })
|
||||
}
|
||||
|
||||
// TODO sqlite3_vtab_on_conflict (http://sqlite.org/c3ref/vtab_on_conflict.html)
|
||||
// TODO sqlite3_vtab_on_conflict (http://sqlite.org/c3ref/vtab_on_conflict.html) & xUpdate
|
||||
|
||||
/// Get access to the underlying SQLite database connection handle.
|
||||
///
|
||||
@@ -310,10 +329,24 @@ impl From<u8> for IndexConstraintOp {
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "modern_sqlite")] // 3.9.0
|
||||
bitflags::bitflags! {
|
||||
/// Virtual table scan flags
|
||||
/// See [Function Flags](https://sqlite.org/c3ref/c_index_scan_unique.html) for details.
|
||||
#[repr(C)]
|
||||
pub struct IndexFlags: ::std::os::raw::c_int {
|
||||
/// Default
|
||||
const NONE = 0;
|
||||
/// Scan visits at most 1 row.
|
||||
const SQLITE_INDEX_SCAN_UNIQUE = ffi::SQLITE_INDEX_SCAN_UNIQUE;
|
||||
}
|
||||
}
|
||||
|
||||
/// Pass information into and receive the reply from the
|
||||
/// [`VTab::best_index`] method.
|
||||
///
|
||||
/// (See [SQLite doc](http://sqlite.org/c3ref/index_info.html))
|
||||
#[derive(Debug)]
|
||||
pub struct IndexInfo(*mut ffi::sqlite3_index_info);
|
||||
|
||||
impl IndexInfo {
|
||||
@@ -376,6 +409,14 @@ impl IndexInfo {
|
||||
}
|
||||
}
|
||||
|
||||
/// String used to identify the index
|
||||
pub fn set_idx_str(&mut self, idx_str: &str) {
|
||||
unsafe {
|
||||
(*self.0).idxStr = alloc(idx_str);
|
||||
(*self.0).needToFreeIdxStr = 1;
|
||||
}
|
||||
}
|
||||
|
||||
/// True if output is already ordered
|
||||
#[inline]
|
||||
pub fn set_order_by_consumed(&mut self, order_by_consumed: bool) {
|
||||
@@ -402,10 +443,60 @@ impl IndexInfo {
|
||||
}
|
||||
}
|
||||
|
||||
// TODO idxFlags
|
||||
// TODO colUsed
|
||||
/// Mask of SQLITE_INDEX_SCAN_* flags.
|
||||
#[cfg(feature = "modern_sqlite")] // SQLite >= 3.9.0
|
||||
#[cfg_attr(docsrs, doc(cfg(feature = "modern_sqlite")))]
|
||||
#[inline]
|
||||
pub fn set_idx_flags(&mut self, flags: IndexFlags) {
|
||||
unsafe { (*self.0).idxFlags = flags.bits() };
|
||||
}
|
||||
|
||||
// TODO sqlite3_vtab_collation (http://sqlite.org/c3ref/vtab_collation.html)
|
||||
/// Mask of columns used by statement
|
||||
#[cfg(feature = "modern_sqlite")] // SQLite >= 3.10.0
|
||||
#[cfg_attr(docsrs, doc(cfg(feature = "modern_sqlite")))]
|
||||
#[inline]
|
||||
pub fn col_used(&self) -> u64 {
|
||||
unsafe { (*self.0).colUsed }
|
||||
}
|
||||
|
||||
/// Determine the collation for a virtual table constraint
|
||||
#[cfg(feature = "modern_sqlite")] // SQLite >= 3.22.0
|
||||
#[cfg_attr(docsrs, doc(cfg(feature = "modern_sqlite")))]
|
||||
pub fn collation(&self, constraint_idx: usize) -> Result<&str> {
|
||||
use std::ffi::CStr;
|
||||
let idx = constraint_idx as c_int;
|
||||
let collation = unsafe { ffi::sqlite3_vtab_collation(self.0, idx) };
|
||||
if collation.is_null() {
|
||||
return Err(Error::SqliteFailure(
|
||||
ffi::Error::new(ffi::SQLITE_MISUSE),
|
||||
Some(format!("{} is out of range", constraint_idx)),
|
||||
));
|
||||
}
|
||||
Ok(unsafe { CStr::from_ptr(collation) }.to_str()?)
|
||||
}
|
||||
|
||||
/*/// Determine if a virtual table query is DISTINCT
|
||||
#[cfg(feature = "modern_sqlite")] // SQLite >= 3.38.0
|
||||
#[cfg_attr(docsrs, doc(cfg(feature = "modern_sqlite")))]
|
||||
pub fn distinct(&self) -> c_int {
|
||||
unsafe { ffi::sqlite3_vtab_distinct(self.0) }
|
||||
}
|
||||
|
||||
/// Constraint values
|
||||
#[cfg(feature = "modern_sqlite")] // SQLite >= 3.38.0
|
||||
#[cfg_attr(docsrs, doc(cfg(feature = "modern_sqlite")))]
|
||||
pub fn set_rhs_value(&mut self, constraint_idx: c_int, value: ValueRef) -> Result<()> {
|
||||
// TODO ValueRef to sqlite3_value
|
||||
crate::error::check(unsafe { ffi::sqlite3_vtab_rhs_value(self.O, constraint_idx, value) })
|
||||
}
|
||||
|
||||
/// Identify and handle IN constraints
|
||||
#[cfg(feature = "modern_sqlite")] // SQLite >= 3.38.0
|
||||
#[cfg_attr(docsrs, doc(cfg(feature = "modern_sqlite")))]
|
||||
pub fn set_in_constraint(&mut self, constraint_idx: c_int, b_handle: c_int) -> bool {
|
||||
unsafe { ffi::sqlite3_vtab_in(self.0, constraint_idx, b_handle) != 0 }
|
||||
} // TODO sqlite3_vtab_in_first / sqlite3_vtab_in_next https://sqlite.org/c3ref/vtab_in_first.html
|
||||
*/
|
||||
}
|
||||
|
||||
/// Iterate on index constraint and its associated usage.
|
||||
@@ -583,7 +674,7 @@ impl Context {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
// TODO sqlite3_vtab_nochange (http://sqlite.org/c3ref/vtab_nochange.html)
|
||||
// TODO sqlite3_vtab_nochange (http://sqlite.org/c3ref/vtab_nochange.html) // 3.22.0 & xColumn
|
||||
}
|
||||
|
||||
/// Wrapper to [`VTabCursor::filter`] arguments, the values
|
||||
@@ -651,6 +742,7 @@ impl Values<'_> {
|
||||
iter: self.args.iter(),
|
||||
}
|
||||
}
|
||||
// TODO sqlite3_vtab_in_first / sqlite3_vtab_in_next https://sqlite.org/c3ref/vtab_in_first.html & 3.38.0
|
||||
}
|
||||
|
||||
impl<'a> IntoIterator for &'a Values<'a> {
|
||||
|
||||
@@ -10,8 +10,8 @@ use std::os::raw::c_int;
|
||||
use crate::ffi;
|
||||
use crate::types::Type;
|
||||
use crate::vtab::{
|
||||
eponymous_only_module, Context, IndexConstraintOp, IndexInfo, VTab, VTabConnection, VTabCursor,
|
||||
Values,
|
||||
eponymous_only_module, Context, IndexConstraintOp, IndexInfo, VTab, VTabConfig, VTabConnection,
|
||||
VTabCursor, Values,
|
||||
};
|
||||
use crate::{Connection, Error, Result};
|
||||
|
||||
@@ -57,13 +57,14 @@ unsafe impl<'vtab> VTab<'vtab> for SeriesTab {
|
||||
type Cursor = SeriesTabCursor<'vtab>;
|
||||
|
||||
fn connect(
|
||||
_: &mut VTabConnection,
|
||||
db: &mut VTabConnection,
|
||||
_aux: Option<&()>,
|
||||
_args: &[&[u8]],
|
||||
) -> Result<(String, SeriesTab)> {
|
||||
let vtab = SeriesTab {
|
||||
base: ffi::sqlite3_vtab::default(),
|
||||
};
|
||||
db.config(VTabConfig::Innocuous)?;
|
||||
Ok((
|
||||
"CREATE TABLE x(value,start hidden,stop hidden,step hidden)".to_owned(),
|
||||
vtab,
|
||||
@@ -103,6 +104,8 @@ unsafe impl<'vtab> VTab<'vtab> for SeriesTab {
|
||||
let mut constraint_usage = info.constraint_usage(*j);
|
||||
constraint_usage.set_argv_index(n_arg);
|
||||
constraint_usage.set_omit(true);
|
||||
#[cfg(all(test, feature = "modern_sqlite"))]
|
||||
debug_assert_eq!(Ok("BINARY"), info.collation(*j));
|
||||
}
|
||||
if !(unusable_mask & !idx_num).is_empty() {
|
||||
return Err(Error::SqliteFailure(
|
||||
|
||||
Reference in New Issue
Block a user