1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118
use crate::{ handles::{self, Statement}, CursorImpl, Error, Parameters, Prepared, }; use std::thread::panicking; use widestring::{U16Str, U16String}; impl<'conn> Drop for Connection<'conn> { fn drop(&mut self) { if let Err(e) = self.connection.disconnect() { // Avoid panicking, if we already have a panic. We don't want to mask the original // error. if !panicking() { panic!("Unexpected error disconnecting: {:?}", e) } } } } /// The connection handle references storage of all information about the connection to the data /// source, including status, transaction state, and error information. pub struct Connection<'c> { connection: handles::Connection<'c>, } impl<'c> Connection<'c> { pub(crate) fn new(connection: handles::Connection<'c>) -> Self { Self { connection } } /// Executes a prepareable statement. This is the fastest way to submit an SQL statement for /// one-time execution. /// /// # Parameters /// /// * `query`: The text representation of the SQL statement. E.g. "SELECT * FROM my_table;". /// * `params`: `?` may be used as a placeholder in the statement text. A type implementing /// `Parameters` is used to bind these parameters before executing the statement. You can use /// `()` to represent no parameters. /// /// # Return /// /// Returns `Some` if a cursor is created. If `None` is returned no cursor has been created ( /// e.g. the query came back empty). Note that an empty query may also create a cursor with zero /// rows. pub fn exec_direct_utf16( &mut self, query: &U16Str, params: impl Parameters, ) -> Result<Option<CursorImpl<Statement>>, Error> { let mut stmt = self.connection.allocate_statement()?; let has_result = unsafe { // Reset parameters so we do not dereference stale once by mistake if we call // `exec_direct`. stmt.reset_parameters()?; // Bind new parameters passed by caller. params.bind_input_parameters(&mut stmt)?; stmt.exec_direct(query)? }; if has_result { Ok(Some(CursorImpl::new(stmt))) } else { // ODBC Driver returned NoData. Ok(None) } } /// Executes a prepareable statement. This is the fastest way to submit an SQL statement for /// one-time execution. /// /// # Parameters /// /// * `query`: The text representation of the SQL statement. E.g. "SELECT * FROM my_table;". /// * `params`: `?` may be used as a placeholder in the statement text. A type implementing /// `Parameters` is used to bind these parameters before executing the statement. You can use /// `()` to represent no parameters. /// /// # Return /// /// Returns `Some` if a cursor is created. If `None` is returned no cursor has been created ( /// e.g. the query came back empty). Note that an empty query may also create a cursor with zero /// rows. pub fn exec_direct( &mut self, query: &str, params: impl Parameters, ) -> Result<Option<CursorImpl<Statement>>, Error> { let query = U16String::from_str(query); self.exec_direct_utf16(&query, params) } /// Prepares an SQL statement. This is recommended for repeated execution of similar queries. /// /// # Parameters /// /// * `query`: The text representation of the SQL statement. E.g. "SELECT * FROM my_table;". `?` /// may be used as a placeholder in the statement text, to be replaced with parameters during /// execution. pub fn prepare_utf16(&self, query: &U16Str) -> Result<Prepared, Error> { let mut stmt = self.connection.allocate_statement()?; stmt.prepare(query)?; Ok(Prepared::new(stmt)) } /// Prepares an SQL statement. This is recommended for repeated execution of similar queries. /// /// # Parameters /// /// * `query`: The text representation of the SQL statement. E.g. "SELECT * FROM my_table;". `?` /// may be used as a placeholder in the statement text, to be replaced with parameters during /// execution. pub fn prepare(&self, query: &str) -> Result<Prepared, Error> { let query = U16String::from_str(query); self.prepare_utf16(&query) } }