Rust Diesel编译报错cannot find derive macro Selectable排查
Rust项目中使用1.4.8版本的Diesel ORM,Cargo.toml内依赖配置如下:
diesel = { version = "1.4.8", features = ["postgres","64-column-tables","chrono","serde_json"] }
定义映射bill_record表的BillRecord结构体时,添加了如下派生宏:
#[derive(Insertable,Queryable,QueryableByName,Debug,Serialize,Deserialize,Default,Clone,Selectable)] #[table_name = "bill_record"] pub struct BillRecord { pub id: i64, pub created_time: i64, pub updated_time: i64, pub deleted: i32, pub user_id: i64, pub bill_book_id: i64, pub remark: Option<String>, pub amount: i64, pub bill_book_contents_id: i64, pub account_id: i32, }
编译阶段抛出错误:
cannot find derive macro `Selectable` in this scope
已尝试的修复操作均未生效:
- 在main.rs中添加宏导入代码:
#[macro_use] extern crate diesel; #[macro_use] extern crate diesel_drivers;
- 在模型定义文件中添加
use diesel::*;导入语句 - 查阅Diesel源码得知
Selectable派生宏来自diesel_drivers,但上述操作没有解决问题。
核心问题是版本不匹配:Selectable派生宏是Diesel 2.0版本才正式推出的稳定功能,1.4.x系列版本的Diesel根本没有提供这个派生宏,也没有对应实现。
你查到的diesel_drivers是Diesel 2.0版本之后才拆分出来的内部驱动crate,1.4.8版本不存在这个独立crate,手动写extern crate diesel_drivers的写法在1.4.8环境下完全无效,甚至会直接触发“找不到crate”的编译错误。
补充说明:1.x版本的Diesel中,Queryable派生已经可以覆盖常规的表字段映射需求,不需要Selectable支持。Selectable是2.0版本为了实现静态字段选择、多表联查类型校验新增的能力,1.x版本没有对应设计。
根据实际需求二选一即可:
方案1:保持Diesel 1.4.8版本(改动最小)
直接从结构体派生宏列表中删除Selectable即可,1.4.8版本下剩余的派生宏组合已经可以支持常规的增、删、改、查操作:
// 移除Selectable派生即可正常编译 #[derive(Insertable,Queryable,QueryableByName,Debug,Serialize,Deserialize,Default,Clone)] #[table_name = "bill_record"] pub struct BillRecord { // 字段定义保持原有内容不变 pub id: i64, pub created_time: i64, pub updated_time: i64, pub deleted: i32, pub user_id: i64, pub bill_book_id: i64, pub remark: Option<String>, pub amount: i64, pub bill_book_contents_id: i64, pub account_id: i32, }
注意同步删除之前添加的extern crate diesel_drivers;代码,1.4.8版本不存在这个crate,残留代码会触发其他编译错误。
方案2:升级Diesel到2.0及以上版本(需适配API变更)
如果确实需要使用Selectable提供的静态字段选择能力,可以将Diesel升级到2.x系列版本,注意2.0存在较多不兼容的API改动:
- 修改
Cargo.toml中的diesel依赖配置,2.0版本的派生宏已经内置在主crate中,不需要手动引入diesel_drivers这类内部crate:diesel = { version = "2.1", features = ["postgres","64-column-tables","chrono","serde_json"] } - 调整模型定义的属性写法,2.0版本使用
#[diesel(table_name = bill_record)]替换旧版的#[table_name = "bill_record"]写法,此时派生宏中的Selectable可以正常识别使用。 - 按照Diesel 2.0的版本变更说明,调整其他不兼容的查询、连接相关代码即可。
内容的提问来源于stack exchange,提问作者Dolphin

