Skip to content

Commit 293e9ef

Browse files
authored
Merge pull request #345 from blackbeam/public-connection-like
Make `ToConnection`, `Connection`, `ToConnectionResult` public
2 parents b830794 + 576d17a commit 293e9ef

File tree

9 files changed

+196
-80
lines changed

9 files changed

+196
-80
lines changed

src/connection_like/mod.rs

Lines changed: 93 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -10,9 +10,9 @@ use futures_util::FutureExt;
1010

1111
use crate::{BoxFuture, Pool};
1212

13-
/// Connection.
13+
/// Inner [`Connection`] representation.
1414
#[derive(Debug)]
15-
pub enum Connection<'a, 't: 'a> {
15+
pub(crate) enum ConnectionInner<'a, 't: 'a> {
1616
/// Just a connection.
1717
Conn(crate::Conn),
1818
/// Mutable reference to a connection.
@@ -21,55 +21,127 @@ pub enum Connection<'a, 't: 'a> {
2121
Tx(&'a mut crate::Transaction<'t>),
2222
}
2323

24+
impl std::ops::Deref for ConnectionInner<'_, '_> {
25+
type Target = crate::Conn;
26+
27+
fn deref(&self) -> &Self::Target {
28+
match self {
29+
ConnectionInner::Conn(ref conn) => conn,
30+
ConnectionInner::ConnMut(conn) => conn,
31+
ConnectionInner::Tx(tx) => tx.0.deref(),
32+
}
33+
}
34+
}
35+
36+
impl std::ops::DerefMut for ConnectionInner<'_, '_> {
37+
fn deref_mut(&mut self) -> &mut Self::Target {
38+
match self {
39+
ConnectionInner::Conn(conn) => conn,
40+
ConnectionInner::ConnMut(conn) => conn,
41+
ConnectionInner::Tx(tx) => tx.0.inner.deref_mut(),
42+
}
43+
}
44+
}
45+
46+
/// Some connection.
47+
///
48+
/// This could at least be queried.
49+
#[derive(Debug)]
50+
pub struct Connection<'a, 't: 'a> {
51+
pub(crate) inner: ConnectionInner<'a, 't>,
52+
}
53+
54+
impl Connection<'_, '_> {
55+
#[inline]
56+
pub(crate) fn as_mut(&mut self) -> &mut crate::Conn {
57+
&mut self.inner
58+
}
59+
}
60+
61+
impl<'a, 't: 'a> Connection<'a, 't> {
62+
/// Borrows a [`Connection`] rather than consuming it.
63+
///
64+
/// This is useful to allow calling [`Query`] methods while still retaining
65+
/// ownership of the original connection.
66+
///
67+
/// # Examples
68+
///
69+
/// ```no_run
70+
/// # use mysql_async::Connection;
71+
/// # use mysql_async::prelude::Query;
72+
/// async fn connection_by_ref(mut connection: Connection<'_, '_>) {
73+
/// // Perform some query
74+
/// "SELECT 1".ignore(connection.by_ref()).await.unwrap();
75+
/// // Perform another query.
76+
/// // We can only do this because we used `by_ref` earlier.
77+
/// "SELECT 2".ignore(connection).await.unwrap();
78+
/// }
79+
/// ```
80+
///
81+
/// [`Query`]: crate::prelude::Query
82+
pub fn by_ref(&mut self) -> Connection<'_, '_> {
83+
Connection {
84+
inner: ConnectionInner::ConnMut(self.as_mut()),
85+
}
86+
}
87+
}
88+
2489
impl From<crate::Conn> for Connection<'static, 'static> {
2590
fn from(conn: crate::Conn) -> Self {
26-
Connection::Conn(conn)
91+
Self {
92+
inner: ConnectionInner::Conn(conn),
93+
}
2794
}
2895
}
2996

3097
impl<'a> From<&'a mut crate::Conn> for Connection<'a, 'static> {
3198
fn from(conn: &'a mut crate::Conn) -> Self {
32-
Connection::ConnMut(conn)
99+
Self {
100+
inner: ConnectionInner::ConnMut(conn),
101+
}
33102
}
34103
}
35104

