Connection

Struct Connection 

Source
pub struct Connection { /* private fields */ }
Expand description

An Oracle database connection.

This is the main type for interacting with Oracle databases. It provides methods for executing queries, DML statements, PL/SQL blocks, and managing transactions.

Connections are created using Connection::connect or Connection::connect_with_config. For connection pooling, use the deadpool-oracle crate.

§Example

use oracle_rs::{Config, Connection, Value};

// Create a connection
let config = Config::new("localhost", 1521, "FREEPDB1", "user", "password");
let conn = Connection::connect_with_config(config).await?;

// Execute a query
let result = conn.query("SELECT * FROM employees WHERE dept_id = :1", &[10.into()]).await?;
for row in &result.rows {
    let name = row.get_by_name("name").and_then(|v| v.as_str()).unwrap_or("");
    println!("Employee: {}", name);
}

// Execute DML with transaction
conn.execute("INSERT INTO logs (msg) VALUES (:1)", &["Hello".into()]).await?;
conn.commit().await?;

// Close the connection
conn.close().await?;

§Thread Safety

Connection is Send and Sync, but operations are serialized internally via a mutex. For parallel query execution, use multiple connections (e.g., via a connection pool).

Implementations§

Source§

impl Connection

Source

pub async fn connect( connect_string: &str, username: &str, password: &str, ) -> Result<Self>

Create a new connection to an Oracle database

§Arguments
  • connect_string - Connection string in EZConnect format (e.g., “host:port/service”)
  • username - Database username
  • password - Database password
§Example
let conn = Connection::connect("localhost:1521/ORCLPDB1", "scott", "tiger").await?;
Source

pub async fn connect_with_config(config: Config) -> Result<Self>

Create a new connection using a Config.

This is the preferred way to create connections as it gives full control over connection parameters including TLS, timeouts, and statement caching.

§Example
use oracle_rs::{Config, Connection};

let config = Config::new("localhost", 1521, "FREEPDB1", "user", "password")
    .with_statement_cache_size(50);

let conn = Connection::connect_with_config(config).await?;
Source

pub fn id(&self) -> u32

Get the connection ID

Source

pub fn is_closed(&self) -> bool

Check if the connection is closed

Source

pub fn mark_closed(&self)

Mark the connection as closed

This should be called when the underlying connection is detected as broken. Once marked closed, is_closed() returns true and operations will fail fast.

Source

pub async fn server_info(&self) -> ServerInfo

Get server information

Source

pub async fn state(&self) -> ConnectionState

Get the current connection state

Source

pub async fn execute(&self, sql: &str, params: &[Value]) -> Result<QueryResult>

Execute a SQL statement and return the result

§Arguments
  • sql - SQL statement to execute
  • params - Bind parameters (use Value::Integer, Value::String, etc.)
§Example
use oracle_rs::Value;

// Query with bind parameters
let result = conn.execute(
    "SELECT * FROM employees WHERE department_id = :1",
    &[Value::Integer(10)]
).await?;

// DML with bind parameters
let result = conn.execute(
    "UPDATE employees SET salary = :1 WHERE employee_id = :2",
    &[Value::Integer(50000), Value::Integer(100)]
).await?;
println!("Rows affected: {}", result.rows_affected);
Source

pub async fn query(&self, sql: &str, params: &[Value]) -> Result<QueryResult>

Execute a query and return rows

§Example
use oracle_rs::Value;

let result = conn.query(
    "SELECT * FROM employees WHERE salary > :1",
    &[Value::Integer(50000)]
).await?;
Source

pub async fn execute_dml_sql(&self, sql: &str, params: &[Value]) -> Result<u64>

Execute DML (INSERT, UPDATE, DELETE) and return rows affected

Source

pub async fn execute_plsql( &self, sql: &str, params: &[BindParam], ) -> Result<PlsqlResult>

Execute a PL/SQL block with IN/OUT/INOUT parameters

This method allows execution of PL/SQL anonymous blocks or procedure calls that have OUT or IN OUT parameters. The params slice specifies the direction and type of each bind parameter.

§Arguments
  • sql - The PL/SQL block or procedure call
  • params - The bind parameters with direction information
