#![warn(missing_docs)]
use std::fmt::Debug;
use crate::schema::Value;
mod filters;
pub use filters::*;
#[derive(Debug, PartialEq, Clone, Copy)]
pub enum FilterType {
Eq,
Neq,
In,
Gt,
Lt,
Gte,
Lte,
Or,
And,
Like,
ILike,
Not,
Between,
SQL,
}
impl FilterType {
pub(crate) fn to_sql(&self) -> &'static str {
match self {
FilterType::Eq => "=",
FilterType::SQL => "",
FilterType::Neq => "!=",
FilterType::In => "IN",
FilterType::Gt => ">",
FilterType::Lt => "<",
FilterType::Gte => ">=",
FilterType::Lte => "<=",
FilterType::Or => "OR",
FilterType::And => "AND",
FilterType::Like => "LIKE",
FilterType::ILike => "ILIKE",
FilterType::Not => "NOT",
FilterType::Between => "BETWEEN",
}
}
}
#[derive(Debug)]
pub struct Filter {
pub column_one: (String, String),
pub value: Option<Value>,
pub column_two: Option<(String, String)>,
pub filter_type: FilterType,
}
#[derive(Debug)]
pub struct SqlFilter {
pub sql: String,
}
#[derive(Debug)]
pub struct OrFilter {
pub(crate) filter1: Box<dyn Filtered>,
pub(crate) filter2: Box<dyn Filtered>,
}
#[derive(Debug)]
pub struct AndFilter {
pub(crate) filter1: Box<dyn Filtered>,
pub(crate) filter2: Box<dyn Filtered>,
}
#[derive(Debug)]
pub struct NotFilter {
pub(crate) filter: Box<dyn Filtered>,
}
#[derive(Debug)]
pub struct ArrayFilter {
pub(crate) column1: Option<(String, String)>,
pub(crate) values: Option<Vec<Value>>,
pub(crate) _column2: Option<(String, String)>,
pub(crate) in_array: bool,
}
pub trait Filtered: Debug + Send + Sync {
fn value(&self) -> Option<&Value> {
None
}
fn column_one(&self) -> Option<&(String, String)>;
fn column_two(&self) -> Option<&(String, String)> {
None
}
fn filter_type(&self) -> FilterType;
fn is_or_filter(&self) -> bool {
false
}
fn is_and_filter(&self) -> bool {
false
}
fn filter1(&self) -> Option<&dyn Filtered>;
fn filter2(&self) -> Option<&dyn Filtered> {
None
}
fn array_values(&self) -> Option<&Vec<Value>> {
None
}
fn is_in_array(&self) -> Option<bool> {
None
}
fn is_not(&self) -> Option<bool> {
None
}
fn is_sql(&self) -> Option<&String> {
None
}
}
impl Filtered for Filter {
fn value(&self) -> Option<&Value> {
self.value.as_ref()
}
fn column_one(&self) -> Option<&(String, String)> {
Some(&self.column_one)
}
fn column_two(&self) -> Option<&(String, String)> {
self.column_two.as_ref()
}
fn filter_type(&self) -> FilterType {
self.filter_type
}
fn filter1(&self) -> Option<&dyn Filtered> {
None
}
}
impl Filtered for SqlFilter {
fn array_values(&self) -> Option<&Vec<Value>> {
None
}
fn column_one(&self) -> Option<&(String, String)> {
None
}
fn column_two(&self) -> Option<&(String, String)> {
None
}
fn filter1(&self) -> Option<&dyn Filtered> {
None
}
fn filter2(&self) -> Option<&dyn Filtered> {
None
}
fn filter_type(&self) -> FilterType {
FilterType::SQL
}
fn is_and_filter(&self) -> bool {
false
}
fn is_in_array(&self) -> Option<bool> {
None
}
fn is_not(&self) -> Option<bool> {
None
}
fn is_or_filter(&self) -> bool {
false
}
fn value(&self) -> Option<&Value> {
None
}
fn is_sql(&self) -> Option<&String> {
Some(&self.sql)
}
}
impl Filtered for OrFilter {
fn column_one(&self) -> Option<&(String, String)> {
None
}
fn filter_type(&self) -> FilterType {
FilterType::Or
}
fn filter1(&self) -> Option<&dyn Filtered> {
Some(&*self.filter1)
}
fn filter2(&self) -> Option<&dyn Filtered> {
Some(&*self.filter2)
}
fn is_or_filter(&self) -> bool {
true
}
}
impl Filtered for AndFilter {
fn column_one(&self) -> Option<&(String, String)> {
None
}
fn filter1(&self) -> Option<&dyn Filtered> {
Some(&*self.filter1)
}
fn filter2(&self) -> Option<&dyn Filtered> {
Some(&*self.filter2)
}
fn filter_type(&self) -> FilterType {
FilterType::And
}
fn is_and_filter(&self) -> bool {
true
}
}
impl Filtered for ArrayFilter {
fn column_one(&self) -> Option<&(String, String)> {
self.column1.as_ref()
}
fn column_two(&self) -> Option<&(String, String)> {
self._column2.as_ref()
}
fn filter_type(&self) -> FilterType {
FilterType::In
}
fn filter1(&self) -> Option<&dyn Filtered> {
None
}
fn array_values(&self) -> Option<&Vec<Value>> {
self.values.as_ref()
}
fn is_in_array(&self) -> Option<bool> {
Some(self.in_array)
}
}
impl Filtered for NotFilter {
fn column_one(&self) -> Option<&(String, String)> {
None
}
fn filter_type(&self) -> FilterType {
FilterType::Not
}
fn filter1(&self) -> Option<&dyn Filtered> {
Some(&*self.filter)
}
fn is_not(&self) -> Option<bool> {
Some(true)
}
}
impl Default for Filter {
fn default() -> Self {
Filter {
value: Some(Value::Null),
filter_type: FilterType::Eq,
column_one: ("".to_string(), "".to_string()),
column_two: None,
}
}
}