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
use crate::{
    execute::execute_with_parameters,
    handles::{ParameterDescription, Statement, StatementImpl},
    prebound::ParameterMutCollection,
    CursorImpl, Error, ParameterRefCollection, Prebound, ResultSetMetadata,
};

/// A prepared query. Prepared queries are useful if the similar queries should executed more than
/// once.
pub struct Prepared<'open_connection> {
    statement: StatementImpl<'open_connection>,
}

impl<'o> Prepared<'o> {
    pub(crate) fn new(statement: StatementImpl<'o>) -> Self {
        Self { statement }
    }

    /// Transfer ownership to the underlying statement handle.
    ///
    /// The resulting type is one level of indirection away from the raw pointer of the ODBC API. It
    /// no longer has any guarantees about bound buffers, but is still guaranteed to be a valid
    /// allocated statement handle. This serves together with
    /// [`crate::handles::StatementImpl::into_sys`] or [`crate::handles::Statement::as_sys`] this
    /// serves as an escape hatch to access the functionality provided by `crate::sys` not yet
    /// accessible through safe abstractions.
    pub fn into_statement(self) -> StatementImpl<'o> {
        self.statement
    }

    /// Execute the prepared statement.
    ///
    /// * `params`: Used to bind these parameters before executing the statement. You can use `()`
    ///   to represent no parameters. In regards to binding arrays of parameters: Should `params`
    ///   specify a parameter set size of `0`, nothing is executed, and `Ok(None)` is returned. See
    ///   the [`crate::parameter`] module level documentation for more information on how to pass
    ///   parameters.
    pub fn execute(
        &mut self,
        params: impl ParameterRefCollection,
    ) -> Result<Option<CursorImpl<&mut StatementImpl<'o>>>, Error> {
        execute_with_parameters(move || Ok(&mut self.statement), None, params)
    }

    /// Describes parameter marker associated with a prepared SQL statement.
    ///
    /// # Parameters
    ///
    /// * `parameter_number`: Parameter marker number ordered sequentially in increasing parameter
    ///   order, starting at 1.
    pub fn describe_param(&self, parameter_number: u16) -> Result<ParameterDescription, Error> {
        self.statement
            .describe_param(parameter_number)
            .into_result(&self.statement)
    }

    /// Bind parameter buffers to the statement. Your motivation for doing so would be that in order
    /// to execute the statement multiple times with different arguments it is now enough to modify
    /// the parameters in the buffer, rather than repeatedly binding new parameters to the
    /// statement. You now need fewer (potentially costly) odbc api calls for the same result.
    /// However in some situations (depending on the size of the paramteres) modifying the buffers
    /// and coping their contents might be more costly than rebinding to a different source. Also
    /// the requirements for these permantent buffers are higher, as they may not become invalid
    /// after the statment is executed, and if the [`Prebound`] instance is moved.
    ///
    /// ```
    /// use odbc_api::{Connection, Error, Prebound};
    /// use std::io::{self, stdin, Read};
    ///
    /// fn make_query<'a>(conn: &'a Connection<'_>) -> Result<Prebound<'a, Box<i32>>, Error>{
    ///     let mut query = "SELECT title FROM Movies WHERE year=?;";
    ///     let prepared = conn.prepare(query)?;
    ///     // We allocate the year parameter on the heap so it's not invalidated once we transfer
    ///     // ownership of the prepared statement + parameter to the caller of the function. Of
    ///     // course the compiler would catch it, if we missed this by mistake.
    ///     let year = Box::new(0);
    ///     let prebound = prepared.bind_parameters(year)?;
    ///     Ok(prebound)
    /// }
    ///
    /// // Later we may execute the query like this
    /// fn use_query(movies_by_year: &mut Prebound<'_, Box<i32>>) -> Result<(), Error> {
    ///     // Let's say we are interested in Movie titles released in 2021. Modify the parameter
    ///     // buffer accordingly.
    ///     *movies_by_year.params_mut() = 2021;
    ///     // and execute. Note that we do not specify the parameter here, since it is already
    ///     // bound.
    ///     let cursor = movies_by_year.execute()?;
    ///
    ///     // ... process cursor ...
    ///
    ///     Ok(())
    /// }
    /// ```
    ///
    pub fn bind_parameters<P>(self, parameters: P) -> Result<Prebound<'o, P>, Error>
    where
        P: ParameterMutCollection,
    {
        // We know that statement is a prepared statement.
        unsafe { Prebound::new(self.into_statement(), parameters) }
    }
}

impl<'o> ResultSetMetadata for Prepared<'o> {
    type Statement = StatementImpl<'o>;

    fn stmt_ref(&self) -> &Self::Statement {
        &self.statement
    }
}