1use crate::{Driver, Error, Executor, Result, truncate_long};
2use anyhow::Context;
3use std::{
4 borrow::Cow,
5 future::{self, Future},
6};
7use url::Url;
8
9pub trait Connection: Executor {
19 fn sanitize_url(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 context = || format!("While trying to connect to `{}`", truncate_long!(url));
31 let mut result = Url::parse(&url).with_context(context)?;
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 = Error::msg(format!(
44 "Connection URL must start with: {}",
45 names.join(", ")
46 ))
47 .context(context());
48 log::error!("{:#}", error);
49 return Err(error);
50 };
51 Ok(result)
52 }
53
54 fn connect(
59 url: Cow<'static, str>,
60 ) -> impl Future<Output = Result<<Self::Driver as Driver>::Connection>>
61 where
62 Self: Sized;
63
64 fn begin(&mut self) -> impl Future<Output = Result<<Self::Driver as Driver>::Transaction<'_>>>;
68
69 fn disconnect(self) -> impl Future<Output = Result<()>>
71 where
72 Self: Sized,
73 {
74 future::ready(Ok(()))
75 }
76}