use std::marker::PhantomData;
use crate::{IntoSqlValue, OrderClause, SortDirection, order::OrderTarget, values::FilterValue};
use super::filter::Filter;
use super::op::FilterOp;
#[derive(Debug, Clone, Copy)]
pub struct FieldRef<M, T> {
pub(super) column: &'static str,
_marker: PhantomData<fn() -> (M, T)>,
}
impl<M, T> FieldRef<M, T> {
pub const fn new(column: &'static str) -> Self {
Self {
column,
_marker: PhantomData,
}
}
pub const fn column_name(self) -> &'static str {
self.column
}
pub fn asc(self) -> OrderClause {
OrderClause {
target: OrderTarget::Column(self.column),
direction: SortDirection::Asc,
null_order: crate::NullOrder::Last,
}
}
pub fn desc(self) -> OrderClause {
OrderClause {
target: OrderTarget::Column(self.column),
direction: SortDirection::Desc,
null_order: crate::NullOrder::Last,
}
}
}
impl<M, T> FieldRef<M, T> {
pub fn eq<V>(self, value: V) -> Filter
where
V: IntoSqlValue,
{
Filter::single(self.column, FilterOp::Eq, value)
}
pub fn ne<V>(self, value: V) -> Filter
where
V: IntoSqlValue,
{
Filter::single(self.column, FilterOp::Ne, value)
}
pub fn in_<I, V>(self, values: I) -> Filter
where
I: IntoIterator<Item = V>,
V: IntoSqlValue,
{
Filter {
column: self.column,
op: FilterOp::In,
value: FilterValue::Many(
values
.into_iter()
.map(IntoSqlValue::into_sql_value)
.collect(),
),
}
}
pub fn lt<V>(self, value: V) -> Filter
where
V: IntoSqlValue,
{
Filter::single(self.column, FilterOp::Lt, value)
}
pub fn lte<V>(self, value: V) -> Filter
where
V: IntoSqlValue,
{
Filter::single(self.column, FilterOp::Lte, value)
}
pub fn gt<V>(self, value: V) -> Filter
where
V: IntoSqlValue,
{
Filter::single(self.column, FilterOp::Gt, value)
}
pub fn gte<V>(self, value: V) -> Filter
where
V: IntoSqlValue,
{
Filter::single(self.column, FilterOp::Gte, value)
}
pub fn eq_or_null<V>(self, value: V) -> Filter
where
V: IntoSqlValue,
{
Filter::single(self.column, FilterOp::EqOrNull, value)
}
pub fn match_optional<V>(self, value: Option<V>) -> Option<Filter>
where
V: IntoSqlValue,
{
value.map(|v| self.eq_or_null(v))
}
}
impl<M> FieldRef<M, bool> {
pub fn is_true(self) -> Filter {
self.eq(true)
}
pub fn is_false(self) -> Filter {
self.eq(false)
}
}
impl<M> FieldRef<M, String> {
pub fn contains(self, value: impl Into<String>) -> Filter {
Filter::string_pattern(self.column, FilterOp::Contains, "%{}%", value)
}
pub fn starts_with(self, value: impl Into<String>) -> Filter {
Filter::string_pattern(self.column, FilterOp::StartsWith, "{}%", value)
}
}
impl<M, T> FieldRef<M, Option<T>> {
pub fn is_null(self) -> Filter {
Filter {
column: self.column,
op: FilterOp::IsNull,
value: FilterValue::None,
}
}
pub fn is_not_null(self) -> Filter {
Filter {
column: self.column,
op: FilterOp::IsNotNull,
value: FilterValue::None,
}
}
}
impl<M> FieldRef<M, Option<String>> {
pub fn contains(self, value: impl Into<String>) -> Filter {
Filter::string_pattern(self.column, FilterOp::Contains, "%{}%", value)
}
pub fn starts_with(self, value: impl Into<String>) -> Filter {
Filter::string_pattern(self.column, FilterOp::StartsWith, "{}%", value)
}
}