#![allow(
clippy::cast_precision_loss,
clippy::cast_possible_truncation,
clippy::cast_sign_loss,
clippy::float_cmp
)]
#![cfg(all(test, feature = "persistence"))]
use crate::collection::Collection;
use crate::velesql::Parser;
use std::collections::HashMap;
use tempfile::TempDir;
#[test]
fn test_bug_5_aggregation_params_should_be_resolved() {
let temp_dir = TempDir::new().unwrap();
let collection = Collection::create(
temp_dir.path().to_path_buf(),
4,
crate::distance::DistanceMetric::Cosine,
)
.unwrap();
collection
.upsert(vec![crate::point::Point {
id: 1,
vector: vec![1.0, 0.0, 0.0, 0.0],
payload: Some(serde_json::json!({"category": "electronics", "price": 100.0})),
sparse_vectors: None,
}])
.unwrap();
collection
.upsert(vec![crate::point::Point {
id: 2,
vector: vec![0.0, 1.0, 0.0, 0.0],
payload: Some(serde_json::json!({"category": "electronics", "price": 200.0})),
sparse_vectors: None,
}])
.unwrap();
collection
.upsert(vec![crate::point::Point {
id: 3,
vector: vec![0.0, 0.0, 1.0, 0.0],
payload: Some(serde_json::json!({"category": "books", "price": 50.0})),
sparse_vectors: None,
}])
.unwrap();
let sql = "SELECT COUNT(*), SUM(price) FROM products WHERE category = $cat";
let query = Parser::parse(sql).expect("Query should parse");
let mut params: HashMap<String, serde_json::Value> = HashMap::new();
params.insert("cat".to_string(), serde_json::json!("electronics"));
let result = collection.execute_aggregate(&query, ¶ms);
assert!(
result.is_ok(),
"Aggregation should succeed: {:?}",
result.err()
);
let json = result.unwrap();
let count = json
.get("count")
.and_then(serde_json::Value::as_i64)
.unwrap_or(0);
assert_eq!(
count, 2,
"Should count only 'electronics' category (2 items). Got {}. Params may not be resolved.",
count
);
let sum = json
.get("sum_price")
.and_then(serde_json::Value::as_f64)
.unwrap_or(0.0);
assert!(
(sum - 300.0).abs() < 0.01,
"Sum should be 300.0 for electronics. Got {}",
sum
);
}
#[test]
fn test_bug_5_grouped_aggregation_with_params() {
let temp_dir = TempDir::new().unwrap();
let collection = Collection::create(
temp_dir.path().to_path_buf(),
4,
crate::distance::DistanceMetric::Cosine,
)
.unwrap();
for i in 0u64..5 {
collection
.upsert(vec![crate::point::Point {
id: i,
vector: vec![i as f32, 0.0, 0.0, 0.0],
payload: Some(serde_json::json!({
"category": if i < 3 { "A" } else { "B" },
"price": (i + 1) * 10
})),
sparse_vectors: None,
}])
.unwrap();
}
let sql = "SELECT category, COUNT(*) FROM products WHERE price > $min GROUP BY category";
let query = Parser::parse(sql).expect("Query should parse");
let mut params: HashMap<String, serde_json::Value> = HashMap::new();
params.insert("min".to_string(), serde_json::json!(20));
let result = collection.execute_aggregate(&query, ¶ms);
assert!(
result.is_ok(),
"Grouped aggregation with params should work: {:?}",
result.err()
);
}