1pub use r2d2::*;
178
179pub type PoolError = r2d2::Error;
184
185use alloc::fmt;
186use core::marker::PhantomData;
187
188use crate::backend::Backend;
189use crate::connection::{
190 ConnectionSealed, LoadConnection, SimpleConnection, TransactionManager,
191 TransactionManagerStatus,
192};
193use crate::expression::QueryMetadata;
194use crate::prelude::*;
195use crate::query_builder::{Query, QueryFragment, QueryId};
196use crate::query_dsl::RunQueryDslSupport;
197
198#[derive(#[automatically_derived]impl<T: ::core::clone::Clone> ::core::clone::Clone for
ConnectionManager<T> {
#[inline]
fn clone(&self) -> Self {
ConnectionManager {
database_url: ::core::clone::Clone::clone(&self.database_url),
_marker: ::core::clone::Clone::clone(&self._marker),
}
}
}Clone)]
202pub struct ConnectionManager<T> {
203 database_url: String,
204 _marker: PhantomData<T>,
205}
206
207impl<T> fmt::Debug for ConnectionManager<T> {
208 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
209 f.write_fmt(format_args!("ConnectionManager<{0}>",
core::any::type_name::<T>()))write!(f, "ConnectionManager<{}>", core::any::type_name::<T>())
210 }
211}
212
213#[allow(unsafe_code)] unsafe impl<T: Send + 'static> Sync for ConnectionManager<T> {}
215
216impl<T> ConnectionManager<T> {
217 pub fn new<S: Into<String>>(database_url: S) -> Self {
220 ConnectionManager {
221 database_url: database_url.into(),
222 _marker: PhantomData,
223 }
224 }
225
226 pub fn update_database_url<S: Into<String>>(&mut self, database_url: S) {
231 self.database_url = database_url.into();
232 }
233}
234
235#[derive(#[automatically_derived]impl ::core::fmt::Debug for Error {
#[inline]
fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
match self {
Self::ConnectionError(__self_0) =>
::core::fmt::Formatter::debug_tuple_field1_finish(f,
"ConnectionError", &__self_0),
Self::QueryError(__self_0) =>
::core::fmt::Formatter::debug_tuple_field1_finish(f,
"QueryError", &__self_0),
}
}
}Debug)]
237pub enum Error {
238 ConnectionError(ConnectionError),
240
241 QueryError(crate::result::Error),
243}
244
245impl fmt::Display for Error {
246 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
247 match *self {
248 Error::ConnectionError(ref e) => e.fmt(f),
249 Error::QueryError(ref e) => e.fmt(f),
250 }
251 }
252}
253
254impl ::core::error::Error for Error {}
255
256impl From<crate::result::Error> for Error {
257 fn from(other: crate::result::Error) -> Self {
258 Self::QueryError(other)
259 }
260}
261
262impl From<ConnectionError> for Error {
263 fn from(other: ConnectionError) -> Self {
264 Self::ConnectionError(other)
265 }
266}
267
268pub trait R2D2Connection: Connection {
270 fn ping(&mut self) -> QueryResult<()>;
272
273 fn is_broken(&mut self) -> bool {
281 false
282 }
283}
284
285impl<T> ManageConnection for ConnectionManager<T>
286where
287 T: R2D2Connection + Send + 'static,
288{
289 type Connection = T;
290 type Error = Error;
291
292 fn connect(&self) -> Result<T, Error> {
293 T::establish(&self.database_url).map_err(Error::ConnectionError)
294 }
295
296 fn is_valid(&self, conn: &mut T) -> Result<(), Error> {
297 conn.ping().map_err(Error::QueryError)
298 }
299
300 fn has_broken(&self, conn: &mut T) -> bool {
301 std::thread::panicking() || conn.is_broken()
302 }
303}
304
305impl<M> SimpleConnection for PooledConnection<M>
306where
307 M: ManageConnection,
308 M::Connection: R2D2Connection + Send + 'static,
309{
310 fn batch_execute(&mut self, query: &str) -> QueryResult<()> {
311 (**self).batch_execute(query)
312 }
313}
314
315impl<M> ConnectionSealed for PooledConnection<M>
316where
317 M: ManageConnection,
318 M::Connection: ConnectionSealed,
319{
320}
321
322impl<M> Connection for PooledConnection<M>
323where
324 M: ManageConnection,
325 M::Connection: Connection + R2D2Connection + Send + 'static,
326{
327 type Backend = <M::Connection as Connection>::Backend;
328 type TransactionManager =
329 PoolTransactionManager<<M::Connection as Connection>::TransactionManager>;
330
331 fn establish(_: &str) -> ConnectionResult<Self> {
332 Err(ConnectionError::BadConnection(String::from(
333 "Cannot directly establish a pooled connection",
334 )))
335 }
336
337 fn begin_test_transaction(&mut self) -> QueryResult<()> {
338 (**self).begin_test_transaction()
339 }
340
341 fn execute_returning_count<T>(&mut self, source: &T) -> QueryResult<usize>
342 where
343 T: QueryFragment<Self::Backend> + QueryId,
344 {
345 (**self).execute_returning_count(source)
346 }
347
348 fn transaction_state(
349 &mut self,
350 ) -> &mut <Self::TransactionManager as TransactionManager<Self>>::TransactionStateData {
351 (**self).transaction_state()
352 }
353
354 fn instrumentation(&mut self) -> &mut dyn crate::connection::Instrumentation {
355 (**self).instrumentation()
356 }
357
358 fn set_instrumentation(&mut self, instrumentation: impl crate::connection::Instrumentation) {
359 (**self).set_instrumentation(instrumentation)
360 }
361
362 fn set_prepared_statement_cache_size(&mut self, size: crate::connection::CacheSize) {
363 (**self).set_prepared_statement_cache_size(size)
364 }
365}
366
367impl<B, M> LoadConnection<B> for PooledConnection<M>
368where
369 M: ManageConnection,
370 M::Connection: LoadConnection<B> + R2D2Connection,
371{
372 type Cursor<'conn, 'query> = <M::Connection as LoadConnection<B>>::Cursor<'conn, 'query>;
373 type Row<'conn, 'query> = <M::Connection as LoadConnection<B>>::Row<'conn, 'query>;
374
375 fn load<'conn, 'query, T>(
376 &'conn mut self,
377 source: T,
378 ) -> QueryResult<Self::Cursor<'conn, 'query>>
379 where
380 T: Query + QueryFragment<Self::Backend> + QueryId + 'query,
381 Self::Backend: QueryMetadata<T::SqlType>,
382 {
383 (**self).load(source)
384 }
385}
386
387#[doc(hidden)]
388#[allow(missing_debug_implementations)]
389pub struct PoolTransactionManager<T>(core::marker::PhantomData<T>);
390
391impl<M, T> TransactionManager<PooledConnection<M>> for PoolTransactionManager<T>
392where
393 M: ManageConnection,
394 M::Connection: Connection<TransactionManager = T> + R2D2Connection,
395 T: TransactionManager<M::Connection>,
396{
397 type TransactionStateData = T::TransactionStateData;
398
399 fn begin_transaction(conn: &mut PooledConnection<M>) -> QueryResult<()> {
400 T::begin_transaction(&mut **conn)
401 }
402
403 fn rollback_transaction(conn: &mut PooledConnection<M>) -> QueryResult<()> {
404 T::rollback_transaction(&mut **conn)
405 }
406
407 fn commit_transaction(conn: &mut PooledConnection<M>) -> QueryResult<()> {
408 T::commit_transaction(&mut **conn)
409 }
410
411 fn transaction_manager_status_mut(
412 conn: &mut PooledConnection<M>,
413 ) -> &mut TransactionManagerStatus {
414 T::transaction_manager_status_mut(&mut **conn)
415 }
416}
417
418impl<M> crate::migration::MigrationConnection for PooledConnection<M>
419where
420 M: ManageConnection,
421 M::Connection: crate::migration::MigrationConnection,
422 Self: Connection,
423{
424 fn setup(&mut self) -> QueryResult<usize> {
425 (**self).setup()
426 }
427}
428
429impl<Changes, Output, M> crate::query_dsl::UpdateAndFetchResults<Changes, Output>
430 for PooledConnection<M>
431where
432 M: ManageConnection,
433 M::Connection: crate::query_dsl::UpdateAndFetchResults<Changes, Output>,
434 Self: Connection,
435{
436 fn update_and_fetch(&mut self, changeset: Changes) -> QueryResult<Output> {
437 (**self).update_and_fetch(changeset)
438 }
439}
440
441#[derive(const _: () =
{
use diesel;
#[allow(non_camel_case_types)]
impl diesel::query_builder::QueryId for CheckConnectionQuery {
type QueryId = CheckConnectionQuery<>;
const HAS_STATIC_QUERY_ID: bool = true;
const IS_WINDOW_FUNCTION: bool = false;
}
};QueryId)]
442pub(crate) struct CheckConnectionQuery;
443
444impl<DB> QueryFragment<DB> for CheckConnectionQuery
445where
446 DB: Backend,
447{
448 fn walk_ast<'b>(
449 &'b self,
450 mut pass: crate::query_builder::AstPass<'_, 'b, DB>,
451 ) -> QueryResult<()> {
452 pass.push_sql("SELECT 1");
453 Ok(())
454 }
455}
456
457impl Query for CheckConnectionQuery {
458 type SqlType = crate::sql_types::Integer;
459}
460
461impl RunQueryDslSupport for CheckConnectionQuery {}
462
463#[derive(#[automatically_derived]impl ::core::fmt::Debug for TestCustomizer {
#[inline]
fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
::core::fmt::Formatter::write_str(f, "TestCustomizer")
}
}Debug, #[automatically_derived]#[doc(hidden)]unsafe impl ::core::clone::TrivialClone
for TestCustomizer {
}
#[automatically_derived]impl ::core::clone::Clone for TestCustomizer {
#[inline]
fn clone(&self) -> Self { *self }
}Clone, #[automatically_derived]impl ::core::marker::Copy for TestCustomizer { }Copy)]
467pub struct TestCustomizer;
468
469impl<C: Connection> CustomizeConnection<C, crate::r2d2::Error> for TestCustomizer {
470 fn on_acquire(&self, conn: &mut C) -> Result<(), crate::r2d2::Error> {
471 conn.begin_test_transaction()
472 .map_err(crate::r2d2::Error::QueryError)
473 }
474}
475
476#[cfg(all(
482 test,
483 not(miri),
484 not(all(target_family = "wasm", target_os = "unknown"))
485))]
486mod tests {
487 use std::sync::Arc;
488 use std::sync::mpsc;
489 use std::thread;
490 use std::time::Duration;
491
492 use crate::r2d2::*;
493 use crate::test_helpers::*;
494
495 #[diesel_test_helper::test]
496 fn establish_basic_connection() {
497 let manager = ConnectionManager::<TestConnection>::new(database_url());
498 let pool = Arc::new(Pool::builder().max_size(2).build(manager).unwrap());
499
500 let (s1, r1) = mpsc::channel();
501 let (s2, r2) = mpsc::channel();
502
503 let pool1 = Arc::clone(&pool);
504 let t1 = thread::spawn(move || {
505 let conn = pool1.get().unwrap();
506 s1.send(()).unwrap();
507 r2.recv().unwrap();
508 drop(conn);
509 });
510
511 let pool2 = Arc::clone(&pool);
512 let t2 = thread::spawn(move || {
513 let conn = pool2.get().unwrap();
514 s2.send(()).unwrap();
515 r1.recv().unwrap();
516 drop(conn);
517 });
518
519 t1.join().unwrap();
520 t2.join().unwrap();
521
522 pool.get().unwrap();
523 }
524
525 #[diesel_test_helper::test]
526 fn is_valid() {
527 let manager = ConnectionManager::<TestConnection>::new(database_url());
528 let pool = Pool::builder()
529 .max_size(1)
530 .test_on_check_out(true)
531 .build(manager)
532 .unwrap();
533
534 pool.get().unwrap();
535 }
536
537 #[diesel_test_helper::test]
538 fn pooled_connection_impls_connection() {
539 use crate::select;
540 use crate::sql_types::Text;
541
542 let manager = ConnectionManager::<TestConnection>::new(database_url());
543 let pool = Pool::builder()
544 .max_size(1)
545 .test_on_check_out(true)
546 .build(manager)
547 .unwrap();
548 let mut conn = pool.get().unwrap();
549
550 let query = select("foo".into_sql::<Text>());
551 assert_eq!("foo", query.get_result::<String>(&mut conn).unwrap());
552 }
553
554 #[diesel_test_helper::test]
555 fn check_pool_does_actually_hold_connections() {
556 use std::sync::atomic::{AtomicU32, Ordering};
557
558 #[derive(Debug)]
559 struct TestEventHandler {
560 acquire_count: Arc<AtomicU32>,
561 release_count: Arc<AtomicU32>,
562 checkin_count: Arc<AtomicU32>,
563 checkout_count: Arc<AtomicU32>,
564 }
565
566 impl r2d2::HandleEvent for TestEventHandler {
567 fn handle_acquire(&self, _event: r2d2::event::AcquireEvent) {
568 self.acquire_count.fetch_add(1, Ordering::Relaxed);
569 }
570 fn handle_release(&self, _event: r2d2::event::ReleaseEvent) {
571 self.release_count.fetch_add(1, Ordering::Relaxed);
572 }
573 fn handle_checkout(&self, _event: r2d2::event::CheckoutEvent) {
574 self.checkout_count.fetch_add(1, Ordering::Relaxed);
575 }
576 fn handle_checkin(&self, _event: r2d2::event::CheckinEvent) {
577 self.checkin_count.fetch_add(1, Ordering::Relaxed);
578 }
579 }
580
581 let acquire_count = Arc::new(AtomicU32::new(0));
582 let release_count = Arc::new(AtomicU32::new(0));
583 let checkin_count = Arc::new(AtomicU32::new(0));
584 let checkout_count = Arc::new(AtomicU32::new(0));
585
586 let handler = Box::new(TestEventHandler {
587 acquire_count: acquire_count.clone(),
588 release_count: release_count.clone(),
589 checkin_count: checkin_count.clone(),
590 checkout_count: checkout_count.clone(),
591 });
592
593 let manager = ConnectionManager::<TestConnection>::new(database_url());
594 let pool = Pool::builder()
595 .max_size(1)
596 .test_on_check_out(true)
597 .event_handler(handler)
598 .build(manager)
599 .unwrap();
600
601 assert_eq!(acquire_count.load(Ordering::Relaxed), 1);
602 assert_eq!(release_count.load(Ordering::Relaxed), 0);
603 assert_eq!(checkin_count.load(Ordering::Relaxed), 0);
604 assert_eq!(checkout_count.load(Ordering::Relaxed), 0);
605
606 {
608 let conn = pool.get().unwrap();
609
610 assert_eq!(acquire_count.load(Ordering::Relaxed), 1);
611 assert_eq!(release_count.load(Ordering::Relaxed), 0);
612 assert_eq!(checkin_count.load(Ordering::Relaxed), 0);
613 assert_eq!(checkout_count.load(Ordering::Relaxed), 1);
614 std::mem::drop(conn);
615 }
616
617 assert_eq!(acquire_count.load(Ordering::Relaxed), 1);
618 assert_eq!(release_count.load(Ordering::Relaxed), 0);
619 assert_eq!(checkin_count.load(Ordering::Relaxed), 1);
620 assert_eq!(checkout_count.load(Ordering::Relaxed), 1);
621
622 {
624 let mut conn = pool.get().unwrap();
625
626 assert_eq!(acquire_count.load(Ordering::Relaxed), 1);
627 assert_eq!(release_count.load(Ordering::Relaxed), 0);
628 assert_eq!(checkin_count.load(Ordering::Relaxed), 1);
629 assert_eq!(checkout_count.load(Ordering::Relaxed), 2);
630
631 <TestConnection as Connection>::TransactionManager::begin_transaction(&mut *conn)
632 .unwrap();
633 }
634
635 assert_eq!(release_count.load(Ordering::Relaxed), 1);
641 assert_eq!(checkin_count.load(Ordering::Relaxed), 2);
642 assert_eq!(checkout_count.load(Ordering::Relaxed), 2);
643
644 #[allow(unreachable_code, unused_variables)]
647 std::panic::catch_unwind(std::panic::AssertUnwindSafe(|| {
648 let conn = pool.get();
649 assert_eq!(acquire_count.load(Ordering::Relaxed), 2);
650 assert_eq!(release_count.load(Ordering::Relaxed), 1);
651 assert_eq!(checkin_count.load(Ordering::Relaxed), 2);
652 assert_eq!(checkout_count.load(Ordering::Relaxed), 3);
653 panic!();
654 std::mem::drop(conn);
655 }))
656 .unwrap_err();
657
658 assert_eq!(release_count.load(Ordering::Relaxed), 2);
664 assert_eq!(checkin_count.load(Ordering::Relaxed), 3);
665 assert_eq!(checkout_count.load(Ordering::Relaxed), 3);
666 std::thread::sleep(Duration::from_millis(100));
669 }
670
671 #[cfg(feature = "postgres")]
672 #[diesel_test_helper::test]
673 fn verify_that_begin_test_transaction_works_with_pools() {
674 use crate::prelude::*;
675 use crate::r2d2::*;
676
677 table! {
678 users {
679 id -> Integer,
680 name -> Text,
681 }
682 }
683
684 #[derive(Debug)]
685 struct TestConnectionCustomizer;
686
687 impl<E> CustomizeConnection<PgConnection, E> for TestConnectionCustomizer {
688 fn on_acquire(&self, conn: &mut PgConnection) -> Result<(), E> {
689 conn.begin_test_transaction()
690 .expect("Failed to start test transaction");
691
692 Ok(())
693 }
694 }
695
696 let manager = ConnectionManager::<PgConnection>::new(database_url());
697 let pool = Pool::builder()
698 .max_size(1)
699 .connection_customizer(Box::new(TestConnectionCustomizer))
700 .build(manager)
701 .unwrap();
702
703 let mut conn = pool.get().unwrap();
704
705 crate::sql_query(
706 "CREATE TABLE IF NOT EXISTS users (id SERIAL PRIMARY KEY, name TEXT NOT NULL)",
707 )
708 .execute(&mut conn)
709 .unwrap();
710
711 crate::insert_into(users::table)
712 .values(users::name.eq("John"))
713 .execute(&mut conn)
714 .unwrap();
715
716 std::mem::drop(conn);
717
718 let mut conn2 = pool.get().unwrap();
719
720 let user_count = users::table.count().get_result::<i64>(&mut conn2).unwrap();
721 assert_eq!(user_count, 1);
722 }
723}