use lazy_static::lazy_static;
use std::os::raw::c_char;
use std::ptr;
use std::result;
use std::slice;
#[allow(dead_code)]
#[allow(non_camel_case_types)]
#[allow(non_snake_case)]
#[allow(improper_ctypes)]
mod binding;
mod connection;
mod error;
mod row;
pub mod sql_type;
mod sql_value;
mod statement;
mod util;
mod version;
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;
pub use crate::error::DbError;
pub use crate::error::Error;
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::StatementType;
pub use crate::statement::StmtParam;
pub use crate::version::Version;
use crate::binding::*;
pub type Result<T> = result::Result<T, Error>;
macro_rules! define_dpi_data_with_refcount {
($name:ident) => {
paste::item! {
struct [<Dpi $name>] {
raw: *mut [<dpi $name>],
}
impl [<Dpi $name>] {
fn new(raw: *mut [<dpi $name>]) -> [<Dpi $name>] {
[<Dpi $name>] { raw: raw }
}
#[allow(dead_code)]
fn with_add_ref(raw: *mut [<dpi $name>]) -> [<Dpi $name>] {
unsafe { [<dpi $name _addRef>](raw) };
[<Dpi $name>] { raw: raw }
}
pub(crate) fn raw(&self) -> *mut [<dpi $name>] {
self.raw
}
}
impl Clone for [<Dpi $name>] {
fn clone(&self) -> [<Dpi $name>] {
unsafe { [<dpi $name _addRef>](self.raw()) };
[<Dpi $name>]::new(self.raw())
}
}
impl Drop for [<Dpi $name>] {
fn drop(&mut self) {
unsafe { [<dpi $name _release>](self.raw()) };
}
}
unsafe impl Send for [<Dpi $name>] {}
unsafe impl Sync for [<Dpi $name>] {}
}
};
}
define_dpi_data_with_refcount!(Conn);
define_dpi_data_with_refcount!(ObjectType);
define_dpi_data_with_refcount!(ObjectAttr);
struct Context {
pub context: *mut dpiContext,
pub common_create_params: dpiCommonCreateParams,
pub conn_create_params: dpiConnCreateParams,
pub pool_create_params: dpiPoolCreateParams,
pub subscr_create_params: dpiSubscrCreateParams,
}
unsafe impl Sync for Context {}
unsafe impl Send for Context {}
enum ContextResult {
Ok(Context),
Err(dpiErrorInfo),
}
unsafe impl Sync for ContextResult {}
unsafe impl Send for ContextResult {}
trait AssertSend: Send {}
trait AssertSync: Sync {}
lazy_static! {
static ref DPI_CONTEXT: ContextResult = {
let mut ctxt = Context {
context: ptr::null_mut(),
common_create_params: Default::default(),
conn_create_params: Default::default(),
pool_create_params: Default::default(),
subscr_create_params: Default::default(),
};
let mut err: dpiErrorInfo = Default::default();
if unsafe {
dpiContext_create(
DPI_MAJOR_VERSION,
DPI_MINOR_VERSION,
&mut ctxt.context,
&mut err,
)
} == DPI_SUCCESS as i32
{
unsafe {
let utf8_ptr = "UTF-8\0".as_ptr() as *const c_char;
let driver_name = concat!("rust-oracle : ", env!("CARGO_PKG_VERSION"));
let driver_name_ptr = driver_name.as_ptr() as *const c_char;
let driver_name_len = driver_name.len() as u32;
dpiContext_initCommonCreateParams(ctxt.context, &mut ctxt.common_create_params);
dpiContext_initConnCreateParams(ctxt.context, &mut ctxt.conn_create_params);
dpiContext_initPoolCreateParams(ctxt.context, &mut ctxt.pool_create_params);
dpiContext_initSubscrCreateParams(ctxt.context, &mut ctxt.subscr_create_params);
ctxt.common_create_params.createMode |= DPI_MODE_CREATE_THREADED;
ctxt.common_create_params.encoding = utf8_ptr;
ctxt.common_create_params.nencoding = utf8_ptr;
ctxt.common_create_params.driverName = driver_name_ptr;
ctxt.common_create_params.driverNameLength = driver_name_len;
}
ContextResult::Ok(ctxt)
} else {
ContextResult::Err(err)
}
};
}
impl Context {
pub fn get() -> Result<&'static Context> {
match *DPI_CONTEXT {
ContextResult::Ok(ref ctxt) => Ok(ctxt),
ContextResult::Err(ref err) => Err(error::error_from_dpi_error(err)),
}
}
}
impl Default for dpiCommonCreateParams {
fn default() -> dpiCommonCreateParams {
dpiCommonCreateParams {
createMode: DPI_MODE_CREATE_DEFAULT,
encoding: ptr::null(),
nencoding: ptr::null(),
edition: ptr::null(),
editionLength: 0,
driverName: ptr::null(),
driverNameLength: 0,
}
}
}
impl Default for dpiConnCreateParams {
fn default() -> dpiConnCreateParams {
dpiConnCreateParams {
authMode: DPI_MODE_AUTH_DEFAULT,
connectionClass: ptr::null(),
connectionClassLength: 0,
purity: 0,
newPassword: ptr::null(),
newPasswordLength: 0,
appContext: ptr::null_mut(),
numAppContext: 0,
externalAuth: 0,
externalHandle: ptr::null_mut(),
pool: ptr::null_mut(),
tag: ptr::null(),
tagLength: 0,
matchAnyTag: 0,
outTag: ptr::null(),
outTagLength: 0,
outTagFound: 0,
shardingKeyColumns: ptr::null_mut(),
numShardingKeyColumns: 0,
superShardingKeyColumns: ptr::null_mut(),
numSuperShardingKeyColumns: 0,
outNewSession: 0,
}
}
}
impl Default for dpiData {
fn default() -> dpiData {
dpiData {
isNull: 0,
value: dpiDataBuffer { asInt64: 0 },
}
}
}
impl Default for dpiPoolCreateParams {
fn default() -> dpiPoolCreateParams {
dpiPoolCreateParams {
minSessions: 0,
maxSessions: 0,
sessionIncrement: 0,
pingInterval: 0,
pingTimeout: 0,
homogeneous: 0,
externalAuth: 0,
getMode: 0,
outPoolName: ptr::null(),
outPoolNameLength: 0,
timeout: 0,
waitTimeout: 0,
maxLifetimeSession: 0,
plsqlFixupCallback: ptr::null(),
plsqlFixupCallbackLength: 0,
}
}
}
impl Default for dpiSubscrCreateParams {
fn default() -> dpiSubscrCreateParams {
dpiSubscrCreateParams {
subscrNamespace: 0,
protocol: 0,
qos: 0,
operations: 0,
portNumber: 0,
timeout: 0,
name: ptr::null(),
nameLength: 0,
callback: None,
callbackContext: ptr::null_mut(),
recipientName: ptr::null(),
recipientNameLength: 0,
ipAddress: ptr::null_mut(),
ipAddressLength: 0,
groupingClass: 0,
groupingValue: 0,
groupingType: 0,
outRegId: 0,
}
}
}
impl Default for dpiErrorInfo {
fn default() -> dpiErrorInfo {
dpiErrorInfo {
code: 0,
offset: 0,
message: ptr::null(),
messageLength: 0,
encoding: ptr::null(),
fnName: ptr::null(),
action: ptr::null(),
sqlState: ptr::null(),
isRecoverable: 0,
}
}
}
impl Default for dpiDataTypeInfo {
fn default() -> dpiDataTypeInfo {
dpiDataTypeInfo {
oracleTypeNum: 0,
defaultNativeTypeNum: 0,
ociTypeCode: 0,
dbSizeInBytes: 0,
clientSizeInBytes: 0,
sizeInChars: 0,
precision: 0,
scale: 0,
fsPrecision: 0,
objectType: ptr::null_mut(),
}
}
}
impl Default for dpiObjectAttrInfo {
fn default() -> dpiObjectAttrInfo {
dpiObjectAttrInfo {
name: ptr::null(),
nameLength: 0,
typeInfo: Default::default(),
}
}
}
impl Default for dpiObjectTypeInfo {
fn default() -> dpiObjectTypeInfo {
dpiObjectTypeInfo {
schema: ptr::null(),
schemaLength: 0,
name: ptr::null(),
nameLength: 0,
isCollection: 0,
elementTypeInfo: Default::default(),
numAttributes: 0,
}
}
}
impl Default for dpiQueryInfo {
fn default() -> dpiQueryInfo {
dpiQueryInfo {
name: ptr::null(),
nameLength: 0,
typeInfo: Default::default(),
nullOk: 0,
}
}
}
impl Default for dpiVersionInfo {
fn default() -> dpiVersionInfo {
dpiVersionInfo {
versionNum: 0,
releaseNum: 0,
updateNum: 0,
portReleaseNum: 0,
portUpdateNum: 0,
fullVersionNum: 0,
}
}
}
impl Default for dpiStmtInfo {
fn default() -> dpiStmtInfo {
dpiStmtInfo {
isQuery: 0,
isPLSQL: 0,
isDDL: 0,
isDML: 0,
statementType: 0,
isReturning: 0,
}
}
}
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.len() == 0 {
OdpiStr {
ptr: ptr::null(),
len: 0,
}
} else {
OdpiStr {
ptr: s.as_ptr() as *const c_char,
len: s.len() as u32,
}
}
}
impl OdpiStr {
pub fn to_string(&self) -> String {
to_rust_str(self.ptr, self.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 {
pub trait Sealed {}
impl Sealed for usize {}
impl<'a> Sealed for &'a str {}
}