Явное JOIN ON в дизеле

У меня есть две таблицы, которые я хочу объединить, отфильтровать и выбрать только определенные столбцы в Diesel:

contest_users::dsl::contest_users
    .inner_join(
        contests::table.on(contest_users::contest_id.eq(contests::contest_id)),
    )
    .filter(contest_users::user_id.eq(42))
    .select((contests::columns::contest_id,))

Вот репозиторий с репро (см. Комментарии в коде) .

Я нашел несколько решений, которые я могу сделать для компиляции, но мне все еще интересно, могу ли я назвать тип этого запроса без использования joinable!.

Компилируемо следующее:

pub fn join_and_filter() -> diesel::dsl::Filter<
    diesel::dsl::Select<
        diesel::dsl::InnerJoin<contest_users::table, contests::table>,
        (contests::columns::contest_id,),
    >,
    diesel::expression::operators::Eq<
        contest_users::columns::user_id,
        diesel::expression::bound::Bound<diesel::sql_types::Integer, i32>,
    >,
> {
    joinable!(contest_users -> contests (contest_id));

    contest_users::dsl::contest_users
        .inner_join(
            contests::table.on(contest_users::contest_id.nullable().eq(contests::contest_id.nullable())),
        )
        .filter(contest_users::user_id.eq(42))
        .select((contests::columns::contest_id,))
}

Хотя следующее (нет joinable, хотя у меня явно указано .on()) вызывает ошибку компиляции:

pub fn join_and_filter() -> diesel::dsl::Filter<
    diesel::dsl::Select<
        diesel::dsl::InnerJoin<contest_users::table, contests::table>,
        (contests::columns::contest_id,),
    >,
    diesel::expression::operators::Eq<
        contest_users::columns::user_id,
        diesel::expression::bound::Bound<diesel::sql_types::Integer, i32>,
    >,
> {
    contest_users::dsl::contest_users
        .inner_join(
            contests::table.on(contest_users::contest_id.eq(contests::contest_id))
        )
        .filter(contest_users::user_id.eq(42))
        .select((contests::columns::contest_id,))
}
error[E0277]: the trait bound `contest_users::table: JoinTo<contests::table>` is not satisfied
  --> src/main.rs:69:1
   |
69 | / pub fn join_and_filter() -> diesel::dsl::Filter<
70 | |     diesel::dsl::Select<
71 | |         diesel::dsl::InnerJoin<contest_users::table, contests::table>,
72 | |         (contests::columns::contest_id,),
...  |
84 | |         .select((contests::columns::contest_id,))
85 | | }
   | |_^ the trait `JoinTo<contests::table>` is not implemented for `contest_users::table`
   |
   = help: the following implementations were found:
             <contest_users::table as JoinTo<JoinOn<Join, On>>>
             <contest_users::table as JoinTo<diesel::query_builder::BoxedSelectStatement<'a, QS, ST, DB>>>
             <contest_users::table as JoinTo<diesel::query_builder::SelectStatement<F, S, D, W, O, L, Of, G>>>
             <contest_users::table as JoinTo<diesel::query_source::joins::Join<Left, Right, Kind>>>
   = note: required because of the requirements on the impl of `JoinWithImplicitOnClause<contests::table, Inner>` for `contest_users::table`

person Vlad Frolov    schedule 10.04.2021    source источник


Ответы (1)


Я нашел несколько решений, которые я могу сделать для компиляции, но мне все еще интересно, могу ли я назвать тип этого запроса без использования joinable !.

Согласно документации diesel::dsl::InnerJoin определяется следующим образом:

type InnerJoin<Source, Rhs> = <Source as JoinWithImplicitOnClause<Rhs, Inner>>::Output;

Это и заявление

Представляет тип возвращаемого значения .inner_join (rhs)

указывает, что этот тип разработан для использования с операторами inner_join без явных предложений on.

Теперь возникает вопрос, как правильно указать тип возврата, поскольку дизель 1.4 не экспортирует соответствующий тип через diesel::dsl. В документации основной ветки дизелей указано, что существует соответствующий тип есть, но соответствующие типы из определения типа не представлены в версии 1.4 как часть общедоступного API. Это указывает на то, что в настоящее время невозможно назвать этот тип с помощью существующей дизельной версии.

person weiznich    schedule 12.04.2021