use vantage_dataset::traits::ReadableValueSet;
use super::{Rows, UNMATCHABLE};
use crate::{Capability, SortDirection, Vista, contract::Probe};
pub(super) async fn search(vista: &Vista, searched: &Vista, probe: &mut Probe) {
match (vista.count().await, searched.count().await) {
(Ok(all), Ok(found)) if found < all => {}
(Ok(all), Ok(found)) => probe.fail(format!(
"`{}` is advertised but with_search({UNMATCHABLE:?}) counts {found} of {all} rows: \
the search is not applied",
Capability::Search
)),
(Err(e), _) | (_, Err(e)) => probe.fail(format!(
"`{}` is advertised but count fails around with_search: {e}",
Capability::Search
)),
}
}
pub(super) async fn filter_gt(
filtered: &Vista,
column: &str,
all: &Rows,
pivot_id: &str,
probe: &mut Probe,
) {
let Ok(rows) = filtered.list_values().await else {
return;
};
let capability = Capability::FilterOps;
if rows.contains_key(pivot_id) {
probe.fail(format!(
"`{capability}` is advertised but with_condition({column} > <row {pivot_id}>) \
still lists row {pivot_id}: the condition is not applied"
));
}
if let Some(stray) = rows.keys().find(|id| !all.contains_key(*id)) {
probe.fail(format!(
"`{capability}` is advertised but with_condition({column} > ..) lists row {stray}, \
which the un-narrowed set does not hold"
));
}
}
pub(super) async fn order(vista: &Vista, asc: &Vista, column: &str, all: &Rows, probe: &mut Probe) {
if !distinct_values(vista, column, all) {
return;
}
let capability = Capability::Order;
let desc = match vista.clone().with_order(column, SortDirection::Descending) {
Ok(desc) => desc,
Err(e) => {
probe.check_ok(capability, "with_order(desc)", &Err::<(), _>(e));
return;
}
};
let (asc_rows, desc_rows) = match (asc.list_values().await, desc.list_values().await) {
(Ok(a), Ok(d)) => (a, d),
(Err(e), _) | (_, Err(e)) => {
probe.check_ok(capability, "list_values after with_order", &Err::<(), _>(e));
return;
}
};
let first_asc = asc_rows.keys().next();
if first_asc == desc_rows.keys().next() {
probe.fail(format!(
"`{capability}` is advertised but ordering by {column} ascending and descending \
both list row {} first: the order is not applied",
first_asc.map(String::as_str).unwrap_or("<none>")
));
}
}
fn distinct_values(vista: &Vista, column: &str, all: &Rows) -> bool {
if all.len() < 2 {
return false;
}
if vista.id_column() == Some(column) {
return true;
}
let mut values = all.values().map(|row| row.get(column));
let first = values.next().flatten();
values.any(|v| v != first)
}