use super::connection::SqlConnection;
use async_trait::async_trait;
use connector_interface::{
self as connector,
error::{ConnectorError, ErrorKind},
Connection, Connector,
};
use quaint::{
connector::{ExternalConnector, IsolationLevel, Transaction},
prelude::{Queryable as QuaintQueryable, *},
};
use std::sync::Arc;
pub struct Js {
connector: DriverAdapter,
connection_info: ConnectionInfo,
features: psl::PreviewFeatures,
}
impl Js {
pub async fn new(
connector: Arc<dyn ExternalConnector>,
features: psl::PreviewFeatures,
) -> connector_interface::Result<Self> {
let external_conn_info = connector.get_connection_info().await.map_err(|e| match e.kind() {
&quaint::error::ErrorKind::ExternalError(id) => ConnectorError::from_kind(ErrorKind::ExternalError(id)),
_ => ConnectorError::from_kind(ErrorKind::InvalidDriverAdapter(
"Error while calling getConnectionInfo()".into(),
)),
})?;
Ok(Js {
connector: DriverAdapter { connector },
features,
connection_info: ConnectionInfo::External(external_conn_info),
})
}
}
#[async_trait]
impl Connector for Js {
async fn get_connection<'a>(&'a self) -> connector::Result<Box<dyn Connection + Send + Sync + 'static>> {
super::catch(&self.connection_info, async move {
let sql_conn = SqlConnection::new(self.connector.clone(), &self.connection_info, self.features);
Ok(Box::new(sql_conn) as Box<dyn Connection + Send + Sync + 'static>)
})
.await
}
fn name(&self) -> &'static str {
"js"
}
fn should_retry_on_transient_error(&self) -> bool {
false
}
}
#[derive(Clone)]
pub struct DriverAdapter {
connector: Arc<dyn ExternalConnector>,
}
#[async_trait]
impl QuaintQueryable for DriverAdapter {
async fn query(&self, q: Query<'_>) -> quaint::Result<quaint::prelude::ResultSet> {
self.connector.query(q).await
}
async fn query_raw(&self, sql: &str, params: &[Value<'_>]) -> quaint::Result<quaint::prelude::ResultSet> {
self.connector.query_raw(sql, params).await
}
async fn query_raw_typed(&self, sql: &str, params: &[Value<'_>]) -> quaint::Result<quaint::prelude::ResultSet> {
self.connector.query_raw_typed(sql, params).await
}
async fn execute(&self, q: Query<'_>) -> quaint::Result<u64> {
self.connector.execute(q).await
}
async fn execute_raw(&self, sql: &str, params: &[Value<'_>]) -> quaint::Result<u64> {
self.connector.execute_raw(sql, params).await
}
async fn execute_raw_typed(&self, sql: &str, params: &[Value<'_>]) -> quaint::Result<u64> {
self.connector.execute_raw_typed(sql, params).await
}
async fn raw_cmd(&self, cmd: &str) -> quaint::Result<()> {
self.connector.raw_cmd(cmd).await
}
async fn version(&self) -> quaint::Result<Option<String>> {
self.connector.version().await
}
fn is_healthy(&self) -> bool {
self.connector.is_healthy()
}
async fn set_tx_isolation_level(&self, isolation_level: IsolationLevel) -> quaint::Result<()> {
self.connector.set_tx_isolation_level(isolation_level).await
}
fn requires_isolation_first(&self) -> bool {
self.connector.requires_isolation_first()
}
}
#[async_trait]
impl TransactionCapable for DriverAdapter {
async fn start_transaction<'a>(
&'a self,
isolation: Option<IsolationLevel>,
) -> quaint::Result<Box<dyn Transaction + 'a>> {
self.connector.start_transaction(isolation).await
}
}