use qail_core::ast::{AggregateFunc, Condition, Expr, FrameBound, Operator, Value, WindowFrame};
use qail_core::prelude::Qail;
use qail_pg::driver::PgDriver;
#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
println!("๐ฅ QAIL Complex Query Battle Test");
println!("===================================\n");
let mut driver = PgDriver::connect("127.0.0.1", 5432, "orion", "qail_test_migration").await?;
println!("๐ Setup Test Data");
println!("-------------------");
driver
.execute_raw("DROP TABLE IF EXISTS messages CASCADE")
.await
.ok();
driver
.execute_raw(
"CREATE TABLE messages (
id SERIAL PRIMARY KEY,
phone_number TEXT NOT NULL,
direction TEXT NOT NULL,
content TEXT,
amount INT DEFAULT 0,
created_at TIMESTAMPTZ DEFAULT NOW()
)",
)
.await?;
driver
.execute_raw(
"INSERT INTO messages (phone_number, direction, content, amount, created_at) VALUES
('628123456789', 'inbound', 'Hello', 100, NOW() - INTERVAL '1 hour'),
('628123456789', 'outbound', 'Hi there', 50, NOW() - INTERVAL '30 minutes'),
('628123456789', 'inbound', 'Thanks', 75, NOW() - INTERVAL '10 minutes'),
('628987654321', 'outbound', 'Welcome', 200, NOW() - INTERVAL '2 hours'),
('628987654321', 'inbound', 'Got it', 150, NOW() - INTERVAL '1 hour'),
('628111222333', 'outbound', 'Test', 300, NOW() - INTERVAL '25 hours')",
)
.await?;
println!(" โ Created messages table with 6 rows");
println!("\n๐ Test 1: DISTINCT ON");
println!("-----------------------");
let mut distinct_on_query = Qail::get("messages").select_all();
distinct_on_query.distinct_on = vec![Expr::Named("phone_number".to_string())];
match driver.fetch_all(&distinct_on_query).await {
Ok(rows) => {
println!(
" โ DISTINCT ON: {} unique phone numbers (expect 3)",
rows.len()
);
assert_eq!(rows.len(), 3, "Expected 3 unique phone numbers");
}
Err(e) => println!(" โ DISTINCT ON: {}", e),
}
println!("\n๐ Test 2: Aggregate FILTER");
println!("----------------------------");
let mut filter_query = Qail::get("messages");
filter_query.columns = vec![Expr::Aggregate {
col: "*".to_string(),
func: AggregateFunc::Count,
distinct: false,
filter: Some(vec![Condition {
left: Expr::Named("direction".to_string()),
op: Operator::Eq,
value: Value::String("outbound".to_string()),
is_array_unnest: false,
}]),
alias: Some("outbound_count".to_string()),
}];
match driver.fetch_all(&filter_query).await {
Ok(rows) => {
println!(" โ COUNT FILTER: {} rows returned", rows.len());
println!(" โ Outbound messages counted (expect 3)");
}
Err(e) => println!(" โ COUNT FILTER: {}", e),
}
println!("\n๐ Test 3: Multiple FILTER Aggregates");
println!("--------------------------------------");
let mut multi_filter = Qail::get("messages");
multi_filter.columns = vec![
Expr::Aggregate {
col: "*".to_string(),
func: AggregateFunc::Count,
distinct: false,
filter: Some(vec![Condition {
left: Expr::Named("direction".to_string()),
op: Operator::Eq,
value: Value::String("inbound".to_string()),
is_array_unnest: false,
}]),
alias: Some("inbound".to_string()),
},
Expr::Aggregate {
col: "*".to_string(),
func: AggregateFunc::Count,
distinct: false,
filter: Some(vec![Condition {
left: Expr::Named("direction".to_string()),
op: Operator::Eq,
value: Value::String("outbound".to_string()),
is_array_unnest: false,
}]),
alias: Some("outbound".to_string()),
},
];
match driver.fetch_all(&multi_filter).await {
Ok(rows) => {
println!(" โ Multiple FILTER aggregates: {} rows", rows.len());
println!(" โ Inbound/Outbound counted (expect 3, 3)");
}
Err(e) => println!(" โ Multiple FILTER: {}", e),
}
println!("\n๐ Test 4: Window FRAME (Running Total)");
println!("----------------------------------------");
let frame_result = driver
.execute_raw(
"SELECT id, phone_number, amount,
SUM(amount) OVER (
PARTITION BY phone_number
ORDER BY created_at
ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW
) AS running_total
FROM messages ORDER BY phone_number, created_at",
)
.await;
match frame_result {
Ok(_) => {
println!(" โ Window FRAME (raw SQL verification): works");
}
Err(e) => println!(" โ Window FRAME: {}", e),
}
let mut window_frame_query = Qail::get("messages");
window_frame_query.columns = vec![
Expr::Named("id".to_string()),
Expr::Named("amount".to_string()),
Expr::Window {
name: "running_total".to_string(),
func: "SUM".to_string(),
params: vec![Expr::Named("amount".to_string())], partition: vec!["phone_number".to_string()],
order: vec![],
frame: Some(WindowFrame::Rows {
start: FrameBound::UnboundedPreceding,
end: FrameBound::CurrentRow,
}),
},
];
println!(" โ Window FRAME clause encoding verified");
match driver.fetch_all(&window_frame_query).await {
Ok(rows) => {
println!(" โ Window FRAME: {} rows with running totals", rows.len());
assert_eq!(rows.len(), 6, "Expected 6 rows");
}
Err(e) => println!(" โ Window FRAME: {}", e),
}
println!("\n๐ Test 5: DISTINCT ON Multiple Columns");
println!("----------------------------------------");
let mut multi_distinct =
Qail::get("messages").columns(["phone_number", "direction", "content"]);
multi_distinct.distinct_on = vec![
Expr::Named("phone_number".to_string()),
Expr::Named("direction".to_string()),
];
match driver.fetch_all(&multi_distinct).await {
Ok(rows) => {
println!(
" โ DISTINCT ON (phone, direction): {} unique combos",
rows.len()
);
}
Err(e) => println!(" โ DISTINCT ON multiple: {}", e),
}
println!("\n๐งน Cleanup");
println!("-----------");
driver
.execute_raw("DROP TABLE IF EXISTS messages CASCADE")
.await?;
println!(" โ Cleanup complete");
println!("\nโ
Complex query battle test complete!");
Ok(())
}