use crate::{ColumnExt, Parameters};
use std::collections::HashMap;
use std::fmt;
use tokio_postgres::types::ToSql;
use tracing::*;
#[derive(Debug)]
pub enum WrapperError {
OrderBy,
}
impl std::error::Error for WrapperError {}
impl WrapperError {
pub fn to_string(&self) -> String {
match self {
WrapperError::OrderBy => "根据不同的元素返回响应的字符串信息 for OrderBy".to_string(),
}
}
}
impl fmt::Display for WrapperError {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match self {
WrapperError::OrderBy => write!(f, "Error: OrderBy"),
}
}
}
#[derive(Clone)]
pub struct Wrapper<'a> {
pub where_sql: Vec<String>,
pub args: Vec<&'a (dyn ToSql + Sync)>,
pub formats: HashMap<String, String>,
pub limit: Option<u64>,
pub page_size: u64,
pub page_no: u64,
pub order_by: &'a str,
pub recoder_field: Vec<&'a str>,
pub desc: bool,
}
fn format_where_sql(temp_where: String, args_number: u32) -> (String, u32) {
match temp_where.find("#args") {
Some(_r) => {
let args_number_str = format!("${}", args_number);
let result = temp_where.replacen("#args", args_number_str.as_str(), 1);
let args_numbers = args_number + 1;
let args_number_result = format_where_sql(result, args_numbers);
args_number_result
}
None => (temp_where, args_number),
}
}
pub fn check_order_by(order_by: &str) -> bool {
let temp = order_by.to_string();
let jh_index = temp.find("--");
if jh_index.is_some() {
return false;
}
let fh_index = temp.find(";");
if fh_index.is_some() {
return false;
}
return true;
}
impl<'a> Wrapper<'a> {
pub fn new() -> Self {
Self {
where_sql: Vec::with_capacity(200),
args: Vec::with_capacity(200),
formats: Default::default(),
limit: None,
page_size: 20,
page_no: 0,
order_by: "",
desc: false,
recoder_field: Vec::new(),
}
}
pub fn eq<T>(mut self, column: &dyn ColumnExt, obj: &'a T) -> Self
where
T: ToSql + Sync,
{
let column_name = column.get();
let s = format!(" \"{}\" = #args ", column_name);
self.where_sql.push(s);
self.args.push(obj);
self
}
pub fn not_eq<T>(mut self, column: &dyn ColumnExt, obj: &'a T) -> Self
where
T: ToSql + Sync,
{
let column_name = column.get();
let s = format!(" \"{}\" <> #args ", column_name);
self.where_sql.push(s);
self.args.push(obj);
self
}
pub fn is_null<T>(mut self, column: &dyn ColumnExt) -> Self
where
T: ToSql + Sync,
{
let column_name = column.get();
let s = format!(" \"{}\" is NULL ", column_name);
self.where_sql.push(s);
self
}
pub fn is_not_null<T>(mut self, column: &dyn ColumnExt) -> Self
where
T: ToSql + Sync,
{
let column_name = column.get();
let s = format!(" \"{}\" is not NULL ", column_name);
self.where_sql.push(s);
self
}
pub fn between<T>(mut self, column: &dyn ColumnExt, min: &'a T, max: &'a T) -> Self
where
T: ToSql + Sync,
{
let column_name = column.get();
let s = format!(" \"{}\" between #args AND #args ", column_name);
self.where_sql.push(s);
self.args.push(min);
self.args.push(max);
self
}
pub fn not_between<T>(mut self, column: &dyn ColumnExt, min: &'a T, max: &'a T) -> Self
where
T: ToSql + Sync,
{
let column_name = column.get();
let s = format!(" not between \"{}\" #args AND #args ", column_name);
self.where_sql.push(s);
self.args.push(min);
self.args.push(max);
self
}
pub fn like<T>(mut self, column: &dyn ColumnExt, obj: &'a T) -> Self
where
T: ToSql + Sync,
{
let column_name = column.get();
let s = format!(" \"{}\" like #args ", column_name);
self.where_sql.push(s);
self.args.push(obj);
self
}
pub fn set_in<T>(mut self, column: &dyn ColumnExt, obj: &'a T) -> Self
where
T: ToSql + Sync,
{
let column_name = column.get();
let s = format!(" \"{}\" in (#args) ", column_name);
self.where_sql.push(s);
self.args.push(obj);
self
}
pub fn gt<T>(mut self, column: &dyn ColumnExt, obj: &'a T) -> Self
where
T: ToSql + Sync,
{
let column_name = column.get();
let s = format!(" \"{}\" > #args ", column_name);
self.where_sql.push(s);
self.args.push(obj);
self
}
pub fn ge<T>(mut self, column: &dyn ColumnExt, obj: &'a T) -> Self
where
T: ToSql + Sync,
{
let column_name = column.get();
let s = format!(" \"{}\" >= #args ", column_name);
self.where_sql.push(s);
self.args.push(obj);
self
}
pub fn lt<T>(mut self, column: &dyn ColumnExt, obj: &'a T) -> Self
where
T: ToSql + Sync,
{
let column_name = column.get();
let s = format!(" \"{}\" < #args ", column_name);
self.where_sql.push(s);
self.args.push(obj);
self
}
pub fn le<T>(mut self, column: &dyn ColumnExt, obj: &'a T) -> Self
where
T: ToSql + Sync,
{
let column_name = column.get();
let s = format!(" \"{}\" <= #args ", column_name);
self.where_sql.push(s);
self.args.push(obj);
self
}
pub fn limit(mut self, limit: u64) -> Self {
self.limit = Some(limit);
self
}
pub fn set_pages(mut self, page_no: u64, page_size: u64) -> Self {
self.page_no = page_no;
self.page_size = page_size;
self
}
pub fn set_order_by(mut self, order_by: &'a str, desc: bool) -> Result<Self, WrapperError> {
if !check_order_by(order_by) {
return Err(WrapperError::OrderBy);
}
self.order_by = order_by;
self.desc = desc;
Ok(self)
}
pub fn set_order_by_column_ext(mut self, order_by: &dyn ColumnExt, desc: bool) -> Self {
self.order_by = order_by.get();
self.desc = desc;
self
}
pub fn get_order_by(self) -> Option<String> {
if self.order_by.is_empty() {
return None;
} else {
let order_by = if self.desc {
format!(" ORDER BY {} DESC ", self.order_by)
} else {
format!(" ORDER BY {} ASC ", self.order_by)
};
return Some(order_by);
}
}
pub fn get_page_info(self) -> (String, u64, u64, u64) {
debug!(
"get_page_info: page_no {},page_size {}",
self.page_no, self.page_size
);
let page_no = if self.page_no < 1 { 1 } else { self.page_no };
let limit = (page_no - 1) * self.page_size;
let limit_str = format!(" LIMIT {} OFFSET {}", self.page_size, limit);
(limit_str, limit, page_no, self.page_size)
}
pub fn build(self, args_number: u32) -> Result<(String, Vec<&'a (dyn ToSql + Sync)>), String> {
let mut args_number = args_number;
let mut temp_where_sql = Vec::new();
for mut temp_where in self.where_sql.iter() {
let (wheresql, temp_args_number) =
format_where_sql((&mut temp_where).to_string(), args_number);
args_number = temp_args_number;
temp_where_sql.push(wheresql);
}
let sql = temp_where_sql.join(" AND ");
let args = self.args;
return Ok((sql, args));
}
pub fn set_recoder_field(mut self, column: &dyn ColumnExt) -> Self {
let column_name = column.get();
self.recoder_field.push(column_name);
self
}
pub fn get_recoder_field<T>(self) -> String
where
T: Parameters,
{
if self.recoder_field.len() == 0 {
T::get_field_list()
} else {
self.recoder_field.join(",")
}
}
pub fn in_array_string(mut self, column: &dyn ColumnExt, obj: &Vec<String>) -> Self
{
let column_name = column.get();
let array_str = obj.iter().map(|s| format!("'{}'", s)).collect::<Vec<String>>().join(", ");
let s = format!(" \"{}\" in ({}) ", column_name,array_str);
self.where_sql.push(s);
self
}
}