pub struct BlockCursor<C: AsStatementRef, B> { /* private fields */ }
Expand description
In order to save on network overhead, it is recommended to use block cursors instead of fetching
values individually. This can greatly reduce the time applications need to fetch data. You can
create a block cursor by binding preallocated memory to a cursor using Cursor::bind_buffer
.
A block cursor saves on a lot of IO overhead by fetching an entire set of rows (called rowset)
at once into the buffer bound to it. Reusing the same buffer for each rowset also saves on
allocations. A challange with using block cursors might be database schemas with columns there
individual fields can be very large. In these cases developers can choose to:
- Reserve less memory for each individual field than the schema indicates and deciding on a
sensible upper bound themselves. This risks truncation of values though, if they are larger
than the upper bound. Using
BlockCursor::fetch_with_truncation_check
instead ofCursor::next_row
your application can detect these truncations. This is usually the best choice, since individual fields in a table rarely actually take up several GiB of memory. - Calculate the number of rows dynamically based on the maximum expected row size.
crate::buffers::BufferDesc::bytes_per_row
, can be helpful with this task. - Not use block cursors and fetch rows slowly with high IO overhead. Calling
[
CursorRow::get_data
] and [CursorRow::get_text
] to fetch large individual values.
See: https://learn.microsoft.com/en-us/sql/odbc/reference/develop-app/block-cursors
Implementations§
Source§impl<C, B> BlockCursor<C, B>where
C: Cursor,
impl<C, B> BlockCursor<C, B>where
C: Cursor,
Sourcepub fn fetch(&mut self) -> Result<Option<&B>, Error>where
B: RowSetBuffer,
pub fn fetch(&mut self) -> Result<Option<&B>, Error>where
B: RowSetBuffer,
Fills the bound buffer with the next row set.
§Return
None
if the result set is empty and all row sets have been extracted. Some
with a
reference to the internal buffer otherwise.
use odbc_api::{buffers::TextRowSet, Cursor};
fn print_all_values(mut cursor: impl Cursor) {
let batch_size = 100;
let max_string_len = 4000;
let buffer = TextRowSet::for_cursor(batch_size, &mut cursor, Some(4000)).unwrap();
let mut cursor = cursor.bind_buffer(buffer).unwrap();
// Iterate over batches
while let Some(batch) = cursor.fetch().unwrap() {
// ... print values in batch ...
}
}
Sourcepub fn fetch_with_truncation_check(
&mut self,
error_for_truncation: bool,
) -> Result<Option<&B>, Error>where
B: RowSetBuffer,
pub fn fetch_with_truncation_check(
&mut self,
error_for_truncation: bool,
) -> Result<Option<&B>, Error>where
B: RowSetBuffer,
Fills the bound buffer with the next row set. Should error_for_truncation
be true
and any
diagnostic indicate truncation of a value an error is returned.
§Return
None
if the result set is empty and all row sets have been extracted. Some
with a
reference to the internal buffer otherwise.
Call this method to find out wether there are any truncated values in the batch, without inspecting all its rows and columns.
use odbc_api::{buffers::TextRowSet, Cursor};
fn print_all_values(mut cursor: impl Cursor) {
let batch_size = 100;
let max_string_len = 4000;
let buffer = TextRowSet::for_cursor(batch_size, &mut cursor, Some(4000)).unwrap();
let mut cursor = cursor.bind_buffer(buffer).unwrap();
// Iterate over batches
while let Some(batch) = cursor.fetch_with_truncation_check(true).unwrap() {
// ... print values in batch ...
}
}
Sourcepub fn unbind(self) -> Result<(C, B), Error>
pub fn unbind(self) -> Result<(C, B), Error>
Unbinds the buffer from the underlying statement handle. Potential usecases for this function include.
- Binding a different buffer to the “same” cursor after letting it point to the next result set obtained with Cursor::more_results`.
- Reusing the same buffer with a different statement.
Source§impl<C, B> BlockCursor<C, B>where
B: RowSetBuffer,
C: AsStatementRef,
impl<C, B> BlockCursor<C, B>where
B: RowSetBuffer,
C: AsStatementRef,
Sourcepub fn row_array_size(&self) -> usize
pub fn row_array_size(&self) -> usize
Maximum amount of rows fetched from the database in the next call to fetch.