Skip to content

Commit

Permalink
Prototyped cmp trait on generic
Browse files Browse the repository at this point in the history
  • Loading branch information
gammelalf committed Sep 5, 2023
1 parent e22e1eb commit 97713e7
Show file tree
Hide file tree
Showing 3 changed files with 100 additions and 36 deletions.
14 changes: 8 additions & 6 deletions src/fields/traits/cmp.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ use crate::internal::relation_path::Path;
/// Trait for equality comparisons.
///
/// **Read module notes, before using.**
pub trait FieldEq<'rhs, Rhs: 'rhs>: FieldType {
pub trait FieldEq<'rhs, Rhs: 'rhs, Any = ()>: FieldType {
/// Condition type returned from [`FieldEq::field_equals`]
type EqCond<A: FieldAccess>: Condition<'rhs>;

Expand All @@ -39,7 +39,7 @@ pub trait FieldEq<'rhs, Rhs: 'rhs>: FieldType {
/// Trait for field types that form an order.
///
/// **Read module notes, before using.**
pub trait FieldOrd<'rhs, Rhs: 'rhs>: FieldEq<'rhs, Rhs> {
pub trait FieldOrd<'rhs, Rhs: 'rhs, Any = ()>: FieldType {
/// Condition type returned from [`FieldOrd::field_less_than`]
type LtCond<A: FieldAccess>: Condition<'rhs>;

Expand Down Expand Up @@ -68,7 +68,7 @@ pub trait FieldOrd<'rhs, Rhs: 'rhs>: FieldEq<'rhs, Rhs> {
/// Trait for field types to implement sql's `LIKE` comparison.
///
/// **Read module notes, before using.**
pub trait FieldLike<'rhs, Rhs: 'rhs> {
pub trait FieldLike<'rhs, Rhs: 'rhs, Any = ()>: FieldType {
/// Condition type returned from [`FieldLike::field_like`]
type LiCond<A: FieldAccess>: Condition<'rhs>;

Expand All @@ -85,7 +85,7 @@ pub trait FieldLike<'rhs, Rhs: 'rhs> {
/// Trait for field types to implement sql's `REGEXP` comparison.
///
/// **Read module notes, before using.**
pub trait FieldRegexp<'rhs, Rhs: 'rhs> {
pub trait FieldRegexp<'rhs, Rhs: 'rhs, Any = ()>: FieldType {
/// Condition type returned from [`FieldRegexp::field_regexp`]
type ReCond<A: FieldAccess>: Condition<'rhs>;

Expand Down Expand Up @@ -154,7 +154,7 @@ impl_FieldEq!(Vec<u8>, Vec<u8>, |b| Value::Binary(Cow::Owned(b)));
impl_FieldEq!(Vec<u8>, Cow<'rhs, [u8]>, Value::Binary);

// Impl FieldEq<FieldProxy> iff FieldEq<Self>
impl<'rhs, F, P, T> FieldEq<'rhs, FieldProxy<F, P>> for T
impl<'rhs, F, P, T> FieldEq<'rhs, FieldProxy<F, P>, Proxy> for T
where
T: FieldEq<'rhs, T>,
F: RawField<Type = T> + SingleColumnField,
Expand Down Expand Up @@ -251,7 +251,7 @@ impl_FieldOrd!(Vec<u8>, Vec<u8>, |b| Value::Binary(Cow::Owned(b)));
impl_FieldOrd!(Vec<u8>, Cow<'rhs, [u8]>, Value::Binary);

// Impl FieldOrd<FieldProxy> iff FieldOrd<Self>
impl<'rhs, F, P, T> FieldOrd<'rhs, FieldProxy<F, P>> for T
impl<'rhs, F, P, T> FieldOrd<'rhs, FieldProxy<F, P>, Proxy> for T
where
T: FieldOrd<'rhs, T>,
F: RawField<Type = T> + SingleColumnField,
Expand Down Expand Up @@ -293,3 +293,5 @@ where
}
}
}

struct Proxy;
62 changes: 34 additions & 28 deletions src/internal/field/access.rs
Original file line number Diff line number Diff line change
Expand Up @@ -61,105 +61,111 @@ pub trait FieldAccess: Sized + Send + 'static {
type Path: Path;

/// Compare the field to another value using `==`
fn equals<'rhs, Rhs: 'rhs>(self, rhs: Rhs) -> <FieldType!() as FieldEq<'rhs, Rhs>>::EqCond<Self>
fn equals<'rhs, Rhs: 'rhs, Any>(
self,
rhs: Rhs,
) -> <FieldType!() as FieldEq<'rhs, Rhs, Any>>::EqCond<Self>
where
FieldType!(): FieldEq<'rhs, Rhs>,
FieldType!(): FieldEq<'rhs, Rhs, Any>,
{
<FieldType!()>::field_equals(self, rhs)
}

/// Compare the field to another value using `!=`
fn not_equals<'rhs, Rhs: 'rhs>(
fn not_equals<'rhs, Rhs: 'rhs, Any>(
self,
rhs: Rhs,
) -> <FieldType!() as FieldEq<'rhs, Rhs>>::NeCond<Self>
) -> <FieldType!() as FieldEq<'rhs, Rhs, Any>>::NeCond<Self>
where
FieldType!(): FieldEq<'rhs, Rhs>,
FieldType!(): FieldEq<'rhs, Rhs, Any>,
{
<FieldType!()>::field_not_equals(self, rhs)
}

/// Compare the field to another value using `<`
fn less_than<'rhs, Rhs: 'rhs>(
fn less_than<'rhs, Rhs: 'rhs, Any>(
self,
rhs: Rhs,
) -> <FieldType!() as FieldOrd<'rhs, Rhs>>::LtCond<Self>
) -> <FieldType!() as FieldOrd<'rhs, Rhs, Any>>::LtCond<Self>
where
FieldType!(): FieldOrd<'rhs, Rhs>,
FieldType!(): FieldOrd<'rhs, Rhs, Any>,
{
<FieldType!()>::field_less_than(self, rhs)
}

/// Compare the field to another value using `<=`
fn less_equals<'rhs, Rhs: 'rhs>(
fn less_equals<'rhs, Rhs: 'rhs, Any>(
self,
rhs: Rhs,
) -> <FieldType!() as FieldOrd<'rhs, Rhs>>::LeCond<Self>
) -> <FieldType!() as FieldOrd<'rhs, Rhs, Any>>::LeCond<Self>
where
FieldType!(): FieldOrd<'rhs, Rhs>,
FieldType!(): FieldOrd<'rhs, Rhs, Any>,
{
<FieldType!()>::field_less_equals(self, rhs)
}

/// Compare the field to another value using `<`
fn greater_than<'rhs, Rhs: 'rhs>(
fn greater_than<'rhs, Rhs: 'rhs, Any>(
self,
rhs: Rhs,
) -> <FieldType!() as FieldOrd<'rhs, Rhs>>::GtCond<Self>
) -> <FieldType!() as FieldOrd<'rhs, Rhs, Any>>::GtCond<Self>
where
FieldType!(): FieldOrd<'rhs, Rhs>,
FieldType!(): FieldOrd<'rhs, Rhs, Any>,
{
<FieldType!()>::field_greater_than(self, rhs)
}

/// Compare the field to another value using `>=`
fn greater_equals<'rhs, Rhs: 'rhs>(
fn greater_equals<'rhs, Rhs: 'rhs, Any>(
self,
rhs: Rhs,
) -> <FieldType!() as FieldOrd<'rhs, Rhs>>::GeCond<Self>
) -> <FieldType!() as FieldOrd<'rhs, Rhs, Any>>::GeCond<Self>
where
FieldType!(): FieldOrd<'rhs, Rhs>,
FieldType!(): FieldOrd<'rhs, Rhs, Any>,
{
<FieldType!()>::field_greater_equals(self, rhs)
}

/// Compare the field to another value using `LIKE`
fn like<'rhs, Rhs: 'rhs>(self, rhs: Rhs) -> <FieldType!() as FieldLike<'rhs, Rhs>>::LiCond<Self>
fn like<'rhs, Rhs: 'rhs, Any>(
self,
rhs: Rhs,
) -> <FieldType!() as FieldLike<'rhs, Rhs, Any>>::LiCond<Self>
where
FieldType!(): FieldLike<'rhs, Rhs>,
FieldType!(): FieldLike<'rhs, Rhs, Any>,
{
<FieldType!()>::field_like(self, rhs)
}

/// Compare the field to another value using `NOT LIKE`
fn not_like<'rhs, Rhs: 'rhs>(
fn not_like<'rhs, Rhs: 'rhs, Any>(
self,
rhs: Rhs,
) -> <FieldType!() as FieldLike<'rhs, Rhs>>::NlCond<Self>
) -> <FieldType!() as FieldLike<'rhs, Rhs, Any>>::NlCond<Self>
where
FieldType!(): FieldLike<'rhs, Rhs>,
FieldType!(): FieldLike<'rhs, Rhs, Any>,
{
<FieldType!()>::field_not_like(self, rhs)
}

/// Compare the field to another value using `>=`
fn regexp<'rhs, Rhs: 'rhs>(
fn regexp<'rhs, Rhs: 'rhs, Any>(
self,
rhs: Rhs,
) -> <FieldType!() as FieldRegexp<'rhs, Rhs>>::ReCond<Self>
) -> <FieldType!() as FieldRegexp<'rhs, Rhs, Any>>::ReCond<Self>
where
FieldType!(): FieldRegexp<'rhs, Rhs>,
FieldType!(): FieldRegexp<'rhs, Rhs, Any>,
{
<FieldType!()>::field_regexp(self, rhs)
}

/// Compare the field to another value using `>=`
fn not_regexp<'rhs, Rhs: 'rhs>(
fn not_regexp<'rhs, Rhs: 'rhs, Any>(
self,
rhs: Rhs,
) -> <FieldType!() as FieldRegexp<'rhs, Rhs>>::NrCond<Self>
) -> <FieldType!() as FieldRegexp<'rhs, Rhs, Any>>::NrCond<Self>
where
FieldType!(): FieldRegexp<'rhs, Rhs>,
FieldType!(): FieldRegexp<'rhs, Rhs, Any>,
{
<FieldType!()>::field_not_regexp(self, rhs)
}
Expand Down
60 changes: 58 additions & 2 deletions src/internal/field/foreign_model.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,9 @@ use std::marker::PhantomData;
use rorm_db::row::DecodeOwned;
use rorm_db::{Error, Row};

use crate::conditions::Value;
use crate::conditions::{Binary, BinaryOperator, Column, Value};
use crate::crud::decoder::Decoder;
use crate::fields::traits::FieldEq;
use crate::fields::types::ForeignModelByField;
use crate::internal::field::as_db_type::AsDbType;
use crate::internal::field::decoder::FieldDecoder;
Expand All @@ -18,7 +19,7 @@ use crate::internal::hmr::Source;
use crate::internal::query_context::QueryContext;
use crate::internal::relation_path::Path;
use crate::model::{GetField, Model};
use crate::sealed;
use crate::{sealed, FieldAccess};

impl<FF> FieldType for ForeignModelByField<FF>
where
Expand Down Expand Up @@ -271,3 +272,58 @@ where
Self(PhantomData)
}
}

impl<'rhs, FF> FieldEq<'rhs, FF::Type> for ForeignModelByField<FF>
where
FF: RawField<Kind = kind::AsDbType> + Field<kind::AsDbType>,
FF::Model: GetField<FF>, // always true
FF: SingleColumnField,
{
type EqCond<A: FieldAccess> = Binary<Column<A>, Value<'rhs>>;

fn field_equals<A: FieldAccess>(access: A, value: FF::Type) -> Self::EqCond<A> {
Binary {
operator: BinaryOperator::Equals,
fst_arg: Column(access),
snd_arg: <FF as SingleColumnField>::type_into_value(value),
}
}

type NeCond<A: FieldAccess> = Binary<Column<A>, Value<'rhs>>;

fn field_not_equals<A: FieldAccess>(access: A, value: FF::Type) -> Self::NeCond<A> {
Binary {
operator: BinaryOperator::Equals,
fst_arg: Column(access),
snd_arg: <FF as SingleColumnField>::type_into_value(value),
}
}
}

impl<'rhs, FF> FieldEq<'rhs, FF::Type> for Option<ForeignModelByField<FF>>
where
FF: RawField<Kind = kind::AsDbType> + Field<kind::AsDbType>,
FF::Model: GetField<FF>, // always true
FF: SingleColumnField,
Option<FF::Type>: AsDbType,
{
type EqCond<A: FieldAccess> = Binary<Column<A>, Value<'rhs>>;

fn field_equals<A: FieldAccess>(access: A, value: FF::Type) -> Self::EqCond<A> {
Binary {
operator: BinaryOperator::Equals,
fst_arg: Column(access),
snd_arg: <FF as SingleColumnField>::type_into_value(value),
}
}

type NeCond<A: FieldAccess> = Binary<Column<A>, Value<'rhs>>;

fn field_not_equals<A: FieldAccess>(access: A, value: FF::Type) -> Self::NeCond<A> {
Binary {
operator: BinaryOperator::Equals,
fst_arg: Column(access),
snd_arg: <FF as SingleColumnField>::type_into_value(value),
}
}
}

0 comments on commit 97713e7

Please sign in to comment.