1use crate::{Driver, Executor, Result};
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 mut result = Url::parse(&url)?;
32 if in_memory {
33 result.query_pairs_mut().append_pair("mode", "memory");
34 }
35 let names = <Self::Driver as Driver>::NAME;
36 'prefix: {
37 for name in names {
38 let prefix = format!("{}://", name);
39 if url.starts_with(&prefix) {
40 break 'prefix prefix;
41 }
42 }
43 let error = anyhow!("Connection URL must start with: {}", names.join(", "));
44 log::error!("{error:#}");
45 return Err(error);
46 };
47 Ok(result)
48 }
49
50 fn connect(
55 driver: &Self::Driver,
56 url: Cow<'static, str>,
57 ) -> impl Future<Output = Result<<Self::Driver as Driver>::Connection>> + Send
58 where
59 Self: Sized;
60
61 fn begin(
65 &mut self,
66 ) -> impl Future<Output = Result<<Self::Driver as Driver>::Transaction<'_>>> + Send;
67
68 fn disconnect(self) -> impl Future<Output = Result<()>> + Send
70 where
71 Self: Sized,
72 {
73 future::ready(Ok(()))
74 }
75}
76
77impl<S: Connection> Connection for &mut S {
78 fn connect(
79 driver: &Self::Driver,
80 url: Cow<'static, str>,
81 ) -> impl Future<Output = Result<<Self::Driver as Driver>::Connection>> + Send
82 where
83 Self: Sized,
84 {
85 S::connect(driver, url)
86 }
87
88 fn begin(
89 &mut self,
90 ) -> impl Future<Output = Result<<Self::Driver as Driver>::Transaction<'_>>> + Send {
91 (**self).begin()
92 }
93
94 fn disconnect(self) -> impl Future<Output = Result<()>> + Send
95 where
96 Self: Sized,
97 {
98 future::ready(Err(anyhow!(
99 "Cannot disconnect using `&mut Connection`, use the actual object.",
100 )))
101 }
102}