36105
impl<'a, 't> From<&'a mut crate::Transaction<'t>> for Connection<'a, 't> {
37106
fn from(tx: &'a mut crate::Transaction<'t>) -> Self {
38-
Connection::Tx(tx)
107+
Self {
108+
inner: ConnectionInner::Tx(tx),
109+
}
39110
}
40111
}
41112

42113
impl std::ops::Deref for Connection<'_, '_> {
43114
type Target = crate::Conn;
44115

45116
fn deref(&self) -> &Self::Target {
46-
match self {
47-
Connection::Conn(ref conn) => conn,
48-
Connection::ConnMut(conn) => conn,
49-
Connection::Tx(tx) => tx.0.deref(),
50-
}
51-
}
52-
}
53-
54-
impl std::ops::DerefMut for Connection<'_, '_> {
55-
fn deref_mut(&mut self) -> &mut Self::Target {
56-
match self {
57-
Connection::Conn(conn) => conn,
58-
Connection::ConnMut(conn) => conn,
59-
Connection::Tx(tx) => tx.0.deref_mut(),
60-
}
117+
&self.inner
61118
}
62119
}
63120

64-
/// Result of `ToConnection::to_connection` call.
121+
/// Result of a [`ToConnection::to_connection`] call.
65122
pub enum ToConnectionResult<'a, 't: 'a> {
66123
/// Connection is immediately available.
67124
Immediate(Connection<'a, 't>),
68125
/// We need some time to get a connection and the operation itself may fail.
69126
Mediate(BoxFuture<'a, Connection<'a, 't>>),
70127
}
71128

129+
impl<'a, 't: 'a> ToConnectionResult<'a, 't> {
130+
/// Resolves `self` to a connection.
131+
#[inline]
132+
pub async fn resolve(self) -> crate::Result<Connection<'a, 't>> {
133+
match self {
134+
ToConnectionResult::Immediate(immediate) => Ok(immediate),
135+
ToConnectionResult::Mediate(mediate) => mediate.await,
136+
}
137+
}
138+
}
139+
140+
/// Everything that can be given in exchange to a connection.
141+
///
142+
/// Note that you could obtain a `'static` connection by giving away `Conn` or `Pool`.
72143
pub trait ToConnection<'a, 't: 'a>: Send {
144+
/// Converts self to a connection.
73145
fn to_connection(self) -> ToConnectionResult<'a, 't>;
74146
}
75147

