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