use ibm_db::{
create_environment_v3,
Statement,
ResultSetState::{Data, NoData},
};
use std::error::Error;
fn main() {
match test_error_handling() {
Ok(()) => println!("\n✓ Error handling test completed successfully"),
Err(e) => println!("\n✗ Error handling test failed: {}", e),
}
}
fn test_error_handling() -> Result<(), Box<dyn Error>> {
println!("\n========== ERROR HANDLING TEST ==========\n");
let env = create_environment_v3().map_err(|e| e.unwrap())?;
let connection_string = "DRIVER={IBM DB2 ODBC DRIVER};DATABASE=SAMPLE;HOSTNAME=db.example.com;PORT=50000;UID=db_user;PWD=YourPassword123";
let conn = env.connect_with_connection_string(connection_string)?;
println!("✓ Connected to database\n");
println!("--- Test 1: Invalid SQL Syntax ---");
let stmt = Statement::with_parent(&conn)?;
let invalid_sql = "SELET * FROM test_types";
match stmt.exec_direct(invalid_sql) {
Ok(_) => println!("✗ Query unexpectedly succeeded"),
Err(e) => {
println!("✓ Caught error (as expected)");
println!(" Error message: {}\n", e);
}
}
println!("--- Test 2: Non-existent Table ---");
let stmt = Statement::with_parent(&conn)?;
let invalid_sql = "SELECT * FROM table_that_does_not_exist_12345";
match stmt.exec_direct(invalid_sql) {
Ok(_) => println!("✗ Query unexpectedly succeeded"),
Err(e) => {
println!("✓ Caught error (as expected)");
println!(" Error message: {}\n", e);
}
}
println!("--- Test 3: Type Mismatch in Comparison ---");
let stmt = Statement::with_parent(&conn)?;
let setup = "CREATE TABLE IF NOT EXISTS test_types (id INT)";
match stmt.exec_direct(setup) {
Ok(Data(s)) => { let _ = s.close_cursor()?; }
Ok(NoData(_)) => {}
Err(e) => println!("Setup error: {}", e),
}
let stmt = Statement::with_parent(&conn)?;
match stmt.exec_direct("INSERT INTO test_types VALUES ('not_a_number')") {
Ok(_) => println!("! Insert succeeded (depends on DB2 behavior)"),
Err(e) => {
println!("✓ Caught type mismatch error");
println!(" Error message: {}\n", e);
}
}
println!("--- Test 4: Safe NULL Value Handling ---");
let stmt = Statement::with_parent(&conn)?;
match stmt.exec_direct("SELECT * FROM test_types WHERE id IS NULL") {
Ok(Data(mut stmt)) => {
let count = 0;
while let Ok(Some(_)) = stmt.fetch() {
}
let _ = stmt.close_cursor()?;
println!("✓ NULL values handled safely");
}
Ok(NoData(_)) => println!("✓ NULL query executed (no results)"),
Err(e) => println!("✗ Query failed: {}", e),
}
println!("\n--- Test 5: Division by Zero ---");
let stmt = Statement::with_parent(&conn)?;
let div_zero = "SELECT 100 / 0 as result";
match stmt.exec_direct(div_zero) {
Ok(Data(mut stmt)) => {
if let Ok(Some(mut cursor)) = stmt.fetch() {
if let Ok(Some(result)) = cursor.get_data::<f64>(1) {
println!("! Result: {} (DB2 returned a value)", result);
} else {
println!("✓ Division by zero returned NULL");
}
}
let _ = stmt.close_cursor()?;
}
Ok(NoData(_)) => println!("✓ Division by zero handled (no data)"),
Err(e) => {
println!("✓ Division by zero caught as error");
println!(" Error message: {}", e);
}
}
println!("\n--- Test 6: Parameter Binding ---");
let stmt = Statement::with_parent(&conn)?;
match stmt.prepare("SELECT * FROM test_types WHERE id = ?") {
Ok(prepared) => {
match prepared.bind_parameter(1, &123i32) {
Ok(prepared) => {
match prepared.execute() {
Ok(_) => println!("✓ Parameter bound and executed successfully"),
Err(e) => println!("✗ Execution failed: {}", e),
}
}
Err(e) => println!("✗ Parameter binding failed: {}", e),
}
}
Err(e) => println!("✗ Prepare failed: {}", e),
}
println!("\n--- Test 7: Error Recovery ---");
println!("Attempting multiple operations with error recovery:\n");
let operations = vec![
("SELECT COUNT(*) FROM test_types", "Valid query"),
("SELECT * FROM invalid_table", "Invalid table"),
("SELECT * FROM test_types WHERE id = 1", "Valid query after error"),
];
let mut success_count = 0;
let mut error_count = 0;
for (sql, description) in operations {
print!(" {} ... ", description);
let stmt = Statement::with_parent(&conn)?;
match stmt.exec_direct(sql) {
Ok(_) => {
println!("OK");
success_count += 1;
}
Err(_) => {
println!("ERROR (recovered)");
error_count += 1;
}
}
}
println!("\n Summary: {} successful, {} errors (recovered)", success_count, error_count);
println!("✓ Error recovery demonstrated\n");
println!("========== TEST COMPLETE ==========\n");
Ok(())
}