use prax_mysql::{MysqlConfig, MysqlEngine, MysqlPool};
use prax_query::filter::FilterValue;
use std::collections::HashMap;
const DATABASE_URL: &str = "mysql://prax:prax_test_password@localhost:3307/prax_test";
#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
tracing_subscriber::fmt()
.with_env_filter("prax_mysql=debug,mysql_demo=info")
.init();
println!("🚀 Prax MySQL Demo\n");
println!("━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n");
println!("📦 Creating connection pool...");
let config = MysqlConfig::from_url(DATABASE_URL)?;
let pool = MysqlPool::new(config).await?;
println!(" ✓ Connection pool created\n");
println!("⚙️ Creating Prax MySQL engine...");
let engine = MysqlEngine::new(pool.clone());
println!(" ✓ Engine created and ready\n");
println!("🔌 Verifying database connection...");
let version_result = engine.raw_sql_scalar("SELECT VERSION()", &[]).await?;
println!(
" ✓ Connected to: MySQL {}\n",
version_result.as_str().unwrap_or("unknown")
);
println!("📊 Checking database schema...");
let tables_result = engine
.raw_sql_query(
"SELECT TABLE_NAME FROM information_schema.TABLES WHERE TABLE_SCHEMA = DATABASE()",
&[],
)
.await?;
println!(" ✓ Found {} tables\n", tables_result.len());
println!(" Tables:");
for table in &tables_result {
if let Some(name) = table.json().get("TABLE_NAME").and_then(|v| v.as_str()) {
println!(" • {}", name);
}
}
println!();
println!("📝 Querying data via Prax engine...\n");
let user_count = engine.count("users", &HashMap::new()).await?;
println!(" Current user count: {}", user_count);
println!(" Inserting test user...");
let existing = engine
.raw_sql_optional(
"SELECT id FROM users WHERE email = ?",
&[FilterValue::String("demo@prax.dev".to_string())],
)
.await?;
if existing.is_none() {
let mut user_data = HashMap::new();
user_data.insert(
"name".to_string(),
FilterValue::String("Prax Demo User".to_string()),
);
user_data.insert(
"email".to_string(),
FilterValue::String("demo@prax.dev".to_string()),
);
user_data.insert(
"status".to_string(),
FilterValue::String("active".to_string()),
);
user_data.insert("role".to_string(), FilterValue::String("admin".to_string()));
user_data.insert("verified".to_string(), FilterValue::Bool(true));
let result = engine.execute_insert("users", &user_data).await?;
let new_id = result
.json()
.get("id")
.and_then(|v| v.as_i64())
.unwrap_or(0);
println!(" ✓ Created user with id: {}", new_id);
} else {
println!(" ✓ Demo user already exists");
}
let new_count = engine.count("users", &HashMap::new()).await?;
println!(" New user count: {}\n", new_count);
println!("🔍 Querying with filters...\n");
let mut filters = HashMap::new();
filters.insert(
"status".to_string(),
FilterValue::String("active".to_string()),
);
let active_users = engine
.query_many("users", &[], &filters, &[], Some(5), None)
.await?;
println!(" Active users (first 5):");
for user in &active_users {
let name = user
.json()
.get("name")
.and_then(|v| v.as_str())
.unwrap_or("unknown");
let email = user
.json()
.get("email")
.and_then(|v| v.as_str())
.unwrap_or("unknown");
println!(" • {} - {}", name, email);
}
println!();
println!("📚 Executing raw SQL with parameters...\n");
let admins = engine
.raw_sql_query(
"SELECT name, email, role FROM users WHERE role = ? ORDER BY name LIMIT 5",
&[FilterValue::String("admin".to_string())],
)
.await?;
println!(" Admin users:");
for admin in &admins {
let name = admin
.json()
.get("name")
.and_then(|v| v.as_str())
.unwrap_or("unknown");
let role = admin
.json()
.get("role")
.and_then(|v| v.as_str())
.unwrap_or("unknown");
println!(" • {} ({})", name, role);
}
println!();
println!("✏️ Updating user...\n");
let mut update_data = HashMap::new();
update_data.insert("score".to_string(), FilterValue::Int(100));
let mut update_filters = HashMap::new();
update_filters.insert(
"email".to_string(),
FilterValue::String("demo@prax.dev".to_string()),
);
let affected = engine
.execute_update("users", &update_data, &update_filters)
.await?;
println!(" ✓ Updated {} row(s)\n", affected);
println!("📈 Running aggregation query...\n");
let stats = engine
.raw_sql_query(
"SELECT role, COUNT(*) as count, AVG(score) as avg_score FROM users GROUP BY role",
&[],
)
.await?;
println!(" User statistics by role:");
for stat in &stats {
let role = stat
.json()
.get("role")
.and_then(|v| v.as_str())
.unwrap_or("unknown");
let count = stat
.json()
.get("count")
.and_then(|v| v.as_i64())
.unwrap_or(0);
let avg_score = stat
.json()
.get("avg_score")
.and_then(|v| v.as_f64())
.unwrap_or(0.0);
println!(
" • {}: {} users, avg score: {:.1}",
role, count, avg_score
);
}
println!();
println!("🔗 Running join query...\n");
let posts_with_authors = engine
.raw_sql_query(
r#"
SELECT p.title, p.view_count, u.name as author
FROM posts p
JOIN users u ON p.user_id = u.id
WHERE p.published = true
ORDER BY p.view_count DESC
LIMIT 5
"#,
&[],
)
.await?;
println!(" Top 5 published posts:");
for post in &posts_with_authors {
let title = post
.json()
.get("title")
.and_then(|v| v.as_str())
.unwrap_or("unknown");
let views = post
.json()
.get("view_count")
.and_then(|v| v.as_i64())
.unwrap_or(0);
let author = post
.json()
.get("author")
.and_then(|v| v.as_str())
.unwrap_or("unknown");
println!(" • {} by {} ({} views)", title, author, views);
}
println!();
println!("━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n");
println!("✅ MySQL Demo completed successfully!\n");
println!("📋 Summary:");
println!(" • Connected to MySQL with connection pooling");
println!(" • Queried and filtered data");
println!(" • Executed raw SQL with parameters");
println!(" • Performed aggregations and joins");
println!("\n🔗 Next steps:");
println!(" • Try 'cargo run --example mssql_demo' for SQL Server");
println!(" • Try 'cargo run --example mongodb_demo' for MongoDB");
Ok(())
}