You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Rust Rocket集成Diesel查询出现E0277编译错误求助

Diesel+SQLite集成E0277编译错误解决方案

问题背景

作为Diesel新手,在Rocket项目中集成Diesel+SQLite,自定义表和查询后,执行SELECT * FROM ... WHERE id = ?这类简单查询时,触发E0277编译错误。

错误详情

error[E0277]: the trait bound `(i32, std::string::String, std::string::String): FromStaticSqlRow<(diesel::sql_types::Nullable<diesel::sql_types::Integer>, diesel::sql_types::Text, diesel::sql_types::Text), Sqlite>` is not satisfied
    --> src/dbal/quote_subject.rs:26:12
     |
26   |     .first(db)
     |      ----- ^^ the trait `FromStaticSqlRow<(diesel::sql_types::Nullable<diesel::sql_types::Integer>, diesel::sql_types::Text, diesel::sql_types::Text), Sqlite>` is not implemented for `(i32, std::string::String, std::string::String)`
     |      |
     |      required by a bound introduced by this call
     |
     = help: the following other types implement trait `FromStaticSqlRow<ST, DB>`:
               <(T0,) as FromStaticSqlRow<(ST0,), __DB>>
               <(T1, T0) as FromStaticSqlRow<(ST1, ST0), __DB>>
               <(T1, T2, T0) as FromStaticSqlRow<(ST1, ST2, ST0), __DB>>
               <(T1, T2, T3, T0) as FromStaticSqlRow<(ST1, ST2, ST3, ST0), __DB>>
               <(T1, T2, T3, T4, T0) as FromStaticSqlRow<(ST1, ST2, ST3, ST4, ST0), __DB>>
               <(T1, T2, T3, T4, T5, T0) as FromStaticSqlRow<(ST1, ST2, ST3, ST4, ST5, ST0), __DB>>
               <(T1, T2, T3, T4, T5, T6, T0) as FromStaticSqlRow<(ST1, ST2, ST3, ST4, ST5, ST6, ST0), __DB>>
               <(T1, T2, T3, T4, T5, T6, T7, T0) as FromStaticSqlRow<(ST1, ST2, ST3, ST4, ST5, ST6, ST7, ST0), __DB>>
             and 24 others
note: required for `QuoteSubject` to implement `diesel::Queryable<(diesel::sql_types::Nullable<diesel::sql_types::Integer>, diesel::sql_types::Text, diesel::sql_types::Text), Sqlite>`
    --> src/models.rs:5:24
     |
5    | #[derive(Identifiable, Queryable, Serialize, Deserialize, Debug, Clone)]
     |                        ^^^^^^^^^
