use std::collections::HashMap;
use super::{FacetCounts, ScalarClauses, ScalarHit};
use crate::catalog::ValType;
use crate::seg_walk::Walker;
use crate::segment::Cursor;
use crate::value::{ValueTest, order_key};
use kevy_text::sorted_order;
pub(super) fn passes(w: &Walker<'_>, filters: &[(usize, ValueTest)], buf: &mut Vec<u8>) -> bool {
filters.iter().all(|(f, t)| w.column(*f, buf).is_some_and(|raw| t.passes(raw)))
}
fn clause_key(w: &Walker<'_>, field: usize, ty: ValType, buf: &mut Vec<u8>) -> Option<Vec<u8>> {
w.column(field, buf).and_then(|raw| order_key(ty, raw))
}
pub(super) fn count_facets(
w: &Walker<'_>,
c: &ScalarClauses<'_>,
facets: &mut [FacetCounts],
buf: &mut Vec<u8>,
) {
for ((f, ty), counts) in c.facets.iter().zip(facets.iter_mut()) {
let Some(raw) = w.column(*f, buf) else { continue };
let Some(id) = order_key(*ty, raw) else { continue };
match counts.get_mut(&id) {
Some(e) => e.1 += 1,
None => {
counts.insert(id, (raw.to_vec(), 1));
}
}
}
}
pub(super) fn select_hit(
w: &mut Walker<'_>,
c: &ScalarClauses<'_>,
hits: &mut Vec<ScalarHit>,
groups: &mut HashMap<Vec<u8>, usize>,
buf: &mut Vec<u8>,
) {
let okey = c.sort.and_then(|(f, _, ty)| clause_key(w, f, ty, buf));
let dkey = c.distinct.and_then(|(f, ty)| clause_key(w, f, ty, buf));
if let Some(id) = &dkey {
match groups.entry(id.clone()) {
std::collections::hash_map::Entry::Occupied(e) => {
let Some((_, order, _)) = c.sort else { return };
let k = w.key();
let prev = &mut hits[*e.get()];
if sorted_order((okey.as_deref(), k), (prev.okey.as_deref(), &prev.key), order)
== std::cmp::Ordering::Less
{
let (v, k) = w.pair();
*prev = ScalarHit { key: k.to_vec(), value: v.clone(), okey, dkey };
}
return;
}
std::collections::hash_map::Entry::Vacant(slot) => {
slot.insert(hits.len());
}
}
}
let (v, k) = w.pair();
hits.push(ScalarHit { key: k.to_vec(), value: v.clone(), okey, dkey });
}
pub(super) fn filter_cursor(c: &ScalarClauses<'_>, hits: &[ScalarHit]) -> Option<Cursor> {
if c.selects() || hits.len() < c.fetch {
return None;
}
hits.last().map(|h| Cursor { value: h.value.clone(), key: h.key.clone() })
}