我正在使用 Diesel 库和 Sqlite 数据库,尝试创建 Rust 枚举,将其保存到数据库中为
diesel::sql_types::Text
,但即使使用示例代码,它也无法正常工作。
这里是示例代码。
我的代码:
#[derive(PartialEq, Eq, AsExpression, FromSqlRow, Serialize, Deserialize, Clone, Debug)]
#[diesel(sql_type = diesel::sql_types::Text)]
pub enum InspectionType {
#[serde(rename = "RUNWAY")]
Runway,
#[serde(rename = "PAPI")]
Papi,
}
impl serialize::ToSql<Text, Sqlite> for InspectionType {
fn to_sql(&self, out: &mut serialize::Output<Sqlite>) -> serialize::Result {
match *self {
InspectionType::Runway => out.write_all(b"RUNWAY")?,
InspectionType::Papi => out.write_all(b"PAPI")?,
}
Ok(IsNull::No)
}
}
impl deserialize::FromSql<Text, Sqlite> for InspectionType {
fn from_sql(bytes: SqliteValue) -> deserialize::Result<Self> {
match bytes.as_bytes() {
b"RUNWAY" => Ok(InspectionType::Runway),
b"PAPI" => Ok(InspectionType::Papi),
_ => Err("Unrecognized enum variant".into()),
}
}
}
编译器错误:
error[E0599]: no method named `as_bytes` found for struct `SqliteValue` in the current scope
--> src/app_data/inspection.rs:40:21
|
40 | match bytes.as_bytes() {
| ^^^^^^^^ method not found in `SqliteValue<'_, '_, '_>`
预计为 postgresql 编写的示例不适用于 sqlite,因为这两个后端之间的许多细节有所不同。这里重要的部分是如何将绑定值传递到数据库。对于 postgresql,它们被序列化为字节缓冲区并通过网络发送,对于在二进制文件中运行的 sqlite,值只是传递到数据库。此外,不同的数据库支持不同的类型集。 Postgresql 支持一组开放的类型,这意味着您可以定义自己的类型。对于 sqlite,您只能使用一小部分封闭的类型,并且无法扩展。这意味着您需要将数据序列化为实际已经存在的类型。
这对于您的示例意味着什么?
FromSql
的相关文档。尤其是那部分很重要:
对于 SQLite,
的实际类型是私有 API。此特征的所有实现都必须根据现有原语编写。DB::RawValue
这意味着编译器没有指出
as_bytes()
方法。您需要在内部使用现有实现之一。在本例中,这就是 String 的那个。这将为您留下类似的实现:
impl deserialize::FromSql<Text, Sqlite> for InspectionType {
fn from_sql(bytes: SqliteValue) -> deserialize::Result<Self> {
let value = <String as deserialize::FromSql<Text, Sqlite>>::from_sql(bytes)?;
match &value as &str {
"RUNWAY" => Ok(InspectionType::Runway),
"PAPI" => Ok(InspectionType::Papi),
_ => Err("Unrecognized enum variant".into()),
}
}
}