use vibesql_types::SqlValue;
use crate::database::indexes::{
index_metadata::{acquire_btree_lock, IndexData},
value_normalization::normalize_for_comparison,
};
impl IndexData {
pub fn skip_scan_equality(
&self,
filter_column_idx: usize,
filter_value: &SqlValue,
) -> Vec<usize> {
if filter_column_idx == 0 {
return self.prefix_multi_lookup(std::slice::from_ref(filter_value));
}
let normalized_filter = normalize_for_comparison(filter_value);
match self {
IndexData::InMemory { data } => {
let mut matching_rows = Vec::new();
for (key, row_indices) in data.iter() {
if key.len() > filter_column_idx {
let key_filter_val = &key[filter_column_idx];
if *key_filter_val == normalized_filter {
matching_rows.extend(row_indices);
}
}
}
matching_rows
}
IndexData::DiskBacked { btree, .. } => match acquire_btree_lock(btree) {
Ok(guard) => guard
.skip_scan_equality(filter_column_idx, &normalized_filter)
.unwrap_or_else(|_| vec![]),
Err(e) => {
log::warn!("BTreeIndex lock acquisition failed in skip_scan_equality: {}", e);
vec![]
}
},
IndexData::IVFFlat { .. } | IndexData::Hnsw { .. } => {
vec![]
}
}
}
pub fn skip_scan_range(
&self,
filter_column_idx: usize,
lower_bound: Option<&SqlValue>,
inclusive_lower: bool,
upper_bound: Option<&SqlValue>,
inclusive_upper: bool,
) -> Vec<usize> {
if filter_column_idx == 0 {
return self.range_scan(lower_bound, upper_bound, inclusive_lower, inclusive_upper);
}
let normalized_lower = lower_bound.map(normalize_for_comparison);
let normalized_upper = upper_bound.map(normalize_for_comparison);
match self {
IndexData::InMemory { data } => {
let mut matching_rows = Vec::new();
for (key, row_indices) in data.iter() {
if key.len() > filter_column_idx {
let key_filter_val = &key[filter_column_idx];
let passes_lower = match &normalized_lower {
None => true,
Some(lb) => {
if inclusive_lower {
key_filter_val >= lb
} else {
key_filter_val > lb
}
}
};
let passes_upper = match &normalized_upper {
None => true,
Some(ub) => {
if inclusive_upper {
key_filter_val <= ub
} else {
key_filter_val < ub
}
}
};
if passes_lower && passes_upper {
matching_rows.extend(row_indices);
}
}
}
matching_rows
}
IndexData::DiskBacked { btree, .. } => match acquire_btree_lock(btree) {
Ok(guard) => guard
.skip_scan_range(
filter_column_idx,
normalized_lower.as_ref(),
inclusive_lower,
normalized_upper.as_ref(),
inclusive_upper,
)
.unwrap_or_else(|_| vec![]),
Err(e) => {
log::warn!("BTreeIndex lock acquisition failed in skip_scan_range: {}", e);
vec![]
}
},
IndexData::IVFFlat { .. } | IndexData::Hnsw { .. } => {
vec![]
}
}
}
}