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
impl Connection
Sourcepub async fn connect_with_config(config: Config) -> Result<Self>
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?;Sourcepub fn mark_closed(&self)
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.
Sourcepub async fn server_info(&self) -> ServerInfo
pub async fn server_info(&self) -> ServerInfo
Get server information
Sourcepub async fn state(&self) -> ConnectionState
pub async fn state(&self) -> ConnectionState
Get the current connection state
Sourcepub async fn execute(&self, sql: &str, params: &[Value]) -> Result<QueryResult>
pub async fn execute(&self, sql: &str, params: &[Value]) -> Result<QueryResult>
Execute a SQL statement and return the result
§Arguments
sql- SQL statement to executeparams- Bind parameters (useValue::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);Sourcepub async fn execute_dml_sql(&self, sql: &str, params: &[Value]) -> Result<u64>
pub async fn execute_dml_sql(&self, sql: &str, params: &[Value]) -> Result<u64>
Execute DML (INSERT, UPDATE, DELETE) and return rows affected
Sourcepub async fn execute_plsql(
&self,
sql: &str,
params: &[BindParam],
) -> Result<PlsqlResult>
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 callparams- 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);
}
}Sourcepub async fn execute_batch(&self, batch: &BatchBinds) -> Result<BatchResult>
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);Sourcepub async fn fetch_more(
&self,
cursor_id: u16,
columns: &[ColumnInfo],
fetch_size: u32,
) -> Result<QueryResult>
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 resultcolumns- Column information from the original queryfetch_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);
}Sourcepub async fn fetch_cursor(&self, cursor: &RefCursor) -> Result<QueryResult>
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);
}
}Sourcepub async fn fetch_cursor_with_size(
&self,
cursor: &RefCursor,
fetch_size: u32,
) -> Result<QueryResult>
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/SQLfetch_size- Number of rows to fetch (default is 100)
Sourcepub async fn fetch_implicit_result(
&self,
result: &ImplicitResult,
) -> Result<QueryResult>
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());
}Sourcepub async fn fetch_implicit_result_with_size(
&self,
result: &ImplicitResult,
fetch_size: u32,
) -> Result<QueryResult>
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
Sourcepub async fn open_scrollable_cursor(
&self,
sql: &str,
) -> Result<ScrollableCursor>
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?;Sourcepub async fn scroll(
&self,
cursor: &mut ScrollableCursor,
orientation: FetchOrientation,
offset: i64,
) -> Result<ScrollResult>
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 scrollorientation- The direction/mode of scrollingoffset- 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?;Sourcepub async fn close_cursor(&self, cursor: &mut ScrollableCursor) -> Result<()>
pub async fn close_cursor(&self, cursor: &mut ScrollableCursor) -> Result<()>
Sourcepub async fn get_type(&self, type_name: &str) -> Result<DbObjectType>
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);Sourcepub async fn commit(&self) -> Result<()>
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 permanentSourcepub async fn rollback(&self) -> Result<()>
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 undoneSourcepub async fn savepoint(&self, name: &str) -> Result<()>
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 insertSourcepub async fn rollback_to_savepoint(&self, name: &str) -> Result<()>
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
Sourcepub async fn ping(&self) -> Result<()>
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");
}Sourcepub async fn clear_statement_cache(&self)
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.
Sourcepub async fn read_lob(&self, locator: &LobLocator) -> Result<LobData>
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 resultoffset- 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
Sourcepub async fn read_lob_range(
&self,
locator: &LobLocator,
offset: u64,
amount: u64,
) -> Result<LobData>
pub async fn read_lob_range( &self, locator: &LobLocator, offset: u64, amount: u64, ) -> Result<LobData>
Read a portion of a LOB
Sourcepub async fn read_clob(&self, locator: &LobLocator) -> Result<String>
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.
Sourcepub async fn read_blob(&self, locator: &LobLocator) -> Result<Bytes>
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).
Sourcepub async fn read_lob_chunked<F, Fut>(
&self,
locator: &LobLocator,
chunk_size: u64,
callback: F,
) -> Result<()>
pub async fn read_lob_chunked<F, Fut>( &self, locator: &LobLocator, chunk_size: u64, callback: F, ) -> 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 locatorchunk_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?;Sourcepub async fn lob_chunk_size(&self, locator: &LobLocator) -> Result<u32>
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.
Sourcepub async fn write_lob(
&self,
locator: &LobLocator,
offset: u64,
data: &[u8],
) -> Result<()>
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 resultoffset- Starting position (1-based, in characters for CLOB, bytes for BLOB)data- Data to write (bytes for BLOB, UTF-8 encoded bytes for CLOB)
Sourcepub async fn write_clob(
&self,
locator: &LobLocator,
offset: u64,
text: &str,
) -> Result<()>
pub async fn write_clob( &self, locator: &LobLocator, offset: u64, text: &str, ) -> Result<()>
Write string data to a CLOB
Sourcepub async fn write_blob(
&self,
locator: &LobLocator,
offset: u64,
data: &[u8],
) -> Result<()>
pub async fn write_blob( &self, locator: &LobLocator, offset: u64, data: &[u8], ) -> Result<()>
Write binary data to a BLOB
Sourcepub async fn lob_length(&self, locator: &LobLocator) -> Result<u64>
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
Sourcepub async fn lob_trim(&self, locator: &LobLocator, new_size: u64) -> Result<()>
pub async fn lob_trim(&self, locator: &LobLocator, new_size: u64) -> Result<()>
Trim a LOB to a specified length
§Arguments
locator- The LOB locatornew_size- The new size (in characters for CLOB, bytes for BLOB)
Sourcepub async fn create_temp_lob(
&self,
oracle_type: OracleType,
) -> Result<LobLocator>
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 columnSourcepub async fn bfile_exists(&self, locator: &LobLocator) -> Result<bool>
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.
Sourcepub async fn bfile_open(&self, locator: &LobLocator) -> Result<()>
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.
Sourcepub async fn bfile_close(&self, locator: &LobLocator) -> Result<()>
pub async fn bfile_close(&self, locator: &LobLocator) -> Result<()>
Close a BFILE after reading
Sourcepub async fn bfile_is_open(&self, locator: &LobLocator) -> Result<bool>
pub async fn bfile_is_open(&self, locator: &LobLocator) -> Result<bool>
Check if a BFILE is currently open
Sourcepub async fn read_bfile(&self, locator: &LobLocator) -> Result<Bytes>
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.
Sourcepub async fn close(&self) -> Result<()>
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?;