bb8_oracle/lib.rs
1#![deny(missing_docs)]
2#![forbid(unsafe_code)]
3
4//! Oracle support for the bb8 connection pool.
5//!
6//! If you want to use chrono data types, enable the ```chrono``` feature:
7//!```toml
8//![dependencies]
9//!bb8-oracle = { version = "0.2.0", features = ["chrono"] }
10//!```
11
12use std::fmt;
13use std::sync::Arc;
14
15pub use bb8;
16pub use oracle;
17
18/// A `bb8::ManageConnection` for `oracle::Connection`s.
19///
20/// # Example
21/// ```no_run
22/// use std::thread;
23/// use bb8_oracle::OracleConnectionManager;
24///
25/// let manager = OracleConnectionManager::new("user", "password", "localhost");
26/// let pool = bb8::Pool::builder()
27/// .max_size(15)
28/// .build(manager).await
29/// .unwrap();
30///
31/// for _ in 0..20 {
32/// let pool = pool.clone();
33/// thread::spawn(move || {
34/// let conn = pool.get().unwrap();
35/// // use the connection
36/// // it will be returned to the pool when it falls out of scope.
37/// });
38/// }
39/// ```
40#[derive(Debug)]
41pub struct OracleConnectionManager {
42 connector: oracle::Connector,
43}
44
45impl OracleConnectionManager {
46 /// Initialise the connection manager with the data needed to create new connections.
47 /// Refer to the documentation of `oracle::Connection` for further details on the parameters.
48 ///
49 /// # Example
50 /// ```
51 /// # use bb8_oracle::OracleConnectionManager;
52 /// let manager = OracleConnectionManager::new("user", "password", "localhost");
53 /// ```
54 pub fn new<U: Into<String>, P: Into<String>, C: Into<String>>(username: U, password: P, connect_string: C) -> OracleConnectionManager {
55 let connector = oracle::Connector::new(username, password, connect_string);
56 OracleConnectionManager {
57 connector,
58 }
59 }
60
61 /// Initialise the connection manager with the data needed to create new connections using `oracle::Connector`.
62 /// This allows setting additional connection data.
63 ///
64 /// If a connection can be established only with a username, password and connect string, use `new` instead.
65 ///
66 /// # Example
67 /// ```
68 /// # use bb8_oracle::OracleConnectionManager;
69 /// // connect system/manager as sysdba
70 /// let mut connector = oracle::Connector::new("system", "manager", "");
71 /// connector.privilege(oracle::Privilege::Sysdba);
72 /// let manager = OracleConnectionManager::from_connector(connector);
73 /// ```
74 pub fn from_connector(connector: oracle::Connector) -> OracleConnectionManager {
75 OracleConnectionManager { connector }
76 }
77}
78
79/// An error that can occur during Oracle database connection pool operations.
80#[derive(Debug)]
81pub enum Error {
82 /// An error that occurred during database communication.
83 Database(oracle::Error),
84
85 /// An error that occurred because a pool operation panicked.
86 Panic(tokio::task::JoinError),
87}
88impl fmt::Display for Error {
89 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
90 match self {
91 Self::Database(e) => write!(f, "database error: {}", e),
92 Self::Panic(e) => write!(f, "operation panicked: {}", e),
93 }
94 }
95}
96impl std::error::Error for Error {
97 fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
98 match self {
99 Self::Database(e) => Some(e),
100 Self::Panic(e) => Some(e),
101 }
102 }
103}
104
105impl bb8::ManageConnection for OracleConnectionManager {
106 type Connection = Arc<oracle::Connection>;
107 type Error = Error;
108
109 async fn connect(&self) -> Result<Self::Connection, Self::Error> {
110 let connector_clone = self.connector.clone();
111 let result = tokio::task::spawn_blocking(move || {
112 connector_clone.connect()
113 }).await;
114 match result {
115 Ok(Ok(c)) => Ok(Arc::new(c)),
116 Ok(Err(e)) => Err(Error::Database(e)),
117 Err(e) => Err(Error::Panic(e)),
118 }
119 }
120
121 async fn is_valid(&self, conn: &mut Self::Connection) -> Result<(), Self::Error> {
122 let conn_clone = Arc::clone(&conn);
123 let result = tokio::task::spawn_blocking(move || {
124 conn_clone.ping()
125 }).await;
126 match result {
127 Ok(Ok(())) => Ok(()),
128 Ok(Err(e)) => Err(Error::Database(e)),
129 Err(e) => Err(Error::Panic(e)),
130 }
131 }
132
133 fn has_broken(&self, conn: &mut Self::Connection) -> bool {
134 !matches!(conn.status(), Ok(oracle::ConnStatus::Normal))
135 }
136}