Struct odbc_api::BlockCursor

source ·
pub struct BlockCursor<C: AsStatementRef, B> { /* private fields */ }
Expand description

In order to safe 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 safes 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 safes 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:

  1. Reserve less memory for each individual field than the schema indicates and deciding on a sensible upper bound themselfes. This risks truncation of values though, if they are larger than the upper bound. Using BlockCursor::fetch_with_truncation_check instead of Cursor::next_row your appliacation can detect these truncations. This is usually the best choice, since individual fields in a table rarerly actuallly take up several GiB of memory.
  2. 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.
  3. 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§

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 ...
    }
}

Fills the bound buffer with the next row set. Should error_for_truncation be trueand 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 ...
    }
}

Trait Implementations§

Executes the destructor for this type. Read more

Auto Trait Implementations§

Blanket Implementations§

Gets the TypeId of self. Read more
Immutably borrows from an owned value. Read more
Mutably borrows from an owned value. Read more

Returns the argument unchanged.

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

The type returned in the event of a conversion error.
Performs the conversion.
The type returned in the event of a conversion error.
Performs the conversion.