Rust Diesel left join on multiple conditions - rust

I am having difficulty determining from Diesel's documentation how to express this query with Diesel (without using raw_sql):
SELECT *
FROM budgets AS b
LEFT JOIN user_budgets AS ub
ON (ub.budget_id = {budget_id}
AND ub.user_id = {user_id})
WHERE b.id = {budget_id}
LIMIT 1;
{budget_id} and {user_id} are variable. This is what I've tried:
let budget = budgets
.select(budget_fields::all_columns)
.left_join(user_budgets.on(user_budget_fields::budget_id.eq(budget_id)))
.left_join(user_budget_fields::user_id.eq(user_id))
.filter(budget_fields::id.eq(budget_id))
.first::<Budget>(db_connection)?;
but I get this error:
error[E0277]: the trait bound `budgets::table: JoinTo<diesel::expression::operators::Eq<user_budgets::columns::user_id, diesel::expression::bound::Bound<diesel::sql_types::Uuid, uuid::Uuid>>>` is not satisfied
--> src/utils/db/budget.rs:46:10
|
46 | .left_join(user_budget_fields::user_id.eq(user_id))
| ^^^^^^^^^ the trait `JoinTo<diesel::expression::operators::Eq<user_budgets::columns::user_id, diesel::expression::bound::Bound<diesel::sql_types::Uuid, uuid::Uuid>>>` is not implemented for `budgets::table`
|
= help: the following other types implement trait `JoinTo<T>`:
<budgets::table as JoinTo<JoinOn<Join, On>>>
<budgets::table as JoinTo<diesel::query_builder::BoxedSelectStatement<'a, QS, ST, DB>>>
<budgets::table as JoinTo<diesel::query_builder::SelectStatement<F, S, D, W, O, L, Of, G>>>
<budgets::table as JoinTo<diesel::query_source::joins::Join<Left, Right, Kind>>>
= note: required because of the requirements on the impl of `JoinTo<diesel::expression::operators::Eq<user_budgets::columns::user_id, diesel::expression::bound::Bound<diesel::sql_types::Uuid, uuid::Uuid>>>` for `diesel::query_source::joins::Join<budgets::table, user_budgets::table, LeftOuter>`
= note: required because of the requirements on the impl of `JoinWithImplicitOnClause<diesel::expression::operators::Eq<user_budgets::columns::user_id, diesel::expression::bound::Bound<diesel::sql_types::Uuid, uuid::Uuid>>, LeftOuter>` for `diesel::query_builder::SelectStatement<JoinOn<diesel::query_source::joins::Join<budgets::table, user_budgets::table, LeftOuter>, diesel::expression::operators::Eq<user_budgets::columns::budget_id, diesel::expression::bound::Bound<diesel::sql_types::Uuid, uuid::Uuid>>>, query_builder::select_clause::SelectClause<(budgets::columns::id, budgets::columns::is_shared, budgets::columns::is_private, budgets::columns::is_deleted, budgets::columns::name, budgets::columns::description, budgets::columns::start_date, budgets::columns::end_date, budgets::columns::latest_entry_time, budgets::columns::modified_timestamp, budgets::columns::created_timestamp)>>`
For more information about this error, try `rustc --explain E0277`.
I have also tried this:
let budget = budgets
.select(budget_fields::all_columns)
.left_join(
user_budgets
.on(user_budget_fields::budget_id.eq(budget_id))
.and(user_budget_fields::user_id.eq(user_id)),
)
.filter(budget_fields::id.eq(budget_id))
.first::<Budget>(db_connection)?;
but I get this error:
error[E0599]: the method `and` exists for struct `OnClauseWrapper<user_budgets::table, diesel::expression::operators::Eq<user_budgets::columns::budget_id, diesel::expression::bound::Bound<diesel::sql_types::Uuid, uuid::Uuid>>>`, but its trait bounds were not satisfied
--> src/utils/db/budget.rs:48:18
|
48 | .and(user_budget_fields::user_id.eq(user_id)),
| ^^^ method cannot be called on `OnClauseWrapper<user_budgets::table, diesel::expression::operators::Eq<user_budgets::columns::budget_id, diesel::expression::bound::Bound<diesel::sql_types::Uuid, uuid::Uuid>>>` due to unsatisfied trait bounds
|
::: /Users/tanner/.cargo/registry/src/github.com-1ecc6299db9ec823/diesel-1.4.8/src/query_source/joins.rs:281:1
|
281 | pub struct OnClauseWrapper<Source, On> {
| --------------------------------------
| |
| doesn't satisfy `<_ as diesel::Expression>::SqlType = diesel::sql_types::Bool`
| doesn't satisfy `_: BoolExpressionMethods`
| doesn't satisfy `_: diesel::Expression`
|
= note: the following trait bounds were not satisfied:
`<OnClauseWrapper<user_budgets::table, diesel::expression::operators::Eq<user_budgets::columns::budget_id, diesel::expression::bound::Bound<diesel::sql_types::Uuid, uuid::Uuid>>> as diesel::Expression>::SqlType = diesel::sql_types::Bool`
which is required by `OnClauseWrapper<user_budgets::table, diesel::expression::operators::Eq<user_budgets::columns::budget_id, diesel::expression::bound::Bound<diesel::sql_types::Uuid, uuid::Uuid>>>: BoolExpressionMethods`
For more information about this error, try `rustc --explain E0599`.
What am I missing here?

You definitely want a single left_join. In your second attempt, the error is that the and needs to be inside the call to on, not after it (the argument to on must be the full boolean expression).
let budget = budgets
.select(budget_fields::all_columns)
.left_join(
user_budgets.on(
user_budget_fields::budget_id.eq(budget_id)
.and(user_budget_fields::user_id.eq(user_id))),
)
.filter(budget_fields::id.eq(budget_id))
.first::<Budget>(db_connection)?;

Related

Error compiling dependency to a proc-macro when targeting wasm

I have a procedural macro I have implemented which depends on the proc-macro-error crate. My client project depends on this macro crate.
When I build for native, everything works perfectly, but when I build for wasm, I get a number of errors thrown from proc-macro-error:
error[E0599]: no method named `unwrap` found for struct `proc_macro2::Span` in the current scope
--> /Users/spencerkohan/.cargo/registry/src/github.com-1ecc6299db9ec823/proc-macro-error-1.0.4/src/imp/delegate.rs:33:38
|
33 | let span = span_range.collapse().unwrap();
| ^^^^^^ method not found in `proc_macro2::Span`
error[E0599]: no method named `unwrap` found for struct `proc_macro2::Span` in the current scope
--> /Users/spencerkohan/.cargo/registry/src/github.com-1ecc6299db9ec823/proc-macro-error-1.0.4/src/imp/delegate.rs:49:53
|
49 | res.span_note(span_range.collapse().unwrap(), msg)
| ^^^^^^ method not found in `proc_macro2::Span`
error[E0599]: no method named `unwrap` found for struct `proc_macro2::Span` in the current scope
--> /Users/spencerkohan/.cargo/registry/src/github.com-1ecc6299db9ec823/proc-macro-error-1.0.4/src/imp/delegate.rs:52:53
|
52 | res.span_help(span_range.collapse().unwrap(), msg)
| ^^^^^^ method not found in `proc_macro2::Span`
error[E0599]: no method named `unwrap` found for struct `proc_macro2::Span` in the current scope
--> /Users/spencerkohan/.cargo/registry/src/github.com-1ecc6299db9ec823/proc-macro-error-1.0.4/src/imp/delegate.rs:60:42
|
60 | let span = span_range.collapse().unwrap();
| ^^^^^^ method not found in `proc_macro2::Span`
error[E0277]: the trait bound `proc_macro::TokenStream: From<TokenStream2>` is not satisfied
--> /Users/spencerkohan/.cargo/registry/src/github.com-1ecc6299db9ec823/proc-macro-error-1.0.4/src/lib.rs:459:29
|
459 | gen_error().into()
| ^^^^ the trait `From<TokenStream2>` is not implemented for `proc_macro::TokenStream`
|
= help: the trait `From<proc_macro::TokenTree>` is implemented for `proc_macro::TokenStream`
= note: required because of the requirements on the impl of `Into<proc_macro::TokenStream>` for `TokenStream2`
error[E0277]: the trait bound `proc_macro::TokenStream: From<TokenStream2>` is not satisfied
--> /Users/spencerkohan/.cargo/registry/src/github.com-1ecc6299db9ec823/proc-macro-error-1.0.4/src/lib.rs:464:34
|
464 | Ok(_) => gen_error().into(),
| ^^^^ the trait `From<TokenStream2>` is not implemented for `proc_macro::TokenStream`
|
= help: the trait `From<proc_macro::TokenTree>` is implemented for `proc_macro::TokenStream`
= note: required because of the requirements on the impl of `Into<proc_macro::TokenStream>` for `TokenStream2`
error[E0277]: the trait bound `proc_macro2::Span: From<proc_macro::Span>` is not satisfied
--> /Users/spencerkohan/.cargo/registry/src/github.com-1ecc6299db9ec823/proc-macro-error-1.0.4/src/lib.rs:549:37
|
549 | first: self.clone().into(),
| ^^^^ the trait `From<proc_macro::Span>` is not implemented for `proc_macro2::Span`
|
= note: required because of the requirements on the impl of `Into<proc_macro2::Span>` for `proc_macro::Span`
error[E0277]: the trait bound `proc_macro2::Span: From<proc_macro::Span>` is not satisfied
--> /Users/spencerkohan/.cargo/registry/src/github.com-1ecc6299db9ec823/proc-macro-error-1.0.4/src/lib.rs:550:36
|
550 | last: self.clone().into(),
| ^^^^ the trait `From<proc_macro::Span>` is not implemented for `proc_macro2::Span`
|
= note: required because of the requirements on the impl of `Into<proc_macro2::Span>` for `proc_macro::Span`
It doesn't make sense to me why there should be an issue: this code is not actually compiled for wasm, it's only called inside the proc macro, which is used at compile time.
How can I solve this issue?

Rust Diesel update on joined table

I am trying to update a field in a table use Diesel. I need to verify an association in another table, so I am LEFT JOIN-ing the other table. Here is a SQL representation of what I am doing:
UPDATE table_name AS tn
SET field = 'value'
FROM table_name
LEFT JOIN other_table AS ot
ON ot.id_field_one = {some_id}
WHERE tn.id_field_one = {some_id} and ot.id_field_two = {some_different_id};
Here is what I have tried with Diesel:
dsl::update(
table_name
.left_join(other_table.on(other_table_fields::id_field_one.eq(some_id)))
.filter(table_fields::id_field_one.eq(some_id))
.filter(other_table_fields::id_field_two.eq(some_different_id))
)
.set(table_fields::field.eq("value"))
.execute(db_connection)?;
I get the following error (I've replaced the table and field names to match the names of my examples above):
error[E0277]: the trait bound `diesel::query_builder::SelectStatement<JoinOn<diesel::query_source::joins::Join<table_name::table, other_table::table, LeftOuter>, diesel::expression::operators::Eq<other_table::columns::some_id, diesel::expression::bound::Bound<diesel::sql_types::Uuid, uuid::Uuid>>>, query_builder::select_clause::DefaultSelectClause, query_builder::distinct_clause::NoDistinctClause, query_builder::where_clause::WhereClause<And<diesel::expression::operators::Eq<other_table::columns::some_different_id, diesel::expression::bound::Bound<diesel::sql_types::Uuid, uuid::Uuid>>, diesel::expression::operators::Eq<table_name::columns::id, diesel::expression::bound::Bound<diesel::sql_types::Uuid, uuid::Uuid>>>>>: diesel::query_builder::IntoUpdateTarget` is not satisfied
--> src/file.rs:297:9
|
296 | match dsl::update(
| ----------- required by a bound introduced by this call
297 | / table_name
298 | | .left_join(other_table.on(other_table_fields::some_id.eq(some_id)))
299 | | .filter(other_table_fields::some_different_id.eq(some_different_id))
300 | | .filter(table_fields::id.eq(some_id)),
| |________________________________________________________________^ the trait `diesel::query_builder::IntoUpdateTarget` is not implemented for `diesel::query_builder::SelectStatement<JoinOn<diesel::query_source::joins::Join<table_name::table, other_table::table, LeftOuter>, diesel::expression::operators::Eq<other_table::columns::some_id, diesel::expression::bound::Bound<diesel::sql_types::Uuid, uuid::Uuid>>>, query_builder::select_clause::DefaultSelectClause, query_builder::distinct_clause::NoDistinctClause, query_builder::where_clause::WhereClause<And<diesel::expression::operators::Eq<other_table::columns::some_different_id, diesel::expression::bound::Bound<diesel::sql_types::Uuid, uuid::Uuid>>, diesel::expression::operators::Eq<table_name::columns::id, diesel::expression::bound::Bound<diesel::sql_types::Uuid, uuid::Uuid>>>>>`
|
= help: the trait `diesel::query_builder::IntoUpdateTarget` is implemented for `diesel::query_builder::SelectStatement<F, query_builder::select_clause::DefaultSelectClause, query_builder::distinct_clause::NoDistinctClause, W>`
note: required by a bound in `diesel::update`
--> /Users/tanner/.cargo/registry/src/github.com-1ecc6299db9ec823/diesel-1.4.8/src/query_builder/functions.rs:80:18
|
80 | pub fn update<T: IntoUpdateTarget>(source: T) -> UpdateStatement<T::Table, T::WhereClause> {
| ^^^^^^^^^^^^^^^^ required by this bound in `diesel::update`
error[E0277]: the trait bound `JoinOn<diesel::query_source::joins::Join<table_name::table, other_table::table, LeftOuter>, diesel::expression::operators::Eq<other_table::columns::some_id, diesel::expression::bound::Bound<diesel::sql_types::Uuid, uuid::Uuid>>>: HasTable` is not satisfied
The SQL works when I run it as a query, but I can't figure out how to represent the same thing in working Rust code. What am I missing here?
Diesel does currently not support joins in that position. You can either use diesel::sql_query to write the whole query or provide a custom query dsl extension for your specific query.

"this trait cannot be made into an object because it requires `Self: Sized`", except it has Sized

Here's the error message:
error[E0038]: the trait `room::RoomInterface` cannot be made into an object
--> src\permanent\registry\mod.rs:12:33
|
12 | pub fn load(id : String) -> Result<Box<dyn RoomInterface>, String>{
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `room::RoomInterface` cannot be made into an object
|
note: for a trait to be "object safe" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety>
--> src\permanent\rooms\mod.rs:36:31
|
36 | pub trait RoomInterface : Copy + Sized {
| ------------- ^^^^ ^^^^^ ...because it requires `Self: Sized`
| | |
| | ...because it requires `Self: Sized`
| this trait cannot be made into an object...
For more information about this error, try `rustc --explain E0038`.
It says that to use the trait as an object, it requires Sized. Except that Sized is right there, in the declaration of the trait! It literally points to the word "Sized" and tells me I need to have "Sized". What's going on?
The problem is opposite to what you think: The problem is that you require Self: Sized but only traits which do not require Self: Sized can be made into an object.
As the error message states you must remove both bounds for Copy and Sized for RoomInterface:
pub trait RoomInterface {
The article linked in the error message is a great resource, I recommend reading it:
https://doc.rust-lang.org/reference/items/traits.html#object-safety
Also this discussion might be interesting:
https://users.rust-lang.org/t/trait-objects-and-the-sized-trait/14410/2

Matrix-matrix multiplication using einsum in Rust

I would like to multiply arrays with random numbers using einsum. Here is the snip of my implementation:
use ndarray_einsum_beta::*;
use ndarray::Array;
use ndarray_rand::RandomExt;
use ndarray_rand::rand_distr::Uniform;
fn main() {
let m1 = Array::random((100, 100), Uniform::new(0., 10.));
let m2 = Array::random((100, 100), Uniform::new(0., 10.));
let res = einsum("ij,jk->ik", &[&m1, &m2]);
}
While compiling the code, the following error message is thrown:
error[E0277]: the trait bound `ArrayBase<OwnedRepr<{float}>, Dim<[usize; 2]>>: ArrayLike<_>` is not satisfied
--> src/main.rs:11:37
|
11 | let res = einsum("ij,jk->ik", &[&m1, &m2]);
| ^^^ the trait `ArrayLike<_>` is not implemented for `ArrayBase<OwnedRepr<{float}>, Dim<[usize; 2]>>`
|
= note: required for the cast to the object type `dyn ArrayLike<_>`
error[E0277]: the trait bound `ArrayBase<OwnedRepr<{float}>, Dim<[usize; 2]>>: ArrayLike<_>` is not satisfied
--> src/main.rs:11:42
|
11 | let res = einsum("ij,jk->ik", &[&m1, &m2]);
| ^^^ the trait `ArrayLike<_>` is not implemented for `ArrayBase<OwnedRepr<{float}>, Dim<[usize; 2]>>`
|
= note: required for the cast to the object type `dyn ArrayLike<_>`
error: aborting due to 2 previous errors
For more information about this error, try `rustc --explain E0277`.
error: could not compile `algebra_test`
It seems that I'm getting ArrayLike instead ArrayBase matrices.
Does anyone now what might cause this issue?
Here is the Cago.toml file content:
[dependencies]
ndarray = "0.14"
ndarray_einsum_beta = "0.4.4"
ndarray-rand = "0.13.0"
rand = "0.8"

Reference traits: no implementation for `&T * &T`

I try to write generic method and specify some type T: num_traits::float::Float from num-traits crate. How should I ask &T to implement basic numeric methods such as multiplication?
use splines::{Interpolation, Key, Spline, interpolate};
use num_traits::{float::Float, identities};
use conv::prelude::*;
struct Interpolator<T>
where T: Float + interpolate::One + interpolate::Trigo {
target_x: Vec<T>,
}
impl<T> Interpolator<T>
where T: Float + interpolate::One + interpolate::Trigo {
fn interpolate<U>(&self, x: &[T], y: &[U]) -> Vec<U>
where U: Float + identities::Zero {
assert_eq!(x.len(), y.len());
let key_iter = x.iter().zip(y).map(|(x, y)| Key::new(x, y, Interpolation::Linear));
let spline = Spline::from_iter(key_iter);
let result: Vec<U> = self.target_x.iter().map(|x| spline.sample(x).unwrap_or(identities::zero())).collect();
result
}
}
fn main() {
}
Cargo.toml
[package]
name = "name"
version = "0.1.0"
edition = "2018"
[dependencies]
conv = "0.3.2"
splines = "1.0.0-rc.3"
num-traits = "0.2"
Compilation errors:
error[E0277]: the trait bound `&T: splines::interpolate::One` is not satisfied
--> src/main.rs:18:66
|
18 | let result: Vec<U> = self.target_x.iter().map(|x| spline.sample(x).unwrap_or(identities::zero())).collect();
| ^^^^^^ the trait `splines::interpolate::One` is not implemented for `&T`
error[E0277]: the trait bound `&T: splines::interpolate::Trigo` is not satisfied
--> src/main.rs:18:66
|
18 | let result: Vec<U> = self.target_x.iter().map(|x| spline.sample(x).unwrap_or(identities::zero())).collect();
| ^^^^^^ the trait `splines::interpolate::Trigo` is not implemented for `&T`
error[E0277]: cannot multiply `&T` to `&T`
--> src/main.rs:18:66
|
18 | let result: Vec<U> = self.target_x.iter().map(|x| spline.sample(x).unwrap_or(identities::zero())).collect();
| ^^^^^^ no implementation for `&T * &T`
|
= help: the trait `std::ops::Mul` is not implemented for `&T`
= help: consider adding a `where &T: std::ops::Mul` bound
error[E0277]: cannot divide `&T` by `&T`
--> src/main.rs:18:66
|
18 | let result: Vec<U> = self.target_x.iter().map(|x| spline.sample(x).unwrap_or(identities::zero())).collect();
| ^^^^^^ no implementation for `&T / &T`
|
= help: the trait `std::ops::Div` is not implemented for `&T`
= help: consider adding a `where &T: std::ops::Div` bound
error[E0277]: the trait bound `&U: splines::interpolate::Interpolate<&T>` is not satisfied
--> src/main.rs:18:66
|
18 | let result: Vec<U> = self.target_x.iter().map(|x| spline.sample(x).unwrap_or(identities::zero())).collect();
| ^^^^^^ the trait `splines::interpolate::Interpolate<&T>` is not implemented for `&U`
error[E0277]: cannot add `&T` to `&T`
--> src/main.rs:18:66
|
18 | let result: Vec<U> = self.target_x.iter().map(|x| spline.sample(x).unwrap_or(identities::zero())).collect();
| ^^^^^^ no implementation for `&T + &T`
|
= help: the trait `std::ops::Add` is not implemented for `&T`
= help: consider adding a `where &T: std::ops::Add` bound
= note: required because of the requirements on the impl of `splines::interpolate::Additive` for `&T`
error[E0277]: cannot subtract `&T` from `&T`
--> src/main.rs:18:66
|
18 | let result: Vec<U> = self.target_x.iter().map(|x| spline.sample(x).unwrap_or(identities::zero())).collect();
| ^^^^^^ no implementation for `&T - &T`
|
= help: the trait `std::ops::Sub` is not implemented for `&T`
= help: consider adding a `where &T: std::ops::Sub` bound
= note: required because of the requirements on the impl of `splines::interpolate::Additive` for `&T`
error[E0277]: the trait bound `&U: num_traits::identities::Zero` is not satisfied
--> src/main.rs:18:86
|
18 | let result: Vec<U> = self.target_x.iter().map(|x| spline.sample(x).unwrap_or(identities::zero())).collect();
| ^^^^^^^^^^^^^^^^ the trait `num_traits::identities::Zero` is not implemented for `&U`
|
= note: required by `num_traits::identities::zero`
error[E0277]: a collection of type `std::vec::Vec<U>` cannot be built from an iterator over elements of type `&U`
--> src/main.rs:18:107
|
18 | let result: Vec<U> = self.target_x.iter().map(|x| spline.sample(x).unwrap_or(identities::zero())).collect();
| ^^^^^^^ a collection of type `std::vec::Vec<U>` cannot be built from `std::iter::Iterator<Item=&U>`
|
= help: the trait `std::iter::FromIterator<&U>` is not implemented for `std::vec::Vec<U>`
error: aborting due to 9 previous errors
For more information about this error, try `rustc --explain E0277`.
error: Could not compile `trait_generic`.
Maybe you could just consider using Key::new(*x, *y, Interpolation::Linear) and spline.sample(*x)?

Resources