mirror of
https://github.com/diesel-rs/diesel.git
synced 2024-10-04 01:28:13 +03:00
Merge pull request #567 from diesel-rs/sg-insert-option-into-not-null
Allow inserting `Option<T>` into columns where the type is not nullable
This commit is contained in:
commit
54a99472ed
@ -17,6 +17,11 @@ for Rust libraries in [RFC #1105](https://github.com/rust-lang/rfcs/blob/master/
|
||||
|
||||
* The `persistable` module has been renamed to `insertable`.
|
||||
|
||||
### Fixed
|
||||
|
||||
* `#[derive(Insertable)]` allows fields of type `Option<T>` to be used with
|
||||
columns that are not null if they have a default value.
|
||||
|
||||
## [0.9.1] - 2016-12-09
|
||||
|
||||
### Fixed
|
||||
|
@ -40,3 +40,7 @@ pub type NotBetween<Lhs, Rhs> = super::predicates::NotBetween<Lhs,
|
||||
pub use super::predicates::{IsNull, IsNotNull, Asc, Desc};
|
||||
#[doc(inline)]
|
||||
pub use super::array_comparison::EqAny;
|
||||
|
||||
#[doc(hidden)]
|
||||
pub type AsNullableExpr<Item, TargetExpr> = AsExprOf<Item,
|
||||
<SqlTypeOf<TargetExpr> as types::IntoNullable>::Nullable>;
|
||||
|
@ -5,6 +5,7 @@ use expression::Expression;
|
||||
use result::QueryResult;
|
||||
use query_builder::{QueryBuilder, BuildQueryResult};
|
||||
use query_source::{Table, Column};
|
||||
use types::IntoNullable;
|
||||
|
||||
/// Represents that a structure can be used to to insert a new row into the
|
||||
/// database. This is automatically implemented for `&[T]` and `&Vec<T>` for
|
||||
@ -32,7 +33,8 @@ pub trait InsertValues<DB: Backend> {
|
||||
#[derive(Debug, Copy, Clone)]
|
||||
pub enum ColumnInsertValue<Col, Expr> where
|
||||
Col: Column,
|
||||
Expr: Expression<SqlType=Col::SqlType>,
|
||||
Col::SqlType: IntoNullable,
|
||||
Expr: Expression<SqlType=<Col::SqlType as IntoNullable>::Nullable>,
|
||||
{
|
||||
Expression(Col, Expr),
|
||||
Default(Col),
|
||||
|
@ -163,7 +163,7 @@ macro_rules! impl_Insertable {
|
||||
($(
|
||||
$crate::insertable::ColumnInsertValue<
|
||||
$table_name::$column_name,
|
||||
$crate::expression::helper_types::AsExpr<
|
||||
$crate::expression::helper_types::AsNullableExpr<
|
||||
&'insert $field_ty,
|
||||
$table_name::$column_name,
|
||||
>,
|
||||
@ -173,7 +173,7 @@ macro_rules! impl_Insertable {
|
||||
type Values = ($(
|
||||
$crate::insertable::ColumnInsertValue<
|
||||
$table_name::$column_name,
|
||||
$crate::expression::helper_types::AsExpr<
|
||||
$crate::expression::helper_types::AsNullableExpr<
|
||||
&'insert $field_ty,
|
||||
$table_name::$column_name,
|
||||
>,
|
||||
@ -184,6 +184,7 @@ macro_rules! impl_Insertable {
|
||||
fn values(self) -> Self::Values {
|
||||
use $crate::expression::{AsExpression, Expression};
|
||||
use $crate::insertable::ColumnInsertValue;
|
||||
use $crate::types::IntoNullable;
|
||||
let $self_to_columns = *self;
|
||||
($(
|
||||
Insertable_column_expr!($table_name::$column_name, $column_name, $field_kind)
|
||||
@ -222,7 +223,7 @@ macro_rules! Insertable_column_expr {
|
||||
($column:path, $field_access:expr, regular) => {
|
||||
ColumnInsertValue::Expression(
|
||||
$column,
|
||||
AsExpression::<<$column as Expression>::SqlType>
|
||||
AsExpression::<<<$column as Expression>::SqlType as IntoNullable>::Nullable>
|
||||
::as_expression($field_access),
|
||||
)
|
||||
};
|
||||
|
@ -111,7 +111,8 @@ macro_rules! tuple_impls {
|
||||
DB: Backend + SupportsDefaultKeyword,
|
||||
Tab: Table,
|
||||
$($T: Column<Table=Tab>,)+
|
||||
$($ST: Expression<SqlType=$T::SqlType> + QueryFragment<DB>,)+
|
||||
$($T::SqlType: IntoNullable,)+
|
||||
$($ST: Expression<SqlType=<$T::SqlType as IntoNullable>::Nullable> + QueryFragment<DB>,)+
|
||||
{
|
||||
fn column_names(&self, out: &mut DB::QueryBuilder) -> BuildQueryResult {
|
||||
$(
|
||||
@ -158,7 +159,8 @@ macro_rules! tuple_impls {
|
||||
for ($(ColumnInsertValue<$T, $ST>,)+) where
|
||||
Tab: Table,
|
||||
$($T: Column<Table=Tab>,)+
|
||||
$($ST: Expression<SqlType=$T::SqlType> + QueryFragment<::sqlite::Sqlite>,)+
|
||||
$($T::SqlType: IntoNullable,)+
|
||||
$($ST: Expression<SqlType=<$T::SqlType as IntoNullable>::Nullable> + QueryFragment<::sqlite::Sqlite>,)+
|
||||
{
|
||||
#[allow(unused_assignments)]
|
||||
fn column_names(&self, out: &mut ::sqlite::SqliteQueryBuilder) -> BuildQueryResult {
|
||||
|
@ -215,3 +215,27 @@ fn derive_identifiable_with_composite_pk() {
|
||||
assert_eq!((&2, &3), foo1.id());
|
||||
assert_eq!((&6, &7), foo2.id());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn derive_insertable_with_option_for_not_null_field_with_default() {
|
||||
#[derive(Insertable)]
|
||||
#[table_name="users"]
|
||||
struct NewUser {
|
||||
id: Option<i32>,
|
||||
name: &'static str,
|
||||
}
|
||||
|
||||
let conn = connection();
|
||||
let data = vec![
|
||||
NewUser { id: None, name: "Jim" },
|
||||
NewUser { id: Some(123), name: "Bob" },
|
||||
];
|
||||
assert_eq!(Ok(2), insert(&data).into(users::table).execute(&conn));
|
||||
|
||||
let users = users::table.load::<User>(&conn).unwrap();
|
||||
let jim = users.iter().find(|u| u.name == "Jim");
|
||||
let bob = users.iter().find(|u| u.name == "Bob");
|
||||
|
||||
assert!(jim.is_some());
|
||||
assert_eq!(Some(&User::new(123, "Bob")), bob);
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user