r2d2_odbc_api 0.2.0

ODBC support for the r2d2 connection pool Via odbc-api Based on https://github.com/Koka/r2d2-odbc
Documentation
use crate::pool::{ODBCConnection, OdbcError};
use crate::ENV;
use crossbeam_queue::ArrayQueue;
pub use odbc_api::*;
use std::sync::{Arc, Mutex, RwLock};

pub(crate) struct SharedPool {
    pub(crate) pool: Mutex<ArrayQueue<odbc_api::force_send_sync::Send<Connection<'static>>>>,
    pub(crate) connection_string: RwLock<String>,
}

impl SharedPool {
    pub(crate) fn new_arc(connection_string: String, limit: u32) -> Arc<Self> {
        let pool = Self {
            pool: Mutex::new(ArrayQueue::new(limit as usize)),
            connection_string: RwLock::new(connection_string),
        };

        Arc::new(pool)
    }

    pub(crate) fn aquire(self: &Arc<Self>) -> Result<ODBCConnection, OdbcError> {
        let pool = self
            .pool
            .lock()
            .map_err(|p| OdbcError::LockError { msg: p.to_string() })?;

        if let Some(connection) = pool.pop() {
            return Ok(ODBCConnection::new(Arc::clone(self), connection));
        }

        let conn_str = self
            .connection_string
            .read()
            .map_err(|p| OdbcError::LockError { msg: p.to_string() })?;

        let env = &ENV;
        let conn = env.connect_with_connection_string(conn_str.as_str())?;
        // Promoting a connection to send is unsafe, since not every ODBC driver is thread safe.
        // Actual thread safety for unixODBC may also depend on the threading level defined for the
        // ODBC driver. Here we assume that the user conciously checked the safety of the
        // application and checked into sending connection then the ODBConnectionManager has been
        // constructed.
        // we will attempt to bypass this by handling the pool ourselves.
        let connection = unsafe { conn.promote_to_send() };

        Ok(ODBCConnection::new(Arc::clone(self), connection))
    }
}