#oracle #sql #async #ffi

sibyl

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

25 releases

0.6.16 Feb 6, 2023
0.6.12 Oct 17, 2022
0.6.9 Jul 26, 2022
0.6.5 Mar 16, 2022
0.1.1 Jun 11, 2019

#84 in Database interfaces

Download history 38/week @ 2023-11-20 5/week @ 2023-11-27 104/week @ 2023-12-11 17/week @ 2023-12-18 35/week @ 2024-01-08 28/week @ 2024-01-15 67/week @ 2024-01-22 35/week @ 2024-01-29 134/week @ 2024-02-05 94/week @ 2024-02-12 47/week @ 2024-02-19 120/week @ 2024-02-26 74/week @ 2024-03-04

337 downloads per month
Used in 2 crates

MIT license

775KB
12K SLoC

Sibyl

Sibyl is an OCI-based interface between Rust applications and Oracle databases. Sibyl supports both blocking (threads) and nonblocking (async) 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(1)?;
        let hire_date  : oracle::Date  = row.get(2)?;

        let hire_date = hire_date.to_string("FMMonth DD, YYYY")?;
        if let Some(first_name) = first_name {
            println!("{}: {} {}", hire_date, first_name, 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(1)?;
        let hire_date  : oracle::Date  = row.get(2)?;

        let hire_date = hire_date.to_string("FMMonth DD, YYYY")?;
        if let Some(first_name) = first_name {
            println!("{}: {} {}", hire_date, first_name, 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, Actix, async-std or async-global-executor as an async executor.

Documentation

Dependencies

~0.4–13MB
~135K SLoC