Struct odbc_api::CursorImpl
source · pub struct CursorImpl<Stmt: AsStatementRef> { /* private fields */ }Expand description
Cursors are used to process and iterate the result sets returned by executing queries. Created
by either a prepared query or direct execution. Usually utilized through the crate::Cursor
trait.
Implementations§
source§impl<S> CursorImpl<S>where
S: AsStatementRef,
impl<S> CursorImpl<S>where
S: AsStatementRef,
sourcepub unsafe fn new(statement: S) -> Self
pub unsafe fn new(statement: S) -> Self
Users of this library are encouraged not to call this constructor directly but rather invoke
crate::Connection::execute or crate::Prepared::execute to get a cursor and utilize
it using the crate::Cursor trait. This method is pubilc so users with an understanding
of the raw ODBC C-API have a way to create a cursor, after they left the safety rails of the
Rust type System, in order to implement a use case not covered yet, by the safe abstractions
within this crate.
Safety
statement must be in Cursor state, for the invariants of this type to hold.
Examples found in repository?
src/connection.rs (line 199)
182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201
pub fn into_cursor(
self,
query: &str,
params: impl ParameterCollectionRef,
) -> Result<Option<CursorImpl<StatementConnection<'c>>>, Error> {
let cursor = match self.execute(query, params) {
Ok(Some(cursor)) => cursor,
Ok(None) => return Ok(None),
Err(e) => return Err(e),
};
// The rust compiler needs some help here. It assumes otherwise that the lifetime of the
// resulting cursor would depend on the lifetime of `params`.
let mut cursor = ManuallyDrop::new(cursor);
let handle = cursor.as_sys();
// Safe: `handle` is a valid statement, and we are giving up ownership of `self`.
let statement = unsafe { StatementConnection::new(handle, self) };
// Safe: `statement is in the cursor state`.
let cursor = unsafe { CursorImpl::new(statement) };
Ok(Some(cursor))
}More examples
src/execute.rs (line 129)
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 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240
pub unsafe fn execute<S>(
mut statement: S,
query: Option<&SqlText<'_>>,
) -> Result<Option<CursorImpl<S>>, Error>
where
S: AsStatementRef,
{
let mut stmt = statement.as_stmt_ref();
let result = if let Some(sql) = query {
// We execute an unprepared "one shot query"
stmt.exec_direct(sql)
} else {
// We execute a prepared query
stmt.execute()
};
// If delayed parameters (e.g. input streams) are bound we might need to put data in order to
// execute.
let need_data =
result
.on_success(|| false)
.into_result_with(&stmt, false, Some(false), Some(true))?;
if need_data {
// Check if any delayed parameters have been bound which stream data to the database at
// statement execution time. Loops over each bound stream.
while let Some(blob_ptr) = stmt.param_data().into_result(&stmt)? {
// The safe interfaces currently exclusively bind pointers to `Blob` trait objects
let blob_ptr: *mut &mut dyn Blob = transmute(blob_ptr);
let blob_ref = &mut *blob_ptr;
// Loop over all batches within each blob
while let Some(batch) = blob_ref.next_batch().map_err(Error::FailedReadingInput)? {
stmt.put_binary_batch(batch).into_result(&stmt)?;
}
}
}
// Check if a result set has been created.
if stmt.num_result_cols().into_result(&stmt)? == 0 {
Ok(None)
} else {
// Safe: `statement` is in cursor state.
let cursor = CursorImpl::new(statement);
Ok(Some(cursor))
}
}
/// # Safety
///
/// * Execute may dereference pointers to bound parameters, so these must guaranteed to be valid
/// then calling this function.
/// * Furthermore all bound delayed parameters must be of type `*mut &mut dyn Blob`.
pub async unsafe fn execute_polling<S>(
mut statement: S,
query: Option<&SqlText<'_>>,
mut sleep: impl Sleep,
) -> Result<Option<CursorPolling<S>>, Error>
where
S: AsStatementRef,
{
let mut stmt = statement.as_stmt_ref();
let result = if let Some(sql) = query {
// We execute an unprepared "one shot query"
wait_for(|| stmt.exec_direct(sql), &mut sleep).await
} else {
// We execute a prepared query
wait_for(|| stmt.execute(), &mut sleep).await
};
// If delayed parameters (e.g. input streams) are bound we might need to put data in order to
// execute.
let need_data =
result
.on_success(|| false)
.into_result_with(&stmt, false, Some(false), Some(true))?;
if need_data {
// Check if any delayed parameters have been bound which stream data to the database at
// statement execution time. Loops over each bound stream.
while let Some(blob_ptr) = stmt.param_data().into_result(&stmt)? {
// The safe interfaces currently exclusively bind pointers to `Blob` trait objects
let blob_ptr: *mut &mut dyn Blob = transmute(blob_ptr);
let blob_ref = &mut *blob_ptr;
// Loop over all batches within each blob
while let Some(batch) = blob_ref.next_batch().map_err(Error::FailedReadingInput)? {
let result = wait_for(|| stmt.put_binary_batch(batch), &mut sleep).await;
result.into_result(&stmt)?;
}
}
}
// Check if a result set has been created.
let num_result_cols = wait_for(|| stmt.num_result_cols(), &mut sleep)
.await
.into_result(&stmt)?;
if num_result_cols == 0 {
Ok(None)
} else {
// Safe: `statement` is in cursor state.
let cursor = CursorPolling::new(statement);
Ok(Some(cursor))
}
}
/// Shared implementation for executing a columns query between [`crate::Connection`] and
/// [`crate::Preallocated`].
pub fn execute_columns<S>(
mut statement: S,
catalog_name: &SqlText,
schema_name: &SqlText,
table_name: &SqlText,
column_name: &SqlText,
) -> Result<CursorImpl<S>, Error>
where
S: AsStatementRef,
{
let mut stmt = statement.as_stmt_ref();
stmt.columns(catalog_name, schema_name, table_name, column_name)
.into_result(&stmt)?;
// We assume columns always creates a result set, since it works like a SELECT statement.
debug_assert_ne!(stmt.num_result_cols().unwrap(), 0);
// Safe: `statement` is in cursor state
let cursor = unsafe { CursorImpl::new(statement) };
Ok(cursor)
}
/// Shared implementation for executing a tables query between [`crate::Connection`] and
/// [`crate::Preallocated`].
pub fn execute_tables<S>(
mut statement: S,
catalog_name: &SqlText,
schema_name: &SqlText,
table_name: &SqlText,
column_name: &SqlText,
) -> Result<CursorImpl<S>, Error>
where
S: AsStatementRef,
{
let mut stmt = statement.as_stmt_ref();
stmt.tables(catalog_name, schema_name, table_name, column_name)
.into_result(&stmt)?;
// We assume columns always creates a result set, since it works like a SELECT statement.
debug_assert_ne!(stmt.num_result_cols().unwrap(), 0);
// Safe: `statement` is in Cursor state.
let cursor = unsafe { CursorImpl::new(statement) };
Ok(cursor)
}Trait Implementations§
source§impl<S> AsStatementRef for CursorImpl<S>where
S: AsStatementRef,
impl<S> AsStatementRef for CursorImpl<S>where
S: AsStatementRef,
source§fn as_stmt_ref(&mut self) -> StatementRef<'_>
fn as_stmt_ref(&mut self) -> StatementRef<'_>
Get an exclusive reference to the underlying statement handle. This method is used to
implement other more higher level methods on top of it. It is not intended to be called by
users of this crate directly, yet it may serve as an escape hatch for low level usecases.
source§impl<S> Cursor for CursorImpl<S>where
S: AsStatementRef,
impl<S> Cursor for CursorImpl<S>where
S: AsStatementRef,
source§fn bind_buffer<B>(self, row_set_buffer: B) -> Result<BlockCursor<Self, B>, Error>where
B: RowSetBuffer,
fn bind_buffer<B>(self, row_set_buffer: B) -> Result<BlockCursor<Self, B>, Error>where
B: RowSetBuffer,
Binds this cursor to a buffer holding a row set.
source§impl<S> Drop for CursorImpl<S>where
S: AsStatementRef,
impl<S> Drop for CursorImpl<S>where
S: AsStatementRef,
source§impl<S> ResultSetMetadata for CursorImpl<S>where
S: AsStatementRef,
impl<S> ResultSetMetadata for CursorImpl<S>where
S: AsStatementRef,
source§fn describe_col(
&mut self,
column_number: u16,
column_description: &mut ColumnDescription
) -> Result<(), Error>
fn describe_col(
&mut self,
column_number: u16,
column_description: &mut ColumnDescription
) -> Result<(), Error>
Fetch a column description using the column index. Read more
source§fn num_result_cols(&mut self) -> Result<i16, Error>
fn num_result_cols(&mut self) -> Result<i16, Error>
Number of columns in result set. Can also be used to see wether executing a prepared
Statement (
crate::Prepared) would yield a result set, as this would return 0 if it
does not. Read moresource§fn column_is_unsigned(&mut self, column_number: u16) -> Result<bool, Error>
fn column_is_unsigned(&mut self, column_number: u16) -> Result<bool, Error>
true if a given column in a result set is unsigned or not a numeric type, false
otherwise. Read moresource§fn col_octet_length(&mut self, column_number: u16) -> Result<isize, Error>
fn col_octet_length(&mut self, column_number: u16) -> Result<isize, Error>
Returns the size in bytes of the columns. For variable sized types the maximum size is
returned, excluding a terminating zero. Read more
source§fn col_display_size(&mut self, column_number: u16) -> Result<isize, Error>
fn col_display_size(&mut self, column_number: u16) -> Result<isize, Error>
Maximum number of characters required to display data from the column. Read more
source§fn col_precision(&mut self, column_number: u16) -> Result<isize, Error>
fn col_precision(&mut self, column_number: u16) -> Result<isize, Error>
Precision of the column. Read more
source§fn col_scale(&mut self, column_number: u16) -> Result<isize, Error>
fn col_scale(&mut self, column_number: u16) -> Result<isize, Error>
The applicable scale for a numeric data type. For DECIMAL and NUMERIC data types, this is
the defined scale. It is undefined for all other data types.
source§fn col_name(&mut self, column_number: u16) -> Result<String, Error>
fn col_name(&mut self, column_number: u16) -> Result<String, Error>
The column alias, if it applies. If the column alias does not apply, the column name is
returned. If there is no column name or a column alias, an empty string is returned.