//! Directly executes an SQL query and prints the result set to standard out //! //! This example also offers an idea, how to set up error handling for your ODBC Application. extern crate odbc_safe; use odbc_safe::*; use std::str::from_utf8; // Setup error handling struct LastError(String); type MyResult = Result; impl From for LastError { fn from(source: D) -> Self { let mut buffer = [0; 512]; match source.diagnostics(1, &mut buffer) { ReturnOption::Success(dr) | ReturnOption::Info(dr) => LastError( from_utf8(&buffer[0..(dr.text_length as usize)]) .unwrap() .to_owned(), ), ReturnOption::Error(()) => panic!("Error during fetching diagnostic record"), ReturnOption::NoData(()) => LastError("No Diagnostic Record present".to_owned()), } } } trait ExtReturn { fn into_result(self) -> MyResult; } impl ExtReturn for Return where D: Diagnostics, { fn into_result(self) -> MyResult { match self { Success(v) | Info(v) => Ok(v), Error(d) => Err(d.into()), } } } // Actual application fn main() { let env = Environment::new().unwrap(); let env = env.declare_version_3().unwrap(); match run(&env) { Ok(()) => (), Err(LastError(message)) => println!("An error occurred: {}", message), } } fn run(env: &Environment) -> MyResult<()> { let conn = connect(&env)?; let result_set = execute_query(&conn)?; print_fields(result_set) } fn connect(env: &Environment) -> MyResult> where V: Version, { let conn = DataSource::with_parent(env).unwrap(); conn.connect("TestDataSource", "", "").into_result() } fn execute_query<'a, AC: AutocommitMode>(conn: &'a Connection) -> MyResult> { let stmt = Statement::with_parent(conn).unwrap(); match stmt.exec_direct("SELECT * FROM MOVIES") { ReturnOption::Success(s) | ReturnOption::Info(s) => Ok(s), ReturnOption::NoData(_) => Err(LastError( "Statement did not return a Result Set.".to_owned(), )), ReturnOption::Error(e) => Err(e.into()), } } fn print_fields(result_set: ResultSet) -> MyResult<()> { let cols = result_set.num_result_cols().unwrap(); let mut buffer = [0u8; 512]; let mut cursor = match result_set.fetch() { ReturnOption::Success(r) | ReturnOption::Info(r) => r, ReturnOption::NoData(_) => return Ok(()), ReturnOption::Error(e) => return Err(e.into()), }; loop { for index in 1..(cols + 1) { match cursor.get_data(index as u16, &mut buffer as &mut [u8]) { ReturnOption::Success(ind) | ReturnOption::Info(ind) => { match ind { Indicator::NoTotal => panic!("No Total"), Indicator::Null => println!("NULL"), Indicator::Length(l) => { print!("{}", from_utf8(&buffer[0..l as usize]).unwrap()); } } } ReturnOption::NoData(_) => panic!("No Field Data"), ReturnOption::Error(_) => return Err(cursor.into()), } print!(" | "); } cursor = match cursor.fetch() { ReturnOption::Success(r) | ReturnOption::Info(r) => r, ReturnOption::NoData(_) => break Ok(()), ReturnOption::Error(e) => break Err(e.into()), }; println!(""); } }