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 );
解决方案
错误根源有两处:
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包裹。类型匹配问题
- 数据库迁移中
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
相关产品推荐
相关产品推荐

