1#![doc = include_str!("../README.md")]
2
3use std::sync::Arc;
4
5mod connection;
6mod pool;
7pub mod prelude;
8pub(crate) mod span;
9mod transaction;
10
11#[cfg(feature = "postgres")]
12pub mod postgres;
13
14#[cfg(feature = "sqlite")]
15pub mod sqlite;
16
17#[cfg(feature = "mysql")]
18pub mod mysql;
19
20#[derive(Debug, Default)]
23struct Attributes {
24 name: Option<String>,
25 host: Option<String>,
26 port: Option<u16>,
27 database: Option<String>,
28}
29
30#[derive(Debug)]
35pub struct PoolBuilder<DB: sqlx::Database> {
36 pool: sqlx::Pool<DB>,
37 attributes: Attributes,
38}
39
40#[cfg(feature = "postgres")]
43impl From<sqlx::Pool<sqlx::Postgres>> for PoolBuilder<sqlx::Postgres> {
44 fn from(pool: sqlx::Pool<sqlx::Postgres>) -> Self {
46 use sqlx::ConnectOptions;
47
48 let url = pool.connect_options().to_url_lossy();
49 let attributes = Attributes {
50 name: None,
51 host: url.host_str().map(String::from),
52 port: url.port(),
53 database: url
54 .path_segments()
55 .and_then(|mut segments| segments.next().map(String::from)),
56 };
57 Self { pool, attributes }
58 }
59}
60
61#[cfg(feature = "sqlite")]
62impl From<sqlx::Pool<sqlx::Sqlite>> for PoolBuilder<sqlx::Sqlite> {
63 fn from(pool: sqlx::Pool<sqlx::Sqlite>) -> Self {
65 let attributes = Attributes {
66 name: None,
67 host: pool
68 .connect_options()
69 .get_filename()
70 .to_str()
71 .map(String::from),
72 port: None,
73 database: None,
74 };
75 Self { pool, attributes }
76 }
77}
78
79#[cfg(feature = "mysql")]
80impl From<sqlx::Pool<sqlx::MySql>> for PoolBuilder<sqlx::MySql> {
81 fn from(pool: sqlx::Pool<sqlx::MySql>) -> Self {
83 use sqlx::ConnectOptions;
84
85 let url = pool.connect_options().to_url_lossy();
86 let attributes = Attributes {
87 name: None,
88 host: url.host_str().map(String::from),
89 port: url.port(),
90 database: url
91 .path_segments()
92 .and_then(|mut segments| segments.next().map(String::from)),
93 };
94 Self { pool, attributes }
95 }
96}
97
98impl<DB: sqlx::Database> PoolBuilder<DB> {
99 pub fn with_name(mut self, name: impl Into<String>) -> Self {
101 self.attributes.name = Some(name.into());
102 self
103 }
104
105 pub fn with_database(mut self, database: impl Into<String>) -> Self {
107 self.attributes.database = Some(database.into());
108 self
109 }
110
111 pub fn with_host(mut self, host: impl Into<String>) -> Self {
113 self.attributes.host = Some(host.into());
114 self
115 }
116
117 pub fn with_port(mut self, port: u16) -> Self {
119 self.attributes.port = Some(port);
120 self
121 }
122
123 pub fn build(self) -> Pool<DB> {
125 Pool {
126 inner: self.pool,
127 attributes: Arc::new(self.attributes),
128 }
129 }
130}
131
132#[derive(Debug)]
136pub struct Pool<DB>
137where
138 DB: sqlx::Database,
139{
140 inner: sqlx::Pool<DB>,
141 attributes: Arc<Attributes>,
142}
143
144impl<DB> Clone for Pool<DB>
145where
146 DB: sqlx::Database,
147{
148 fn clone(&self) -> Self {
149 Self {
150 inner: self.inner.clone(),
151 attributes: self.attributes.clone(),
152 }
153 }
154}
155
156impl<DB> From<sqlx::Pool<DB>> for Pool<DB>
157where
158 DB: sqlx::Database,
159 PoolBuilder<DB>: From<sqlx::Pool<DB>>,
160{
161 fn from(inner: sqlx::Pool<DB>) -> Self {
163 PoolBuilder::from(inner).build()
164 }
165}
166
167impl<DB> Pool<DB>
168where
169 DB: sqlx::Database,
170{
171 pub async fn begin<'c>(&'c self) -> Result<Transaction<'c, DB>, sqlx::Error> {
175 self.inner.begin().await.map(|inner| Transaction {
176 inner,
177 attributes: self.attributes.clone(),
178 })
179 }
180
181 pub async fn try_begin<'c>(&'c self) -> Result<Option<Transaction<'c, DB>>, sqlx::Error> {
185 self.inner.try_begin().await.map(|t| {
186 t.map(|inner| Transaction {
187 inner,
188 attributes: self.attributes.clone(),
189 })
190 })
191 }
192
193 pub async fn acquire(&self) -> Result<PoolConnection<DB>, sqlx::Error> {
195 self.inner.acquire().await.map(|inner| PoolConnection {
196 attributes: self.attributes.clone(),
197 inner,
198 })
199 }
200}
201
202pub struct Connection<'c, DB>
206where
207 DB: sqlx::Database,
208{
209 inner: &'c mut DB::Connection,
210 attributes: Arc<Attributes>,
211}
212
213impl<'c, DB: sqlx::Database> std::fmt::Debug for Connection<'c, DB> {
214 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
215 f.debug_struct("Connection").finish_non_exhaustive()
216 }
217}
218
219#[derive(Debug)]
223pub struct PoolConnection<DB>
224where
225 DB: sqlx::Database,
226{
227 inner: sqlx::pool::PoolConnection<DB>,
228 attributes: Arc<Attributes>,
229}
230
231#[derive(Debug)]
235pub struct Transaction<'c, DB>
236where
237 DB: sqlx::Database,
238{
239 inner: sqlx::Transaction<'c, DB>,
240 attributes: Arc<Attributes>,
241}