#![doc = include_str!("../README.md")]
use std::os::raw::c_char;
use std::ptr;
use std::result;
use std::slice;
#[cfg(feature = "aq_unstable")]
pub mod aq;
mod batch;
#[allow(dead_code)]
#[allow(non_camel_case_types)]
#[allow(non_snake_case)]
#[allow(improper_ctypes)]
mod binding;
pub mod conn;
mod connection;
mod context;
mod error;
pub mod io;
pub mod oci_attr;
pub mod pool;
#[cfg(doctest)]
mod procmacro;
mod row;
pub mod sql_type;
mod sql_value;
mod statement;
mod util;
mod version;
pub use crate::batch::Batch;
pub use crate::batch::BatchBindIndex;
pub use crate::batch::BatchBuilder;
pub use crate::connection::ConnStatus;
pub use crate::connection::Connection;
pub use crate::connection::Connector;
pub use crate::connection::Privilege;
pub use crate::connection::ShutdownMode;
pub use crate::connection::StartupMode;
use crate::context::Context;
pub use crate::error::DbError;
pub use crate::error::Error;
pub use crate::error::ErrorKind;
pub use crate::error::ParseOracleTypeError;
pub use crate::row::ResultSet;
pub use crate::row::Row;
pub use crate::row::RowValue;
pub use crate::sql_value::SqlValue;
pub use crate::statement::BindIndex;
pub use crate::statement::ColumnIndex;
pub use crate::statement::ColumnInfo;
pub use crate::statement::Statement;
pub use crate::statement::StatementBuilder;
pub use crate::statement::StatementType;
pub use crate::version::Version;
pub use oracle_procmacro::RowValue;
use crate::binding::*;
pub type Result<T> = result::Result<T, Error>;
macro_rules! define_dpi_data_with_refcount {
($name:ident) => {
define_dpi_data_with_refcount!(__define_struct__, $name);
paste::item! {
unsafe impl Send for [<Dpi $name>] {}
unsafe impl Sync for [<Dpi $name>] {}
}
};
($name:ident, nosync) => {
define_dpi_data_with_refcount!(__define_struct__, $name);
paste::item! {
unsafe impl Send for [<Dpi $name>] {}
}
};
(__define_struct__, $name:ident) => {
paste::item! {
#[derive(Debug)]
struct [<Dpi $name>] {
raw: *mut [<dpi $name>],
}
impl [<Dpi $name>] {
fn new(raw: *mut [<dpi $name>]) -> [<Dpi $name>] {
[<Dpi $name>] { raw }
}
#[allow(dead_code)]
fn with_add_ref(raw: *mut [<dpi $name>]) -> [<Dpi $name>] {
unsafe { [<dpi $name _addRef>](raw) };
[<Dpi $name>] { raw }
}
#[allow(dead_code)]
fn null() -> [<Dpi $name>] {
[<Dpi $name>] {
raw: ptr::null_mut(),
}
}
#[allow(dead_code)]
fn is_null(&self) -> bool {
self.raw.is_null()
}
pub(crate) fn raw(&self) -> *mut [<dpi $name>] {
self.raw
}
}
impl Clone for [<Dpi $name>] {
fn clone(&self) -> [<Dpi $name>] {
if !self.is_null() {
unsafe { [<dpi $name _addRef>](self.raw()) };
}
[<Dpi $name>]::new(self.raw())
}
}
impl Drop for [<Dpi $name>] {
fn drop(&mut self) {
if !self.is_null() {
unsafe { [<dpi $name _release>](self.raw()) };
}
}
}
}
};
}
define_dpi_data_with_refcount!(Conn);
define_dpi_data_with_refcount!(MsgProps);
define_dpi_data_with_refcount!(ObjectType);
define_dpi_data_with_refcount!(Pool);
define_dpi_data_with_refcount!(ObjectAttr);
define_dpi_data_with_refcount!(Queue);
define_dpi_data_with_refcount!(Object, nosync);
define_dpi_data_with_refcount!(Stmt, nosync);
define_dpi_data_with_refcount!(Var, nosync);
trait AssertSend: Send {}
trait AssertSync: Sync {}
struct OdpiStr {
pub ptr: *const c_char,
pub len: u32,
}
fn new_odpi_str() -> OdpiStr {
OdpiStr {
ptr: ptr::null(),
len: 0,
}
}
fn to_odpi_str(s: &str) -> OdpiStr {
if s.is_empty() {
OdpiStr {
ptr: ptr::null(),
len: 0,
}
} else {
OdpiStr {
ptr: s.as_ptr() as *const c_char,
len: s.len() as u32,
}
}
}
impl OdpiStr {
#[allow(clippy::inherent_to_string)]
pub fn to_string(&self) -> String {
to_rust_str(self.ptr, self.len)
}
#[cfg(feature = "aq_unstable")]
pub fn to_vec(&self) -> Vec<u8> {
if self.ptr.is_null() {
Vec::new()
} else {
let ptr = self.ptr as *mut u8;
let len = self.len as usize;
unsafe { Vec::from_raw_parts(ptr, len, len) }
}
}
}
fn to_rust_str(ptr: *const c_char, len: u32) -> String {
if ptr.is_null() {
"".to_string()
} else {
let s = unsafe { slice::from_raw_parts(ptr as *mut u8, len as usize) };
String::from_utf8_lossy(s).into_owned()
}
}
fn to_rust_slice<'a>(ptr: *const c_char, len: u32) -> &'a [u8] {
if ptr.is_null() {
&[]
} else {
unsafe { slice::from_raw_parts(ptr as *mut u8, len as usize) }
}
}
mod private {
use std::os::raw::c_void;
pub trait Sealed {}
impl Sealed for u8 {}
impl Sealed for u16 {}
impl Sealed for u32 {}
impl Sealed for u64 {}
impl Sealed for usize {}
impl Sealed for bool {}
impl Sealed for str {}
impl Sealed for [u8] {}
impl Sealed for *mut c_void {}
impl Sealed for &str {}
}
#[allow(dead_code)]
#[doc(hidden)]
pub mod test_util {
use super::*;
use std::env;
pub const VER11_2: Version = Version::new(11, 2, 0, 0, 0);
pub const VER12_1: Version = Version::new(12, 1, 0, 0, 0);
pub const VER18: Version = Version::new(18, 0, 0, 0, 0);
fn env_var_or(env_name: &str, default: &str) -> String {
match env::var_os(env_name) {
Some(env_var) => env_var.into_string().unwrap(),
None => String::from(default),
}
}
pub fn main_user() -> String {
env_var_or("ODPIC_TEST_MAIN_USER", "odpic")
}
pub fn main_password() -> String {
env_var_or("ODPIC_TEST_MAIN_PASSWORD", "welcome")
}
pub fn edition_user() -> String {
env_var_or("ODPIC_TEST_EDITION_USER", "odpic_edition")
}
pub fn edition_password() -> String {
env_var_or("ODPIC_TEST_EDITION_PASSWORD", "welcome")
}
pub fn connect_string() -> String {
env_var_or("ODPIC_TEST_CONNECT_STRING", "localhost/orclpdb")
}
pub fn connect() -> Result<Connection> {
Connection::connect(main_user(), main_password(), connect_string())
}
pub fn check_version(
conn: &Connection,
client_ver: &Version,
server_ver: &Version,
) -> Result<bool> {
Ok(&Version::client()? >= client_ver && &conn.server_version()?.0 >= server_ver)
}
}