带有eq_any的子查询无法编译

问题描述

我模型的相关部分:

table! {
    server_website {
        id -> Integer,server_database_id -> Nullable<Integer>,server_id -> Integer,}
}

table! {
    server_database {
        id -> Integer,}
}

table! {
    server {
        id -> Integer,}
}

joinable!(server_website -> server_database (server_database_id));
allow_tables_to_appear_in_same_query!(server_website,server_database);

#[derive(Queryable,Debug,Clone,PartialEq,Eq)]
pub struct Server {
    pub id: i32,}

#[derive(Queryable,Eq)]
pub struct ServerWebsite {
    pub id: i32,pub server_database_id: Option<i32>,pub server_id: i32,Eq)]
pub struct ServerDatabase {
    pub id: i32,}

我正在尝试使用Diesel表示以下工作的sqlite查询

select * from server_website where server_database_id in (
    select id from server_database where server_id = 83
);

这是我的柴油查询代码

use projectpadsql::schema::server::dsl as srv;
use projectpadsql::schema::server_database::dsl as db;
use projectpadsql::schema::server_website::dsl as srvw;

let database_ids_from_server = db::server_database
    .filter(db::server_id.eq(83))
    .select(db::id);
let used_websites = srvw::server_website
    .filter(srvw::server_database_id.eq_any(database_ids_from_server))
    .load::<ServerWebsite>(sql_conn)
    .unwrap();

此操作失败,并显示以下错误

error[E0277]: the trait bound `diesel::query_builder::SelectStatement<projectpadsql::schema::server_database::table,diesel::query_builder::select_clause::SelectClause<projectpadsql::schema::server_database::columns::id>,diesel::query_builder::distinct_clause::NodistinctClause,diesel::query_builder::where_clause::WhereClause<diesel::expression::operators::Eq<projectpadsql::schema::server_database::columns::server_id,diesel::expression::bound::Bound<diesel::sql_types::Integer,i32>>>>: diesel::expression::array_comparison::AsInExpression<diesel::sql_types::Nullable<diesel::sql_types::Integer>>` is not satisfied

我看到编译器希望内部查询的类型AsInExpression<Nullable<Integer>>对我来说看起来很好(可空值除外)。

内部查询或多或少具有类型SelectStatement<server_database,SelectClause<server_database::id>>,这对我来说很好,因为id是Integer,就像外部查询想要的一样。

我感觉自己已经很接近了,但是我不能指望问题所在。

解决方法

我需要使用nullable()来匹配类型。请注意db::id.nullable()

let database_ids_from_server = db::server_database
    .filter(db::server_id.eq(server_id))
    .select(db::id.nullable());
let used_websites = srvw::server_website
    .filter(srvw::server_database_id.eq_any(database_ids_from_server))
    .load::<ServerWebsite>(sql_conn)
    .unwrap();

Georg Semmler-Diesel Gitter channel上的@weiznich回答了这个问题。