§Example
use oracle_rs::{Connection, BindParam, OracleType, Value};

// Call a procedure with IN and OUT parameters
let result = conn.execute_plsql(
    "BEGIN get_employee_name(:1, :2); END;",
    &[
        BindParam::input(Value::Integer(100)),           // IN: employee_id
        BindParam::output(OracleType::Varchar, 100),     // OUT: employee_name
    ]
).await?;

// Get the OUT parameter value
let name = result.get_string(0).unwrap_or("Unknown");
println!("Employee name: {}", name);
§REF CURSOR Example
use oracle_rs::{Connection, BindParam, Value};

// Call a procedure that returns a REF CURSOR
let result = conn.execute_plsql(
    "BEGIN OPEN :1 FOR SELECT * FROM employees; END;",
    &[BindParam::output_cursor()]
).await?;

// Get the cursor ID and fetch rows
if let Some(cursor_id) = result.get_cursor_id(0) {
    let rows = conn.fetch_cursor(cursor_id, 100).await?;
    for row in rows {
        println!("{:?}", row);
    }
}
Source

pub async fn execute_batch(&self, batch: &BatchBinds) -> Result<BatchResult>

Execute a batch of DML statements with multiple rows of bind values

This method efficiently executes the same SQL statement multiple times with different bind values (executemany pattern).

§Arguments
  • batch - The batch containing SQL and rows of bind values
§Example
use oracle_rs::{Connection, BatchBuilder, Value};

let batch = BatchBuilder::new("INSERT INTO users (id, name) VALUES (:1, :2)")
    .add_row(vec![Value::Integer(1), Value::String("Alice".to_string())])
    .add_row(vec![Value::Integer(2), Value::String("Bob".to_string())])
    .with_row_counts()
    .build();

let result = conn.execute_batch(&batch).await?;
println!("Total rows affected: {}", result.total_rows_affected);
Source

pub async fn fetch_more( &self, cursor_id: u16, columns: &[ColumnInfo], fetch_size: u32, ) -> Result<QueryResult>

Fetch more rows from an open cursor

This method is used when a query result has has_more_rows == true to retrieve additional rows from the server.

§Arguments
  • cursor_id - The cursor ID from a previous query result
  • columns - Column information from the original query
  • fetch_size - Number of rows to fetch
§Example
let mut result = conn.query("SELECT * FROM large_table", &[]).await?;
let mut all_rows = result.rows.clone();

while result.has_more_rows {
    result = conn.fetch_more(result.cursor_id, &result.columns, 100).await?;
    all_rows.extend(result.rows);
}
Source

pub async fn fetch_cursor(&self, cursor: &RefCursor) -> Result<QueryResult>

Fetch rows from a REF CURSOR

This method fetches rows from a REF CURSOR that was returned from a PL/SQL procedure or function. The cursor contains the column metadata and cursor ID needed to fetch the rows.

§Arguments
  • cursor - The REF CURSOR returned from PL/SQL
§Example
use oracle_rs::{Connection, BindParam, Value};

// Call a procedure that returns a REF CURSOR
let result = conn.execute_plsql(
    "BEGIN OPEN :1 FOR SELECT id, name FROM employees; END;",
    &[BindParam::output_cursor()]
).await?;

// Get the cursor and fetch rows
if let Value::Cursor(cursor) = &result.out_values[0] {
    let rows = conn.fetch_cursor(cursor).await?;
    println!("Fetched {} rows", rows.row_count());
    for row in &rows.rows {
        println!("{:?}", row);
    }
}
Source

pub async fn fetch_cursor_with_size( &self, cursor: &RefCursor, fetch_size: u32, ) -> Result<QueryResult>

Fetch rows from a REF CURSOR with a specified fetch size

This is the same as fetch_cursor but allows specifying how many rows to fetch at once.

REF CURSORs use an ExecuteMessage with only the FETCH option because the cursor is already open from the PL/SQL execution. The cursor_id and column metadata were obtained when the REF CURSOR was returned.

§Arguments
  • cursor - The REF CURSOR returned from PL/SQL
  • fetch_size - Number of rows to fetch (default is 100)
Source

