use crate::dialect::Dialect;
use crate::row::Row;
use crate::value::Value;
use rustlavel_core::Result;
use std::pin::Pin;
use std::sync::Arc;
pub type BoxFuture<'a, T> = Pin<Box<dyn Future<Output = T> + Send + 'a>>;
#[derive(Debug, Default)]
pub struct QueryResult {
pub rows: Vec<Row>,
pub affected: u64,
pub last_insert_id: Option<i64>,
}
pub trait DriverConnection: Send {
fn query<'a>(
&'a mut self,
sql: &'a str,
params: &'a [Value],
) -> BoxFuture<'a, Result<QueryResult>>;
fn simple_query<'a>(&'a mut self, sql: &'a str) -> BoxFuture<'a, Result<QueryResult>>;
fn is_broken(&self) -> bool;
fn in_transaction(&self) -> bool;
fn close(self: Box<Self>) -> BoxFuture<'static, ()>;
}
pub trait Driver: Send + Sync + 'static {
fn dialect(&self) -> Arc<dyn Dialect>;
fn connect(&self) -> BoxFuture<'_, Result<Box<dyn DriverConnection>>>;
fn describe(&self) -> String;
fn max_connections(&self) -> usize {
10
}
fn generation(&self) -> u64 {
0
}
}
#[cfg(test)]
mod tests {
use super::*;
use crate::dialect::Postgres;
use rustlavel_core::Error;
struct Offline;
impl Driver for Offline {
fn dialect(&self) -> Arc<dyn Dialect> {
Arc::new(Postgres)
}
fn connect(&self) -> BoxFuture<'_, Result<Box<dyn DriverConnection>>> {
Box::pin(async { Err(Error::msg("this driver never connects")) })
}
fn describe(&self) -> String {
"offline://nowhere".into()
}
}
#[tokio::test]
async fn a_driver_can_be_held_without_naming_its_type() {
let driver: Arc<dyn Driver> = Arc::new(Offline);
assert_eq!(driver.dialect().name(), "postgres");
assert_eq!(driver.describe(), "offline://nowhere");
assert_eq!(driver.max_connections(), 10);
assert!(driver.connect().await.is_err());
}
}