use crate::Error;
use futures_core::future::BoxFuture;
use rbs::value::map::ValueMap;
use rbs::Value;
use std::any::Any;
use std::fmt::{Debug, Display, Formatter};
use std::ops::{Deref, DerefMut};
pub trait Driver: Debug + Sync + Send {
fn name(&self) -> &str;
fn connect(&self, url: &str) -> BoxFuture<Result<Box<dyn Connection>, Error>>;
fn connect_opt<'a>(
&'a self,
opt: &'a dyn ConnectOptions,
) -> BoxFuture<'a,Result<Box<dyn Connection>, Error>>;
fn default_option(&self) -> Box<dyn ConnectOptions>;
}
impl Driver for Box<dyn Driver> {
fn name(&self) -> &str {
self.deref().name()
}
fn connect(&self, url: &str) -> BoxFuture<Result<Box<dyn Connection>, Error>> {
self.deref().connect(url)
}
fn connect_opt<'a>(
&'a self,
opt: &'a dyn ConnectOptions,
) -> BoxFuture<'a,Result<Box<dyn Connection>, Error>> {
self.deref().connect_opt(opt)
}
fn default_option(&self) -> Box<dyn ConnectOptions> {
self.deref().default_option()
}
}
#[derive(Debug, Default, serde::Serialize, serde::Deserialize, Eq, PartialEq)]
pub struct ExecResult {
pub rows_affected: u64,
pub last_insert_id: Value,
}
impl Display for ExecResult {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
struct DisplayBox<'a> {
inner: &'a Value,
}
impl<'a> Debug for DisplayBox<'a> {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
std::fmt::Display::fmt(&self.inner, f)
}
}
f.debug_map()
.key(&"rows_affected")
.value(&self.rows_affected)
.key(&"last_insert_id")
.value(&DisplayBox {
inner: &self.last_insert_id,
})
.finish()
}
}
pub trait Connection: Send {
fn get_rows(
&mut self,
sql: &str,
params: Vec<Value>,
) -> BoxFuture<Result<Vec<Box<dyn Row>>, Error>>;
fn get_values(
&mut self,
sql: &str,
params: Vec<Value>,
) -> BoxFuture<Result<Vec<Value>, Error>> {
let v = self.get_rows(sql, params);
Box::pin(async move {
let v = v.await?;
let mut rows = Vec::with_capacity(v.len());
for mut x in v {
let md = x.meta_data();
let mut m = ValueMap::with_capacity(md.column_len());
for mut i in 0..md.column_len() {
i = md.column_len() - i - 1;
let n = md.column_name(i);
m.insert(Value::String(n), x.get(i)?);
}
rows.push(Value::Map(m));
}
Ok(rows)
})
}
fn exec(&mut self, sql: &str, params: Vec<Value>) -> BoxFuture<Result<ExecResult, Error>>;
fn ping(&mut self) -> BoxFuture<Result<(), Error>>;
fn close(&mut self) -> BoxFuture<Result<(), Error>>;
fn begin(&mut self) -> BoxFuture<Result<(), Error>> {
Box::pin(async {
_ = self.exec("begin", vec![]).await?;
Ok(())
})
}
fn commit(&mut self) -> BoxFuture<Result<(), Error>> {
Box::pin(async {
_ = self.exec("commit", vec![]).await?;
Ok(())
})
}
fn rollback(&mut self) -> BoxFuture<Result<(), Error>> {
Box::pin(async {
_ = self.exec("rollback", vec![]).await?;
Ok(())
})
}
}
impl Connection for Box<dyn Connection> {
fn get_rows(
&mut self,
sql: &str,
params: Vec<Value>,
) -> BoxFuture<Result<Vec<Box<dyn Row>>, Error>> {
self.deref_mut().get_rows(sql, params)
}
fn get_values(
&mut self,
sql: &str,
params: Vec<Value>,
) -> BoxFuture<Result<Vec<Value>, Error>> {
self.deref_mut().get_values(sql, params)
}
fn exec(&mut self, sql: &str, params: Vec<Value>) -> BoxFuture<Result<ExecResult, Error>> {
self.deref_mut().exec(sql, params)
}
fn ping(&mut self) -> BoxFuture<Result<(), Error>> {
self.deref_mut().ping()
}
fn close(&mut self) -> BoxFuture<Result<(), Error>> {
self.deref_mut().close()
}
fn begin(&mut self) -> BoxFuture<Result<(), Error>> {
self.deref_mut().begin()
}
fn rollback(&mut self) -> BoxFuture<Result<(), Error>> {
self.deref_mut().rollback()
}
fn commit(&mut self) -> BoxFuture<Result<(), Error>> {
self.deref_mut().commit()
}
}
pub trait Row: 'static + Send + Debug {
fn meta_data(&self) -> Box<dyn MetaData>;
fn get(&mut self, i: usize) -> Result<Value, Error>;
}
pub trait MetaData: Debug {
fn column_len(&self) -> usize;
fn column_name(&self, i: usize) -> String;
fn column_type(&self, i: usize) -> String;
}
pub trait ConnectOptions: Any + Send + Sync + Debug + 'static {
fn connect(&self) -> BoxFuture<Result<Box<dyn Connection>, Error>>;
#[inline]
fn set(&mut self, arg: Box<dyn Any>)
where
Self: Sized,
{
*self = *arg.downcast().expect("must be self type!");
}
fn set_uri(&mut self, uri: &str) -> Result<(), Error>;
}
impl dyn ConnectOptions {
pub fn downcast_ref<E: ConnectOptions>(&self) -> Option<&E> {
let v = unsafe {
std::mem::transmute_copy::<&dyn ConnectOptions, &E>(&self)
};
Some(v)
}
pub fn downcast_ref_mut<E: ConnectOptions>(&mut self) -> Option<&mut E> {
let v = unsafe {
std::mem::transmute_copy::<&mut dyn ConnectOptions, &mut E>(&self)
};
Some(v)
}
}
pub trait Placeholder {
fn exchange(&self, sql: &str) -> String;
}