1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
use crate::database::{Database, HasStatementCache};
use crate::error::Error;
use crate::transaction::Transaction;
use std::fmt::Debug;
use std::str::FromStr;
use std::time::Duration;
use crate::executor::Executor;
/// Represents a single database connection.
pub trait Connection: Send+Executor {
type Options: ConnectOptions<Connection = Self>;
/// Explicitly close this database connection.
///
/// This method is **not required** for safe and consistent operation. However, it is
/// recommended to call it instead of letting a connection `drop` as the database backend
/// will be faster at cleaning up resources.
fn close(self) -> Result<(), Error>;
/// Checks if a connection to the database is still valid.
fn ping(&mut self) -> Result<(), Error>;
/// Begin a new transaction or establish a savepoint within the active transaction.
///
/// Returns a [`Transaction`] for controlling and tracking the new transaction.
fn begin(&mut self) -> Result<Transaction<'_, Self::Database>, Error>
where
Self: Sized;
/// Execute the function inside a transaction.
///
/// If the function returns an error, the transaction will be rolled back. If it does not
/// return an error, the transaction will be committed.
///
/// # Example
///
///
/// use cdbc::connection::Connection;
/// use cdbc::error::Error;
/// use cdbc::executor::Executor;
/// use cdbc_pg::{PgConnection, PgRow};
/// use cdbc::query::query;
///
/// # pub fn _f(conn: &mut PgConnection) -> Result<Vec<PgRow>, Error> {
/// conn.transaction(|conn|Box::pin( || {
/// query("select * from ..").fetch_all(conn)
/// }))
/// # }
///
fn transaction<'a, F, R, E>(&'a mut self, callback: F) -> Result<R, E>
where
for<'c> F: FnOnce(&'c mut Transaction<'_, Self::Database>) -> Result<R, E>
+ 'a
+ Send
+ Sync,
Self: Sized,
R: Send,
E: From<Error> + Send,
{
let mut transaction = self.begin()?;
let ret = callback(&mut transaction);
match ret {
Ok(ret) => {
transaction.commit()?;
Ok(ret)
}
Err(err) => {
transaction.rollback()?;
Err(err)
}
}
}
/// The number of statements currently cached in the connection.
fn cached_statements_size(&self) -> usize
where
Self::Database: HasStatementCache,
{
0
}
/// Removes all statements from the cache, closing them on the server if
/// needed.
fn clear_cached_statements(&mut self) -> Result<(), Error>
where
Self::Database: HasStatementCache,
{
Ok(())
}
#[doc(hidden)]
fn flush(&mut self) -> Result<(), Error>;
#[doc(hidden)]
fn should_flush(&self) -> bool;
/// Establish a new database connection.
///
/// A value of [`Options`][Self::Options] is parsed from the provided connection string. This parsing
/// is database-specific.
#[inline]
fn connect(url: &str) -> Result<Self, Error>
where
Self: Sized,
{
let options = url.parse();
Ok(Self::connect_with(&options?)?)
}
/// Establish a new database connection with the provided options.
fn connect_with(options: &Self::Options) -> Result<Self, Error>
where
Self: Sized,
{
options.connect(Duration::from_secs(10 * 60))
}
}
pub trait ConnectOptions: 'static + Send + Sync + FromStr<Err = Error> + Debug {
type Connection: Connection + ?Sized;
/// Establish a new database connection with the options specified by `self`.
fn connect(&self,d:Duration) -> Result<Self::Connection, Error>
where
Self::Connection: Sized;
}