use crate::{filter::Filter, RelationCompare, RelationField};
#[derive(Clone, PartialEq, Eq, Hash)]
pub struct RelationFilter {
pub field: RelationField,
pub nested_filter: Box<Filter>,
pub condition: RelationCondition,
}
impl std::fmt::Debug for RelationFilter {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.debug_struct("RelationFilter")
.field("field", &format!("{}", self.field))
.field("nested_filter", &self.nested_filter)
.field("condition", &self.condition)
.finish()
}
}
impl RelationFilter {
pub fn invert(self, invert: bool) -> Self {
if invert {
let is_to_one = !self.field.is_list();
Self {
field: self.field,
nested_filter: self.nested_filter,
condition: self.condition.invert(invert, is_to_one),
}
} else {
self
}
}
}
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
pub struct OneRelationIsNullFilter {
pub field: RelationField,
}
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, PartialOrd, Ord)]
pub enum RelationCondition {
EveryRelatedRecord,
AtLeastOneRelatedRecord,
NoRelatedRecord,
ToOneRelatedRecord,
}
impl RelationCondition {
pub fn invert_of_subselect(self) -> bool {
matches!(self, RelationCondition::EveryRelatedRecord)
}
pub fn invert(self, invert: bool, to_one: bool) -> Self {
if invert {
match self {
RelationCondition::EveryRelatedRecord => RelationCondition::NoRelatedRecord,
RelationCondition::AtLeastOneRelatedRecord => RelationCondition::NoRelatedRecord,
RelationCondition::NoRelatedRecord if to_one => RelationCondition::ToOneRelatedRecord,
RelationCondition::NoRelatedRecord => RelationCondition::AtLeastOneRelatedRecord,
RelationCondition::ToOneRelatedRecord => RelationCondition::NoRelatedRecord,
}
} else {
self
}
}
}
impl RelationCompare for RelationField {
fn every_related<T>(&self, filter: T) -> Filter
where
T: Into<Filter>,
{
Filter::from(RelationFilter {
field: self.clone(),
nested_filter: Box::new(filter.into()),
condition: RelationCondition::EveryRelatedRecord,
})
}
fn at_least_one_related<T>(&self, filter: T) -> Filter
where
T: Into<Filter>,
{
Filter::from(RelationFilter {
field: self.clone(),
nested_filter: Box::new(filter.into()),
condition: RelationCondition::AtLeastOneRelatedRecord,
})
}
fn to_one_related<T>(&self, filter: T) -> Filter
where
T: Into<Filter>,
{
Filter::from(RelationFilter {
field: self.clone(),
nested_filter: Box::new(filter.into()),
condition: RelationCondition::ToOneRelatedRecord,
})
}
fn no_related<T>(&self, filter: T) -> Filter
where
T: Into<Filter>,
{
Filter::from(RelationFilter {
field: self.clone(),
nested_filter: Box::new(filter.into()),
condition: RelationCondition::NoRelatedRecord,
})
}
fn one_relation_is_null(&self) -> Filter {
Filter::from(OneRelationIsNullFilter { field: self.clone() })
}
}