//! Binds columns to a result set and fills them with fetch. This is still super akward. extern crate odbc_safe; extern crate odbc_sys; use odbc_safe::*; use odbc_sys::SQLLEN; 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 year, title 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 mut year = 0; let mut title = [0u8; 512]; let mut ind_year = 0; let mut ind_title = 0; let mut cursor_opt = fetch( result_set, &mut year, &mut title, &mut ind_year, &mut ind_title, )?; while let Some(p) = cursor_opt { println!( "year: {}, title: {}", year, from_utf8(&title[0..(ind_title as usize)]).unwrap() ); cursor_opt = fetch(p, &mut year, &mut title, &mut ind_year, &mut ind_title)? } Ok(()) } fn fetch<'con, 'p, 'c, C>( cursor: Statement<'con, 'p, 'c, C>, year: &mut u32, title: &mut [u8], ind_year: &mut SQLLEN, ind_title: &mut SQLLEN, ) -> MyResult>> where C: CursorState, { use ReturnOption::*; let cursor = cursor.bind_col(1, year, Some(ind_year)).into_result()?; let cursor = cursor.bind_col(2, &mut title[..], Some(ind_title)).into_result()?; let cursor = match cursor.fetch() { Success(s) | Info(s) => Some(s.reset_columns()), NoData(_) => None, Error(s) => return Err(s.into()), }; Ok(cursor) }