bind_columns/
bind_columns.rs1extern crate odbc_safe;
3extern crate odbc_sys;
4use odbc_safe::*;
5use odbc_sys::SQLLEN;
6use std::str::from_utf8;
7
8struct LastError(String);
10type MyResult<T> = Result<T, LastError>;
11
12impl<D: Diagnostics> From<D> for LastError {
13 fn from(source: D) -> Self {
14 let mut buffer = [0; 512];
15 match source.diagnostics(1, &mut buffer) {
16 ReturnOption::Success(dr) |
17 ReturnOption::Info(dr) => LastError(
18 from_utf8(&buffer[0..(dr.text_length as usize)])
19 .unwrap()
20 .to_owned(),
21 ),
22 ReturnOption::Error(()) => panic!("Error during fetching diagnostic record"),
23 ReturnOption::NoData(()) => LastError("No Diagnostic Record present".to_owned()),
24 }
25 }
26}
27
28trait ExtReturn<T> {
29 fn into_result(self) -> MyResult<T>;
30}
31
32impl<T, D> ExtReturn<T> for Return<T, D>
33where
34 D: Diagnostics,
35{
36 fn into_result(self) -> MyResult<T> {
37 match self {
38 Success(v) | Info(v) => Ok(v),
39 Error(d) => Err(d.into()),
40 }
41 }
42}
43
44fn main() {
46
47 let env = Environment::new().unwrap();
48 let env = env.declare_version_3().unwrap();
49
50 match run(&env) {
51 Ok(()) => (),
52 Err(LastError(message)) => println!("An error occurred: {}", message),
53 }
54}
55
56fn run(env: &Environment<Odbc3>) -> MyResult<()> {
57
58 let conn = connect(env)?;
59 let result_set = execute_query(&conn)?;
60 print_fields(result_set)
61}
62
63fn connect<V>(env: &Environment<V>) -> MyResult<Connection<impl AutocommitMode>>
64where
65 V: Version,
66{
67 let conn = DataSource::with_parent(env).unwrap();
68 conn.connect("TestDataSource", "", "").into_result()
69}
70
71fn execute_query<'a, AC: AutocommitMode>(conn: &'a Connection<AC>) -> MyResult<ResultSet<'a, 'a, 'a, Unprepared>> {
72 let stmt = Statement::with_parent(conn).unwrap();
73 match stmt.exec_direct("SELECT year, title FROM Movies") {
74 ReturnOption::Success(s) |
75 ReturnOption::Info(s) => Ok(s),
76 ReturnOption::NoData(_) => Err(LastError(
77 "Statement did not return a Result Set.".to_owned(),
78 )),
79 ReturnOption::Error(e) => Err(e.into()),
80 }
81}
82
83fn print_fields(result_set: ResultSet<Unprepared>) -> MyResult<()> {
84 let mut year = 0;
85 let mut title = [0u8; 512];
86 let mut ind_year = 0;
87 let mut ind_title = 0;
88 let mut cursor_opt = fetch(
89 result_set,
90 &mut year,
91 &mut title,
92 &mut ind_year,
93 &mut ind_title,
94 )?;
95 while let Some(p) = cursor_opt {
96 println!(
97 "year: {}, title: {}",
98 year,
99 from_utf8(&title[0..(ind_title as usize)]).unwrap()
100 );
101 cursor_opt = fetch(p, &mut year, &mut title, &mut ind_year, &mut ind_title)?
102 }
103 Ok(())
104}
105
106fn fetch<'con, 'p, 'c, C>(
107 cursor: Statement<'con, 'p, 'c, C>,
108 year: &mut u32,
109 title: &mut [u8],
110 ind_year: &mut SQLLEN,
111 ind_title: &mut SQLLEN,
112) -> MyResult<Option<Statement<'con, 'p, 'c, Positioned>>>
113where
114 C: CursorState,
115{
116 use ReturnOption::*;
117 let cursor = cursor.bind_col(1, year, Some(ind_year)).into_result()?;
118 let cursor = cursor.bind_col(2, &mut title[..], Some(ind_title)).into_result()?;
119 let cursor = match cursor.fetch() {
120 Success(s) | Info(s) => Some(s.reset_columns()),
121 NoData(_) => None,
122 Error(s) => return Err(s.into()),
123 };
124 Ok(cursor)
125}