1use crate::{Driver, Error, Executor, Result};
2use std::{
3 borrow::Cow,
4 future::{self, Future},
5};
6use url::Url;
7
8pub trait Connection: Executor {
18 fn sanitize_url(_driver: &Self::Driver, mut url: Cow<'static, str>) -> Result<Url>
20 where
21 Self: Sized,
22 {
23 let mut in_memory = false;
24 if let Some((scheme, host)) = url.split_once("://")
25 && host.starts_with(":memory:")
26 {
27 url = format!("{scheme}://localhost{}", &host[8..]).into();
28 in_memory = true;
29 }
30 let mut result = Url::parse(&url)?;
31 if in_memory {
32 result.query_pairs_mut().append_pair("mode", "memory");
33 }
34 let names = <Self::Driver as Driver>::NAME;
35 'prefix: {
36 for name in names {
37 let prefix = format!("{}://", name);
38 if url.starts_with(&prefix) {
39 break 'prefix prefix;
40 }
41 }
42 let error = Error::msg(format!(
43 "Connection URL must start with: {}",
44 names.join(", ")
45 ));
46 log::error!("{:#}", error);
47 return Err(error);
48 };
49 Ok(result)
50 }
51
52 fn connect(
57 driver: &Self::Driver,
58 url: Cow<'static, str>,
59 ) -> impl Future<Output = Result<<Self::Driver as Driver>::Connection>> + Send
60 where
61 Self: Sized;
62
63 fn begin(
67 &mut self,
68 ) -> impl Future<Output = Result<<Self::Driver as Driver>::Transaction<'_>>> + Send;
69
70 fn disconnect(self) -> impl Future<Output = Result<()>> + Send
72 where
73 Self: Sized,
74 {
75 future::ready(Ok(()))
76 }
77}
78
79impl<S: Connection> Connection for &mut S {
80 fn connect(
81 driver: &Self::Driver,
82 url: Cow<'static, str>,
83 ) -> impl Future<Output = Result<<Self::Driver as Driver>::Connection>> + Send
84 where
85 Self: Sized,
86 {
87 S::connect(driver, url)
88 }
89
90 fn begin(
91 &mut self,
92 ) -> impl Future<Output = Result<<Self::Driver as Driver>::Transaction<'_>>> + Send {
93 (**self).begin()
94 }
95
96 fn disconnect(self) -> impl Future<Output = Result<()>> + Send
97 where
98 Self: Sized,
99 {
100 future::ready(Err(Error::msg(
101 "Cannot disconnect using `&mut Connection`, use the actual object.",
102 )))
103 }
104}