src/io/read_packet.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -37,15 +37,15 @@ impl Future for ReadPacket<'_, '_> {
3737
type Output = std::result::Result<PooledBuf, IoError>;
3838

3939
fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
40-
let packet_opt = match self.0.stream_mut() {
40+
let packet_opt = match self.0.as_mut().stream_mut() {
4141
Ok(stream) => ready!(Pin::new(stream).poll_next(cx)).transpose()?,
4242
// `ConnectionClosed` error.
4343
Err(_) => None,
4444
};
4545

4646
match packet_opt {
4747
Some(packet) => {
48-
self.0.touch();
48+
self.0.as_mut().touch();
4949
Poll::Ready(Ok(packet))
5050
}
5151
None => Poll::Ready(Err(Error::new(

src/io/write_packet.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,7 @@ impl Future for WritePacket<'_, '_> {
4444
ref mut data,
4545
} = *self;
4646

47-
match conn.stream_mut() {
47+
match conn.as_mut().stream_mut() {
4848
Ok(stream) => {
4949
if data.is_some() {
5050
let codec = Pin::new(stream.codec.as_mut().expect("must be here"));

src/lib.rs

Lines changed: 5 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -553,13 +553,18 @@ pub use self::queryable::stmt::Statement;
553553
#[doc(inline)]
554554
pub use self::conn::pool::Metrics;
555555

556+
#[doc(inline)]
557+
pub use crate::connection_like::{Connection, ToConnectionResult};
558+
556559
/// Futures used in this crate
557560
pub mod futures {
558561
pub use crate::conn::pool::futures::{DisconnectPool, GetConn};
559562
}
560563

561564
/// Traits used in this crate
562565
pub mod prelude {
566+
#[doc(inline)]
567+
pub use crate::connection_like::ToConnection;
563568
#[doc(inline)]
564569
pub use crate::local_infile_handler::GlobalHandler;
565570
#[doc(inline)]
@@ -596,17 +601,6 @@ pub mod prelude {
596601
pub trait StatementLike: crate::queryable::stmt::StatementLike {}
597602
impl<T: crate::queryable::stmt::StatementLike> StatementLike for T {}
598603

599-
/// Everything that is a connection.
600-
///
601-
/// Note that you could obtain a `'static` connection by giving away `Conn` or `Pool`.
602-
pub trait ToConnection<'a, 't: 'a>: crate::connection_like::ToConnection<'a, 't> {}
603-
// explicitly implemented because of rusdoc
604-
impl<'a> ToConnection<'a, 'static> for &'a crate::Pool {}
605-
impl ToConnection<'static, 'static> for crate::Pool {}
606-
impl ToConnection<'static, 'static> for crate::Conn {}
607-
impl<'a> ToConnection<'a, 'static> for &'a mut crate::Conn {}
608-
impl<'a, 't> ToConnection<'a, 't> for &'a mut crate::Transaction<'t> {}
609-
610604
/// Trait for protocol markers [`crate::TextProtocol`] and [`crate::BinaryProtocol`].
611605
pub trait Protocol: crate::queryable::Protocol {}
612606
impl Protocol for crate::BinaryProtocol {}

src/query.rs

Lines changed: 9 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,6 @@ use std::borrow::Cow;
1111
use futures_util::FutureExt;
1212

1313
use crate::{
14-
connection_like::ToConnectionResult,
1514
from_row,
1615
prelude::{FromRow, StatementLike, ToConnection},
1716
tracing_utils::LevelInfo,
@@ -217,11 +216,8 @@ impl<Q: AsQuery> Query for Q {
217216
C: ToConnection<'a, 't> + 'a,
218217
{
219218
async move {
220-
let mut conn = match conn.to_connection() {
221-
ToConnectionResult::Immediate(conn) => conn,
222-
ToConnectionResult::Mediate(fut) => fut.await?,
223-
};
224-
conn.raw_query::<'_, _, LevelInfo>(self).await?;
219+
let mut conn = conn.to_connection().resolve().await?;
220+
conn.as_mut().raw_query::<'_, _, LevelInfo>(self).await?;
225221
Ok(QueryResult::new(conn))
226222
}
227223
.boxed()
@@ -264,14 +260,12 @@ where
264260
C: ToConnection<'a, 't> + 'a,
265261
{
266262
async move {
267-
let mut conn = match conn.to_connection() {
268-
ToConnectionResult::Immediate(conn) => conn,
269-
ToConnectionResult::Mediate(fut) => fut.await?,
270-
};
263+
let mut conn = conn.to_connection().resolve().await?;
271264

272-
let statement = conn.get_statement(self.query).await?;
265+
let statement = conn.as_mut().get_statement(self.query).await?;
273266

274-
conn.execute_statement(&statement, self.params.into())
267+
conn.as_mut()
268+
.execute_statement(&statement, self.params.into())
275269
.await?;
276270

277271
Ok(QueryResult::new(conn))
@@ -324,15 +318,12 @@ where
324318
C: ToConnection<'a, 't> + 'a,
325319
{
326320
async move {
327-
let mut conn = match conn.to_connection() {
328-
ToConnectionResult::Immediate(conn) => conn,
329-
ToConnectionResult::Mediate(fut) => fut.await?,
330-
};
321+
let mut conn = conn.to_connection().resolve().await?;
331322

332-
let statement = conn.get_statement(self.query).await?;
323+
let statement = conn.as_mut().get_statement(self.query).await?;
333324

334325
for params in self.params {
335-
conn.execute_statement(&statement, params).await?;
326+
conn.as_mut().execute_statement(&statement, params).await?;
336327
}
337328

338329
Ok(())

src/queryable/mod.rs

Lines changed: 58 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ use crate::{
3131
query::AsQuery,
3232
queryable::query_result::ResultSetMeta,
3333
tracing_utils::{LevelInfo, LevelTrace, TracingLevel},
34-
BoxFuture, Column, Conn, Params, ResultSetStream, Row,
34+
BoxFuture, Column, Conn, Connection, Params, ResultSetStream, Row,
3535
};
3636

3737
pub mod query_result;
@@ -537,7 +537,7 @@ impl Queryable for Conn {
537537

538538
impl Queryable for Transaction<'_> {
539539
fn ping(&mut self) -> BoxFuture<'_, ()> {
540-
self.0.ping()
540+
self.0.as_mut().ping()
541541
}
542542

543543
fn query_iter<'a, Q>(
@@ -547,18 +547,18 @@ impl Queryable for Transaction<'_> {
547547
where
548548
Q: AsQuery + 'a,
549549
{
550-
self.0.query_iter(query)
550+
self.0.as_mut().query_iter(query)
551551
}
552552

553553
fn prep<'a, Q>(&'a mut self, query: Q) -> BoxFuture<'a, Statement>
554554
where
555555
Q: AsQuery + 'a,
556556
{
557-
self.0.prep(query)
557+
self.0.as_mut().prep(query)
558558
}
559559

560560
fn close(&mut self, stmt: Statement) -> BoxFuture<'_, ()> {
561-
self.0.close(stmt)
561+
self.0.as_mut().close(stmt)
562562
}
563563

564564
fn exec_iter<'a: 's, 's, Q, P>(
@@ -570,7 +570,7 @@ impl Queryable for Transaction<'_> {
570570
Q: StatementLike + 'a,
571571
P: Into<Params>,
572572
{
573-
self.0.exec_iter(stmt, params)
573+
self.0.as_mut().exec_iter(stmt, params)
574574
}
575575

576576
fn exec_batch<'a: 'b, 'b, S, P, I>(&'a mut self, stmt: S, params_iter: I) -> BoxFuture<'b, ()>
@@ -580,7 +580,58 @@ impl Queryable for Transaction<'_> {
580580
I::IntoIter: Send,
581581
P: Into<Params> + Send,
582582
{
583-
self.0.exec_batch(stmt, params_iter)
583+
self.0.as_mut().exec_batch(stmt, params_iter)
584+
}
585+
}
586+
587+
impl<'c, 't: 'c> Queryable for Connection<'c, 't> {
588+
#[inline]
589+
fn ping(&mut self) -> BoxFuture<'_, ()> {
590+
self.as_mut().ping()
591+
}
592+
593+
#[inline]
594+
fn query_iter<'a, Q>(
595+
&'a mut self,
596+
query: Q,
597+
) -> BoxFuture<'a, QueryResult<'a, 'static, TextProtocol>>
598+
where
599+
Q: AsQuery + 'a,
600+
{
601+
self.as_mut().query_iter(query)
602+
}
603+
604+
fn prep<'a, Q>(&'a mut self, query: Q) -> BoxFuture<'a, Statement>
605+
where
606+
Q: AsQuery + 'a,
607+
{
608+
self.as_mut().prep(query)
609+
}
610+
611+
fn close(&mut self, stmt: Statement) -> BoxFuture<'_, ()> {
612+
self.as_mut().close(stmt)
613+
}
614+
615+
fn exec_iter<'a: 's, 's, Q, P>(
616+
&'a mut self,
617+
stmt: Q,
618+
params: P,
619+
) -> BoxFuture<'s, QueryResult<'a, 'static, BinaryProtocol>>
620+
where
621+
Q: StatementLike + 'a,
622+
P: Into<Params>,
623+
{
624+
self.as_mut().exec_iter(stmt, params)
625+
}
626+
627+
fn exec_batch<'a: 'b, 'b, S, P, I>(&'a mut self, stmt: S, params_iter: I) -> BoxFuture<'b, ()>
628+
where
629+
S: StatementLike + 'b,
630+
I: IntoIterator<Item = P> + Send + 'b,
631+
I::IntoIter: Send,
632+
P: Into<Params> + Send,
633+
{
634+
self.as_mut().exec_batch(stmt, params_iter)
584635
}
585636
}
586637

0 commit comments

Comments
 (0)