use qail_core::ast::builders::*;
use qail_core::ast::{Qail, SortOrder};
use qail_pg::PgDriver;
#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
let mut driver = PgDriver::connect("localhost", 5432, "orion", "postgres").await?;
println!("✅ Connected to PostgreSQL\n");
let mut passed = 0;
let mut failed = 0;
println!("━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━");
println!("FLUENT METHODS (ExprExt)");
println!("━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━");
let q = Qail::get("harbors")
.column_expr("name".upper().with_alias("u"))
.limit(1);
match driver.fetch_all(&q).await {
Ok(_) => {
passed += 1;
println!("✅ upper()");
}
Err(e) => {
failed += 1;
println!("❌ upper(): {}", e);
}
}
let q = Qail::get("harbors")
.column_expr("name".lower().with_alias("l"))
.limit(1);
match driver.fetch_all(&q).await {
Ok(_) => {
passed += 1;
println!("✅ lower()");
}
Err(e) => {
failed += 1;
println!("❌ lower(): {}", e);
}
}
let q = Qail::get("harbors")
.column_expr("name".trim().with_alias("t"))
.limit(1);
match driver.fetch_all(&q).await {
Ok(_) => {
passed += 1;
println!("✅ trim()");
}
Err(e) => {
failed += 1;
println!("❌ trim(): {}", e);
}
}
let q = Qail::get("harbors")
.column_expr("name".length().with_alias("len"))
.limit(1);
match driver.fetch_all(&q).await {
Ok(_) => {
passed += 1;
println!("✅ length()");
}
Err(e) => {
failed += 1;
println!("❌ length(): {}", e);
}
}
let q = Qail::get("harbors")
.column_expr(col("id").abs().with_alias("a"))
.limit(1);
match driver.fetch_all(&q).await {
Ok(_) => {
passed += 1;
println!("✅ abs()");
}
Err(e) => {
failed += 1;
println!("❌ abs(): {}", e);
}
}
let q = Qail::get("harbors")
.column_expr(col("id").cast("text").with_alias("c"))
.limit(1);
match driver.fetch_all(&q).await {
Ok(_) => {
passed += 1;
println!("✅ cast()");
}
Err(e) => {
failed += 1;
println!("❌ cast(): {}", e);
}
}
let q = Qail::get("harbors")
.column_expr(col("name").or_default(text("N/A")).with_alias("d"))
.limit(1);
match driver.fetch_all(&q).await {
Ok(_) => {
passed += 1;
println!("✅ or_default()");
}
Err(e) => {
failed += 1;
println!("❌ or_default(): {}", e);
}
}
println!("\n━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━");
println!("COMPARISON CONDITIONS");
println!("━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━");
let q = Qail::get("harbors").column("id").filter_cond(eq("id", 1));
match driver.fetch_all(&q).await {
Ok(r) => {
passed += 1;
println!("✅ eq() - {} rows", r.len());
}
Err(e) => {
failed += 1;
println!("❌ eq(): {}", e);
}
}
let q = Qail::get("harbors")
.column("id")
.filter_cond(ne("id", 1))
.limit(3);
match driver.fetch_all(&q).await {
Ok(r) => {
passed += 1;
println!("✅ ne() - {} rows", r.len());
}
Err(e) => {
failed += 1;
println!("❌ ne(): {}", e);
}
}
let q = Qail::get("harbors")
.column("id")
.filter_cond(gt("id", 5))
.limit(3);
match driver.fetch_all(&q).await {
Ok(r) => {
passed += 1;
println!("✅ gt() - {} rows", r.len());
}
Err(e) => {
failed += 1;
println!("❌ gt(): {}", e);
}
}
let q = Qail::get("harbors")
.column("id")
.filter_cond(gte("id", 5))
.limit(3);
match driver.fetch_all(&q).await {
Ok(r) => {
passed += 1;
println!("✅ gte() - {} rows", r.len());
}
Err(e) => {
failed += 1;
println!("❌ gte(): {}", e);
}
}
let q = Qail::get("harbors")
.column("id")
.filter_cond(lt("id", 5))
.limit(3);
match driver.fetch_all(&q).await {
Ok(r) => {
passed += 1;
println!("✅ lt() - {} rows", r.len());
}
Err(e) => {
failed += 1;
println!("❌ lt(): {}", e);
}
}
let q = Qail::get("harbors")
.column("id")
.filter_cond(lte("id", 5))
.limit(3);
match driver.fetch_all(&q).await {
Ok(r) => {
passed += 1;
println!("✅ lte() - {} rows", r.len());
}
Err(e) => {
failed += 1;
println!("❌ lte(): {}", e);
}
}
println!("\n━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━");
println!("PATTERN MATCHING");
println!("━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━");
let q = Qail::get("harbors")
.column("name")
.filter_cond(like("name", "Harbor%"))
.limit(3);
match driver.fetch_all(&q).await {
Ok(r) => {
passed += 1;
println!("✅ like() - {} rows", r.len());
}
Err(e) => {
failed += 1;
println!("❌ like(): {}", e);
}
}
let q = Qail::get("harbors")
.column("name")
.filter_cond(not_like("name", "Harbor 1%"))
.limit(3);
match driver.fetch_all(&q).await {
Ok(r) => {
passed += 1;
println!("✅ not_like() - {} rows", r.len());
}
Err(e) => {
failed += 1;
println!("❌ not_like(): {}", e);
}
}
let q = Qail::get("harbors")
.column("name")
.filter_cond(ilike("name", "harbor%"))
.limit(3);
match driver.fetch_all(&q).await {
Ok(r) => {
passed += 1;
println!("✅ ilike() - {} rows", r.len());
}
Err(e) => {
failed += 1;
println!("❌ ilike(): {}", e);
}
}
let q = Qail::get("harbors")
.column("name")
.filter_cond(regex("name", "^Harbor [0-9]+$"))
.limit(3);
match driver.fetch_all(&q).await {
Ok(r) => {
passed += 1;
println!("✅ regex() - {} rows", r.len());
}
Err(e) => {
failed += 1;
println!("❌ regex(): {}", e);
}
}
let q = Qail::get("harbors")
.column("name")
.filter_cond(regex_i("name", "^harbor"))
.limit(3);
match driver.fetch_all(&q).await {
Ok(r) => {
passed += 1;
println!("✅ regex_i() - {} rows", r.len());
}
Err(e) => {
failed += 1;
println!("❌ regex_i(): {}", e);
}
}
println!("\n━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━");
println!("RANGE CONDITIONS");
println!("━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━");
let q = Qail::get("harbors")
.column("id")
.filter_cond(between("id", 1, 5))
.order_by("id", SortOrder::Asc);
match driver.fetch_all(&q).await {
Ok(r) => {
passed += 1;
println!("✅ between() - {} rows", r.len());
}
Err(e) => {
failed += 1;
println!("❌ between(): {}", e);
}
}
let q = Qail::get("harbors")
.column("id")
.filter_cond(not_between("id", 1, 5))
.limit(5);
match driver.fetch_all(&q).await {
Ok(r) => {
passed += 1;
println!("✅ not_between() - {} rows", r.len());
}
Err(e) => {
failed += 1;
println!("❌ not_between(): {}", e);
}
}
println!("\n━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━");
println!("SET CONDITIONS");
println!("━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━");
let q = Qail::get("harbors")
.column("id")
.filter_cond(is_in("id", [1, 2, 3]))
.order_by("id", SortOrder::Asc);
match driver.fetch_all(&q).await {
Ok(r) => {
passed += 1;
println!("✅ is_in() - {} rows", r.len());
}
Err(e) => {
failed += 1;
println!("❌ is_in(): {}", e);
}
}
let q = Qail::get("harbors")
.column("id")
.filter_cond(not_in("id", [1, 2, 3]))
.limit(5);
match driver.fetch_all(&q).await {
Ok(r) => {
passed += 1;
println!("✅ not_in() - {} rows", r.len());
}
Err(e) => {
failed += 1;
println!("❌ not_in(): {}", e);
}
}
println!("\n━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━");
println!("NULL CONDITIONS");
println!("━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━");
let q = Qail::get("harbors")
.column("id")
.filter_cond(is_null("name"))
.limit(3);
match driver.fetch_all(&q).await {
Ok(r) => {
passed += 1;
println!("✅ is_null() - {} rows", r.len());
}
Err(e) => {
failed += 1;
println!("❌ is_null(): {}", e);
}
}
let q = Qail::get("harbors")
.column("id")
.filter_cond(is_not_null("name"))
.limit(3);
match driver.fetch_all(&q).await {
Ok(r) => {
passed += 1;
println!("✅ is_not_null() - {} rows", r.len());
}
Err(e) => {
failed += 1;
println!("❌ is_not_null(): {}", e);
}
}
println!("\n━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━");
println!("AGGREGATE FUNCTIONS");
println!("━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━");
let q = Qail::get("harbors").column_expr(count().alias("cnt"));
match driver.fetch_all(&q).await {
Ok(r) => {
passed += 1;
println!("✅ count() - {} rows", r.len());
}
Err(e) => {
failed += 1;
println!("❌ count(): {}", e);
}
}
let q = Qail::get("harbors").column_expr(sum("id").alias("total"));
match driver.fetch_all(&q).await {
Ok(r) => {
passed += 1;
println!("✅ sum() - {} rows", r.len());
}
Err(e) => {
failed += 1;
println!("❌ sum(): {}", e);
}
}
let q = Qail::get("harbors").column_expr(avg("id").alias("average"));
match driver.fetch_all(&q).await {
Ok(r) => {
passed += 1;
println!("✅ avg() - {} rows", r.len());
}
Err(e) => {
failed += 1;
println!("❌ avg(): {}", e);
}
}
let q = Qail::get("harbors").column_expr(min("id").alias("minimum"));
match driver.fetch_all(&q).await {
Ok(r) => {
passed += 1;
println!("✅ min() - {} rows", r.len());
}
Err(e) => {
failed += 1;
println!("❌ min(): {}", e);
}
}
let q = Qail::get("harbors").column_expr(max("id").alias("maximum"));
match driver.fetch_all(&q).await {
Ok(r) => {
passed += 1;
println!("✅ max() - {} rows", r.len());
}
Err(e) => {
failed += 1;
println!("❌ max(): {}", e);
}
}
let q = Qail::get("harbors").column_expr(count_distinct("name").alias("distinct_names"));
match driver.fetch_all(&q).await {
Ok(r) => {
passed += 1;
println!("✅ count_distinct() - {} rows", r.len());
}
Err(e) => {
failed += 1;
println!("❌ count_distinct(): {}", e);
}
}
let q = Qail::get("harbors")
.column_expr(array_agg("name").alias("names"))
.limit(1);
match driver.fetch_all(&q).await {
Ok(r) => {
passed += 1;
println!("✅ array_agg() - {} rows", r.len());
}
Err(e) => {
failed += 1;
println!("❌ array_agg(): {}", e);
}
}
let q = Qail::get("harbors")
.column_expr(string_agg(col("name"), ", ").alias("all_names"))
.limit(1);
match driver.fetch_all(&q).await {
Ok(r) => {
passed += 1;
println!("✅ string_agg() - {} rows", r.len());
}
Err(e) => {
failed += 1;
println!("❌ string_agg(): {}", e);
}
}
let q = Qail::get("harbors")
.column_expr(json_agg("name").alias("json_names"))
.limit(1);
match driver.fetch_all(&q).await {
Ok(r) => {
passed += 1;
println!("✅ json_agg() - {} rows", r.len());
}
Err(e) => {
failed += 1;
println!("❌ json_agg(): {}", e);
}
}
println!("\n━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━");
println!("FUNCTION BUILDERS");
println!("━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━");
let q = Qail::get("harbors")
.column_expr(coalesce([col("name"), text("N/A")]).alias("coalesced"))
.limit(1);
match driver.fetch_all(&q).await {
Ok(r) => {
passed += 1;
println!("✅ coalesce() - {} rows", r.len());
}
Err(e) => {
failed += 1;
println!("❌ coalesce(): {}", e);
}
}
let q = Qail::get("harbors")
.column_expr(concat([col("name"), text(" - "), col("id").cast("text")]).alias("combined"))
.limit(1);
match driver.fetch_all(&q).await {
Ok(r) => {
passed += 1;
println!("✅ concat() - {} rows", r.len());
}
Err(e) => {
failed += 1;
println!("❌ concat(): {}", e);
}
}
println!("\n━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━");
println!("TIME FUNCTIONS");
println!("━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━");
let q = Qail::get("harbors")
.column_expr(now().with_alias("current_time"))
.limit(1);
match driver.fetch_all(&q).await {
Ok(r) => {
passed += 1;
println!("✅ now() - {} rows", r.len());
}
Err(e) => {
failed += 1;
println!("❌ now(): {}", e);
}
}
let q = Qail::get("harbors")
.column_expr(now_minus("1 hour").with_alias("hour_ago"))
.limit(1);
match driver.fetch_all(&q).await {
Ok(r) => {
passed += 1;
println!("✅ now_minus() - {} rows", r.len());
}
Err(e) => {
failed += 1;
println!("❌ now_minus(): {}", e);
}
}
let q = Qail::get("harbors")
.column_expr(now_plus("1 day").with_alias("tomorrow"))
.limit(1);
match driver.fetch_all(&q).await {
Ok(r) => {
passed += 1;
println!("✅ now_plus() - {} rows", r.len());
}
Err(e) => {
failed += 1;
println!("❌ now_plus(): {}", e);
}
}
println!("\n━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━");
println!("CASE EXPRESSIONS");
println!("━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━");
let q = Qail::get("harbors")
.column("id")
.column_expr(
case_when(gt("id", 5), text("big"))
.otherwise(text("small"))
.alias("size"),
)
.limit(10);
match driver.fetch_all(&q).await {
Ok(r) => {
passed += 1;
println!("✅ case_when() - {} rows", r.len());
}
Err(e) => {
failed += 1;
println!("❌ case_when(): {}", e);
}
}
println!("\n━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━");
println!("SUMMARY");
println!("━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━");
println!("✅ Passed: {}", passed);
println!("❌ Failed: {}", failed);
println!("📊 Total: {}", passed + failed);
if failed == 0 {
println!("\n🎉 ALL TESTS PASSED!");
} else {
println!("\n⚠️ Some tests failed. Please review.");
}
Ok(())
}