cargorust-diesel85% confidence\u2191 6

Rust Diesel, error loading results of a sql_query that select columns from multiple tables

Full error message
I tried to execute an sql_query with Diesel that doesn't match a single table and I got the following error:

    error[E0277]: the trait bound `Untyped: load_dsl::private::CompatibleType<TimeCountSumaryEntry, _>` is not satisfied
        --> src/api/cra_service.rs:263:10
         |
    263  |         .load::<TimeCountSumaryEntry>(connection)
         |          ^^^^ the trait `load_dsl::private::CompatibleType<TimeCountSumaryEntry, _>` is not implemented for `Untyped`
         |
         = help: the trait `load_dsl::private::CompatibleType<U, DB>` is implemented for `Untyped`
         = note: required because of the requirements on the impl of `LoadQuery<'_, _, TimeCountSumaryEntry>` for `SqlQuery`
    note: required by a bound in `diesel::RunQueryDsl::load

Here is the relevant code (where clauses are fixed to simplify experimentations):

#[derive(QueryableByName, Debug)]
struct TimeCountSumaryEntry {
    #[diesel(sql_type = Integer)]
    month: i32,
    #[diesel(sql_type = Integer)]
    year: i32,
    #[diesel(sql_type = Integer)]
    project_id: i32,
    #[diesel(sql_type = Text)]
    project_code: String,
    #[diesel(sql_type = Double)]
    time_spent: f32,
    #[diesel(sql_type = Text)]
    fullname: String,
}

fn _timecount_by_filters(
    user_id: Option<i32>,
    month: Option<u8>,
    year: Option<u16>,
    connection: &mut PgConnection,
) {
    let query =
        "SELECT
            EXTRACT(MONTH FROM tc.date_assigned) as \"month\",
            EXTRACT(YEAR FROM tc.date_assigned) as \"year\",
            tc.project_id as project_id,
            p.project_code as project_code,
            sum(tc.time_spent) as time_spent,
            u.lastname || ' ' || u.firstname as fullname
        FROM
            time_count tc
            JOIN cra c on tc.cra_id = c.cra_id
            JOIN project p on p.project_id = tc.project_id
            JOIN \"user\" u on u.user_id = c.user_id
        WHERE
            u.user_id = 3
            and EXTRACT(MONTH FROM tc.date_assigned) = 8
            and EXTRACT(YEAR FROM tc.date_assigned) = 2022
        GROUP BY
            tc.project_id, u.lastname, u.firstname, \"month\", \"year\", p.project_code
        ORDER BY
            \"year\", \"month\", u.lastname, u.firstname, tc.project_id";

    let time_counts_sumary = diesel::dsl::sql_query(query)
        .load::<TimeCountSumaryEntry>(connection)
        .expect("Error getting cra ids");
    println!("{:?}", time_counts_sumary);
}

I can't find any resource that mention how to deal with this use case (or even that this isn't possible at all). I first tried with the query builder, but it didn't seem possible, so I thought sql_query the way to get those data from DB (postgresql) without getting useless information in the process, but maybe there is a better one.

Does anyone have encountered this use case or have any hints about how to deal with it ?

If someone have the same problem, I found where it was. Diesel couldn't match types it got from sql_query and what I mentioned in TimeCountSumaryEntry. First here: #[diesel(sql_type = Double)] time_spent: f32, I mistyped the Double (it should be f64) And second the EXTRACT() function return a numeric in postgresql. I could use the numeric diesel feature, but in my case (year and month), an Integer is enough. So I must specify the type in the request with CAST(). Like this: CAST(EXTRACT(MONTH FROM tc.date_assigned) as Integer) as "month", CAST(EXTRACT(YEAR FROM tc.date_assigned) as Integer) as "year", Here is the working code: #[derive(QueryableByName, Debug)] struct TimeCountSumaryEntry { #[diesel(sql_type = Integer)] month: i32, #[diesel(sql_type = Integer)] year: i32, #[diesel(sql_type = Integer)] project_id: i32, #[diesel(sql_type = Text)] project_code: String, #[diesel(sql_type = Double)] time_spent: f64, #[diesel(sql_type = Text)] fullname: String, } fn _timecount_by_filters( user_id: Option<i32>, month: Option<u8>, year: Option<u16>, connection: &mut PgConnection, ) { let query = "SELECT CAST(EXTRACT(MONTH FROM tc.date_assigned) as integer) as \"month\", CAST(EXTRACT(YEAR FROM tc.date_assigned) as integer) as \"year\", tc.project_id as project_id, p.project_code as project_code, sum(tc.time_spent) as time_spent, u.lastname || ' ' || u.firstname as fullname FROM time_count tc JOIN cra c on tc.cra_id = c.cra_id JOIN project p on p.project_id = tc.project_id JOIN \"user\" u on u.user_id = c.user_id WHERE u.user_id = 3 and EXTRACT(MONTH FROM tc.date_assigned) = 8 and EXTRACT(YEAR FROM tc.date_assigned) = 2022 GROUP BY tc.project_id, u.lastname, u.firstname, \"month\", \"year\", p.project_code ORDER BY \"year\", \"month\", u.lastname, u.firstname, tc.project_id"; let time_counts_sumary = diesel::dsl::sql_query(query) .load::<TimeCountSumaryEntry>(connection) .expect("Error getting cra ids"); println!("{:?}", time_counts_sumary); }

API access

Get this solution programmatically \u2014 free, no authentication.

curl https://depscope.dev/api/error/8eba1ca08c3c1c4960b27e327b27b3cd4a2adb537d71f8acc747d6ea69b505a4
hash \u00b7 8eba1ca08c3c1c4960b27e327b27b3cd4a2adb537d71f8acc747d6ea69b505a4
Rust Diesel, error loading results of a sql_query that selec… — DepScope fix | DepScope