pub struct Prepared<S> { /* private fields */ }
Expand description
A prepared query. Prepared queries are useful if the similar queries should executed more than
once. See crate::Connection::prepare
.
Implementations§
Source§impl<S> Prepared<S>
impl<S> Prepared<S>
Sourcepub fn into_statement(self) -> S
pub fn into_statement(self) -> S
Transfer ownership to the underlying statement handle.
The resulting type is one level of indirection away from the raw pointer of the ODBC API. It
no longer has any guarantees about bound buffers, but is still guaranteed to be a valid
allocated statement handle. This serves together with
crate::handles::StatementImpl::into_sys
or crate::handles::Statement::as_sys
this
serves as an escape hatch to access the functionality provided by crate::sys
not yet
accessible through safe abstractions.
Source§impl<S> Prepared<S>where
S: AsStatementRef,
impl<S> Prepared<S>where
S: AsStatementRef,
Sourcepub fn execute(
&mut self,
params: impl ParameterCollectionRef,
) -> Result<Option<CursorImpl<StatementRef<'_>>>, Error>
pub fn execute( &mut self, params: impl ParameterCollectionRef, ) -> Result<Option<CursorImpl<StatementRef<'_>>>, Error>
Execute the prepared statement.
params
: Used to bind these parameters before executing the statement. You can use()
to represent no parameters. In regards to binding arrays of parameters: Shouldparams
specify a parameter set size of0
, nothing is executed, andOk(None)
is returned. See thecrate::parameter
module level documentation for more information on how to pass parameters.
Sourcepub fn describe_param(
&mut self,
parameter_number: u16,
) -> Result<ParameterDescription, Error>
pub fn describe_param( &mut self, parameter_number: u16, ) -> Result<ParameterDescription, Error>
Describes parameter marker associated with a prepared SQL statement.
§Parameters
parameter_number
: Parameter marker number ordered sequentially in increasing parameter order, starting at 1.
Sourcepub fn num_params(&mut self) -> Result<u16, Error>
pub fn num_params(&mut self) -> Result<u16, Error>
Number of placeholders which must be provided with Self::execute
in order to execute
this statement. This is equivalent to the number of placeholders used in the SQL string
used to prepare the statement.
Sourcepub fn parameter_descriptions(
&mut self,
) -> Result<impl DoubleEndedIterator<Item = Result<ParameterDescription, Error>> + ExactSizeIterator<Item = Result<ParameterDescription, Error>> + '_, Error>
pub fn parameter_descriptions( &mut self, ) -> Result<impl DoubleEndedIterator<Item = Result<ParameterDescription, Error>> + ExactSizeIterator<Item = Result<ParameterDescription, Error>> + '_, Error>
Number of placeholders which must be provided with Self::execute
in order to execute
this statement. This is equivalent to the number of placeholders used in the SQL string
used to prepare the statement.
use odbc_api::{Connection, Error, handles::ParameterDescription};
fn collect_parameter_descriptions(
connection: Connection<'_>
) -> Result<Vec<ParameterDescription>, Error>{
// Note the two `?` used as placeholders for the parameters.
let sql = "INSERT INTO NationalDrink (country, drink) VALUES (?, ?)";
let mut prepared = connection.prepare(sql)?;
let params: Vec<_> = prepared.parameter_descriptions()?.collect::<Result<_,_>>()?;
Ok(params)
}
Sourcepub unsafe fn unchecked_bind_columnar_array_parameters<C>(
self,
parameter_buffers: Vec<C>,
) -> Result<ColumnarBulkInserter<S, C>, Error>where
C: ColumnBuffer + HasDataType,
pub unsafe fn unchecked_bind_columnar_array_parameters<C>(
self,
parameter_buffers: Vec<C>,
) -> Result<ColumnarBulkInserter<S, C>, Error>where
C: ColumnBuffer + HasDataType,
Unless you want to roll your own column buffer implementation users are encouraged to use
Self::into_text_inserter
instead.
§Safety
- Parameters must all be valid for insertion. An example for an invalid parameter would be a text buffer with a cell those indiactor value exceeds the maximum element length. This can happen after when truncation occurs then writing into a buffer.
Sourcepub fn into_text_inserter(
self,
capacity: usize,
max_str_len: impl IntoIterator<Item = usize>,
) -> Result<ColumnarBulkInserter<S, TextColumn<u8>>, Error>
pub fn into_text_inserter( self, capacity: usize, max_str_len: impl IntoIterator<Item = usize>, ) -> Result<ColumnarBulkInserter<S, TextColumn<u8>>, Error>
Use this to insert rows of string input into the database.
use odbc_api::{Connection, Error};
fn insert_text<'e>(connection: Connection<'e>) -> Result<(), Error>{
// Insert six rows of text with two columns each into the database in batches of 3. In a
// real use case you are likely to achieve a better results with a higher batch size.
// Note the two `?` used as placeholders for the parameters.
let prepared = connection.prepare("INSERT INTO NationalDrink (country, drink) VALUES (?, ?)")?;
// We assume both parameter inputs never exceed 50 bytes.
let mut prebound = prepared.into_text_inserter(3, [50, 50])?;
// A cell is an option to byte. We could use `None` to represent NULL but we have no
// need to do that in this example.
let as_cell = |s: &'static str| { Some(s.as_bytes()) } ;
// First batch of values
prebound.append(["England", "Tea"].into_iter().map(as_cell))?;
prebound.append(["Germany", "Beer"].into_iter().map(as_cell))?;
prebound.append(["Russia", "Vodka"].into_iter().map(as_cell))?;
// Execute statement using values bound in buffer.
prebound.execute()?;
// Clear buffer contents, otherwise the previous values would stay in the buffer.
prebound.clear();
// Second batch of values
prebound.append(["India", "Tea"].into_iter().map(as_cell))?;
prebound.append(["France", "Wine"].into_iter().map(as_cell))?;
prebound.append(["USA", "Cola"].into_iter().map(as_cell))?;
// Send second batch to the database
prebound.execute()?;
Ok(())
}
Sourcepub fn into_column_inserter(
self,
capacity: usize,
descriptions: impl IntoIterator<Item = BufferDesc>,
) -> Result<ColumnarBulkInserter<S, AnyBuffer>, Error>
pub fn into_column_inserter( self, capacity: usize, descriptions: impl IntoIterator<Item = BufferDesc>, ) -> Result<ColumnarBulkInserter<S, AnyBuffer>, Error>
A crate::ColumnarBulkInserter
which takes ownership of both the statement and the bound
array parameter buffers.
use odbc_api::{Connection, Error, IntoParameter, buffers::BufferDesc};
fn insert_birth_years(
conn: &Connection,
names: &[&str],
years: &[i16]
) -> Result<(), Error> {
// All columns must have equal length.
assert_eq!(names.len(), years.len());
let prepared = conn.prepare("INSERT INTO Birthdays (name, year) VALUES (?, ?)")?;
// Create a columnar buffer which fits the input parameters.
let buffer_description = [
BufferDesc::Text { max_str_len: 255 },
BufferDesc::I16 { nullable: false },
];
// The capacity must be able to hold at least the largest batch. We do everything in one
// go, so we set it to the length of the input parameters.
let capacity = names.len();
// Allocate memory for the array column parameters and bind it to the statement.
let mut prebound = prepared.into_column_inserter(capacity, buffer_description)?;
// Length of this batch
prebound.set_num_rows(capacity);
// Fill the buffer with values column by column
let mut col = prebound
.column_mut(0)
.as_text_view()
.expect("We know the name column to hold text.");
for (index, name) in names.iter().enumerate() {
col.set_cell(index, Some(name.as_bytes()));
}
let col = prebound
.column_mut(1)
.as_slice::<i16>()
.expect("We know the year column to hold i16.");
col.copy_from_slice(years);
prebound.execute()?;
Ok(())
}
Sourcepub fn column_inserter(
&mut self,
capacity: usize,
descriptions: impl IntoIterator<Item = BufferDesc>,
) -> Result<ColumnarBulkInserter<StatementRef<'_>, AnyBuffer>, Error>
pub fn column_inserter( &mut self, capacity: usize, descriptions: impl IntoIterator<Item = BufferDesc>, ) -> Result<ColumnarBulkInserter<StatementRef<'_>, AnyBuffer>, Error>
A crate::ColumnarBulkInserter
which has ownership of the bound array parameter buffers
and borrows the statement. For most usecases Self::into_column_inserter
is what you
want to use, yet on some instances you may want to bind new paramater buffers to the same
prepared statement. E.g. to grow the capacity dynamically during insertions with several
chunks. In such use cases you may only want to borrow the prepared statemnt, so it can be
reused with a different set of parameter buffers.
Sourcepub fn row_count(&mut self) -> Result<Option<usize>, Error>
pub fn row_count(&mut self) -> Result<Option<usize>, Error>
Number of rows affected by the last INSERT
, UPDATE
or DELETE
statement. May return
None
if row count is not available. Some drivers may also allow to use this to determine
how many rows have been fetched using SELECT
. Most drivers however only know how many rows
have been fetched after they have been fetched.
use odbc_api::{Connection, Error, IntoParameter};
/// Deletes all comments for every user in the slice. Returns the number of deleted
/// comments.
pub fn delete_all_comments_from(
users: &[&str],
conn: Connection<'_>,
) -> Result<usize, Error>
{
// Store prepared query for fast repeated execution.
let mut prepared = conn.prepare("DELETE FROM Comments WHERE user=?")?;
let mut total_deleted_comments = 0;
for user in users {
prepared.execute(&user.into_parameter())?;
total_deleted_comments += prepared
.row_count()?
.expect("Row count must always be available for DELETE statements.");
}
Ok(total_deleted_comments)
}
Trait Implementations§
Source§impl<S> AsStatementRef for Prepared<S>where
S: AsStatementRef,
impl<S> AsStatementRef for Prepared<S>where
S: AsStatementRef,
Source§fn as_stmt_ref(&mut self) -> StatementRef<'_>
fn as_stmt_ref(&mut self) -> StatementRef<'_>
Source§impl<S> ResultSetMetadata for Prepared<S>where
S: AsStatementRef,
impl<S> ResultSetMetadata for Prepared<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>
Source§fn num_result_cols(&mut self) -> Result<i16, Error>
fn num_result_cols(&mut self) -> Result<i16, Error>
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<Option<NonZeroUsize>, Error>
fn col_octet_length( &mut self, column_number: u16, ) -> Result<Option<NonZeroUsize>, Error>
Source§fn col_display_size(
&mut self,
column_number: u16,
) -> Result<Option<NonZeroUsize>, Error>
fn col_display_size( &mut self, column_number: u16, ) -> Result<Option<NonZeroUsize>, Error>
None
is returned. Read more