use crate::types::{CompareOp, FilterExpr, SqlPlan, SqlValue};
const MAX_IN_LIST: usize = 1024;
#[derive(Debug, Clone)]
pub struct BitmapHint {
pub collection: String,
pub field: String,
pub primary_value: SqlValue,
pub extra_values: Vec<SqlValue>,
}
pub fn analyze(plan: &SqlPlan) -> Option<BitmapHint> {
match plan {
SqlPlan::DocumentIndexLookup {
collection,
field,
value,
..
} => Some(BitmapHint {
collection: collection.clone(),
field: field.clone(),
primary_value: value.clone(),
extra_values: Vec::new(),
}),
SqlPlan::Scan {
collection,
filters,
..
} => {
analyze_scan_filters(collection, filters)
}
_ => None,
}
}
fn analyze_scan_filters(collection: &str, filters: &[crate::types::Filter]) -> Option<BitmapHint> {
if filters.len() != 1 {
return None;
}
match &filters[0].expr {
FilterExpr::Comparison {
field,
op: CompareOp::Eq,
value,
} => Some(BitmapHint {
collection: collection.to_string(),
field: field.clone(),
primary_value: value.clone(),
extra_values: Vec::new(),
}),
FilterExpr::InList { field, values }
if !values.is_empty() && values.len() <= MAX_IN_LIST =>
{
let mut iter = values.iter().cloned();
let primary = iter.next()?;
Some(BitmapHint {
collection: collection.to_string(),
field: field.clone(),
primary_value: primary,
extra_values: iter.collect(),
})
}
_ => None,
}
}