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 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173
use std::cell::RefCell;
use std::rc::Rc;
use super::row::{PrivateSqliteRow, SqliteRow};
use super::stmt::StatementUse;
use crate::result::QueryResult;
#[allow(missing_debug_implementations)]
pub struct StatementIterator<'stmt, 'query> {
inner: PrivateStatementIterator<'stmt, 'query>,
column_names: Option<Rc<[Option<String>]>>,
field_count: usize,
}
impl<'stmt, 'query> StatementIterator<'stmt, 'query> {
#[cold]
fn handle_duplicated_row_case(
outer_last_row: &mut Rc<RefCell<PrivateSqliteRow<'stmt, 'query>>>,
column_names: &mut Option<Rc<[Option<String>]>>,
field_count: usize,
) -> Option<QueryResult<SqliteRow<'stmt, 'query>>> {
// We don't own the statement. There is another existing reference, likely because
// a user stored the row in some long time container before calling next another time
// In this case we copy out the current values into a temporary store and advance
// the statement iterator internally afterwards
let last_row = {
let mut last_row = match outer_last_row.try_borrow_mut() {
Ok(o) => o,
Err(_e) => {
return Some(Err(crate::result::Error::DeserializationError(
"Failed to reborrow row. Try to release any `SqliteField` or `SqliteValue` \
that exists at this point"
.into(),
)));
}
};
let last_row = &mut *last_row;
let duplicated = last_row.duplicate(column_names);
std::mem::replace(last_row, duplicated)
};
if let PrivateSqliteRow::Direct(mut stmt) = last_row {
let res = unsafe {
// This is actually safe here as we've already
// performed one step. For the first step we would have
// used `PrivateStatementIterator::NotStarted` where we don't
// have access to `PrivateSqliteRow` at all
stmt.step(false)
};
*outer_last_row = Rc::new(RefCell::new(PrivateSqliteRow::Direct(stmt)));
match res {
Err(e) => Some(Err(e)),
Ok(false) => None,
Ok(true) => {
let field_count = field_count;
Some(Ok(SqliteRow {
inner: Rc::clone(outer_last_row),
field_count,
}))
}
}
} else {
// any other state than `PrivateSqliteRow::Direct` is invalid here
// and should not happen. If this ever happens this is a logic error
// in the code above
unreachable!(
"You've reached an impossible internal state. \
If you ever see this error message please open \
an issue at https://github.com/diesel-rs/diesel \
providing example code how to trigger this error."
)
}
}
}
enum PrivateStatementIterator<'stmt, 'query> {
NotStarted(Option<StatementUse<'stmt, 'query>>),
Started(Rc<RefCell<PrivateSqliteRow<'stmt, 'query>>>),
}
impl<'stmt, 'query> StatementIterator<'stmt, 'query> {
pub fn new(stmt: StatementUse<'stmt, 'query>) -> StatementIterator<'stmt, 'query> {
Self {
inner: PrivateStatementIterator::NotStarted(Some(stmt)),
column_names: None,
field_count: 0,
}
}
}
impl<'stmt, 'query> Iterator for StatementIterator<'stmt, 'query> {
type Item = QueryResult<SqliteRow<'stmt, 'query>>;
fn next(&mut self) -> Option<Self::Item> {
use PrivateStatementIterator::{NotStarted, Started};
match &mut self.inner {
NotStarted(ref mut stmt) if stmt.is_some() => {
let mut stmt = stmt
.take()
.expect("It must be there because we checked that above");
let step = unsafe {
// This is safe as we pass `first_step = true` to reset the cached column names
stmt.step(true)
};
match step {
Err(e) => Some(Err(e)),
Ok(false) => None,
Ok(true) => {
let field_count = stmt.column_count() as usize;
self.field_count = field_count;
let inner = Rc::new(RefCell::new(PrivateSqliteRow::Direct(stmt)));
self.inner = Started(inner.clone());
Some(Ok(SqliteRow { inner, field_count }))
}
}
}
Started(ref mut last_row) => {
// There was already at least one iteration step
// We check here if the caller already released the row value or not
// by checking if our Rc owns the data or not
if let Some(last_row_ref) = Rc::get_mut(last_row) {
// We own the statement, there is no other reference here.
// This means we don't need to copy out values from the sqlite provided
// datastructures for now
// We don't need to use the runtime borrowing system of the RefCell here
// as we have a mutable reference, so all of this below is checked at compile time
if let PrivateSqliteRow::Direct(ref mut stmt) = last_row_ref.get_mut() {
let step = unsafe {
// This is actually safe here as we've already
// performed one step. For the first step we would have
// used `PrivateStatementIterator::NotStarted` where we don't
// have access to `PrivateSqliteRow` at all
stmt.step(false)
};
match step {
Err(e) => Some(Err(e)),
Ok(false) => None,
Ok(true) => {
let field_count = self.field_count;
Some(Ok(SqliteRow {
inner: Rc::clone(last_row),
field_count,
}))
}
}
} else {
// any other state than `PrivateSqliteRow::Direct` is invalid here
// and should not happen. If this ever happens this is a logic error
// in the code above
unreachable!(
"You've reached an impossible internal state. \
If you ever see this error message please open \
an issue at https://github.com/diesel-rs/diesel \
providing example code how to trigger this error."
)
}
} else {
Self::handle_duplicated_row_case(
last_row,
&mut self.column_names,
self.field_count,
)
}
}
NotStarted(_) => unreachable!(
"You've reached an impossible internal state. \
If you ever see this error message please open \
an issue at https://github.com/diesel-rs/diesel \
providing example code how to trigger this error."
),
}
}
}