use crate::{
Error,
handles::{AsStatementRef, Statement, StatementRef},
sleep::{Sleep, wait_for},
};
use super::{
RowSetBuffer, bind_row_set_buffer_to_statement, error_handling_for_fetch,
unbind_buffer_from_cursor,
};
use std::thread::panicking;
pub struct CursorPolling<Stmt: Statement> {
statement: Stmt,
}
impl<S> CursorPolling<S>
where
S: Statement,
{
pub unsafe fn new(statement: S) -> Self {
Self { statement }
}
pub fn bind_buffer<B>(
mut self,
mut row_set_buffer: B,
) -> Result<BlockCursorPolling<Self, B>, Error>
where
B: RowSetBuffer,
{
let stmt = self.statement.as_stmt_ref();
unsafe {
bind_row_set_buffer_to_statement(stmt, &mut row_set_buffer)?;
}
Ok(BlockCursorPolling::new(row_set_buffer, self))
}
}
impl<S> AsStatementRef for CursorPolling<S>
where
S: Statement,
{
fn as_stmt_ref(&mut self) -> StatementRef<'_> {
self.statement.as_stmt_ref()
}
}
impl<S> Drop for CursorPolling<S>
where
S: Statement,
{
fn drop(&mut self) {
if let Err(e) = self
.statement
.end_cursor_scope()
.into_result(&self.statement)
{
if !panicking() {
panic!("Unexpected error closing cursor: {e:?}")
}
}
}
}
pub struct BlockCursorPolling<C, B>
where
C: AsStatementRef,
{
buffer: B,
cursor: C,
}
impl<C, B> BlockCursorPolling<C, B>
where
C: AsStatementRef,
{
fn new(buffer: B, cursor: C) -> Self {
Self { buffer, cursor }
}
pub async fn fetch(&mut self, sleep: impl Sleep) -> Result<Option<&B>, Error>
where
B: RowSetBuffer,
{
self.fetch_with_truncation_check(false, sleep).await
}
pub async fn fetch_with_truncation_check(
&mut self,
error_for_truncation: bool,
mut sleep: impl Sleep,
) -> Result<Option<&B>, Error>
where
B: RowSetBuffer,
{
let mut stmt = self.cursor.as_stmt_ref();
let result = unsafe { wait_for(|| stmt.fetch(), &mut sleep).await };
let has_row = error_handling_for_fetch(result, stmt, &self.buffer, error_for_truncation)?;
Ok(has_row.then_some(&self.buffer))
}
}
impl<C, B> Drop for BlockCursorPolling<C, B>
where
C: AsStatementRef,
{
fn drop(&mut self) {
if let Err(e) = unbind_buffer_from_cursor(&mut self.cursor) {
if !panicking() {
panic!("Unexpected error unbinding columns: {e:?}")
}
}
}
}