Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions diesel/src/expression/count.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ use super::{Expression, ValidGrouping};
use crate::backend::Backend;
use crate::query_builder::*;
use crate::result::QueryResult;
use crate::sql_types::{BigInt, DieselNumericOps, Nullable, SingleValue, SqlType};
use crate::sql_types::{BigInt, DieselNumericOps, SingleValue, SqlType};

sql_function! {
/// Creates a SQL `COUNT` expression
Expand All @@ -25,7 +25,7 @@ sql_function! {
/// # }
/// ```
#[aggregate]
fn count<T: SqlType + SingleValue>(expr: Nullable<T>) -> BigInt;
fn count<T: SqlType + SingleValue>(expr: T) -> BigInt;
}

/// Creates a SQL `COUNT(*)` expression
Expand Down
6 changes: 3 additions & 3 deletions diesel/src/expression/functions/aggregate_folding.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
use crate::expression::functions::sql_function;
use crate::sql_types::{Foldable, Nullable};
use crate::sql_types::Foldable;

sql_function! {
/// Represents a SQL `SUM` function. This function can only take types which are
Expand All @@ -18,7 +18,7 @@ sql_function! {
/// # }
/// ```
#[aggregate]
fn sum<ST: Foldable>(expr: Nullable<ST>) -> ST::Sum;
fn sum<ST: Foldable>(expr: ST) -> ST::Sum;
}

sql_function! {
Expand Down Expand Up @@ -64,5 +64,5 @@ sql_function! {
/// # Ok(())
/// # }
#[aggregate]
fn avg<ST: Foldable>(expr: Nullable<ST>) -> ST::Avg;
fn avg<ST: Foldable>(expr: ST) -> ST::Avg;
}
14 changes: 7 additions & 7 deletions diesel/src/expression/functions/aggregate_ordering.rs
Original file line number Diff line number Diff line change
@@ -1,16 +1,16 @@
use crate::expression::functions::sql_function;
use crate::sql_types::{IntoNullable, Nullable, SingleValue, SqlOrd, SqlType};
use crate::sql_types::{IntoNullable, SingleValue, SqlOrd, SqlType};

pub trait SqlOrdAggregate: SingleValue {
type Ret: SqlType + SingleValue;
}

impl<ST> SqlOrdAggregate for ST
impl<T> SqlOrdAggregate for T
where
ST: SqlOrd + SingleValue + IntoNullable,
ST::Nullable: SingleValue,
T: SqlOrd + IntoNullable + SingleValue,
T::Nullable: SqlType + SingleValue,
{
type Ret = <Self as IntoNullable>::Nullable;
type Ret = T::Nullable;
}

sql_function! {
Expand All @@ -29,7 +29,7 @@ sql_function! {
/// assert_eq!(Ok(Some(8)), animals.select(max(legs)).first(&connection));
/// # }
#[aggregate]
fn max<ST: SqlOrdAggregate>(expr: Nullable<ST>) -> ST::Ret;
fn max<ST: SqlOrdAggregate>(expr: ST) -> ST::Ret;
}

sql_function! {
Expand All @@ -48,5 +48,5 @@ sql_function! {
/// assert_eq!(Ok(Some(4)), animals.select(min(legs)).first(&connection));
/// # }
#[aggregate]
fn min<ST: SqlOrdAggregate>(expr: Nullable<ST>) -> ST::Ret;
fn min<ST: SqlOrdAggregate>(expr: ST) -> ST::Ret;
}
21 changes: 18 additions & 3 deletions diesel/src/expression/functions/date_and_time.rs
Original file line number Diff line number Diff line change
@@ -1,8 +1,7 @@
use crate::backend::Backend;
use crate::expression::coerce::Coerce;
use crate::expression::functions::sql_function;
#[cfg(feature = "postgres")]
use crate::expression::{coerce::Coerce, AsExpression};
use crate::expression::{Expression, ValidGrouping};
use crate::expression::{AsExpression, Expression, ValidGrouping};
use crate::query_builder::*;
use crate::result::QueryResult;
use crate::sql_types::*;
Expand Down Expand Up @@ -47,6 +46,14 @@ sql_function! {
fn date(expr: Timestamp) -> Date;
}

impl AsExpression<Nullable<Timestamp>> for now {
type Expression = Coerce<now, Nullable<Timestamp>>;

fn as_expression(self) -> Self::Expression {
Coerce::new(self)
}
}

#[cfg(feature = "postgres")]
impl AsExpression<Timestamptz> for now {
type Expression = Coerce<now, Timestamptz>;
Expand Down Expand Up @@ -85,3 +92,11 @@ impl_selectable_expression!(today);

operator_allowed!(today, Add, add);
operator_allowed!(today, Sub, sub);

impl AsExpression<Nullable<Date>> for today {
type Expression = Coerce<today, Nullable<Date>>;

fn as_expression(self) -> Self::Expression {
Coerce::new(self)
}
}
5 changes: 2 additions & 3 deletions diesel/src/expression/functions/helper_types.rs
Original file line number Diff line number Diff line change
@@ -1,12 +1,11 @@
#![allow(non_camel_case_types)]

use crate::dsl::{AsExprOf, SqlTypeOf};
use crate::dsl::SqlTypeOf;
use crate::expression::grouped::Grouped;
use crate::expression::operators;
use crate::sql_types::{Bool, Nullable};

/// The return type of [`not(expr)`](../dsl/fn.not.html)
pub type not<Expr> = operators::Not<Grouped<AsExprOf<Expr, Nullable<Bool>>>>;
pub type not<Expr> = operators::Not<Grouped<Expr>>;

/// The return type of [`max(expr)`](../dsl/fn.max.html)
pub type max<Expr> = super::aggregate_ordering::max::HelperType<SqlTypeOf<Expr>, Expr>;
Expand Down
5 changes: 3 additions & 2 deletions diesel/src/expression/helper_types.rs
Original file line number Diff line number Diff line change
Expand Up @@ -89,11 +89,12 @@ pub type Nullable<Expr> = super::nullable::Nullable<Expr>;

/// The return type of
/// [`lhs.and(rhs)`](../expression_methods/trait.BoolExpressionMethods.html#method.and)
pub type And<Lhs, Rhs> = Grouped<super::operators::And<Nullable<Lhs>, AsExpr<Rhs, Nullable<Lhs>>>>;
pub type And<Lhs, Rhs, ST = sql_types::Bool> =
Grouped<super::operators::And<Lhs, AsExprOf<Rhs, ST>>>;

/// The return type of
/// [`lhs.or(rhs)`](../expression_methods/trait.BoolExpressionMethods.html#method.or)
pub type Or<Lhs, Rhs> = Grouped<super::operators::Or<Lhs, AsExpr<Rhs, Nullable<Lhs>>>>;
pub type Or<Lhs, Rhs, ST = sql_types::Bool> = Grouped<super::operators::Or<Lhs, AsExprOf<Rhs, ST>>>;

/// The return type of
/// [`lhs.escape('x')`](../expression_methods/trait.EscapeExpressionMethods.html#method.escape)
Expand Down
99 changes: 6 additions & 93 deletions diesel/src/expression/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,7 @@ pub use self::sql_literal::{SqlLiteral, UncheckedBind};

use crate::backend::Backend;
use crate::dsl::AsExprOf;
use crate::sql_types::{HasSqlType, IntoNotNullable, SingleValue, SqlType};
use crate::sql_types::{HasSqlType, SingleValue, SqlType};

/// Represents a typed fragment of SQL.
///
Expand Down Expand Up @@ -208,101 +208,14 @@ pub use diesel_derives::AsExpression;

impl<T, ST> AsExpression<ST> for T
where
ST: SqlType + IntoNotNullable + TypedExpressionType,
ST::NotNullable: SingleValue,
self::as_expression_impl::ExpressionImplHelper<T, ST::IsNull, <T::SqlType as SqlType>::IsNull>:
self::as_expression_impl::AsExpressionHelper<ST>,
T: Expression,
T::SqlType: SqlType,
T: Expression<SqlType = ST>,
ST: SqlType + TypedExpressionType,
{
type Expression = <self::as_expression_impl::ExpressionImplHelper<
T,
ST::IsNull,
<T::SqlType as SqlType>::IsNull,
> as self::as_expression_impl::AsExpressionHelper<ST>>::Expression;

fn as_expression(self) -> Self::Expression {
use self::as_expression_impl::AsExpressionHelper;

let t = self::as_expression_impl::ExpressionImplHelper::<
_,
ST::IsNull,
<T::SqlType as SqlType>::IsNull,
>(self, std::marker::PhantomData);
t.as_expression()
}
}

mod as_expression_impl {
use super::*;
use crate::sql_types::is_nullable;
type Expression = Self;

#[allow(missing_debug_implementations)]
pub struct ExpressionImplHelper<T, IsNullExpr, IsNullAsExpr>(
pub T,
pub std::marker::PhantomData<(IsNullExpr, IsNullAsExpr)>,
);

// We could use `AsExpression` here instead of defining a new trait in theory
// in practice we hit https://github.com/rust-lang/rust/issues/77446 then
// when defining a custom type in a third party crate
pub trait AsExpressionHelper<ST: TypedExpressionType> {
type Expression: Expression<SqlType = ST>;

fn as_expression(self) -> Self::Expression;
fn as_expression(self) -> Self {
self
}

// This impl is for accepting a not nullable expression in a position where
// a not nullable expression is expected
impl<T, ST> AsExpressionHelper<ST>
for ExpressionImplHelper<T, is_nullable::NotNull, is_nullable::NotNull>
where
ST: SqlType<IsNull = is_nullable::NotNull> + TypedExpressionType,
T: Expression<SqlType = ST>,
{
type Expression = T;

fn as_expression(self) -> Self::Expression {
self.0
}
}

// This impl is for accepting a not nullable expression in a position where
// a nullable expression is expected
impl<T, ST> AsExpressionHelper<ST>
for ExpressionImplHelper<T, is_nullable::IsNullable, is_nullable::NotNull>
where
ST: SqlType<IsNull = is_nullable::IsNullable> + IntoNotNullable + TypedExpressionType,
ST::NotNullable: TypedExpressionType + SqlType,
T: Expression<SqlType = ST::NotNullable>,
super::nullable::Nullable<T>: Expression<SqlType = ST>,
{
type Expression = super::nullable::Nullable<T>;

fn as_expression(self) -> Self::Expression {
super::nullable::Nullable::new(self.0)
}
}

// This impl is for accepting a nullable expression in a position where
// a nullable expression is expected
impl<T, ST> AsExpressionHelper<ST>
for ExpressionImplHelper<T, is_nullable::IsNullable, is_nullable::IsNullable>
where
ST: SqlType<IsNull = is_nullable::IsNullable> + TypedExpressionType,
T: Expression<SqlType = ST>,
{
type Expression = T;

fn as_expression(self) -> Self::Expression {
self.0
}
}

// impl<T, ST> AsExpressionHelper<ST> for
// ExpressionImplHelper<T, is_nullable::NotNull, is_nullable::IsNullable>
// is missing because we don't want to accept a nullable expression in possition where
// where a not nullable expression is expected
}

/// Converts a type to its representation for use in Diesel's query builder.
Expand Down
9 changes: 5 additions & 4 deletions diesel/src/expression/not.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
use crate::expression::grouped::Grouped;
use crate::expression::AsExpression;
use crate::expression::Expression;
use crate::helper_types::not;
use crate::sql_types::{Bool, Nullable};
use crate::sql_types::BoolOrNullableBool;

/// Creates a SQL `NOT` expression
///
Expand All @@ -25,7 +25,8 @@ use crate::sql_types::{Bool, Nullable};
/// ```
pub fn not<T>(expr: T) -> not<T>
where
T: AsExpression<Nullable<Bool>>,
T: Expression,
<T as Expression>::SqlType: BoolOrNullableBool,
{
super::operators::Not::new(Grouped(expr.as_expression()))
super::operators::Not::new(Grouped(expr))
}
40 changes: 33 additions & 7 deletions diesel/src/expression/operators.rs
Original file line number Diff line number Diff line change
Expand Up @@ -436,11 +436,26 @@ macro_rules! prefix_operator {
notation = prefix,
struct_name = $name,
operator = $operator,
return_ty = ($return_ty),
return_ty = (
$crate::sql_types::is_nullable::MaybeNullable<
$crate::sql_types::is_nullable::IsSqlTypeNullable<
<Expr as $crate::expression::Expression>::SqlType
>,
$return_ty,
>
),
ty_params = (Expr,),
field_names = (expr,),
backend_ty_params = (DB,),
backend_ty = DB,
expression_ty_params = (),
expression_bounds = (
Expr: $crate::expression::Expression,
<Expr as $crate::expression::Expression>::SqlType: $crate::sql_types::SqlType,
$crate::sql_types::is_nullable::IsSqlTypeNullable<
<Expr as $crate::expression::Expression>::SqlType
>: $crate::sql_types::MaybeNullableType<$return_ty>,
),
);
};

Expand All @@ -449,11 +464,26 @@ macro_rules! prefix_operator {
notation = prefix,
struct_name = $name,
operator = $operator,
return_ty = ($return_ty),
return_ty = (
$crate::sql_types::is_nullable::MaybeNullable<
$crate::sql_types::is_nullable::IsSqlTypeNullable<
<Expr as $crate::expression::Expression>::SqlType
>,
$return_ty,
>
),
ty_params = (Expr,),
field_names = (expr,),
backend_ty_params = (),
backend_ty = $backend,
expression_ty_params = (),
expression_bounds = (
Expr: $crate::expression::Expression,
<Expr as $crate::expression::Expression>::SqlType: $crate::sql_types::SqlType,
$crate::sql_types::is_nullable::IsSqlTypeNullable<
<Expr as $crate::expression::Expression>::SqlType
>: $crate::sql_types::MaybeNullableType<$return_ty>,
),
);
};
}
Expand Down Expand Up @@ -495,11 +525,7 @@ postfix_operator!(
crate::expression::expression_types::NotSelectable
);

prefix_operator!(
Not,
" NOT ",
crate::sql_types::Nullable<crate::sql_types::Bool>
);
prefix_operator!(Not, " NOT ");

use crate::backend::Backend;
use crate::expression::{TypedExpressionType, ValidGrouping};
Expand Down
Loading