diesel_bind_if_some/
lib.rs

1use diesel::{
2    backend::Backend,
3    expression::ValidGrouping,
4    query_builder::{AstPass, QueryFragment, QueryId},
5    sql_types::{self, SingleValue},
6    AppearsOnTable, Expression, QueryResult, SelectableExpression,
7};
8
9/// Causes `None` to be included as "NULL" in the SQL code instead of a value for a bind parameter.
10///
11/// This causes separate prepared statements to be created for the `Some` and `None` variants, which
12/// can result in better performance if one of the variants allows a more efficient query plan or causes
13/// a different amount of rows to be estimated.
14///
15/// This struct also allows wrapping an expression in `Option`, even if the expression isn't just a bind
16/// parameter. For example, it can be a column.
17#[derive(Clone, Copy)]
18pub struct BindIfSome<T>(pub Option<T>);
19
20/* Conflicts with implementation from Diesel
21
22impl<ST: SqlType + TypedExpressionType, T: AsExpression<ST>> AsExpression<sql_types::Nullable<ST>> for BindIfSome<T> {
23    type Expression = BindIfSome<T::Expression>;
24
25    fn as_expression(self) -> Self::Expression {
26        BindIfSome(self.0.map(AsExpression::as_expression))
27    }
28}
29*/
30
31impl<T> QueryId for BindIfSome<T> {
32    type QueryId = ();
33    const HAS_STATIC_QUERY_ID: bool = false;
34}
35
36impl<T: Expression> Expression for BindIfSome<T>
37where
38    T::SqlType: SingleValue,
39{
40    type SqlType = sql_types::Nullable<T::SqlType>;
41}
42
43impl<DB: Backend, T: QueryFragment<DB>> QueryFragment<DB> for BindIfSome<T> {
44    fn walk_ast<'b>(&'b self, mut out: AstPass<'_, 'b, DB>) -> QueryResult<()> {
45        if let Some(value) = &self.0 {
46            value.walk_ast(out)?;
47        } else {
48            out.push_sql("(NULL)");
49        }
50
51        Ok(())
52    }
53}
54
55impl<QS: ?Sized, T: AppearsOnTable<QS>> AppearsOnTable<QS> for BindIfSome<T> where
56    T::SqlType: SingleValue
57{
58}
59
60impl<QS: ?Sized, T: SelectableExpression<QS>> SelectableExpression<QS> for BindIfSome<T> where
61    T::SqlType: SingleValue
62{
63}
64
65impl<GB, T: ValidGrouping<GB>> ValidGrouping<GB> for BindIfSome<T> {
66    type IsAggregate = T::IsAggregate;
67}