6    | #[diesel(table_name = quote_subject)]
7    | pub struct QuoteSubject {
     |            ^^^^^^^^^^^^
     = note: required for `QuoteSubject` to implement `FromSqlRow<(diesel::sql_types::Nullable<diesel::sql_types::Integer>, diesel::sql_types::Text, diesel::sql_types::Text), Sqlite>`
     = note: required for `(diesel::sql_types::Nullable<diesel::sql_types::Integer>, diesel::sql_types::Text, diesel::sql_types::Text)` to implement `load_dsl::private::CompatibleType<QuoteSubject, Sqlite>`
     = note: required for `SelectStatement<FromClause<schema::quote_subject::table>, diesel::query_builder::select_clause::DefaultSelectClause<FromClause<schema::quote_subject::table>>, diesel::query_builder::distinct_clause::NoDistinctClause, diesel::query_builder::where_clause::WhereClause<expression::grouped::Grouped<expression::operators::Eq<schema::quote_subject::columns::id, _>>>, diesel::query_builder::order_clause::NoOrderClause, diesel::query_builder::limit_offset_clause::LimitOffsetClause<diesel::query_builder::limit_clause::LimitClause<expression::bound::Bound<BigInt, i64>>, diesel::query_builder::offset_clause::NoOffsetClause>>` to implement `LoadQuery<'_, diesel::SqliteConnection, QuoteSubject>`
note: required by a bound in `first`
    --> /usr/local/cargo/registry/src/github.com-1ecc6299db9ec823/diesel-2.0.2/src/query_dsl/mod.rs:1736:22
     |
1736 |         Limit<Self>: LoadQuery<'query, Conn, U>,
     |                      ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `first`
     = note: this error originates in the derive macro `Queryable` (in Nightly builds, run with -Z macro-backtrace for more info)

For more information about this error, try `rustc --explain E0277`.
error: could not compile `le-saviez-vous` due to previous error

相关代码

src/dbal/quote_subject.rs

/// src/dbal/quote_subject.rs

use crate::schema::quote_subject::dsl::*;
use crate::models::QuoteSubject;
use diesel::{SqliteConnection, QueryDsl, RunQueryDsl};
use crate::helpers::database;

use diesel::prelude::*;

/// this function aims to get one QuoteSubject object from table `quote_subject` with it's Id.
pub fn find(object_id: i64) -> QuoteSubject {
    let db: &mut SqliteConnection = &mut get_connection();

    quote_subject
    .filter(id.eq(object_id.into()))
    .first(db)
    .unwrap()
}

src/models.rs

/// src/models.rs

use diesel::prelude::*;
use serde::{Serialize, Deserialize};
use crate::schema::*;

#[derive(Identifiable, Queryable, Serialize, Deserialize, Debug, Clone)]
#[diesel(table_name = quote_subject)]
pub struct QuoteSubject {
    pub id: i32,
    pub quote_singular: String,
    pub quote_plural: String
}

#[derive(Queryable)]
pub struct QuoteVerb {
    pub id: i32,
    pub quote_singular: String,
    pub quote_plural: String
}

#[derive(Queryable)]
pub struct QuoteDescription {
    pub id: i32,
    pub quote_singular: String,
    pub quote_plural: String
}

src/schema.rs

/// src/schema.rs

diesel::table! {
    quote_description (id) {
        id -> Nullable<Integer>,
        quote_singular -> Text,
        quote_plural -> Text,
    }
}

数据库迁移SQL

-- the migration used to create the table inside the SQLite database
CREATE TABLE "quote_subject" (
    id             INTEGER      PRIMARY KEY AUTOINCREMENT,
    quote_singular VARCHAR (255) NOT NULL,
    quote_plural   VARCHAR (255) NOT NULL
);

解决方案

错误根源有两处:

  1. schema.rs缺少quote_subject表定义
    当前schema.rs仅定义了quote_description表,但代码中实际使用的是quote_subject表。需要补充quote_subject的表定义,且注意id字段应为非空(因为数据库中是主键且AUTOINCREMENT,对应Diesel的Integer而非Nullable<Integer>):

    diesel::table! {
        quote_subject (id) {
            id -> Integer,
            quote_singular -> Text,
            quote_plural -> Text,
        }
    }
    
    diesel::table! {
        quote_description (id) {
            id -> Integer,
            quote_singular -> Text,
            quote_plural -> Text,
        }
    }
    

    同时修正quote_description的id字段为Integer,因为数据库主键不可能为空,模型中对应的id: i32也不需要Option包裹。

  2. 类型匹配问题

    • 数据库迁移中id是INTEGER,对应Diesel的Integer类型,模型中用i32是正确的,但schema中不能写成Nullable<Integer>,否则Diesel会尝试将可空值映射到非Option类型,触发 trait 不匹配错误。
    • 查询函数中object_id是i64,而表中id是i32,可以直接用object_id as i32转换,避免不必要的into()调用,减少类型歧义:
      pub fn find(object_id: i64) -> QuoteSubject {
          let db: &mut SqliteConnection = &mut get_connection();
      
          quote_subject
          .filter(id.eq(object_id as i32))
          .first(db)
          .unwrap()
      }
      

执行以上修改后,重新编译即可解决E0277错误。

内容的提问来源于stack exchange,提问作者Adrien Gras

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.13 13:55:20