diff --git a/CHANGELOG.md b/CHANGELOG.md index 77b30318f30d..4ebe951301dd 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -31,6 +31,12 @@ for Rust libraries in [RFC #1105](https://github.com/rust-lang/rfcs/blob/master/ have been. All types in Diesel are now correctly only considered non-aggregate if their parts are. +* Parenthesis are now inserted around all mathematical operations. This means + that `(2.into_sql() + 3) * 4` will correctly evaluate to 20 as expected. + Previously we would generate SQL that evaluated to 14. This could even result + in runtime errors if multiple types were involved (for example, `interval * + (integer + 1)`) + ### Deprecated * `diesel_(prefix|postfix|infix)_operator!` have been deprecated. These macros diff --git a/diesel/src/expression/ops/numeric.rs b/diesel/src/expression/ops/numeric.rs index 5a266b8a944d..8bdf37bf052e 100644 --- a/diesel/src/expression/ops/numeric.rs +++ b/diesel/src/expression/ops/numeric.rs @@ -37,9 +37,11 @@ macro_rules! numeric_operation { Rhs: QueryFragment, { fn walk_ast(&self, mut out: AstPass) -> QueryResult<()> { + out.push_sql("("); self.lhs.walk_ast(out.reborrow())?; out.push_sql($op); self.rhs.walk_ast(out.reborrow())?; + out.push_sql(")"); Ok(()) } } diff --git a/diesel_tests/tests/expressions/ops.rs b/diesel_tests/tests/expressions/ops.rs index a6bf7813d0bc..931405b63d77 100644 --- a/diesel_tests/tests/expressions/ops.rs +++ b/diesel_tests/tests/expressions/ops.rs @@ -174,6 +174,7 @@ fn test_dividing_nullables() { let data = nullable_table.select(value / value).load(&connection); assert_eq!(Ok(expected_data), data); } + #[test] fn mix_and_match_all_numeric_ops() { use schema::users::dsl::*; @@ -190,3 +191,11 @@ fn mix_and_match_all_numeric_ops() { let data = users.select(id * 3 / 2 + 4 - 1).load(&connection); assert_eq!(Ok(expected_data), data); } + +#[test] +fn precedence_with_parens_is_maintained() { + use diesel::sql_types::Integer; + + let x = select((2.into_sql::() + 3) * 4).get_result::(&connection()); + assert_eq!(Ok(20), x); +}