pub async fn fetch_implicit_result( &self, result: &ImplicitResult, ) -> Result<QueryResult>

Fetch rows from an implicit result set

Implicit results are returned via DBMS_SQL.RETURN_RESULT from PL/SQL. They contain cursor metadata but no rows until fetched.

§Arguments
  • result - The implicit result from PL/SQL execution
§Example
let plsql_result = conn.execute_plsql(r#"
    declare
        c sys_refcursor;
    begin
        open c for select * from employees;
        dbms_sql.return_result(c);
    end;
"#, &[]).await?;

for implicit in plsql_result.implicit_results.iter() {
    let rows = conn.fetch_implicit_result(implicit).await?;
    println!("Fetched {} rows", rows.row_count());
}
Source

pub async fn fetch_implicit_result_with_size( &self, result: &ImplicitResult, fetch_size: u32, ) -> Result<QueryResult>

Fetch rows from an implicit result set with a specified fetch size

Source

pub async fn open_scrollable_cursor( &self, sql: &str, ) -> Result<ScrollableCursor>

Open a scrollable cursor for bidirectional navigation

Scrollable cursors allow moving forward and backward through result sets, jumping to specific positions, and fetching from various locations.

§Arguments
  • sql - SQL query to execute
§Example
let mut cursor = conn.open_scrollable_cursor("SELECT * FROM employees").await?;

// Move to different positions
let first = conn.scroll(&mut cursor, FetchOrientation::First, 0).await?;
let last = conn.scroll(&mut cursor, FetchOrientation::Last, 0).await?;
let row5 = conn.scroll(&mut cursor, FetchOrientation::Absolute, 5).await?;

conn.close_cursor(&mut cursor).await?;
Source

pub async fn scroll( &self, cursor: &mut ScrollableCursor, orientation: FetchOrientation, offset: i64, ) -> Result<ScrollResult>

Scroll to a position in a scrollable cursor and fetch rows

§Arguments
  • cursor - The scrollable cursor to scroll
  • orientation - The direction/mode of scrolling
  • offset - Position offset (used for Absolute and Relative modes)
§Example
// Go to first row
let first = conn.scroll(&mut cursor, FetchOrientation::First, 0).await?;

// Go to absolute position 10
let row10 = conn.scroll(&mut cursor, FetchOrientation::Absolute, 10).await?;

// Move 5 rows forward from current position
let plus5 = conn.scroll(&mut cursor, FetchOrientation::Relative, 5).await?;

// Move 3 rows backward
let minus3 = conn.scroll(&mut cursor, FetchOrientation::Relative, -3).await?;
Source

pub async fn close_cursor(&self, cursor: &mut ScrollableCursor) -> Result<()>

Close a scrollable cursor

§Arguments
  • cursor - The scrollable cursor to close
Source

pub async fn get_type(&self, type_name: &str) -> Result<DbObjectType>

Get type information for a database object or collection type

This method queries Oracle’s data dictionary to retrieve type metadata for collections (VARRAY, Nested Table) and user-defined object types.

§Arguments
  • type_name - Fully qualified type name (e.g., “SCHEMA.TYPE_NAME” or just “TYPE_NAME”)
§Returns

A DbObjectType containing the type metadata, including:

  • Schema and type name
  • Whether it’s a collection
  • Collection type (VARRAY, Nested Table, etc.)
  • Element type for collections
§Example
let number_array = conn.get_type("MY_NUMBER_ARRAY").await?;
assert!(number_array.is_collection);
Source

pub async fn commit(&self) -> Result<()>

Commit the current transaction.

Makes all changes in the current transaction permanent. After commit, a new transaction begins automatically.

§Example
conn.execute("INSERT INTO users (name) VALUES (:1)", &["Alice".into()]).await?;
conn.execute("INSERT INTO users (name) VALUES (:1)", &["Bob".into()]).await?;
conn.commit().await?; // Both inserts are now permanent
Source

pub async fn rollback(&self) -> Result<()>

Rollback the current transaction.

Discards all changes made in the current transaction. After rollback, a new transaction begins automatically.

§Example
conn.execute("DELETE FROM users WHERE id = :1", &[1.into()]).await?;
// Oops, wrong user!
conn.rollback().await?; // Delete is undone
Source

pub async fn savepoint(&self, name: &str) -> Result<()>

Create a savepoint within the current transaction

Savepoints allow partial rollback of a transaction. You can create multiple savepoints and rollback to any of them without affecting work done before that savepoint.

§Arguments
  • name - The savepoint name (must be a valid Oracle identifier)
§Example
conn.execute("INSERT INTO t VALUES (1)", &[]).await?;
conn.savepoint("sp1").await?;
conn.execute("INSERT INTO t VALUES (2)", &[]).await?;
conn.rollback_to_savepoint("sp1").await?; // Undoes the second insert
conn.commit().await?; // Commits only the first insert
Source

pub async fn rollback_to_savepoint(&self, name: &str) -> Result<()>

Rollback to a previously created savepoint

This undoes all changes made after the savepoint was created, but keeps the transaction active. Changes made before the savepoint are preserved.

§Arguments
  • name - The savepoint name to rollback to
Source

pub async fn ping(&self) -> Result<()>

Ping the server to check if the connection is still alive.

This executes a lightweight query (SELECT 1 FROM DUAL) to verify the connection is responsive. Useful for connection health checks in pooling scenarios.

§Example
if conn.ping().await.is_ok() {
    println!("Connection is alive");
} else {
    println!("Connection is dead");
}
Source

pub async fn clear_statement_cache(&self)

Clear the statement cache

This should be called when recycling a connection in a pool to ensure that any stale cursor state is cleared. This is useful after errors or when the connection state may be inconsistent.

Source

pub async fn read_lob(&self, locator: &LobLocator) -> Result<LobData>

Read data from a LOB (CLOB or BLOB)

§Arguments
  • locator - The LOB locator obtained from a query result
  • offset - Starting position (1-based, in characters for CLOB, bytes for BLOB)
  • amount - Amount to read (0 for entire LOB)
§Returns

For CLOB: returns the text content as a String For BLOB: returns the binary content as bytes

Source

pub async fn read_lob_range( &self, locator: &LobLocator, offset: u64, amount: u64, ) -> Result<LobData>

Read a portion of a LOB

Source

pub async fn read_clob(&self, locator: &LobLocator) -> Result<String>

Read a CLOB and return as String

This is a convenience method for reading CLOB data directly as a String. Returns an error if the LOB is not a CLOB.

Source

pub async fn read_blob(&self, locator: &LobLocator) -> Result<Bytes>

Read a BLOB and return as bytes

This is a convenience method for reading BLOB data directly as bytes. Returns an error if the LOB is a CLOB (use read_clob instead).

Source

pub async fn read_lob_chunked<F, Fut>( &self, locator: &LobLocator, chunk_size: u64, callback: F, ) -> Result<()>
where F: FnMut(LobData) -> Fut, Fut: Future<Output = Result<()>>,

Read a LOB in chunks, calling a callback for each chunk

This is useful for processing large LOBs without loading the entire content into memory. The callback receives each chunk as it’s read.

§Arguments
  • locator - The LOB locator
  • chunk_size - Size of each chunk to read (0 uses the LOB’s natural chunk size)
  • callback - Async function called for each chunk
§Example
let mut total_size = 0;
conn.read_lob_chunked(&locator, 8192, |chunk| async move {
    match chunk {
        LobData::Bytes(b) => total_size += b.len(),
        LobData::String(s) => total_size += s.len(),
    }
    Ok(())
}).await?;
Source

pub async fn lob_chunk_size(&self, locator: &LobLocator) -> Result<u32>

Get the optimal chunk size for a LOB

This returns the chunk size that Oracle recommends for efficient reading and writing to this LOB.

Source

pub async fn write_lob( &self, locator: &LobLocator, offset: u64, data: &[u8], ) -> Result<()>

Write data to a LOB

§Arguments
  • locator - The LOB locator obtained from a query result
  • offset - Starting position (1-based, in characters for CLOB, bytes for BLOB)
  • data - Data to write (bytes for BLOB, UTF-8 encoded bytes for CLOB)
Source

pub async fn write_clob( &self, locator: &LobLocator, offset: u64, text: &str, ) -> Result<()>

Write string data to a CLOB

Source

pub async fn write_blob( &self, locator: &LobLocator, offset: u64, data: &[u8], ) -> Result<()>

Write binary data to a BLOB

Source

pub async fn lob_length(&self, locator: &LobLocator) -> Result<u64>

Get the length of a LOB

For CLOB: returns length in characters For BLOB: returns length in bytes

Source

pub async fn lob_trim(&self, locator: &LobLocator, new_size: u64) -> Result<()>

Trim a LOB to a specified length

§Arguments
  • locator - The LOB locator
  • new_size - The new size (in characters for CLOB, bytes for BLOB)
Source

pub async fn create_temp_lob( &self, oracle_type: OracleType, ) -> Result<LobLocator>

Create a temporary LOB on the server

Creates a temporary LOB of the specified type that lives until the connection is closed or the LOB is explicitly freed.

§Arguments
  • oracle_type - The LOB type to create (Clob or Blob)
§Returns

A LobLocator for the newly created temporary LOB

§Example
use oracle_rs::OracleType;

let locator = conn.create_temp_lob(OracleType::Clob).await?;
conn.write_clob(&locator, 1, "Hello, World!").await?;
// Now bind the locator to insert into a CLOB column
Source

pub async fn bfile_exists(&self, locator: &LobLocator) -> Result<bool>

Check if a BFILE exists on the server

Returns true if the file referenced by the BFILE locator exists on the server.

Source

pub async fn bfile_open(&self, locator: &LobLocator) -> Result<()>

Open a BFILE for reading

The BFILE must be opened before reading. After reading, close it with bfile_close.

Source

pub async fn bfile_close(&self, locator: &LobLocator) -> Result<()>

Close a BFILE after reading

Source

pub async fn bfile_is_open(&self, locator: &LobLocator) -> Result<bool>

Check if a BFILE is currently open

Source

pub async fn read_bfile(&self, locator: &LobLocator) -> Result<Bytes>

Read BFILE data

This is a convenience method that opens the BFILE if needed, reads all content, and returns it as bytes. For large BFILEs, consider using read_lob_chunked.

Source

pub async fn close(&self) -> Result<()>

Close the connection.

Sends a logoff message to the server and closes the underlying TCP connection. After calling close, the connection cannot be reused.

If the connection is already closed, this method returns Ok(()) without doing anything.

§Note

Any uncommitted transaction is rolled back by the server when the connection is closed.

§Example
let config = Config::new("localhost", 1521, "FREEPDB1", "user", "password");
let conn = Connection::connect_with_config(config).await?;

// Do work...
conn.commit().await?;

// Explicitly close when done
conn.close().await?;

Trait Implementations§

Source§

impl Drop for Connection

Source§

fn drop(&mut self)

Executes the destructor for this type. Read more

Auto Trait Implementations§

Blanket Implementations§

§

impl<T> Any for T
where T: 'static + ?Sized,

§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
§

impl<T> Borrow<T> for T
where T: ?Sized,

§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
§

impl<T> BorrowMut<T> for T
where T: ?Sized,

§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
§

impl<T> From<T> for T

§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T> Instrument for T

Source§

fn instrument(self, span: Span) -> Instrumented<Self>

Instruments this type with the provided Span, returning an Instrumented wrapper. Read more
Source§

fn in_current_span(self) -> Instrumented<Self>

Instruments this type with the current Span, returning an Instrumented wrapper. Read more
§

impl<T, U> Into<U> for T
where U: From<T>,

§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T> Same for T

Source§

type Output = T

Should always be Self
§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

§

type Error = Infallible

The type returned in the event of a conversion error.
§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.
Source§

impl<V, T> VZip<V> for T
where V: MultiLane<T>,

Source§

fn vzip(self) -> V

Source§

impl<T> WithSubscriber for T

Source§

fn with_subscriber<S>(self, subscriber: S) -> WithDispatch<Self>
where S: Into<Dispatch>,

Attaches the provided Subscriber to this type, returning a WithDispatch wrapper. Read more
Source§

fn with_current_subscriber(self) -> WithDispatch<Self>

Attaches the current default Subscriber to this type, returning a WithDispatch wrapper. Read more