Module oci_rs::types[][src]

Types used in conversion between OCI and Rust types.

This module provides a type SqlValue and two traits ToSqlValue and FromSqlValue that allow the underlying OCI types to be converted into Rust types. They do not map exactly to the corresponding SQL standard types.

For number types in particular there are less SqlValues than SQL types. Inside Oracle all numbers are stored as a NUMBER. This is an Oracle format that can handle all integer and float values with a precision of 38 digits. Regardless of whether the SQL statement specifies an INTEGER or FLOAT or LONG, Oracle will store it as a NUMBER. The OCI library then allows you to convert it into any numeric type you like, but that forces you to explicitly state the type of the columns when retrieving the values. To avoid this, this crate makes some executive decisions based on the NUMBER value. As per the OCI documentation the basic type of a number can be determined by the scale and precision of the NUMBER value. If the precision is non-zero and scale is -127 then the number is a FLOAT otherwise we can consider it an INTEGER. So, according to this logic the caller will receive either SqlValue::Integer or SqlValue::Float. These two variants contain an i64 and f64 respectively. If a smaller type is needed in Rust code, then further conversions can be made. This appears to be sufficient to allow retrieval of data in queries, without having specify column types on the Rust side ahead of time.

Note: Oracle also supports types known as BINARY_FLOAT and BINARY_DOUBLE. These can also be used to store numbers inside the database as an alternative to NUMBER. They are not currently supported.

The traits allow conversion to and from Rust types into SqlValue.

Type conversions

Oracle SQL type Rust type
VARCHAR String
VARCHAR2 String
CHAR String
NUMBER i64, f64
DATE Date<Utc>
TIMESTAMP DateTime<Utc>
TIMESTAMP WITH TIME ZONE DateTime<FixedOffset>

Examples

This example highlights the automatic conversion. If it is confusing then I suggest reading Communicating Intent as it explains very well how Rust's trait system makes this work, the postgres crate also makes use of the same process to convert the column values in a result row into Rust. This crate copies postgres's approach except that it makes use of an intermediary SqlValue instead of returning a trait. I think that it is fair to argue that SqlValue is not needed, postgres skips such an intermediary value, but using it simplifies the current implementation.

use oci_rs::connection::Connection;

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

// Create a table
let sql_create = "CREATE TABLE Men (ManId INTEGER,
                                    Name VARCHAR2(20),
                                    Height FLOAT)";

let mut create = conn.create_prepared_statement(sql_create).unwrap();

// Execute the create statement
create.execute().unwrap();

// Commit in case we lose connection (an abnormal disconnection would result
// in an automatic roll-back.)
create.commit().unwrap();

// Insert some values
let sql_insert = "INSERT INTO Men (ManId, Name, Height)
                  VALUES (1, 'Roger', 183.4)";
 let mut insert = conn.create_prepared_statement(sql_insert).unwrap();

insert.execute().unwrap();
insert.commit().unwrap();

// Create a query
let sql_select = "SELECT * FROM Men";

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

// Execute
select.execute().unwrap();

// Get the result set
let result_set = select.result_set().unwrap();
assert_eq!(result_set.len(), 1);
let first_row = &result_set[0];

// Types are automatically converted
let id: i64 = first_row[0].value().unwrap();
let name: String = first_row[1].value().unwrap();
let height: f64 = first_row[2].value().unwrap();

assert_eq!(id, 1);
assert_eq!(name, "Roger");
assert_eq!(height, 183.4);

// Integer and Float can also be turned into Strings
let id_as_string: String = first_row[0].value().unwrap();
let height_as_string: String = first_row[2].value().unwrap();

assert_eq!(id_as_string, "1");
assert_eq!(height_as_string, "183.4");

Enums

SqlValue

The types that support conversion from OCI to Rust types.

Traits

FromSqlValue

Allows conversion from a SqlValue.

ToSqlValue

Allows conversion into a SqlValue.