Skip to main content

odbc_api/
preallocated_polling.rs

1use crate::{
2    CursorPolling, Error, ParameterCollectionRef, Sleep,
3    execute::execute_with_parameters_polling,
4    handles::{AsStatementRef, SqlText, StatementRef},
5};
6
7/// Asynchronous sibling of [`crate::Preallocated`] using polling mode for execution. Can be
8/// obtained using [`crate::Preallocated::into_polling`].
9pub struct PreallocatedPolling<S> {
10    /// A valid statement handle in polling mode
11    statement: S,
12}
13
14impl<S> PreallocatedPolling<S> {
15    pub(crate) fn new(statement: S) -> Self {
16        Self { statement }
17    }
18}
19
20impl<S> PreallocatedPolling<S>
21where
22    S: AsStatementRef,
23{
24    /// Executes a statement. This is the fastest way to sequentially execute different SQL
25    /// Statements asynchronously.
26    ///
27    /// # Parameters
28    ///
29    /// * `query`: The text representation of the SQL statement. E.g. "SELECT * FROM my_table;".
30    /// * `params`: `?` may be used as a placeholder in the statement text. You can use `()` to
31    ///   represent no parameters. Check the [`crate::parameter`] module level documentation for
32    ///   more information on how to pass parameters.
33    /// * `sleep`: Governs the polling intervals
34    ///
35    /// # Return
36    ///
37    /// Returns `Some` if a cursor is created. If `None` is returned no cursor has been created (
38    /// e.g. the query came back empty). Note that an empty query may also create a cursor with zero
39    /// rows. Since we want to reuse the statement handle a returned cursor will not take ownership
40    /// of it and instead burrow it.
41    ///
42    /// # Example
43    ///
44    /// ```
45    /// use odbc_api::{Connection, Error};
46    /// use std::{io::{self, stdin, Read}, time::Duration};
47    ///
48    /// /// Execute many different queries sequentially.
49    /// async fn execute_all(conn: &Connection<'_>, queries: &[&str]) -> Result<(), Error>{
50    ///     let mut statement = conn.preallocate()?.into_polling()?;
51    ///     let sleep = || tokio::time::sleep(Duration::from_millis(20));
52    ///     for query in queries {
53    ///         println!("Executing {query}");
54    ///         match statement.execute(&query, (), sleep).await {
55    ///             Err(e) => println!("{}", e),
56    ///             Ok(None) => println!("No results set generated."),
57    ///             Ok(Some(cursor)) => {
58    ///                 // ...print cursor contents...
59    ///             },
60    ///         }
61    ///     }
62    ///     Ok(())
63    /// }
64    /// ```
65    pub async fn execute(
66        &mut self,
67        query: &str,
68        params: impl ParameterCollectionRef,
69        sleep: impl Sleep,
70    ) -> Result<Option<CursorPolling<StatementRef<'_>>>, Error> {
71        let query = SqlText::new(query);
72        let stmt = self.statement.as_stmt_ref();
73        execute_with_parameters_polling(stmt, Some(&query), params, sleep).await
74    }
75}
76
77impl<S> AsStatementRef for PreallocatedPolling<S>
78where
79    S: AsStatementRef,
80{
81    fn as_stmt_ref(&mut self) -> StatementRef<'_> {
82        self.statement.as_stmt_ref()
83    }
84}