use crate::common::return_codes::MIMER_SUCCESS;
use crate::common::traits::*;
use crate::inner_statement::*;
use crate::mimer_error::*;
use mimerrust_sys as ffi;
#[doc(hidden)]
use lazy_static::lazy_static;
#[doc(hidden)]
use parking_lot::{MappedMutexGuard, Mutex, MutexGuard};
lazy_static! {
static ref connect_disconnect_mtx: Mutex<i32> = Mutex::new(0);
}
#[doc(hidden)]
use std::{
cmp::Ordering,
collections::HashMap,
ffi::CString,
result::Result::{Err, Ok},
sync::Weak,
};
pub struct InnerConnection {
pub(crate) session: Mutex<ffi::MimerSession>,
pub(crate) statements: Mutex<HashMap<u64, Weak<InnerStatement>>>,
}
unsafe impl Send for InnerConnection {} unsafe impl Sync for InnerConnection {}
impl InnerConnection {
pub fn open(
database: &str,
ident: &str,
password: &str,
) -> Result<InnerConnection, MimerError> {
let mut sess: ffi::MimerSession = std::ptr::null_mut();
let db_char_ptr = CString::new(database)
.or_else(|_| Err(MimerError::mimer_error_from_code(-26999)))?
.into_raw();
let ident_char_ptr = CString::new(ident)
.or_else(|_| Err(MimerError::mimer_error_from_code(-26999)))?
.into_raw();
let pw_char_ptr = CString::new(password)
.or_else(|_| Err(MimerError::mimer_error_from_code(-26999)))?
.into_raw();
unsafe {
let _lck = connect_disconnect_mtx.lock();
let rc = ffi::MimerBeginSession8(db_char_ptr, ident_char_ptr, pw_char_ptr, &mut sess);
let _ = CString::from_raw(db_char_ptr);
let _ = CString::from_raw(ident_char_ptr);
let _ = CString::from_raw(pw_char_ptr);
match rc.cmp(MIMER_SUCCESS) {
Ordering::Greater => {
panic!("Return code is positive from C API function which doesn't return a positive value")
}
Ordering::Equal => (),
Ordering::Less => return Err(MimerError::mimer_error_from_code(rc)),
}
match sess.as_mut() {
Some(session) => Ok(InnerConnection {
session: Mutex::new(session),
statements: Mutex::new(HashMap::new()),
}),
None => Err(MimerError::mimer_error_from_code(-26002)), }
}
}
pub(crate) fn push_statement(&self, stmt: Weak<InnerStatement>) {
let strong_stmt = stmt.upgrade().unwrap(); let id = strong_stmt.get_statement_handle().unwrap().unwrap(); self.statements.lock().insert(*id as u64, stmt);
}
pub(crate) fn remove_statement(&self, id: u64) {
self.statements.lock().remove(&id);
}
}
impl Drop for InnerConnection {
fn drop(&mut self) {
for stmt in self.statements.lock().values_mut() {
if let Some(stmt) = stmt.upgrade() {
stmt.end_statement().unwrap(); }
}
unsafe {
let _lck = connect_disconnect_mtx.lock();
ffi::MimerEndSessionHard(&mut *self.get_session_handle().unwrap().unwrap());
}
}
}
impl GetHandle for InnerConnection {
fn get_handle(&self) -> Result<MimerHandle, i32> {
Ok(MimerHandle::Session(MutexGuard::map(
self.session.lock(),
|inner| &mut *inner,
)))
}
fn get_session_handle(&self) -> Result<Option<MappedMutexGuard<ffi::MimerSession>>, i32> {
Ok(Some(MutexGuard::map(self.session.lock(), |inner| {
&mut *inner
})))
}
}