use crate::common::mimer_options::*;
use crate::common::return_codes::MIMER_SUCCESS;
use crate::common::traits::GetHandle;
use crate::common::traits::MimerHandle;
use crate::inner_connection::*;
use mimerrust_sys as ffi;
#[doc(hidden)]
use parking_lot::{MappedMutexGuard, Mutex, MutexGuard};
#[doc(hidden)]
use std::{
cmp::Ordering,
ffi::CString,
result::Result::{Err, Ok},
sync::Weak,
};
pub struct InnerStatement {
statement: Mutex<ffi::MimerStatement>,
pub(crate) inner_connection: Weak<InnerConnection>,
statement_list_in_connection_id: u64,
}
unsafe impl Send for InnerStatement {} unsafe impl Sync for InnerStatement {}
impl Drop for InnerStatement {
fn drop(&mut self) {
let mut handle = self.get_statement_handle().unwrap().unwrap(); match self.check_connection() {
Ok(_) => {
self.inner_connection
.upgrade()
.unwrap()
.remove_statement(self.statement_list_in_connection_id); unsafe {
ffi::MimerEndStatement(&mut *handle);
}
}
Err(-26003) => (),
Err(ec) => panic!("Failed to check connection while dropping statement: {ec}"),
}
}
}
impl InnerStatement {
pub(crate) fn check_connection(&self) -> Result<(), i32> {
if Weak::strong_count(&self.inner_connection) == 0 {
return Err(-26003); }
Ok(())
}
pub(crate) fn new(
inner_connection: Weak<InnerConnection>,
sqlstatement: &str,
cursor_mode: CursorMode,
) -> Result<(InnerStatement, usize), i32> {
let stmnt_char_ptr = CString::new(sqlstatement)
.or_else(|_| Err(-26999))?
.into_raw();
let mut statement = std::ptr::null_mut();
let rc: i32;
unsafe {
rc = ffi::MimerBeginStatement8(
*inner_connection
.upgrade()
.ok_or(-26003)?
.get_session_handle()?
.unwrap(), stmnt_char_ptr,
cursor_mode as i32,
&mut statement,
);
let _ = CString::from_raw(stmnt_char_ptr);
match rc.cmp(MIMER_SUCCESS) {
Ordering::Less => Err(rc),
Ordering::Equal => {
let rc = ffi::MimerParameterCount(statement);
match rc.cmp(MIMER_SUCCESS) {
Ordering::Equal | Ordering::Greater => {
let num_param = rc as usize;
Ok((
InnerStatement {
statement: Mutex::new(statement),
inner_connection,
statement_list_in_connection_id: statement as u64,
},
num_param,
))
}
Ordering::Less => Err(rc),
}
}
Ordering::Greater => {
panic!("Return code is positive from C API function which doesn't return a positive value");
}
}
}
}
pub(crate) fn end_statement(&self) -> Result<(), i32> {
let mut handle = self.get_statement_handle()?.unwrap(); unsafe {
let rc = ffi::MimerEndStatement(&mut *handle);
if rc < 0 {
return Err(rc);
}
}
Ok(())
}
}
impl GetHandle for InnerStatement {
fn get_handle(&self) -> Result<MimerHandle, i32> {
Ok(MimerHandle::Statement(MutexGuard::map(
self.statement.lock(),
|inner| &mut *inner,
)))
}
fn get_statement_handle(&self) -> Result<Option<MappedMutexGuard<ffi::MimerStatement>>, i32> {
Ok(Some(MutexGuard::map(self.statement.lock(), |inner| {
&mut *inner
})))
}
}