柴油中的显式 JOIN ON
Posted
技术标签:
【中文标题】柴油中的显式 JOIN ON【英文标题】:Explicit JOIN ON in diesel 【发布时间】:2021-07-06 08:43:23 【问题描述】:我有两个表要加入、过滤并仅选择 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,))
这是一个repo with a repro(见代码中的 cmets)。
我找到了一些可以编译的解决方案,但我仍然想知道是否可以在不使用 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`
【问题讨论】:
【参考方案1】:我找到了一些可以编译的解决方案,但我仍然想知道是否可以在不使用 joinable 的情况下命名此查询的类型!。
根据文档diesel::dsl::InnerJoin
定义如下:
type InnerJoin<Source, Rhs> = <Source as JoinWithImplicitOnClause<Rhs, Inner>>::Output;
这和声明
表示.inner_join(rhs)的返回类型
表示此类型旨在与不带显式 on
子句的 inner_join
语句一起使用。
现在这引发了如何正确指定返回类型的问题,因为柴油 1.4 不会通过 diesel::dsl
导出相应的类型。柴油机主分支的文档表明那里存在相应的type,但类型定义中的相关类型并未作为公共 API 的一部分在 1.4 版本中公开。这表明目前无法使用现有的柴油版本命名此类型。
【讨论】:
以上是关于柴油中的显式 JOIN ON的主要内容,如果未能解决你的问题,请参考以下文章