use futures_core::future::BoxFuture;
use std::future::Future;
use crate::any::{Any, AnyConnectOptions};
use crate::connection::{ConnectOptions, Connection};
use crate::error::Error;
use crate::config;
use crate::database::Database;
use crate::sql_str::SqlSafeStr;
use crate::transaction::Transaction;
pub use backend::AnyConnectionBackend;
mod backend;
mod executor;
#[derive(Debug)]
pub struct AnyConnection {
pub(crate) backend: Box<dyn AnyConnectionBackend>,
}
impl AnyConnection {
pub fn backend_name(&self) -> &str {
self.backend.name()
}
pub(crate) fn connect(options: &AnyConnectOptions) -> BoxFuture<'_, crate::Result<Self>> {
Box::pin(async {
let driver = crate::any::driver::from_url(&options.database_url)?;
(*driver.connect)(options, None).await
})
}
#[doc(hidden)]
pub async fn connect_with_driver_config(
url: &str,
driver_config: &config::drivers::Config,
) -> Result<Self, Error>
where
Self: Sized,
{
let options: AnyConnectOptions = url.parse()?;
let driver = crate::any::driver::from_url(&options.database_url)?;
(*driver.connect)(&options, Some(driver_config)).await
}
pub(crate) fn connect_with_db<'a, DB: Database>(
options: &'a AnyConnectOptions,
driver_config: Option<&'a config::drivers::Config>,
) -> BoxFuture<'a, crate::Result<Self>>
where
DB::Connection: AnyConnectionBackend,
<DB::Connection as Connection>::Options:
for<'b> TryFrom<&'b AnyConnectOptions, Error = Error>,
{
let res = TryFrom::try_from(options);
Box::pin(async move {
let mut options: <DB::Connection as Connection>::Options = res?;
if let Some(config) = driver_config {
options = options.__unstable_apply_driver_config(config)?;
}
Ok(AnyConnection {
backend: Box::new(options.connect().await?),
})
})
}
#[cfg(feature = "migrate")]
pub(crate) fn get_migrate(
&mut self,
) -> crate::Result<&mut (dyn crate::migrate::Migrate + Send + 'static)> {
self.backend.as_migrate()
}
}
impl Connection for AnyConnection {
type Database = Any;
type Options = AnyConnectOptions;
fn close(self) -> impl Future<Output = Result<(), Error>> + Send + 'static {
self.backend.close()
}
fn close_hard(self) -> impl Future<Output = Result<(), Error>> + Send + 'static {
self.backend.close()
}
fn ping(&mut self) -> impl Future<Output = Result<(), Error>> + Send + '_ {
self.backend.ping()
}
fn begin(
&mut self,
) -> impl Future<Output = Result<Transaction<'_, Self::Database>, Error>> + Send + '_
where
Self: Sized,
{
Transaction::begin(self, None)
}
fn begin_with(
&mut self,
statement: impl SqlSafeStr,
) -> impl Future<Output = Result<Transaction<'_, Self::Database>, Error>> + Send + '_
where
Self: Sized,
{
Transaction::begin(self, Some(statement.into_sql_str()))
}
fn cached_statements_size(&self) -> usize {
self.backend.cached_statements_size()
}
fn clear_cached_statements(&mut self) -> impl Future<Output = crate::Result<()>> + Send + '_ {
self.backend.clear_cached_statements()
}
fn shrink_buffers(&mut self) {
self.backend.shrink_buffers()
}
#[doc(hidden)]
fn flush(&mut self) -> impl Future<Output = Result<(), Error>> + Send + '_ {
self.backend.flush()
}
#[doc(hidden)]
fn should_flush(&self) -> bool {
self.backend.should_flush()
}
}