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 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142
use crate::{ handles::{self, Statement}, parameter_collection::ParameterCollection, CursorImpl, Error, 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 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;". A /// question mark (`?`) may be used to indicate positional parameters in the statement text. /// * `params`: Used to bind the placeholders in the statement text to argument values 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 ParameterCollection, ) -> Result<Option<CursorImpl<Statement>>, Error> { let mut stmt = self.connection.allocate_statement()?; let paramset_size = params.parameter_set_size(); if paramset_size == 0 { Ok(None) } else { // Reset parameters so we do not dereference stale once by mistake if we call // `exec_direct`. stmt.reset_parameters()?; unsafe { stmt.set_paramset_size(paramset_size)?; // Bind new parameters passed by caller. params.bind_parameters_to(&mut stmt)?; stmt.exec_direct(query)? }; // Check if a result set has been created. if stmt.num_result_cols()? == 0 { Ok(None) } else { Ok(Some(CursorImpl::new(stmt))) } } } /// 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. 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. /// /// # Example /// /// ```no_run /// use odbc_api::Environment; /// /// // I herby solemnly swear that this is the only ODBC environment in the entire process, thus /// // making this call safe. /// let env = unsafe { /// Environment::new()? /// }; /// /// let mut conn = env.connect("YourDatabase", "SA", "<YourStrong@Passw0rd>")?; /// if let Some(cursor) = conn.execute("SELECT year, name FROM Birthdays;", ())? { /// // Use cursor to process query results. /// } /// # Ok::<(), odbc_api::Error>(()) /// ``` pub fn execute( &mut self, query: &str, params: impl ParameterCollection, ) -> 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) } }