Skip to main content

Statement

Struct Statement 

Source
pub struct Statement<'conn> { /* private fields */ }
Expand description

Represents a statement that is executed against a database.

A Statement cannot be created directly, instead it is brought to life through the .create_prepared_statement method of a Connection. It can only live as long as its parent Connection and when it goes out of scope the underlying resources will be released via a Drop implementation.

A Statement is stateful. Binding parameters and retrieving the result set will update the state of the object. The underlying OCI objects are stateful and re-use of an OCI statement for new binding parameters or diferent results is more efficient than allocating resources for a new statement. At the moment changing the SQL requires a new Statement but it might prove useful in future to allow this to be also changed without new allocation in the OCI library.

See the module level documentation for an overview plus examples.

Implementations§

Source§

impl<'conn> Statement<'conn>

Source

pub fn bind(&mut self, params: &[&dyn ToSqlValue]) -> Result<(), OciError>

Sets the parameters that will be used in a SQL statement with bind variables.

The parameters are anything that implement the ToSqlValue trait.

§Errors

Any error in the underlying calls to the OCI library will be returned.

§Examples

Here are various ways to bind parameters:

use oci_rs::connection::Connection;

let conn = Connection::new("localhost:1521/xe", "oci_rs", "test").unwrap();


// Insert some values using bind variables
let sql_insert = "INSERT INTO Dogs (DogId, Name)
                  VALUES (:id, :name)";

let mut insert = conn.create_prepared_statement(sql_insert).unwrap();

let id = 1;
let name = "Poodle";

insert.bind(&[&id, &name]).unwrap();
insert.execute().unwrap();

insert.bind(&[&2, &"Bulldog"]).unwrap();
insert.execute().unwrap();

insert.commit();

let sql_select = "SELECT Name FROM Dogs";

let mut select = conn.create_prepared_statement(sql_select).unwrap();
select.execute().unwrap();

let correct_results = vec!["Poodle".to_string(), "Bulldog".to_string()];
let results: Vec<String> = select.lazy_result_set()
                                 .map(|row_result| row_result.unwrap())
                                 .map(|row| row[0].value::<String>().unwrap())
                                 .collect();

assert_eq!(results, correct_results);

For large scale inserts to the database this is a bit inefficient as many calls to bind the parameters are needed. OCI does support batch processing and/or arrays of bind parameters, however this is not yet available through this crate.

Source

pub fn execute(&mut self) -> Result<(), OciError>

Executes the SQL statement.

§Errors

Any error in the underlying calls to the OCI library will be returned.

Source

pub fn result_set(&mut self) -> Result<&[Row], OciError>

Returns the results of a SELECT statement.

After the execution of a SELECT statement a result set will be available from the database. This will contain none or many Rows of data depending on the query. There are two options for seeing the results, the first is to call this method to retrieve all the rows in one go, the second is to iterate through them row by row.

Should you go for the first option then the rows will be fetched once this method is called. They will not be fetched eagerly as part of the .execute call, although this is not apparent to the caller. Once the results are retrieved from the database then they will be held until either the Statement goes out of scope or .execute is called again. This way, repeated calls to .result_set will be the same. If there are no data then an empty Vec<Row> will be returned.

§Errors

Any error in the underlying calls to the OCI library will be returned.

Source

pub fn set_prefetch(&mut self, nmb_of_rows: i32) -> Result<(), OciError>

Set the number of rows that will be prefetched from the database.

The OCI library internally manages the number of rows that are pre-fetched from the database. This can be tweaked. The OCI default is one row, so for each call to the database two rows are retrieved, thus half the number of round trips needed.

§Errors

Any error in the underlying calls to the OCI library will be returned.

Source

pub fn lazy_result_set(&mut self) -> RowIter<'_>

Returns the results of a SELECT statement row by row via the RowIter iterator.

The RowIter returned can then be used to run through the rows of data in the result set. This is a more attractive option if there are many rows or you want to process the results in a pipeline.

The same comments about pre-fetching configuration applies here as to .result_set.

§Errors

This method will not report errors directly however subsequent use of RowIter will return any OCI errors encountered as each row is fetched.

§Examples
use oci_rs::connection::Connection;

let conn = Connection::new("localhost:1521/xe", "oci_rs", "test").unwrap();


// Insert some values using bind variables
let sql_insert = "INSERT INTO Countries (CountryId, Name)
                  VALUES (:id, :name)";
let mut insert = conn.create_prepared_statement(sql_insert).unwrap();

let countries = vec!["Great Britain",
                     "Australia",
                     "Burma",
                     "Japan",
                     "Sudan",
                     "France",
                     "Germany",
                     "China"];

for (index, country) in countries.iter().enumerate(){
    let id = (index + 1) as i64;
    insert.bind(&[&id, country]).unwrap();
    insert.execute();
}
insert.commit();

let sql_select = "SELECT Name FROM Countries";
let mut select = conn.create_prepared_statement(sql_select).unwrap();
select.execute().unwrap();

let results: Vec<String> = select.lazy_result_set()
                                 .map(|row_result| row_result.unwrap())
                                 .map(|row| row[0].value::<String>().unwrap())
                                 .filter(|country| country.contains("c") ||
                                                   country.contains("C"))
                                 .map(|country| country.to_uppercase())
                                 .collect();
assert_eq!(results.len(), 2);
assert!(results.contains(&"CHINA".to_string()));
assert!(results.contains(&"FRANCE".to_string()));
Source

pub fn commit(&self) -> Result<(), OciError>

Commits the changes to the database.

When a statement makes changes to the database Oracle implicitly starts a transaction. If all is well and the session is closed normally this will cause an implicit commit of the changes. If anything goes wrong and the sesssion is not closed or the connection is broken, Oracle will roll back the changes. This method, therefore allows you to commit changes when you want, rather than relying on a successfull disconnection.

§Errors

Any error in the underlying calls to the OCI library will be returned.

Trait Implementations§

Source§

impl<'conn> Debug for Statement<'conn>

Source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more
Source§

impl<'conn> Drop for Statement<'conn>

Source§

fn drop(&mut self)

Frees any internal handles allocated by the OCI library.

§Panics

Panics if the resources can’t be freed. This would be a failure of the underlying OCI function.

Source§

fn pin_drop(self: Pin<&mut Self>)

🔬This is a nightly-only experimental API. (pin_ergonomics)
Execute the destructor for this type, but different to Drop::drop, it requires self to be pinned. Read more

Auto Trait Implementations§

§

impl<'conn> !Send for Statement<'conn>

§

impl<'conn> !Sync for Statement<'conn>

§

impl<'conn> Freeze for Statement<'conn>

§

impl<'conn> RefUnwindSafe for Statement<'conn>

§

impl<'conn> Unpin for Statement<'conn>

§

impl<'conn> UnsafeUnpin for Statement<'conn>

§

impl<'conn> UnwindSafe for Statement<'conn>

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

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

Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = Infallible

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.