diff --git a/diesel/src/query_builder/delete_statement.rs b/diesel/src/query_builder/delete_statement.rs index 06b330cad15c..792c267ba9f7 100644 --- a/diesel/src/query_builder/delete_statement.rs +++ b/diesel/src/query_builder/delete_statement.rs @@ -1,63 +1,80 @@ -use backend::{Backend, SupportsReturningClause}; -use expression::{Expression, SelectableExpression, NonAggregate}; +use backend::Backend; +use expression::SelectableExpression; use query_builder::*; +use query_builder::returning_clause::*; use query_source::Table; use result::QueryResult; #[derive(Debug)] -pub struct DeleteStatement(UpdateTarget); +pub struct DeleteStatement { + table: T, + where_clause: U, + returning: Ret, +} -impl DeleteStatement { +impl DeleteStatement { #[doc(hidden)] - pub fn new(t: UpdateTarget) -> Self { - DeleteStatement(t) + pub fn new(table: T, where_clause: U) -> Self { + DeleteStatement { + table: table, + where_clause: where_clause, + returning: NoReturningClause, + } } } -impl QueryFragment for DeleteStatement where +impl QueryFragment for DeleteStatement where DB: Backend, T: Table, T::FromClause: QueryFragment, U: QueryFragment, + Ret: QueryFragment, { fn to_sql(&self, out: &mut DB::QueryBuilder) -> BuildQueryResult { out.push_sql("DELETE FROM "); - try!(self.0.table.from_clause().to_sql(out)); - try!(self.0.where_clause.to_sql(out)); + try!(self.table.from_clause().to_sql(out)); + try!(self.where_clause.to_sql(out)); + try!(self.returning.to_sql(out)); Ok(()) } fn collect_binds(&self, out: &mut DB::BindCollector) -> QueryResult<()> { - try!(self.0.table.from_clause().collect_binds(out)); - try!(self.0.where_clause.collect_binds(out)); + try!(self.table.from_clause().collect_binds(out)); + try!(self.where_clause.collect_binds(out)); + try!(self.returning.collect_binds(out)); Ok(()) } fn is_safe_to_cache_prepared(&self) -> bool { - self.0.table.from_clause().is_safe_to_cache_prepared() && - self.0.where_clause.is_safe_to_cache_prepared() + self.table.from_clause().is_safe_to_cache_prepared() && + self.where_clause.is_safe_to_cache_prepared() && + self.returning.is_safe_to_cache_prepared() } } -impl_query_id!(noop: DeleteStatement); +impl_query_id!(DeleteStatement); -impl AsQuery for DeleteStatement where +impl AsQuery for DeleteStatement where T: Table, - ::AllColumns: Expression + SelectableExpression, - DeleteQuery<::AllColumns, DeleteStatement>: Query, + T::AllColumns: SelectableExpression, + DeleteStatement>: Query, { type SqlType = ::SqlType; - type Query = DeleteQuery<::AllColumns, DeleteStatement>; + type Query = DeleteStatement>; fn as_query(self) -> Self::Query { - DeleteQuery { - returning: T::all_columns(), - statement: self, - } + self.returning(T::all_columns()) } } -impl DeleteStatement { +impl Query for DeleteStatement> where + T: Table, + Ret: SelectableExpression, +{ + type SqlType = Ret::SqlType; +} + +impl DeleteStatement { /// Specify what expression is returned after execution of the `delete`. /// /// # Examples @@ -87,52 +104,14 @@ impl DeleteStatement { /// # #[cfg(not(feature = "postgres"))] /// # fn main() {} /// ``` - pub fn returning(self, returns: E) -> DeleteQuery where - E: Expression + SelectableExpression, - DeleteQuery: Query, + pub fn returning(self, returns: E) -> DeleteStatement> where + E: SelectableExpression, + DeleteStatement>: Query, { - DeleteQuery { - returning: returns, - statement: self, + DeleteStatement { + table: self.table, + where_clause: self.where_clause, + returning: ReturningClause(returns), } } } - -#[doc(hidden)] -#[derive(Debug, Copy, Clone)] -pub struct DeleteQuery { - returning: T, - statement: U, -} - -impl Query for DeleteQuery where - T: Expression + NonAggregate, -{ - type SqlType = T::SqlType; -} - -impl QueryFragment for DeleteQuery where - DB: Backend + SupportsReturningClause, - T: QueryFragment, - U: QueryFragment, -{ - fn to_sql(&self, out: &mut DB::QueryBuilder) -> BuildQueryResult { - try!(self.statement.to_sql(out)); - out.push_sql(" RETURNING "); - try!(self.returning.to_sql(out)); - Ok(()) - } - - fn collect_binds(&self, out: &mut DB::BindCollector) -> QueryResult<()> { - try!(self.statement.collect_binds(out)); - try!(self.returning.collect_binds(out)); - Ok(()) - } - - fn is_safe_to_cache_prepared(&self) -> bool { - self.statement.is_safe_to_cache_prepared() && - self.returning.is_safe_to_cache_prepared() - } -} - -impl_query_id!(noop: DeleteQuery); diff --git a/diesel/src/query_builder/functions.rs b/diesel/src/query_builder/functions.rs index 31bcb9a5ed1f..d74d63bb36b3 100644 --- a/diesel/src/query_builder/functions.rs +++ b/diesel/src/query_builder/functions.rs @@ -104,7 +104,8 @@ pub fn update(source: T) -> IncompleteUpdateStatement(source: T) -> DeleteStatement { - DeleteStatement::new(source.into_update_target()) + let target = source.into_update_target(); + DeleteStatement::new(target.table, target.where_clause) } /// Creates an insert statement. Will add the given data to a table. This diff --git a/diesel/src/query_builder/update_statement/mod.rs b/diesel/src/query_builder/update_statement/mod.rs index 739f04c381da..8c10b3e5c902 100644 --- a/diesel/src/query_builder/update_statement/mod.rs +++ b/diesel/src/query_builder/update_statement/mod.rs @@ -4,9 +4,10 @@ pub mod target; pub use self::changeset::{Changeset, AsChangeset}; pub use self::target::{UpdateTarget, IntoUpdateTarget}; -use backend::{Backend, SupportsReturningClause}; +use backend::Backend; use expression::{Expression, SelectableExpression, NonAggregate}; use query_builder::{Query, AsQuery, QueryFragment, QueryBuilder, BuildQueryResult}; +use query_builder::returning_clause::*; use query_source::Table; use result::QueryResult; @@ -23,32 +24,35 @@ impl IncompleteUpdateStatement { } impl IncompleteUpdateStatement { - pub fn set(self, values: V) -> UpdateStatement where + pub fn set(self, values: V) -> UpdateStatement where T: Table, V: changeset::AsChangeset, - UpdateStatement: AsQuery, + UpdateStatement: AsQuery, { UpdateStatement { table: self.0.table, where_clause: self.0.where_clause, values: values.as_changeset(), + returning: NoReturningClause, } } } #[derive(Debug, Copy, Clone)] -pub struct UpdateStatement { +pub struct UpdateStatement { table: T, where_clause: U, values: V, + returning: Ret, } -impl QueryFragment for UpdateStatement where +impl QueryFragment for UpdateStatement where DB: Backend, T: Table, T::FromClause: QueryFragment, U: QueryFragment, V: changeset::Changeset, + Ret: QueryFragment, { fn to_sql(&self, out: &mut DB::QueryBuilder) -> BuildQueryResult { if self.values.is_noop() { @@ -61,6 +65,7 @@ impl QueryFragment for UpdateStatement where out.push_sql(" SET "); try!(self.values.to_sql(out)); try!(self.where_clause.to_sql(out)); + try!(self.returning.to_sql(out)); Ok(()) } @@ -68,6 +73,7 @@ impl QueryFragment for UpdateStatement where try!(self.table.from_clause().collect_binds(out)); try!(self.values.collect_binds(out)); try!(self.where_clause.collect_binds(out)); + try!(self.returning.collect_binds(out)); Ok(()) } @@ -76,24 +82,28 @@ impl QueryFragment for UpdateStatement where } } -impl_query_id!(noop: UpdateStatement); +impl_query_id!(noop: UpdateStatement); -impl AsQuery for UpdateStatement where +impl AsQuery for UpdateStatement where T: Table, - UpdateQuery>: Query, + UpdateStatement>: Query, { type SqlType = ::SqlType; - type Query = UpdateQuery; + type Query = UpdateStatement>; fn as_query(self) -> Self::Query { - UpdateQuery { - returning: T::all_columns(), - statement: self, - } + self.returning(T::all_columns()) } } -impl UpdateStatement { +impl Query for UpdateStatement> where + T: Table, + Ret: Expression + SelectableExpression + NonAggregate, +{ + type SqlType = Ret::SqlType; +} + +impl UpdateStatement { /// Specify what expression is returned after execution of the `update`. /// # Examples /// @@ -123,52 +133,15 @@ impl UpdateStatement { /// # #[cfg(not(feature = "postgres"))] /// # fn main() {} /// ``` - pub fn returning(self, returns: E) -> UpdateQuery where + pub fn returning(self, returns: E) -> UpdateStatement> where T: Table, - UpdateQuery: Query, + UpdateStatement>: Query, { - UpdateQuery { - returning: returns, - statement: self, + UpdateStatement { + table: self.table, + where_clause: self.where_clause, + values: self.values, + returning: ReturningClause(returns), } } } - -#[doc(hidden)] -#[derive(Debug, Copy, Clone)] -pub struct UpdateQuery { - returning: T, - statement: U, -} - -impl Query for UpdateQuery> where - T: Table, - Ret: Expression + SelectableExpression + NonAggregate, -{ - type SqlType = Ret::SqlType; -} - -impl QueryFragment for UpdateQuery where - DB: Backend + SupportsReturningClause, - T: QueryFragment, - U: QueryFragment, -{ - fn to_sql(&self, out: &mut DB::QueryBuilder) -> BuildQueryResult { - try!(self.statement.to_sql(out)); - out.push_sql(" RETURNING "); - try!(self.returning.to_sql(out)); - Ok(()) - } - - fn collect_binds(&self, out: &mut DB::BindCollector) -> QueryResult<()> { - try!(self.statement.collect_binds(out)); - try!(self.returning.collect_binds(out)); - Ok(()) - } - - fn is_safe_to_cache_prepared(&self) -> bool { - false - } -} - -impl_query_id!(noop: UpdateQuery);