use super::*;
pub trait ReadableField<Model, Value, Meta: TypeMeta>: Copy {
fn column(self) -> expression::Column<Model, Meta>;
fn getter(self) -> for<'a> fn(&'a Model) -> &'a Value;
}
pub trait WritableField<Model, Value, Meta: TypeMeta>: ReadableField<Model, Value, Meta> {
fn setter(self) -> fn(&mut Model, Value);
fn dirty_field(self) -> DraftField<Model>;
}
#[doc(hidden)]
pub trait ReadableFieldInfo<Model> {
type Value;
type Meta: TypeMeta;
}
impl<Model, Value, Meta: TypeMeta> ReadableFieldInfo<Model> for ModelField<Model, Value, Meta> {
type Value = Value;
type Meta = Meta;
}
impl<Model, Value, Meta: TypeMeta, Kind> ReadableFieldInfo<Model>
for PersistedField<Model, Value, Meta, Kind>
{
type Value = Value;
type Meta = Meta;
}
#[doc(hidden)]
pub trait PrimaryKeyOrderFields<Child>: Copy
where
Child: Qrafting + FromRow,
{
fn order_min<SortMeta: crate::TypeMeta>(
self,
query: QueryOf<Child>,
sort: expression::Column<Child, SortMeta>,
) -> QueryOf<Child>;
fn order_max<SortMeta: crate::TypeMeta>(
self,
query: QueryOf<Child>,
sort: expression::Column<Child, SortMeta>,
) -> QueryOf<Child>;
}
impl<Child, Key, Meta> PrimaryKeyOrderFields<Child> for ModelField<Child, Key, Meta>
where
Child: Qrafting + FromRow,
Meta: crate::TypeMeta,
{
fn order_min<SortMeta: crate::TypeMeta>(
self,
query: QueryOf<Child>,
sort: expression::Column<Child, SortMeta>,
) -> QueryOf<Child> {
query.order_by((sort.asc(), self.asc()))
}
fn order_max<SortMeta: crate::TypeMeta>(
self,
query: QueryOf<Child>,
sort: expression::Column<Child, SortMeta>,
) -> QueryOf<Child> {
query.order_by((sort.desc(), self.desc()))
}
}
pub struct ModelField<Model, Value, Meta: TypeMeta> {
column: expression::Column<Model, Meta>,
getter: for<'a> fn(&'a Model) -> &'a Value,
}
impl<Model, Value, Meta: TypeMeta> ModelField<Model, Value, Meta> {
pub const fn new(
column: expression::Column<Model, Meta>,
getter: for<'a> fn(&'a Model) -> &'a Value,
) -> Self {
Self { column, getter }
}
pub const fn name(self) -> &'static str {
self.column.name()
}
}
impl<Model, Value, Meta: TypeMeta + Required> ModelField<Model, Value, Meta> {
pub fn nullable(self) -> ModelField<Model, Value, crate::Nullable<Meta>> {
ModelField {
column: self.column.nullable(),
getter: self.getter,
}
}
}
impl<Model, Value, Meta: TypeMeta> Copy for ModelField<Model, Value, Meta> {}
impl<Model, Value, Meta: TypeMeta> Clone for ModelField<Model, Value, Meta> {
fn clone(&self) -> Self {
*self
}
}
impl<Model, Value, Meta: TypeMeta> ReadableField<Model, Value, Meta>
for ModelField<Model, Value, Meta>
{
fn column(self) -> expression::Column<Model, Meta> {
self.column
}
fn getter(self) -> for<'a> fn(&'a Model) -> &'a Value {
self.getter
}
}
pub struct RequiredField;
pub struct NullableField;
pub struct PersistedField<Model, Value, Meta: TypeMeta, Kind = RequiredField> {
column: expression::Column<Model, Meta>,
getter: for<'a> fn(&'a Model) -> &'a Value,
setter: fn(&mut Model, Value),
dirty_field: DraftField<Model>,
_kind: PhantomData<Kind>,
}
impl<Model, Value, Meta: TypeMeta, Kind> PersistedField<Model, Value, Meta, Kind> {
pub const fn new(
column: expression::Column<Model, Meta>,
getter: for<'a> fn(&'a Model) -> &'a Value,
setter: fn(&mut Model, Value),
dirty_field: DraftField<Model>,
) -> Self {
Self {
column,
getter,
setter,
dirty_field,
_kind: PhantomData,
}
}
pub const fn name(self) -> &'static str {
self.column.name()
}
}
impl<Model, Value, Meta: TypeMeta + Required, Kind> PersistedField<Model, Value, Meta, Kind> {
pub fn nullable(self) -> PersistedField<Model, Value, crate::Nullable<Meta>, Kind> {
PersistedField {
column: self.column.nullable(),
getter: self.getter,
setter: self.setter,
dirty_field: self.dirty_field,
_kind: PhantomData,
}
}
}
impl<Model, Value, Meta: TypeMeta, Kind> Copy for PersistedField<Model, Value, Meta, Kind> {}
impl<Model, Value, Meta: TypeMeta, Kind> Clone for PersistedField<Model, Value, Meta, Kind> {
fn clone(&self) -> Self {
*self
}
}
impl<Model, Value, Meta: TypeMeta, Kind> ReadableField<Model, Value, Meta>
for PersistedField<Model, Value, Meta, Kind>
{
fn column(self) -> expression::Column<Model, Meta> {
self.column
}
fn getter(self) -> for<'a> fn(&'a Model) -> &'a Value {
self.getter
}
}
impl<Model, Value, Meta: TypeMeta, Kind> WritableField<Model, Value, Meta>
for PersistedField<Model, Value, Meta, Kind>
{
fn setter(self) -> fn(&mut Model, Value) {
self.setter
}
fn dirty_field(self) -> DraftField<Model> {
self.dirty_field
}
}
#[qraft_expression_macro::as_expression]
impl<Model: Qrafting, Value, Meta: TypeMeta> Expression for ModelField<Model, Value, Meta> {
type Type = Meta;
fn lower(&self, ctx: &mut LowerCtx) -> usize {
self.column.lower(ctx)
}
}
#[qraft_expression_macro::as_expression]
impl<Model: Qrafting, Value, Meta: TypeMeta, Kind> Expression
for PersistedField<Model, Value, Meta, Kind>
{
type Type = Meta;
fn lower(&self, ctx: &mut LowerCtx) -> usize {
self.column.lower(ctx)
}
}
impl<Model, Value, Meta: TypeMeta> IntoColumn for ModelField<Model, Value, Meta> {
type Out = expression::Column<Model, Meta>;
fn into_as(self, alias: &'static str) -> expression::As<Self::Out> {
self.column.into_as(alias)
}
}
impl<Model, Value, Meta: TypeMeta, Kind> IntoColumn for PersistedField<Model, Value, Meta, Kind> {
type Out = expression::Column<Model, Meta>;
fn into_as(self, alias: &'static str) -> expression::As<Self::Out> {
self.column.into_as(alias)
}
}
macro_rules! impl_field_methods {
($ty:ident$(<$kind:ident>)?) => {
impl<Model: Qrafting, Value, Meta: Comparable, $($kind,)? > $ty<Model, Value, Meta $(, $kind)?> {
pub fn eq<E>(self, e: E) -> crate::expression::Binary<Eq, Self, E>
where
E: crate::LowerCompatible<Meta>,
{
EqExt::eq(self, e)
}
pub fn neq<E>(self, e: E) -> crate::expression::Binary<Neq, Self, E>
where
E: crate::LowerCompatible<Meta>,
{
EqExt::neq(self, e)
}
}
impl<Model: Qrafting, Value, T: Comparable + Required, $($kind,)? > $ty<Model, Value, crate::Nullable<T> $(, $kind)?> {
pub fn is_null(self) -> Postfix<Self> {
IsNull::is_null(self)
}
pub fn is_not_null(self) -> Postfix<Self> {
IsNull::is_not_null(self)
}
}
impl<Model: Qrafting, Value, T: crate::Boolean, $($kind,)? > $ty<Model, Value, T $(, $kind)?> {
pub fn is_true(self) -> Postfix<Self> {
IsPredicate::is_true(self)
}
pub fn is_false(self) -> Postfix<Self> {
IsPredicate::is_false(self)
}
}
impl<Model: Qrafting, Value, T: Likeable, $($kind,)? > $ty<Model, Value, T $(, $kind)?> {
pub fn like<E>(self, other: E) -> Like<Self, E>
where
E: crate::LowerCompatible<T>,
{
LikeExt::like(self, other)
}
pub fn not_like<E>(self, other: E) -> Like<Self, E>
where
E: crate::LowerCompatible<T>,
{
LikeExt::not_like(self, other)
}
}
impl<Model: Qrafting, Value, T: Orderable, $($kind,)? > $ty<Model, Value, T $(, $kind)?> {
pub fn between<L, H>(self, low: L, high: H) -> Between<Self, L, H>
where
L: crate::LowerCompatible<T>,
H: crate::LowerCompatible<T>,
{
BetweenExt::between(self, low, high)
}
pub fn not_between<L, H>(self, low: L, high: H) -> Between<Self, L, H>
where
L: crate::LowerCompatible<T>,
H: crate::LowerCompatible<T>,
{
BetweenExt::not_between(self, low, high)
}
}
};
}
impl_field_methods!(ModelField);
impl_field_methods!(PersistedField<Kind>);
pub struct OptionalQuery<Model> {
inner: Option<QueryOf<Model>>,
}
impl<Model> OptionalQuery<Model> {
pub const fn new(inner: Option<QueryOf<Model>>) -> Self {
Self { inner }
}
pub fn into_option(self) -> Option<QueryOf<Model>> {
self.inner
}
pub async fn optional(self, exec: impl crate::quex::Executor) -> quex::Result<Option<Model>>
where
Model: FromRow,
{
match self.inner {
Some(query) => query.optional(exec).await,
None => Ok(None),
}
}
}
macro_rules! impl_optional_query_forwarding {
($target:ident) => {
impl<$target> OptionalQuery<$target>
where
$target: FromRow,
{
pub fn filter<E>(self, expr: E) -> Self
where
E: query::LowerFilter,
{
Self::new(self.inner.map(|query| query.filter(expr)))
}
pub fn or_filter<E>(self, expr: E) -> Self
where
E: query::LowerFilter,
{
Self::new(self.inner.map(|query| query.or_filter(expr)))
}
pub fn order_by<T>(self, by: T) -> Self
where
T: LowerOrderBy,
{
Self::new(self.inner.map(|query| query.order_by(by)))
}
pub fn order_by_random(self) -> Self {
Self::new(self.inner.map(QueryOf::order_by_random))
}
pub fn limit<E>(self, expr: E) -> Self
where
E: crate::LowerCompatible<BigInt>,
{
Self::new(self.inner.map(|query| query.limit(expr)))
}
pub fn offset<E>(self, expr: E) -> Self
where
E: crate::LowerCompatible<BigInt>,
{
Self::new(self.inner.map(|query| query.offset(expr)))
}
pub fn distinct(self) -> Self {
Self::new(self.inner.map(QueryOf::distinct))
}
pub fn not_distinct(self) -> Self {
Self::new(self.inner.map(QueryOf::not_distinct))
}
pub fn with<C>(self, ctes: C) -> Self
where
C: IntoCtes,
{
Self::new(self.inner.map(|query| query.with(ctes)))
}
pub fn with_recursive<C>(self, ctes: C) -> Self
where
C: IntoCtes,
{
Self::new(self.inner.map(|query| query.with_recursive(ctes)))
}
pub fn untyped(self) -> Option<Query> {
self.inner.map(QueryOf::untyped)
}
pub fn to_sql<D: crate::HasDialect>(self) -> Option<String> {
self.inner.map(|mut query| query.to_sql::<D>())
}
pub fn to_debug_sql<D: crate::HasDialect>(self) -> Option<String> {
self.inner.map(|mut query| query.to_debug_sql::<D>())
}
}
};
}
impl_optional_query_forwarding!(Model);