#![cfg(any(feature = "sqlite", feature = "postgresql", feature = "mysql"))]
mod _test_common;
define_test_user_with_score!(TestGroupedE2EUser, "test_grouped_e2e_basic_1");
use ormer::model::{FromRowValues, Value};
#[allow(dead_code)]
#[derive(Debug, Clone)]
struct AgeGroupStats {
age: i32,
user_count: i64,
avg_score: f64,
}
impl FromRowValues for AgeGroupStats {
fn from_row_values(values: &[Value]) -> ormer::Result<Self> {
if values.len() < 3 {
return Err(ormer::ormer_error!("Expected at least 3 values"));
}
let age = match &values[0] {
Value::Integer(i) => *i as i32,
_ => {
return Err(ormer::ormer_error!("Expected integer for age"));
}
};
let user_count = match &values[1] {
Value::Integer(i) => *i,
_ => {
return Err(ormer::ormer_error!("Expected integer for user_count"));
}
};
let avg_score = match &values[2] {
Value::Real(f) => *f,
_ => {
return Err(ormer::ormer_error!("Expected real for avg_score"));
}
};
Ok(AgeGroupStats {
age,
user_count,
avg_score,
})
}
}
async fn test_grouped_select_basic_impl(
config: &_test_common::DbConfig,
) -> Result<(), Box<dyn std::error::Error>> {
let db = _test_common::create_db_connection(config).await?;
let _ = db.drop_table::<TestGroupedE2EUser>().execute().await;
db.create_table::<TestGroupedE2EUser>().execute().await?;
let users = vec![
TestGroupedE2EUser {
id: 1,
name: "Alice".to_string(),
age: 20,
score: 85,
},
TestGroupedE2EUser {
id: 2,
name: "Bob".to_string(),
age: 20,
score: 90,
},
TestGroupedE2EUser {
id: 3,
name: "Charlie".to_string(),
age: 25,
score: 78,
},
TestGroupedE2EUser {
id: 4,
name: "Diana".to_string(),
age: 25,
score: 92,
},
TestGroupedE2EUser {
id: 5,
name: "Eve".to_string(),
age: 20,
score: 88,
},
];
for user in users {
db.insert(&user).execute().await?;
}
let count: Vec<ormer::query::builder::TypedColumn<usize, TestGroupedE2EUser>> = db
.select::<TestGroupedE2EUser>()
.select_column(|u| u.id.count())
.group_by(|u| u.age)
.collect()
.await?;
println!("GROUP BY count result: {:?} groups", count.len());
assert_eq!(count.len(), 2);
let _ = db.drop_table::<TestGroupedE2EUser>().execute().await;
Ok(())
}
test_on_all_dbs_result!(test_grouped_select_basic_impl);
async fn test_grouped_select_with_having_impl(
config: &_test_common::DbConfig,
) -> Result<(), Box<dyn std::error::Error>> {
define_test_user_with_score!(TestGroupedE2EUserHaving, "test_grouped_e2e_having_2");
let db = _test_common::create_db_connection(config).await?;
let _ = db.drop_table::<TestGroupedE2EUserHaving>().execute().await;
db.create_table::<TestGroupedE2EUserHaving>()
.execute()
.await?;
let users = vec![
TestGroupedE2EUserHaving {
id: 1,
name: "Alice".to_string(),
age: 20,
score: 85,
},
TestGroupedE2EUserHaving {
id: 2,
name: "Bob".to_string(),
age: 20,
score: 90,
},
TestGroupedE2EUserHaving {
id: 3,
name: "Charlie".to_string(),
age: 25,
score: 78,
},
];
for user in users {
db.insert(&user).execute().await?;
}
let count: Vec<ormer::query::builder::TypedColumn<usize, TestGroupedE2EUserHaving>> = db
.select::<TestGroupedE2EUserHaving>()
.select_column(|u| u.id.count())
.group_by(|u| u.age)
.having(|u| u.id.count().ge(2))
.collect()
.await?;
println!("GROUP BY HAVING result: {:?} groups", count.len());
assert_eq!(count.len(), 1);
let _ = db.drop_table::<TestGroupedE2EUserHaving>().execute().await;
Ok(())
}
test_on_all_dbs_result!(test_grouped_select_with_having_impl);
async fn test_grouped_select_with_filter_impl(
config: &_test_common::DbConfig,
) -> Result<(), Box<dyn std::error::Error>> {
define_test_user_with_score!(TestGroupedE2EUserFilter, "test_grouped_e2e_filter_3");
let db = _test_common::create_db_connection(config).await?;
let _ = db.drop_table::<TestGroupedE2EUserFilter>().execute().await;
db.create_table::<TestGroupedE2EUserFilter>()
.execute()
.await?;
let users = vec![
TestGroupedE2EUserFilter {
id: 1,
name: "Alice".to_string(),
age: 20,
score: 85,
},
TestGroupedE2EUserFilter {
id: 2,
name: "Bob".to_string(),
age: 20,
score: 90,
},
TestGroupedE2EUserFilter {
id: 3,
name: "Charlie".to_string(),
age: 25,
score: 78,
},
TestGroupedE2EUserFilter {
id: 4,
name: "Diana".to_string(),
age: 25,
score: 95,
},
];
for user in users {
db.insert(&user).execute().await?;
}
let count: Vec<ormer::query::builder::TypedColumn<usize, TestGroupedE2EUserFilter>> = db
.select::<TestGroupedE2EUserFilter>()
.select_column(|u| u.id.count())
.filter(|u| u.score.gt(80))
.group_by(|u| u.age)
.collect()
.await?;
println!("GROUP BY FILTER result: {:?} groups", count.len());
assert_eq!(count.len(), 2);
let _ = db.drop_table::<TestGroupedE2EUserFilter>().execute().await;
Ok(())
}
test_on_all_dbs_result!(test_grouped_select_with_filter_impl);