#database #sql #oracle #ffi #async

sibyl

An OCI-based (synchronous or asynchronous) interface between Rust applications and Oracle databases

10 releases (5 breaking)

new 0.6.1 Jan 19, 2022
0.6.0 Jan 14, 2022
0.5.1 Jan 13, 2022
0.4.0 Oct 25, 2021
0.1.1 Jun 11, 2019

#56 in Database interfaces

Download history 19/week @ 2021-10-02 20/week @ 2021-10-09 20/week @ 2021-10-16 34/week @ 2021-10-23 9/week @ 2021-10-30 43/week @ 2021-11-06 10/week @ 2021-11-13 20/week @ 2021-11-20 7/week @ 2021-11-27 10/week @ 2021-12-04 4/week @ 2021-12-11 17/week @ 2021-12-18 12/week @ 2021-12-25 10/week @ 2022-01-01 54/week @ 2022-01-08 37/week @ 2022-01-15

116 downloads per month

MIT license

720KB
10K SLoC

Sibyl

Sibyl is an OCI-based interface between Rust applications and Oracle databases. Sibyl supports both sync (blocking) and async (nonblocking) API.

crates.io Documentation MIT

Example

Blocking Mode

use sibyl as oracle; // pun intended :)

fn main() -> Result<(),Box<dyn std::error::Error>> {
    let oracle = oracle::env()?;

    let dbname = std::env::var("DBNAME").expect("database name");
    let dbuser = std::env::var("DBUSER").expect("user name");
    let dbpass = std::env::var("DBPASS").expect("password");

    let session = oracle.connect(&dbname, &dbuser, &dbpass)?;
    let stmt = session.prepare("
        SELECT first_name, last_name, hire_date
          FROM hr.employees
         WHERE hire_date >= :hire_date
      ORDER BY hire_date
    ")?;
    let date = oracle::Date::from_string("January 1, 2005", "MONTH DD, YYYY", &session)?;
    let rows = stmt.query(&date)?;
    while let Some( row ) = rows.next()? {
        let first_name : Option<&str>  = row.get(0)?;
        let last_name  : &str          = row.get_not_null(1)?;
        let hire_date  : oracle::Date  = row.get_not_null(2)?;

        let hire_date = hire_date.to_string("FMMonth DD, YYYY")?;
        if first_name.is_some() {
            println!("{}: {} {}", hire_date, first_name.unwrap(), last_name);
        } else {
            println!("{}: {}", hire_date, last_name);
        }
    }
    if stmt.row_count()? == 0 {
        println!("No one was hired after {}", date.to_string("FMMonth DD, YYYY")?);
    }
    Ok(())
}

Nonblocking Mode

use sibyl as oracle;

#[tokio::main]
async fn main() -> Result<(),Box<dyn std::error::Error>> {
    let oracle = oracle::env()?;

    let dbname = std::env::var("DBNAME").expect("database name");
    let dbuser = std::env::var("DBUSER").expect("user name");
    let dbpass = std::env::var("DBPASS").expect("password");

    let session = oracle.connect(&dbname, &dbuser, &dbpass).await?;
    let stmt = session.prepare("
        SELECT first_name, last_name, hire_date
          FROM hr.employees
         WHERE hire_date >= :hire_date
      ORDER BY hire_date
    ").await?;
    let date = oracle::Date::from_string("January 1, 2005", "MONTH DD, YYYY", &oracle)?;
    let rows = stmt.query(&date).await?;
    while let Some( row ) = rows.next().await? {
        let first_name : Option<&str>  = row.get(0)?;
        let last_name  : &str          = row.get_not_null(1)?;
        let hire_date  : oracle::Date  = row.get_not_null(2)?;

        let hire_date = hire_date.to_string("FMMonth DD, YYYY")?;
        if first_name.is_some() {
            println!("{}: {} {}", hire_date, first_name.unwrap(), last_name);
        } else {
            println!("{}: {}", hire_date, last_name);
        }
    }
    if stmt.row_count()? == 0 {
        println!("No one was hired after {}", date.to_string("FMMonth DD, YYYY")?);
    }
    Ok(())
}

Note that:

  • The nonblocking mode example is almost a verbatim copy of the blocking mode example with awaits added.
  • The async example uses and depends on Tokio
  • For the moment, Sibyl can use only Tokio as an async executor.

Documentation

Dependencies

~635KB
~12K SLoC

oa