Rust-oracle

This is an Oracle database driver for Rust based on ODPI-C.

Change Log

See ChangeLog.md.

Build-time Requirements

Run-time Requirements

Usage

Put this in your Cargo.toml:

text [dependencies] oracle = "0.1"

When you need to fetch or bind chrono data types, enable chrono feature:

text [dependencies] oracle = { version = "0.1", features = ["chrono"] }

Then put this in your crate root:

rust extern crate oracle;

Examples

Executes select statements and get rows:

```rust use oracle::{Connection, Error};

// Connect to a database. let conn = Connection::connect("scott", "tiger", "//localhost/XE", &[])?;

let sql = "select ename, sal, comm from emp where deptno = :1";

// Select a table with a bind variable. println!("---------------|---------------|---------------|"); let rows = conn.query(sql, &[&30])?; for rowresult in &rows { let row = rowresult?; // get a column value by position (0-based) let ename: String = row.get(0)?; // get a column by name (case-insensitive) let sal: i32 = row.get("sal")?; // Use Option<...> to get a nullable column. // Otherwise, Err(Error::NullValue) is returned // for null values. let comm: Option = row.get(2)?;

println!(" {:14}| {:>10}    | {:>10}    |",
         ename,
         sal,
         comm.map_or("".to_string(), |v| v.to_string()));

}

// Another way to fetch rows. // The rows iterator returns Result<(String, i32, Option)>. println!("---------------|---------------|---------------|"); let rows = conn.queryas::<(String, i32, Option)>(sql, &[&10])?; for rowresult in &rows { let (ename, sal, comm) = rowresult?; println!(" {:14}| {:>10} | {:>10} |", ename, sal, comm.mapor("".tostring(), |v| v.tostring())); } ```

Executes select statements and get the first rows:

```rust use oracle::Connection;

// Connect to a database. let conn = Connection::connect("scott", "tiger", "//localhost/XE", &[])?;

let sql = "select ename, sal, comm from emp where empno = :1";

// Print the first row. let row = conn.queryrow(sql, &[&7369])?; let ename: String = row.get("empno")?; let sal: i32 = row.get("sal")?; let comm: Option = row.get("comm")?; println!("---------------|---------------|---------------|"); println!(" {:14}| {:>10} | {:>10} |", ename, sal, comm.mapor("".tostring(), |v| v.tostring())); // When no rows are found, conn.query_row() returns Err(Error::NoDataFound).

// Get the first row as a tupple let row = conn.queryrowas::<(String, i32, Option)>(sql, &[&7566])?; println!("---------------|---------------|---------------|"); println!(" {:14}| {:>10} | {:>10} |", row.0, row.1, row.2.mapor("".tostring(), |v| v.to_string())); ```

Executes non-select statements:

```rust use oracle::Connection;

// Connect to a database. let conn = Connection::connect("scott", "tiger", "//localhost/XE", &[])?;

conn.execute("create table person (id number(38), name varchar2(40))", &[])?;

// Execute a statement with positional parameters. conn.execute("insert into person values (:1, :2)", &[&1, // first parameter &"John" // second parameter ])?;

// Execute a statement with named parameters. conn.execute_named("insert into person values (:id, :name)", &[("id", &2), // 'id' parameter ("name", &"Smith"), // 'name' parameter ])?;

// Commit the transaction. conn.commit()?;

// Delete rows conn.execute("delete from person", &[])?;

// Rollback the transaction. conn.rollback()?; ```

Prints column information:

```rust use oracle::Connection;

// Connect to a database. let conn = Connection::connect("scott", "tiger", "//localhost/XE", &[])?;

let sql = "select ename, sal, comm from emp where 1 = 2"; let rows = conn.query(sql, &[])?;

// Print column names for info in rows.column_info() { print!(" {:14}|", info.name()); } println!("");

// Print column types for info in rows.columninfo() { print!(" {:14}|", info.oracletype().to_string()); } println!(""); ```

Prepared statement:

```rust use oracle::Connection;

let conn = Connection::connect("scott", "tiger", "//localhost/XE", &[])?;

// Create a prepared statement let mut stmt = conn.prepare("insert into person values (:1, :2)", &[])?; // Insert one row stmt.execute(&[&1, &"John"])?; // Insert another row stmt.execute(&[&2, &"Smith"])?; ```

This is more efficient than two conn.execute(). An SQL statement is executed in the DBMS as follows:

When a prepared statement is used, step 1 is called only once.

NLS_LANG parameter

NLS_LANG consists of three components: language, territory and charset. However the charset component is ignored and UTF-8(AL32UTF8) is used as charset because rust characters are UTF-8.

The territory component specifies numeric format, date format and so on. However it affects only conversion in Oracle. See the following example:

```rust use oracle::Connection;

// The territory is France. std::env::setvar("NLSLANG", "french_france.AL32UTF8"); let conn = Connection::connect("scott", "tiger", "", &[])?;

// 10.1 is converted to a string in Oracle and fetched as a string. let result = conn.queryrowas::("select tochar(10.1) from dual", &[])?; asserteq!(result, "10,1"); // The decimal mark depends on the territory.

// 10.1 is fetched as a number and converted to a string in rust-oracle let result = conn.queryrowas::("select 10.1 from dual", &[])?; assert_eq!(result, "10.1"); // The decimal mark is always period(.). ```

Note that NLS_LANG must be set before first rust-oracle function execution if required.

TODO

License

Rust-oracle itself is under 2-clause BSD-style license.

ODPI-C bundled in rust-oracle is under the terms of:

  1. the Universal Permissive License v 1.0 or at your option, any later version; and/or
  2. the Apache License v 2.0.