Skip to content

Commit 6d4eb45

Browse files
authored
Add more method to result streams (#223)
aligning them a bit more with product driver API
1 parent 4db8dd7 commit 6d4eb45

File tree

2 files changed

+170
-3
lines changed

2 files changed

+170
-3
lines changed

lib/src/errors.rs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -85,6 +85,12 @@ pub enum Error {
8585
#[error("conversion error")]
8686
ConversionError,
8787

88+
#[error("No more rows available in the query result")]
89+
NoMoreRows,
90+
91+
#[error("Result contains more than one row")]
92+
NotSingleResult,
93+
8894
#[error("{0}")]
8995
AuthenticationError(String),
9096

lib/src/stream.rs

Lines changed: 164 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -131,9 +131,99 @@ impl RowStream {
131131
.map(|item| item.and_then(RowItem::into_row))
132132
}
133133

134-
/// A call to next_or_summary() will return a row from an internal buffer if the buffer has any entries,
135-
/// if the buffer is empty and the server has more rows left to consume, then a new batch of rows
136-
/// are fetched from the server (using the fetch_size value configured see [`crate::ConfigBuilder::fetch_size`])
134+
/// Return the [`RowStream::next`] item,
135+
/// converted into a `T` by calling [`crate::row::Row::to`].
136+
///
137+
/// Unlike `next`, this method returns a missing items as an error ([`Error::NoMoreRows`]).
138+
pub async fn next_as<'this, 'db: 'this, T: DeserializeOwned + 'this>(
139+
&'this mut self,
140+
handle: impl TransactionHandle + 'db,
141+
) -> Result<T> {
142+
self.next(handle)
143+
.await
144+
.and_then(|row| row.ok_or(Error::NoMoreRows))
145+
.and_then(|row| row.to::<T>().map_err(Error::DeserializationError))
146+
}
147+
148+
/// Return the first [`create::Row`] in the result.
149+
///
150+
/// If there are 0 results, [`Error::NoMoreRows`] is returned.
151+
/// If there are 2 or more results, [`Error::NotSingleResult`] is returned.
152+
pub async fn single(&mut self, mut handle: impl TransactionHandle) -> Result<Row> {
153+
let row = self
154+
.next(&mut handle)
155+
.await
156+
.and_then(|row| row.ok_or(Error::NoMoreRows))?;
157+
let None = self.next(handle).await? else {
158+
return Err(Error::NotSingleResult);
159+
};
160+
Ok(row)
161+
}
162+
163+
/// Return the first [`create::Row`] in the result.
164+
/// converted into a `T` by calling [`crate::row::Row::to`].
165+
///
166+
/// If there are 0 results, [`Error::NoMoreRows`] is returned.
167+
/// If there are 2 or more results, [`Error::NotSingleResult`] is returned.
168+
pub async fn single_as<'this, 'db: 'this, T: DeserializeOwned + 'this>(
169+
&'this mut self,
170+
handle: impl TransactionHandle + 'db,
171+
) -> Result<T> {
172+
self.single(handle)
173+
.await
174+
.and_then(|row| row.to::<T>().map_err(Error::DeserializationError))
175+
}
176+
177+
/// Return the first [`create::Row`] buffered result without consuming it.
178+
///
179+
/// Note that this method is not `async` and does not require a `TransactionHandle` because
180+
/// only buffered results are inspected and no actual communication is done.
181+
///
182+
/// As such, returning `None` does not mean that there are no more results,
183+
/// it just means that the buffer is empty.
184+
pub fn peek(&self) -> Option<&Row> {
185+
self.buffer.front()
186+
}
187+
188+
/// Return the first [`create::Row`] buffered result without consuming it,
189+
/// converted into a `T` by calling [`crate::row::Row::to`].
190+
///
191+
/// Note that this method is not `async` and does not require a `TransactionHandle` because
192+
/// only buffered results are inspected and no actual communication is done.
193+
///
194+
/// As such, returning [`Error::NoMoreRows`] does not mean that there are no more results,
195+
/// it just means that the buffer is empty.
196+
pub fn peek_as<'this, T: DeserializeOwned + 'this>(&'this self) -> Result<T> {
197+
self.peek()
198+
.ok_or(Error::NoMoreRows)
199+
.and_then(|row| row.to::<T>().map_err(Error::DeserializationError))
200+
}
201+
202+
/// Return the first [`create::Row`] buffered result and consume it.
203+
///
204+
/// Note that this method is not `async` and does not require a `TransactionHandle` because
205+
/// only buffered results are inspected and no actual communication is done.
206+
///
207+
/// As such, returning `None` does not mean that there are no more results,
208+
/// it just means that the buffer is empty.
209+
pub fn pop(&mut self) -> Option<Row> {
210+
self.buffer.pop_front()
211+
}
212+
213+
/// Return the first [`create::Row`] buffered result and consume it,
214+
/// converted into a `T` by calling [`crate::row::Row::to`].
215+
///
216+
/// Note that this method is not `async` and does not require a `TransactionHandle` because
217+
/// only buffered results are inspected and no actual communication is done.
218+
///
219+
/// As such, returning [`Error::NoMoreRows`] does not mean that there are no more results,
220+
/// it just means that the buffer is empty.
221+
pub fn pop_as<'this, T: DeserializeOwned + 'this>(&'this mut self) -> Result<T> {
222+
self.pop()
223+
.ok_or(Error::NoMoreRows)
224+
.and_then(|row| row.to::<T>().map_err(Error::DeserializationError))
225+
}
226+
137227
pub async fn next_or_summary(
138228
&mut self,
139229
mut handle: impl TransactionHandle,
@@ -396,6 +486,77 @@ impl DetachedRowStream {
396486
self.stream.next(&mut self.connection).await
397487
}
398488

489+
/// Return the [`RowStream::next`] item,
490+
/// converted into a `T` by calling [`crate::row::Row::to`].
491+
///
492+
/// Unlike `next`, this method returns a missing items as an error ([`Error::NoMoreRows`]).
493+
pub async fn next_as<'this, T: DeserializeOwned + 'this>(&'this mut self) -> Result<T> {
494+
self.stream.next_as(&mut self.connection).await
495+
}
496+
497+
/// Return the first [`create::Row`] in the result.
498+
///
499+
/// If there are 0 results, [`Error::NoMoreRows`] is returned.
500+
/// If there are 2 or more results, [`Error::NotSingleResult`] is returned.
501+
pub async fn single(&mut self) -> Result<Row> {
502+
self.stream.single(&mut self.connection).await
503+
}
504+
505+
/// Return the first [`create::Row`] in the result.
506+
/// converted into a `T` by calling [`crate::row::Row::to`].
507+
///
508+
/// If there are 0 results, [`Error::NoMoreRows`] is returned.
509+
/// If there are 2 or more results, [`Error::NotSingleResult`] is returned.
510+
pub async fn single_as<'this, T: DeserializeOwned + 'this>(&'this mut self) -> Result<T> {
511+
self.stream.single_as(&mut self.connection).await
512+
}
513+
514+
/// Return the first [`create::Row`] buffered result without consuming it.
515+
///
516+
/// Note that this method is not `async` and does not require a `TransactionHandle` because
517+
/// only buffered results are inspected and no actual communication is done.
518+
///
519+
/// As such, returning `None` does not mean that there are no more results,
520+
/// it just means that the buffer is empty.
521+
pub fn peek(&self) -> Option<&Row> {
522+
self.stream.peek()
523+
}
524+
525+
/// Return the first [`create::Row`] buffered result without consuming it,
526+
/// converted into a `T` by calling [`crate::row::Row::to`].
527+
///
528+
/// Note that this method is not `async` and does not require a `TransactionHandle` because
529+
/// only buffered results are inspected and no actual communication is done.
530+
///
531+
/// As such, returning [`Error::NoMoreRows`] does not mean that there are no more results,
532+
/// it just means that the buffer is empty.
533+
pub fn peek_as<'this, T: DeserializeOwned + 'this>(&'this self) -> Result<T> {
534+
self.stream.peek_as()
535+
}
536+
537+
/// Return the first [`create::Row`] buffered result and consume it.
538+
///
539+
/// Note that this method is not `async` and does not require a `TransactionHandle` because
540+
/// only buffered results are inspected and no actual communication is done.
541+
///
542+
/// As such, returning `None` does not mean that there are no more results,
543+
/// it just means that the buffer is empty.
544+
pub fn pop(&mut self) -> Option<Row> {
545+
self.stream.pop()
546+
}
547+
548+
/// Return the first [`create::Row`] buffered result and consume it,
549+
/// converted into a `T` by calling [`crate::row::Row::to`].
550+
///
551+
/// Note that this method is not `async` and does not require a `TransactionHandle` because
552+
/// only buffered results are inspected and no actual communication is done.
553+
///
554+
/// As such, returning [`Error::NoMoreRows`] does not mean that there are no more results,
555+
/// it just means that the buffer is empty.
556+
pub fn pop_as<'this, T: DeserializeOwned + 'this>(&'this mut self) -> Result<T> {
557+
self.stream.pop_as()
558+
}
559+
399560
/// A call to next_or_summary() will return a row from an internal buffer if the buffer has any entries,
400561
/// if the buffer is empty and the server has more rows left to consume, then a new batch of rows
401562
/// are fetched from the server (using the fetch_size value configured see [`crate::ConfigBuilder::fetch_size`])

0 commit comments

Comments
 (0)