use std::collections::{BTreeMap, HashMap, HashSet, LinkedList, VecDeque};
use std::fmt::Display;
use std::hash::Hash;
use async_trait::async_trait;
use serde::de::DeserializeOwned;
use serde::{Serialize, Serializer, Deserialize, Deserializer};
use crate::core::convert::{ResultCodec, StmtConvert};
use crate::core::db::DBExecResult;
use crate::core::db::DriverType;
use crate::core::Error;
use crate::core::Result;
use crate::executor::{ExecutorMut, RBatisConnExecutor, RBatisTxExecutor};
use crate::plugin::page::{IPageRequest, Page, IPage};
use crate::rbatis::Rbatis;
use crate::sql::rule::SqlRule;
use crate::utils::string_util::to_snake_name;
use crate::wrapper::Wrapper;
use std::marker::PhantomData;
use std::ops::{Deref, DerefMut};
use rbson::Bson::Null;
use std::option::Option::Some;
use rbson::Bson;
use rbatis_sql::ops::AsProxy;
pub trait CRUDTable: Send + Sync + Serialize {
fn table_name() -> String {
let type_name = std::any::type_name::<Self>();
let mut name = type_name.to_string();
let names: Vec<&str> = name.split("::").collect();
name = names.get(names.len() - 1).unwrap_or(&"").to_string();
return to_snake_name(&name);
}
fn table_columns() -> String;
fn do_format_column(driver_type: &DriverType, column: &str, data: &mut String) {
let m = Self::formats(driver_type);
let source = m.get(column);
match source {
Some(s) => {
*data = s(&data);
}
_ => {}
}
}
fn make_value_sql_arg(
&self,
db_type: &DriverType,
index: &mut usize,
skips: &[Skip],
) -> Result<(String, String, Vec<rbson::Bson>)> {
let mut value_sql = String::new();
let mut arr = vec![];
let cols = Self::table_columns();
let columns: Vec<&str> = cols.split(",").collect();
let mut map;
match crate::as_bson!(self) {
rbson::Bson::Document(m) => {
map = m;
}
_ => {
return Err(Error::from("[rbatis] arg not an struct or map!"));
}
}
let mut column_sql = String::new();
for column in columns {
let mut do_continue = false;
let column_unpacking = crate::utils::string_util::un_packing_string(column);
for x in skips {
match x {
Skip::Column(skip_column) => {
if column_unpacking.eq(*skip_column) || column.eq(*skip_column) {
do_continue = true;
break;
}
}
_ => {}
}
}
if do_continue {
continue;
}
let v = map.remove(column_unpacking).unwrap_or(rbson::Bson::Null);
for x in skips {
match x {
Skip::Value(skip_value) => {
if v.eq(skip_value) {
do_continue = true;
break;
}
}
_ => {}
}
}
if do_continue {
continue;
}
column_sql = column_sql + column + ",";
let mut data = String::new();
db_type.stmt_convert(*index, &mut data);
Self::do_format_column(db_type, &column_unpacking, &mut data);
value_sql = value_sql
+ data.as_str()
+ ",";
arr.push(v);
*index += 1;
}
column_sql.pop(); value_sql.pop(); return Ok((column_sql, value_sql, arr));
}
fn formats(
driver_type: &crate::core::db::DriverType,
) -> HashMap<String, fn(arg: &str) -> String> {
return HashMap::new();
}
fn get(&self, column: &str) -> rbson::Bson {
let s = rbson::to_bson(self).unwrap_or_default();
match s {
rbson::Bson::Document(d) => {
d.get(column).unwrap_or(&Bson::Null).clone()
}
_ => {
Bson::Null
}
}
}
}
impl<T> CRUDTable for &T where T: CRUDTable {
fn table_name() -> String {
T::table_name()
}
fn table_columns() -> String {
T::table_columns()
}
}
impl<T> CRUDTable for &mut T where T: CRUDTable {
fn table_name() -> String {
T::table_name()
}
fn table_columns() -> String {
T::table_columns()
}
}
impl<T> CRUDTable for Option<T>
where
T: CRUDTable,
{
fn table_name() -> String {
T::table_name()
}
fn table_columns() -> String {
T::table_columns()
}
fn formats(driver_type: &DriverType) -> HashMap<String, fn(arg: &str) -> String> {
T::formats(driver_type)
}
fn make_value_sql_arg(
&self,
db_type: &DriverType,
index: &mut usize,
skips: &[Skip],
) -> Result<(String, String, Vec<rbson::Bson>)> {
if self.is_none() {
return Err(crate::core::Error::from(
"[rbatis] can not call make_sql_arg() for an None table!",
));
}
T::make_value_sql_arg(self.as_ref().unwrap(), db_type, index, skips)
}
}
#[async_trait]
pub trait CRUD {
async fn save_by_wrapper<T,R>(
&self,
table: &T,
w: Wrapper,
skips: &[Skip],
) -> Result<R>
where
T: CRUDTable,R:DeserializeOwned;
async fn save<T>(&self, table: &T, skips: &[Skip]) -> Result<DBExecResult>
where
T: CRUDTable;
async fn save_batch<T>(&self, tables: &[T], skips: &[Skip]) -> Result<DBExecResult>
where
T: CRUDTable;
async fn save_batch_slice<T>(
&self,
tables: &[T],
slice_len: usize,
skips: &[Skip],
) -> Result<DBExecResult>
where
T: CRUDTable;
async fn remove_by_wrapper<T>(&self, w: Wrapper) -> Result<u64>
where
T: CRUDTable;
async fn remove_by_column<T, P>(&self, column: &str, column_value: P) -> Result<u64> where T: CRUDTable, P: Serialize + Send + Sync;
async fn remove_batch_by_column<T, P>(&self, column: &str, column_values: &[P]) -> Result<u64>
where
T: CRUDTable, P: Serialize + Send + Sync;
async fn update_by_wrapper<T>(
&self,
table: &T,
w: Wrapper,
skips: &[Skip],
) -> Result<u64>
where
T: CRUDTable;
async fn update_by_column<T>(&self, column: &str, table: &T) -> Result<u64>
where
T: CRUDTable;
async fn update_batch_by_column<T>(&self, column: &str, tables: &[T]) -> Result<u64>
where
T: CRUDTable;
async fn fetch_by_column<T, P>(&self, column: &str, value: P) -> Result<T>
where
T: CRUDTable + DeserializeOwned, P: Serialize + Send + Sync;
async fn fetch_by_wrapper<T>(&self, w: Wrapper) -> Result<T>
where
T: CRUDTable + DeserializeOwned;
async fn fetch_count<T>(&self) -> Result<u64>
where
T: CRUDTable;
async fn fetch_count_by_wrapper<T>(&self, w: Wrapper) -> Result<u64>
where
T: CRUDTable;
async fn fetch_page_by_wrapper<T>(
&self,
w: Wrapper,
page: &dyn IPageRequest,
) -> Result<Page<T>>
where
T: CRUDTable + DeserializeOwned;
async fn fetch_list<T>(&self) -> Result<Vec<T>>
where
T: CRUDTable + DeserializeOwned;
async fn fetch_list_by_column<T, P>(&self, column: &str, column_values: &[P]) -> Result<Vec<T>>
where
T: CRUDTable + DeserializeOwned, P: Serialize + Send + Sync;
async fn fetch_list_by_wrapper<T>(&self, w: Wrapper) -> Result<Vec<T>>
where
T: CRUDTable + DeserializeOwned;
async fn fetch_page<T>(
&self,
sql: &str,
args: Vec<rbson::Bson>,
page_request: &dyn IPageRequest,
) -> Result<Page<T>>
where
T: DeserializeOwned + Serialize + Send + Sync;
}
#[async_trait]
pub trait CRUDMut: ExecutorMut {
async fn save_by_wrapper<T,R>(
&mut self,
table: &T,
mut w: Wrapper,
skips: &[Skip],
) -> Result<R>
where
T: CRUDTable, R:DeserializeOwned
{
if w.sql.starts_with(crate::sql::TEMPLATE.insert_into.value) {
let res= self.exec(&w.sql, w.args).await?;
return Ok(rbson::from_bson(rbson::to_bson(&res)?)?);
} else {
let driver_type = self.driver_type()?;
let mut new_w = Wrapper::new(&driver_type);
let mut index = 0;
let (columns, column_values, args) = table.make_value_sql_arg(&self.driver_type()?, &mut index, skips)?;
let table_name = choose_dyn_table_name::<T>(&new_w);
new_w = new_w.insert_into(&table_name, &columns, &column_values);
for x in args {
new_w.args.push(x);
}
new_w = new_w.push_wrapper(w);
return self.fetch(&new_w.sql, new_w.args).await;
}
}
async fn save<T>(&mut self, table: &T, skips: &[Skip]) -> Result<DBExecResult>
where
T: CRUDTable,
{
let mut index = 0;
let (columns, values, args) =
table.make_value_sql_arg(&self.driver_type()?, &mut index, skips)?;
let sql = format!(
"{} {} ({}) {} ({})",
crate::sql::TEMPLATE.insert_into.value,
T::table_name(),
columns,
crate::sql::TEMPLATE.values.value,
values
);
return self.exec(sql.as_str(), args).await;
}
async fn save_batch<T>(&mut self, tables: &[T], skips: &[Skip]) -> Result<DBExecResult>
where
T: CRUDTable,
{
if tables.is_empty() {
return Ok(DBExecResult {
rows_affected: 0,
last_insert_id: None,
});
}
let mut value_arr = String::new();
let mut arg_arr = vec![];
let mut column_sql = String::new();
let mut field_index = 0;
for x in tables {
let (columns, values, args) =
x.make_value_sql_arg(&self.driver_type()?, &mut field_index, skips)?;
if column_sql.is_empty() {
column_sql = columns;
}
value_arr = value_arr + format!("({}),", values).as_str();
for x in args {
arg_arr.push(x);
}
}
value_arr.pop(); let sql = format!(
"{} {} ({}) {} {}",
crate::sql::TEMPLATE.insert_into.value,
T::table_name(),
column_sql,
crate::sql::TEMPLATE.values.value,
value_arr
);
return self.exec(sql.as_str(), arg_arr).await;
}
async fn save_batch_slice<T>(
&mut self,
tables: &[T],
slice_len: usize,
skips: &[Skip],
) -> Result<DBExecResult>
where
T: CRUDTable,
{
if slice_len == 0 || tables.len() <= slice_len {
return self.save_batch(tables, skips).await;
} else {
let mut temp_result = DBExecResult {
rows_affected: 0,
last_insert_id: None,
};
let total = tables.len();
let mut pages = tables.len() / slice_len;
if total % slice_len != 0 {
pages = pages + 1;
}
for page in 0..pages {
let mut temp_len = slice_len * (1 + page);
if temp_len > total {
temp_len = total;
}
let temp = &tables[page * slice_len..temp_len];
let result = self.save_batch(temp, skips).await?;
temp_result.last_insert_id = result.last_insert_id;
temp_result.rows_affected = result.rows_affected + temp_result.rows_affected;
}
return Ok(temp_result);
}
}
async fn remove_by_wrapper<T>(&mut self, w: Wrapper) -> Result<u64>
where
T: CRUDTable,
{
let table_name = choose_dyn_table_name::<T>(&w);
let where_sql = self.driver_type()?.make_where(&w.sql);
let mut sql = String::new();
if let Some(logic) = &self.get_rbatis().logic_plugin {
if w.dml.eq("where") {
sql = logic.create_remove_sql(
&self.driver_type()?,
&table_name,
&T::table_columns(),
&where_sql,
)?;
}
}
if sql.is_empty() {
sql = format!(
"{} {} {}",
crate::sql::TEMPLATE.delete_from.value,
table_name,
&where_sql
);
}
return Ok(self
.exec(sql.as_str(), w.args)
.await?
.rows_affected);
}
async fn remove_by_column<T, P>(&mut self, column: &str, value: P) -> Result<u64>
where
T: CRUDTable, P: Serialize + Send + Sync,
{
let mut sql = String::new();
let driver_type = &self.driver_type()?;
let mut data = String::new();
driver_type.stmt_convert(0, &mut data);
T::do_format_column(&driver_type, column, &mut data);
if let Some(logic) = &self.get_rbatis().logic_plugin {
sql = logic.create_remove_sql(
&driver_type,
T::table_name().as_str(),
&T::table_columns(),
format!(
"{} {} = {}",
crate::sql::TEMPLATE.r#where.value,
column,
data
).as_str(),
)?;
}
if sql.is_empty() {
sql = format!(
"{} {} {} {} = {}",
crate::sql::TEMPLATE.delete_from.value,
T::table_name(),
crate::sql::TEMPLATE.r#where.value,
column,
data
);
}
return Ok(self
.exec(&sql, vec![crate::as_bson!(&value)])
.await?
.rows_affected);
}
async fn remove_batch_by_column<T, P>(&mut self, column: &str, values: &[P]) -> Result<u64>
where
T: CRUDTable, P: Serialize + Send + Sync
{
if values.is_empty() {
return Ok(0);
}
let w = self
.get_rbatis()
.new_wrapper_table::<T>()
.and()
.in_array(column, values);
return self.remove_by_wrapper::<T>(w).await;
}
async fn update_by_wrapper<T>(
&mut self,
table: &T,
w: Wrapper,
skips: &[Skip],
) -> Result<u64>
where
T: CRUDTable,
{
let table_name = choose_dyn_table_name::<T>(&w);
let mut args = vec![];
let mut old_version = rbson::Bson::Null;
let driver_type = &self.driver_type()?;
let columns = T::table_columns();
let columns_vec: Vec<&str> = columns.split(",").collect();
let map;
match crate::as_bson!(table) {
rbson::Bson::Document(m) => {
map = m;
}
_ => {
return Err(Error::from("[rbatis] arg not an struct or map!"));
}
}
let null = rbson::Bson::Null;
let mut sets = String::new();
for column in columns_vec {
let mut is_continue = false;
for x in skips {
match x {
Skip::Column(skip_column) => {
if skip_column.eq(&column) {
is_continue = true;
break;
}
}
_ => {}
}
}
if is_continue {
continue;
}
let mut v = map.get(column).unwrap_or_else(|| &null).clone();
let is_null = v.is_null();
for x in skips {
match x {
Skip::Value(skip_value) => {
if (*skip_value).eq(&v) {
is_continue = true;
break;
}
}
_ => {}
}
}
if is_continue {
continue;
}
let mut data = String::new();
driver_type.stmt_convert(args.len(), &mut data);
T::do_format_column(
&driver_type,
&column,
&mut data,
);
sets.push_str(
format!(
" {} = {},",
column,
data
).as_str(),
);
args.push(v.clone());
}
sets.pop();
let mut wrapper = self.get_rbatis().new_wrapper_table::<T>();
wrapper.sql = format!(
"{} {} {} {} ",
crate::sql::TEMPLATE.update.value,
table_name,
crate::sql::TEMPLATE.set.value,
sets
);
wrapper.args = args;
if !w.sql.is_empty() {
if !wrapper
.sql
.contains(crate::sql::TEMPLATE.r#where.left_right_space)
{
wrapper
.sql
.push_str(crate::sql::TEMPLATE.r#where.left_right_space);
}
wrapper = wrapper.and();
wrapper = wrapper.push_wrapper(w);
}
let rows_affected = self
.exec(wrapper.sql.as_str(), wrapper.args)
.await?
.rows_affected;
return Ok(rows_affected);
}
async fn update_by_column<T>(&mut self, column: &str, table: &T) -> Result<u64>
where
T: CRUDTable
{
let rb = self
.get_rbatis();
let value = table.get(column);
self.update_by_wrapper(
table, rb
.new_wrapper_table::<T>()
.eq(column, value),
&[Skip::Value(Bson::Null), Skip::Column("id"), Skip::Column(column)],
)
.await
}
async fn update_batch_by_column<T>(&mut self, column: &str, args: &[T]) -> Result<u64>
where
T: CRUDTable
{
let mut updates = 0;
for x in args {
updates += self.update_by_column(column, x).await?
}
Ok(updates)
}
async fn fetch_by_wrapper<T>(&mut self, w: Wrapper) -> Result<T>
where
T: CRUDTable + DeserializeOwned,
{
let sql = make_select_sql::<T>(self.get_rbatis(), &T::table_columns(), &w)?;
return self.fetch(sql.as_str(), w.args).await;
}
async fn fetch_count<T>(&mut self) -> Result<u64>
where
T: CRUDTable,
{
let sql = make_select_sql::<T>(self.get_rbatis(), "count(1)", &Wrapper::new(&self.driver_type()?))?;
return self.fetch(sql.as_str(), vec![]).await;
}
async fn fetch_count_by_wrapper<T>(&mut self, w: Wrapper) -> Result<u64>
where
T: CRUDTable,
{
let sql = make_select_sql::<T>(self.get_rbatis(), "count(1)", &w)?;
return self.fetch(sql.as_str(), w.args).await;
}
async fn fetch_by_column<T, P>(&mut self, column: &str, value: P) -> Result<T>
where
T: CRUDTable + DeserializeOwned, P: Serialize + Send + Sync,
{
let w = self.get_rbatis().new_wrapper_table::<T>().eq(&column, value);
return self.fetch_by_wrapper(w).await;
}
async fn fetch_list_by_wrapper<T>(&mut self, w: Wrapper) -> Result<Vec<T>>
where
T: CRUDTable + DeserializeOwned,
{
let sql = make_select_sql::<T>(self.get_rbatis(), &T::table_columns(), &w)?;
return self.fetch(sql.as_str(), w.args).await;
}
async fn fetch_list<T>(&mut self) -> Result<Vec<T>>
where
T: CRUDTable + DeserializeOwned,
{
let rb = self.get_rbatis();
return self.fetch_list_by_wrapper(rb.new_wrapper_table::<T>())
.await;
}
async fn fetch_list_by_column<T, P>(&mut self, column: &str, column_values: &[P]) -> Result<Vec<T>>
where
T: CRUDTable + DeserializeOwned, P: Serialize + Send + Sync,
{
if column_values.is_empty() {
return Ok(vec![]);
}
let w = self.get_rbatis().new_wrapper_table::<T>().in_array(&column, column_values);
return self.fetch_list_by_wrapper(w).await;
}
async fn fetch_page_by_wrapper<T>(
&mut self,
w: Wrapper,
page: &dyn IPageRequest,
) -> Result<Page<T>>
where
T: CRUDTable + DeserializeOwned,
{
let sql = make_select_sql::<T>(self.get_rbatis(), &T::table_columns(), &w)?;
self.fetch_page(sql.as_str(), w.args, page).await
}
async fn fetch_page<T>(
&mut self,
sql: &str,
args: Vec<rbson::Bson>,
page_request: &dyn IPageRequest,
) -> Result<Page<T>>
where
T: DeserializeOwned + Serialize + Send + Sync,
{
let mut page_result = Page::new(page_request.get_page_no(), page_request.get_page_size());
page_result.search_count = page_request.is_search_count();
let (count_sql, sql) = self.get_rbatis().page_plugin.make_page_sql(
&self.driver_type()?,
&sql,
&args,
page_request,
)?;
if page_request.is_search_count() {
let total: Option<u64> = self
.fetch(&count_sql, args.clone())
.await?;
page_result.set_total(total.unwrap_or(0));
page_result.pages = page_result.get_pages();
if page_result.get_total() == 0 {
return Ok(page_result);
}
}
let data: Option<Vec<T>> = self.fetch(sql.as_str(), args).await?;
page_result.set_records(data.unwrap_or(vec![]));
page_result.pages = page_result.get_pages();
return Ok(page_result);
}
}
impl CRUDMut for RBatisConnExecutor<'_> {}
impl CRUDMut for RBatisTxExecutor<'_> {}
fn choose_dyn_table_name<T>(w: &Wrapper) -> String
where
T: CRUDTable,
{
let mut table_name = T::table_name();
let table_name_format = w.formats.get("table_name");
if let Some(table_name_format) = table_name_format {
table_name = table_name_format(&table_name);
}
return table_name;
}
fn make_select_sql<T>(rb: &Rbatis, column: &str, w: &Wrapper) -> Result<String>
where
T: CRUDTable,
{
let driver_type = rb.driver_type()?;
let table_name = choose_dyn_table_name::<T>(w);
Ok(format!(
"{} {} {} {} {}",
crate::sql::TEMPLATE.select.value,
column,
crate::sql::TEMPLATE.from.value,
table_name,
driver_type.make_where(&w.sql)
))
}
#[async_trait]
impl CRUD for Rbatis {
async fn save_by_wrapper<T,R>(&self, table: &T, w: Wrapper, skips: &[Skip]) -> Result<R> where
T: CRUDTable,R:DeserializeOwned {
let mut conn = self.acquire().await?;
conn.save_by_wrapper(table, w, skips).await
}
async fn save<T>(&self, table: &T, skips: &[Skip]) -> Result<DBExecResult> where
T: CRUDTable {
let mut conn = self.acquire().await?;
conn.save(table, skips).await
}
async fn save_batch<T>(&self, tables: &[T], skips: &[Skip]) -> Result<DBExecResult> where
T: CRUDTable {
let mut conn = self.acquire().await?;
conn.save_batch(tables, skips).await
}
async fn save_batch_slice<T>(&self, tables: &[T], slice_len: usize, skips: &[Skip]) -> Result<DBExecResult> where
T: CRUDTable {
let mut conn = self.acquire().await?;
conn.save_batch_slice(tables, slice_len, skips).await
}
async fn remove_by_wrapper<T>(&self, w: Wrapper) -> Result<u64> where
T: CRUDTable {
let mut conn = self.acquire().await?;
conn.remove_by_wrapper::<T>(w).await
}
async fn remove_by_column<T, P>(&self, column: &str, value: P) -> Result<u64> where
T: CRUDTable, P: Serialize + Send + Sync {
let mut conn = self.acquire().await?;
conn.remove_by_column::<T, P>(column, value).await
}
async fn remove_batch_by_column<T, P>(&self, column: &str, values: &[P]) -> Result<u64> where
T: CRUDTable, P: Serialize + Send + Sync {
let mut conn = self.acquire().await?;
conn.remove_batch_by_column::<T, P>(column, values).await
}
async fn update_by_wrapper<T>(&self, table: &T, w: Wrapper, skips: &[Skip]) -> Result<u64> where
T: CRUDTable {
let mut conn = self.acquire().await?;
conn.update_by_wrapper(table, w, skips).await
}
async fn update_by_column<T>(&self, column: &str, table: &T) -> Result<u64> where
T: CRUDTable {
let mut conn = self.acquire().await?;
conn.update_by_column(column, table).await
}
async fn update_batch_by_column<T>(&self, column: &str, args: &[T]) -> Result<u64> where
T: CRUDTable {
let mut conn = self.acquire().await?;
conn.update_batch_by_column::<T>(column, args).await
}
async fn fetch_by_column<T, P>(&self, column: &str, value: P) -> Result<T> where
T: CRUDTable + DeserializeOwned, P: Serialize + Send + Sync {
let mut conn = self.acquire().await?;
conn.fetch_by_column::<T, P>(column, value).await
}
async fn fetch_by_wrapper<T>(&self, w: Wrapper) -> Result<T> where
T: CRUDTable + DeserializeOwned {
let mut conn = self.acquire().await?;
conn.fetch_by_wrapper(w).await
}
async fn fetch_count<T>(&self) -> Result<u64> where
T: CRUDTable {
let mut conn = self.acquire().await?;
conn.fetch_count::<T>().await
}
async fn fetch_count_by_wrapper<T>(&self, w: Wrapper) -> Result<u64> where
T: CRUDTable {
let mut conn = self.acquire().await?;
conn.fetch_count_by_wrapper::<T>(w).await
}
async fn fetch_page_by_wrapper<T>(&self, w: Wrapper, page: &dyn IPageRequest) -> Result<Page<T>> where
T: CRUDTable + DeserializeOwned {
let mut conn = self.acquire().await?;
conn.fetch_page_by_wrapper::<T>(w, page).await
}
async fn fetch_list<T>(&self) -> Result<Vec<T>> where
T: CRUDTable + DeserializeOwned {
let mut conn = self.acquire().await?;
conn.fetch_list().await
}
async fn fetch_list_by_column<T, P>(&self, column: &str, column_values: &[P]) -> Result<Vec<T>> where
T: CRUDTable + DeserializeOwned, P: Serialize + Send + Sync {
if column_values.is_empty() {
return Ok(vec![]);
}
let mut conn = self.acquire().await?;
conn.fetch_list_by_column::<T, P>(column, column_values).await
}
async fn fetch_list_by_wrapper<T>(&self, w: Wrapper) -> Result<Vec<T>> where
T: CRUDTable + DeserializeOwned {
let mut conn = self.acquire().await?;
conn.fetch_list_by_wrapper(w).await
}
async fn fetch_page<T>(
&self,
sql: &str,
args: Vec<rbson::Bson>,
page_request: &dyn IPageRequest,
) -> Result<Page<T>>
where
T: DeserializeOwned + Serialize + Send + Sync,
{
let mut conn = self.acquire().await?;
conn.fetch_page(sql, args, page_request).await
}
}
pub enum Skip<'a> {
Column(&'a str),
Value(rbson::Bson),
}
impl<'a> Skip<'a> {
pub fn value<T>(arg: T) -> Self where T: Serialize {
Self::Value(crate::as_bson!(&arg))
}
}
pub trait TableColumnProvider: Send + Sync {
fn table_name() -> String;
fn table_columns() -> String;
}
pub struct DynTableColumn<T: CRUDTable, P: TableColumnProvider> {
pub inner: T,
pub p: PhantomData<P>,
}
impl<T, P> Serialize for DynTableColumn<T, P> where T: CRUDTable, P: TableColumnProvider {
fn serialize<S>(&self, serializer: S) -> std::result::Result<<S as Serializer>::Ok, <S as Serializer>::Error> where
S: Serializer {
T::serialize(&self.inner, serializer)
}
}
impl<'de, T, P> Deserialize<'de> for DynTableColumn<T, P> where T: CRUDTable + DeserializeOwned, P: TableColumnProvider {
fn deserialize<D>(deserializer: D) -> std::result::Result<Self, <D as Deserializer<'de>>::Error> where
D: Deserializer<'de> {
let result = T::deserialize(deserializer)?;
return Ok(DynTableColumn {
inner: result,
p: Default::default(),
});
}
}
impl<T, P> Deref for DynTableColumn<T, P> where T: CRUDTable, P: TableColumnProvider {
type Target = T;
fn deref(&self) -> &Self::Target {
&self.inner
}
}
impl<T, P> DerefMut for DynTableColumn<T, P> where T: CRUDTable, P: TableColumnProvider {
fn deref_mut(&mut self) -> &mut Self::Target {
&mut self.inner
}
}
impl<T, P> CRUDTable for DynTableColumn<T, P> where T: CRUDTable, P: TableColumnProvider {
fn table_name() -> String {
P::table_name()
}
fn table_columns() -> String {
P::table_columns()
}
fn do_format_column(driver_type: &DriverType, column: &str, data: &mut String) {
T::do_format_column(driver_type, column, data)
}
fn make_value_sql_arg(
&self,
db_type: &DriverType,
index: &mut usize,
skips: &[Skip],
) -> Result<(String, String, Vec<rbson::Bson>)> {
T::make_value_sql_arg(self, db_type, index, skips)
}
fn formats(
driver_type: &crate::core::db::DriverType,
) -> HashMap<String, fn(arg: &str) -> String> {
T::formats(driver_type)
}
fn get(&self, column: &str) -> rbson::Bson {
T::get(self, column)
}
}