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
    }
}