diff --git a/src/vtab/array.rs b/src/vtab/array.rs index 2143ad4..dadd637 100644 --- a/src/vtab/array.rs +++ b/src/vtab/array.rs @@ -91,8 +91,8 @@ unsafe impl<'vtab> VTab<'vtab> for ArrayTab { fn best_index(&self, info: &mut IndexInfo) -> Result<()> { // Index of the pointer= constraint - let mut ptr_idx = None; - for (i, constraint) in info.constraints().enumerate() { + let mut ptr_idx = false; + for (constraint, mut constraint_usage) in info.constraints_and_usages() { if !constraint.is_usable() { continue; } @@ -100,15 +100,12 @@ unsafe impl<'vtab> VTab<'vtab> for ArrayTab { continue; } if let CARRAY_COLUMN_POINTER = constraint.column() { - ptr_idx = Some(i); - } - } - if let Some(ptr_idx) = ptr_idx { - { - let mut constraint_usage = info.constraint_usage(ptr_idx); + ptr_idx = true; constraint_usage.set_argv_index(1); constraint_usage.set_omit(true); } + } + if ptr_idx { info.set_estimated_cost(1f64); info.set_estimated_rows(100); info.set_idx_num(1); diff --git a/src/vtab/mod.rs b/src/vtab/mod.rs index 12d71e2..8398c47 100644 --- a/src/vtab/mod.rs +++ b/src/vtab/mod.rs @@ -309,6 +309,19 @@ impl From for IndexConstraintOp { pub struct IndexInfo(*mut ffi::sqlite3_index_info); impl IndexInfo { + /// Iterate on index constraint and its associated usage. + #[inline] + pub fn constraints_and_usages(&mut self) -> IndexConstraintAndUsageIter<'_> { + let constraints = + unsafe { slice::from_raw_parts((*self.0).aConstraint, (*self.0).nConstraint as usize) }; + let constraint_usages = unsafe { + slice::from_raw_parts_mut((*self.0).aConstraintUsage, (*self.0).nConstraint as usize) + }; + IndexConstraintAndUsageIter { + iter: constraints.iter().zip(constraint_usages.iter_mut()), + } + } + /// Record WHERE clause constraints. #[inline] pub fn constraints(&self) -> IndexConstraintIter<'_> { @@ -384,6 +397,30 @@ impl IndexInfo { // TODO sqlite3_vtab_collation (http://sqlite.org/c3ref/vtab_collation.html) } +/// Iterate on index constraint and its associated usage. +pub struct IndexConstraintAndUsageIter<'a> { + iter: std::iter::Zip< + slice::Iter<'a, ffi::sqlite3_index_constraint>, + slice::IterMut<'a, ffi::sqlite3_index_constraint_usage>, + >, +} + +impl<'a> Iterator for IndexConstraintAndUsageIter<'a> { + type Item = (IndexConstraint<'a>, IndexConstraintUsage<'a>); + + #[inline] + fn next(&mut self) -> Option<(IndexConstraint<'a>, IndexConstraintUsage<'a>)> { + self.iter + .next() + .map(|raw| (IndexConstraint(raw.0), IndexConstraintUsage(raw.1))) + } + + #[inline] + fn size_hint(&self) -> (usize, Option) { + self.iter.size_hint() + } +} + /// `feature = "vtab"` pub struct IndexConstraintIter<'a> { iter: slice::Iter<'a, ffi::sqlite3_index_constraint>,