use mongreldb_kit::{ApproxAggKind, Column, ColumnType, Database, Schema, Table};
use serde_json::json;
use std::path::PathBuf;
fn temp_dir() -> PathBuf {
tempfile::tempdir().unwrap().keep()
}
fn schema() -> Schema {
Schema::new(vec![Table {
id: 1,
name: "t".into(),
columns: vec![
Column::new(1, "id", ColumnType::Int64),
Column::new(2, "val", ColumnType::Int64),
],
primary_key: vec!["id".into()],
indexes: vec![],
foreign_keys: vec![],
unique_constraints: vec![],
check_constraints: vec![],
}])
.unwrap()
}
#[test]
fn approx_aggregate_estimates_with_ci() {
let db = Database::create(&temp_dir(), schema()).unwrap();
let n = 1000i64;
let rows: Vec<_> = (1..=n)
.map(|i| {
[("id".to_string(), json!(i)), ("val".to_string(), json!(i))]
.into_iter()
.collect()
})
.collect();
db.transaction(1, |tx| {
tx.insert_many("t", rows.clone())?;
Ok(())
})
.unwrap();
let c = db
.approx_aggregate("t", None, ApproxAggKind::Count, 1.96)
.unwrap()
.expect("reservoir populated");
assert_eq!(c.n_population, n as u64);
assert!(c.n_sample_live > 0);
assert!(
(c.point - n as f64).abs() < 1e-6,
"point {} vs {n}",
c.point
);
assert!(c.ci_low <= c.point && c.point <= c.ci_high);
let a = db
.approx_aggregate("t", Some("val"), ApproxAggKind::Avg, 1.96)
.unwrap()
.expect("reservoir populated");
assert!(
a.point > 100.0 && a.point < 900.0,
"avg estimate {}",
a.point
);
assert!(db
.approx_aggregate("t", None, ApproxAggKind::Sum, 1.96)
.is_err());
}