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
use crate::{
CursorPolling, Error, ParameterCollectionRef, Sleep,
execute::execute_with_parameters_polling,
handles::{AsStatementRef, SqlText, StatementRef},
};
/// Asynchronous sibling of [`crate::Preallocated`] using polling mode for execution. Can be
/// obtained using [`crate::Preallocated::into_polling`].
pub struct PreallocatedPolling<S> {
/// A valid statement handle in polling mode
statement: S,
}
impl<S> PreallocatedPolling<S> {
pub(crate) fn new(statement: S) -> Self {
Self { statement }
}
}
impl<S> PreallocatedPolling<S>
where
S: AsStatementRef,
{
/// Executes a statement. This is the fastest way to sequentially execute different SQL
/// Statements asynchronously.
///
/// # 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. Check the [`crate::parameter`] module level documentation for
/// more information on how to pass parameters.
/// * `sleep`: Governs the polling intervals
///
/// # 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. Since we want to reuse the statement handle a returned cursor will not take ownership
/// of it and instead burrow it.
///
/// # Example
///
/// ```
/// use odbc_api::{Connection, Error};
/// use std::{io::{self, stdin, Read}, time::Duration};
///
/// /// Execute many different queries sequentially.
/// async fn execute_all(conn: &Connection<'_>, queries: &[&str]) -> Result<(), Error>{
/// let mut statement = conn.preallocate()?.into_polling()?;
/// let sleep = || tokio::time::sleep(Duration::from_millis(20));
/// for query in queries {
/// println!("Executing {query}");
/// match statement.execute(&query, (), sleep).await {
/// Err(e) => println!("{}", e),
/// Ok(None) => println!("No results set generated."),
/// Ok(Some(cursor)) => {
/// // ...print cursor contents...
/// },
/// }
/// }
/// Ok(())
/// }
/// ```
pub async fn execute(
&mut self,
query: &str,
params: impl ParameterCollectionRef,
sleep: impl Sleep,
) -> Result<Option<CursorPolling<StatementRef<'_>>>, Error> {
let query = SqlText::new(query);
let stmt = self.statement.as_stmt_ref();
execute_with_parameters_polling(stmt, Some(&query), params, sleep).await
}
}
impl<S> AsStatementRef for PreallocatedPolling<S>
where
S: AsStatementRef,
{
fn as_stmt_ref(&mut self) -> StatementRef<'_> {
self.statement.as_stmt_ref()
}
}