Skip to content

Commit 29280bf

Browse files
committed
Remove the ability to have Nullable<Nullable<T>> as a type
This is part of a greater effort to clean up some of the messier bits of our type system. Unfortunately, we still can't implement something both for null and not null in a non-overlapping way most of the time, as we still will bump into rust-lang/rust#20400. Otherwise we could write something like: ```rust impl<T, ST> Expression for Something<T> where T: Expression<SqlType=ST>, ST: NotNull, { } impl<T, ST> Expression for Something<T> where T: Expression<SqlType=Nullable<ST>>, ST: NotNull, { } ``` While these clearly do not overlap, rust treats them as overlapping. Unfortunately this is just one more type that we need to implement for new SQL types added in the future. I can't just make `IntoNullable` be a requirement of `NativeSqlType`, as it would require specifying the nullable case when packing it into a trait object. `NotNull` can just be replaced with an OIBIT in the future.
1 parent 4120ecf commit 29280bf

File tree

11 files changed

+52
-23
lines changed

11 files changed

+52
-23
lines changed

diesel/src/macros.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -320,8 +320,8 @@ macro_rules! select_column_inner {
320320

321321
impl $crate::expression::SelectableExpression<
322322
$crate::query_source::LeftOuterJoinSource<$child::table, $parent::table>,
323-
$crate::types::Nullable<
324-
<$parent::$column_name as $crate::Expression>::SqlType>,
323+
<<$parent::$column_name as $crate::Expression>::SqlType
324+
as $crate::types::IntoNullable>::Nullable,
325325
> for $parent::$column_name
326326
{
327327
}

diesel/src/query_source/joins.rs

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
use super::{QuerySource, Table};
22
use query_builder::*;
33
use expression::SelectableExpression;
4-
use types::Nullable;
4+
use types::IntoNullable;
55

66
#[derive(Debug, Clone, Copy)]
77
#[doc(hidden)]
@@ -80,14 +80,15 @@ impl<Left, Right> QuerySource for LeftOuterJoinSource<Left, Right> where
8080
impl<Left, Right> AsQuery for LeftOuterJoinSource<Left, Right> where
8181
Left: Table + JoinTo<Right>,
8282
Right: Table,
83+
Right::SqlType: IntoNullable,
8384
(Left::AllColumns, Right::AllColumns): SelectableExpression<
8485
LeftOuterJoinSource<Left, Right>,
85-
(Left::SqlType, Nullable<Right::SqlType>),
86+
(Left::SqlType, <Right::SqlType as IntoNullable>::Nullable),
8687
>,
8788
{
88-
type SqlType = (Left::SqlType, Nullable<Right::SqlType>);
89+
type SqlType = (Left::SqlType, <Right::SqlType as IntoNullable>::Nullable);
8990
type Query = SelectStatement<
90-
(Left::SqlType, Nullable<Right::SqlType>),
91+
Self::SqlType,
9192
(Left::AllColumns, Right::AllColumns),
9293
Self,
9394
>;

diesel/src/types/impls/array.rs

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ use std::io::Write;
66

77
use query_source::Queryable;
88
use super::option::UnexpectedNullError;
9-
use types::{NativeSqlType, FromSql, ToSql, Array, IsNull};
9+
use types::{NativeSqlType, FromSql, ToSql, Array, IsNull, NotNull};
1010

1111
impl<T: NativeSqlType> NativeSqlType for Array<T> {
1212
fn oid(&self) -> u32 {
@@ -22,6 +22,9 @@ impl<T: NativeSqlType> NativeSqlType for Array<T> {
2222
}
2323
}
2424

25+
impl<T: NativeSqlType> NotNull for Array<T> {
26+
}
27+
2528
impl<T, ST> FromSql<Array<ST>> for Vec<T> where
2629
T: FromSql<ST>,
2730
ST: NativeSqlType,

diesel/src/types/impls/mod.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -81,6 +81,9 @@ macro_rules! primitive_impls {
8181
types::$Source
8282
}
8383
}
84+
85+
impl types::NotNull for types::$Source {
86+
}
8487
)+
8588
queryable_impls!($($Source -> $Target),+,);
8689
expression_impls!($($Source -> $Target),+,);

diesel/src/types/impls/option.rs

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -4,9 +4,9 @@ use expression::bound::Bound;
44
use std::error::Error;
55
use std::fmt;
66
use std::io::Write;
7-
use types::{NativeSqlType, FromSql, FromSqlRow, Nullable, ToSql, IsNull};
7+
use types::{NativeSqlType, FromSql, FromSqlRow, Nullable, ToSql, IsNull, NotNull};
88

9-
impl<T: NativeSqlType> NativeSqlType for Nullable<T> {
9+
impl<T: NativeSqlType + NotNull> NativeSqlType for Nullable<T> {
1010
fn oid(&self) -> u32 {
1111
self.0.oid()
1212
}
@@ -22,7 +22,7 @@ impl<T: NativeSqlType> NativeSqlType for Nullable<T> {
2222

2323
impl<T, ST> FromSql<Nullable<ST>> for Option<T> where
2424
T: FromSql<ST>,
25-
ST: NativeSqlType,
25+
ST: NativeSqlType + NotNull,
2626
{
2727
fn from_sql(bytes: Option<&[u8]>) -> Result<Self, Box<Error>> {
2828
match bytes {
@@ -35,7 +35,7 @@ impl<T, ST> FromSql<Nullable<ST>> for Option<T> where
3535
impl<T, ST> Queryable<Nullable<ST>> for Option<T> where
3636
T: Queryable<ST>,
3737
Option<T::Row>: FromSqlRow<Nullable<ST>>,
38-
ST: NativeSqlType,
38+
ST: NativeSqlType + NotNull,
3939
{
4040
type Row = Option<T::Row>;
4141

@@ -46,7 +46,7 @@ impl<T, ST> Queryable<Nullable<ST>> for Option<T> where
4646

4747
impl<T, ST> ToSql<Nullable<ST>> for Option<T> where
4848
T: ToSql<ST>,
49-
ST: NativeSqlType,
49+
ST: NativeSqlType + NotNull,
5050
{
5151
fn to_sql<W: Write>(&self, out: &mut W) -> Result<IsNull, Box<Error>> {
5252
if let &Some(ref value) = self {
@@ -59,7 +59,7 @@ impl<T, ST> ToSql<Nullable<ST>> for Option<T> where
5959

6060
impl<T, ST> AsExpression<Nullable<ST>> for Option<T> where
6161
Option<T>: ToSql<Nullable<ST>>,
62-
ST: NativeSqlType,
62+
ST: NativeSqlType + NotNull,
6363
{
6464
type Expression = Bound<Nullable<ST>, Self>;
6565

@@ -70,7 +70,7 @@ impl<T, ST> AsExpression<Nullable<ST>> for Option<T> where
7070

7171
impl<'a, T, ST> AsExpression<Nullable<ST>> for &'a Option<T> where
7272
Option<T>: ToSql<Nullable<ST>>,
73-
ST: NativeSqlType,
73+
ST: NativeSqlType + NotNull,
7474
{
7575
type Expression = Bound<Nullable<ST>, Self>;
7676

diesel/src/types/impls/primitives.rs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ use data_types::PgNumeric;
55
use expression::bound::Bound;
66
use expression::{Expression, AsExpression};
77
use super::option::UnexpectedNullError;
8-
use types::{NativeSqlType, FromSql, ToSql, IsNull};
8+
use types::{NativeSqlType, FromSql, ToSql, IsNull, NotNull};
99
use {Queryable, types};
1010

1111
primitive_impls! {
@@ -48,6 +48,8 @@ impl NativeSqlType for () {
4848
}
4949
}
5050

51+
impl NotNull for () {}
52+
5153
impl FromSql<types::Bool> for bool {
5254
fn from_sql(bytes: Option<&[u8]>) -> Result<Self, Box<Error>> {
5355
match bytes {

diesel/src/types/impls/tuples.rs

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ use query_builder::{Changeset, QueryBuilder, BuildQueryResult};
44
use query_source::{QuerySource, Queryable, Table, Column};
55
use row::Row;
66
use std::error::Error;
7-
use types::{NativeSqlType, FromSqlRow, ToSql, Nullable};
7+
use types::{NativeSqlType, FromSqlRow, ToSql, Nullable, IntoNullable, NotNull};
88

99
// FIXME(https://github.com/rust-lang/rust/issues/19630) Remove this work-around
1010
macro_rules! e {
@@ -32,6 +32,9 @@ macro_rules! tuple_impls {
3232
}
3333
}
3434

35+
impl<$($T: NativeSqlType),+> NotNull for ($($T,)+) {
36+
}
37+
3538
impl<$($T),+,$($ST),+> FromSqlRow<($($ST,)+)> for ($($T,)+) where
3639
$($T: FromSqlRow<$ST>),+,
3740
$($ST: NativeSqlType),+
@@ -115,8 +118,8 @@ macro_rules! tuple_impls {
115118
impl<$($T),+, $($ST),+, QS>
116119
SelectableExpression<QS, Nullable<($($ST,)+)>>
117120
for ($($T,)+) where
118-
$($ST: NativeSqlType),+,
119-
$($T: SelectableExpression<QS, Nullable<$ST>>),+,
121+
$($ST: NativeSqlType + IntoNullable),+,
122+
$($T: SelectableExpression<QS, $ST::Nullable, SqlType=$ST>),+,
120123
($($T,)+): Expression,
121124
{
122125
}

diesel/src/types/mod.rs

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,7 @@ pub type BigSerial = BigInt;
5454
#[derive(Clone, Copy, Default)] pub struct Time;
5555
#[derive(Clone, Copy, Default)] pub struct Timestamp;
5656

57-
#[derive(Clone, Copy, Default)] pub struct Nullable<T: NativeSqlType>(T);
57+
#[derive(Clone, Copy, Default)] pub struct Nullable<T: NativeSqlType + NotNull>(T);
5858
#[derive(Clone, Copy, Default)] pub struct Array<T: NativeSqlType>(T);
5959

6060
pub trait NativeSqlType {
@@ -63,6 +63,21 @@ pub trait NativeSqlType {
6363
fn new() -> Self where Self: Sized;
6464
}
6565

66+
pub trait NotNull {
67+
}
68+
69+
pub trait IntoNullable {
70+
type Nullable: NativeSqlType;
71+
}
72+
73+
impl<T: NativeSqlType + NotNull> IntoNullable for T {
74+
type Nullable = Nullable<T>;
75+
}
76+
77+
impl<T: NativeSqlType + NotNull> IntoNullable for Nullable<T> {
78+
type Nullable = Nullable<T>;
79+
}
80+
6681
/// How to deserialize a single field of a given type. The input will always be
6782
/// the binary representation, not the text.
6883
pub trait FromSql<A: NativeSqlType>: Sized {

diesel/src/types/ord.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
use types::{self, NativeSqlType};
1+
use types::{self, NativeSqlType, NotNull};
22

33
pub trait SqlOrd {}
44

@@ -13,4 +13,4 @@ impl SqlOrd for types::Date {}
1313
impl SqlOrd for types::Interval {}
1414
impl SqlOrd for types::Time {}
1515
impl SqlOrd for types::Timestamp {}
16-
impl<T: SqlOrd + NativeSqlType> SqlOrd for types::Nullable<T> {}
16+
impl<T: SqlOrd + NativeSqlType + NotNull> SqlOrd for types::Nullable<T> {}

diesel_codegen/src/associations/belongs_to.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -200,7 +200,8 @@ fn selectable_column_impl(
200200
).unwrap(), quote_item!(cx,
201201
impl ::diesel::expression::SelectableExpression<
202202
::diesel::query_source::LeftOuterJoinSource<$parent_table, $child_table>,
203-
::diesel::types::Nullable<<$column as ::diesel::Expression>::SqlType>,
203+
<<$column as ::diesel::Expression>::SqlType
204+
as ::diesel::types::IntoNullable>::Nullable,
204205
> for $column {}
205206
).unwrap()].to_vec()
206207
}

diesel_codegen/src/associations/has_many.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -143,7 +143,8 @@ fn selectable_column_impl(
143143
).unwrap(), quote_item!(cx,
144144
impl ::diesel::expression::SelectableExpression<
145145
::diesel::query_source::LeftOuterJoinSource<$foreign_table, $table>,
146-
::diesel::types::Nullable<<$column as ::diesel::Expression>::SqlType>,
146+
<<$column as ::diesel::Expression>::SqlType
147+
as ::diesel::types::IntoNullable>::Nullable,
147148
> for $column {}
148149
).unwrap()].to_vec()
149150
}

0 commit comments

Comments
 (0)