use std::collections::VecDeque;
#[cfg(feature = "arrow")]
use crate::bind_params::BindParameters;
use crate::client::Client;
use crate::error::Error;
use crate::metadata::Metadata;
use crate::response::Response;
use crate::row::{Row, RowData};
use crate::statement::CachedStatement;
use crate::statement::StatementHolder;
use crate::statement::StatementOptions;
#[derive(Clone)]
pub struct Cursor {
statement_holder: StatementHolder,
rows: VecDeque<RowData>,
last_row: Option<RowData>,
end_of_fetch: bool,
}
impl Cursor {
fn get_more_rows(&mut self) -> Result<(), Error> {
let last_row = self.last_row.take();
self.set_from_response(self.statement_holder.fetch(last_row)?);
Ok(())
}
fn set_from_response(&mut self, mut response: Response) {
self.end_of_fetch = response.is_end_of_fetch();
if let Some(rows) = response.take_rows() {
self.rows = rows.into();
} else {
self.rows.clear();
}
}
#[cfg(feature = "arrow")]
pub(crate) fn execute(
&mut self,
params: BindParameters,
) -> Result<(), Error> {
let response = self.statement_holder.execute_batch(params)?;
self.set_from_initial_response(response);
Ok(())
}
pub(crate) fn from_resp(
resp: &mut Response,
client: &Client,
is_nested: bool,
options: &StatementOptions,
) -> Result<Option<Self>, Error> {
let mut statement =
CachedStatement::create_empty(String::new(), is_nested, options);
let _length = resp.read_u8()?;
statement.populate_from_describe_info(client, resp)?;
statement.set_cursor_id(resp.read_ub2()?);
let holder = StatementHolder::new(resp.get_client_ref(), statement);
Ok(Some(Self::new(holder)))
}
pub(crate) fn new(statement_holder: StatementHolder) -> Self {
Self {
statement_holder,
rows: VecDeque::<RowData>::new(),
last_row: None,
end_of_fetch: false,
}
}
pub(crate) fn set_from_initial_response(&mut self, response: Response) {
self.rows.clear();
self.last_row = None;
self.set_from_response(response);
}
pub fn columns(&self) -> &Vec<Metadata> {
self.statement_holder.out_metadata()
}
pub fn sql(&self) -> &str {
self.statement_holder.sql()
}
}
impl Iterator for Cursor {
type Item = Result<Row, Error>;
fn next(&mut self) -> Option<Self::Item> {
if self.rows.is_empty()
&& !self.end_of_fetch
&& let Err(e) = self.get_more_rows()
{
return Some(Err(e));
}
if let Some(row) = self.rows.pop_front() {
if self.rows.is_empty() {
self.last_row = Some(row.clone());
}
Some(Ok(Row::new(row)))
} else {
None
}
}
}