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 SqlValue
s 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
.
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 |
ToSqlValue |
Allows conversion into a |