gpt4 book ai didi

generics - 一般使用 Diesel 的查找或过滤器来执行删除

转载 作者:行者123 更新时间:2023-11-29 08:31:58 25 4
gpt4 key购买 nike

我正在尝试使用通用 Diesel 函数来减少重复性任务,例如根据主键删除行。

我的一般行插入工作相对较快,但删除查询似乎相当困难。我尝试使用 find()filter() 解决它。我也引用了类似的话题12没有成功。

使用查找

use diesel::prelude::*;
use diesel::query_dsl::methods::FindDsl;
use std::error::Error;

pub struct DB {
conn: SqliteConnection,
}

impl DB {
pub fn remove_row<'a, T>(&self, table: T, pk: &'a str) -> Result<(), Box<Error>>
where
T: FindDsl<&'a str>,
<T as FindDsl<&'a str>>::Output: diesel::Identifiable,
<T as FindDsl<&'a str>>::Output: diesel::associations::HasTable,
{
diesel::delete(table.find(pk)).execute(&self.conn)?;
Ok(())
}
}

这会导致以下错误,我根本无法解释:

error[E0275]: overflow evaluating the requirement `_: std::marker::Sized`
--> src/db/mod.rs:103:3
|
103 | diesel::delete (table.find (pk)) .execute (&self.conn) ?;
| ^^^^^^^^^^^^^^
|
= help: consider adding a `#![recursion_limit="128"]` attribute to your crate
= note: required because of the requirements on the impl of `diesel::query_dsl::filter_dsl::FilterDsl<_>` for `<<<T as diesel::query_dsl::filter_dsl::FindDsl<&'a str>>::Output as diesel::associations::HasTable>::Table as diesel::query_builder::AsQuery>::Query`
= note: required because of the requirements on the impl of `diesel::query_builder::IntoUpdateTarget` for `<T as diesel::query_dsl::filter_dsl::FindDsl<&'a str>>::Output`
= note: required by `diesel::delete`

使用过滤器()

use diesel::prelude::*;
use diesel::query_dsl::methods::FilterDsl;
use std::error::Error;

pub struct DB {
conn: SqliteConnection,
}

impl DB {
pub fn remove_row<T>(&self, table: T, pk: &str) -> Result<(), Box<Error>>
where
T: FilterDsl<bool>,
<T as FilterDsl<bool>>::Output: diesel::Identifiable,
<T as FilterDsl<bool>>::Output: diesel::associations::HasTable,
{
diesel::delete(table.filter(id.eq(pk))).execute(&self.conn)?;
Ok(())
}
}

除了前面的错误之外,还有一条关于 id 在数据结构中未知的错误消息。我可以考虑一个缺失的特征,它保证了该行的存在,但我还没有发现任何关于这种行为的信息。

error[E0425]: cannot find value `id` in this scope
--> src/db/mod.rs:117:33
|
117 | diesel::delete (table.filter (id.eq (pk))) .execute (&self.conn) ?;
| ^^ not found in this scope
help: possible candidates are found in other modules, you can import them into scope
|
4 | use crate::db::schema::events::columns::id;
|
4 | use crate::db::schema::ignored_events::columns::id;
|
4 | use crate::db::schema::locations::columns::id;
|
4 | use std::process::id;


error[E0275]: overflow evaluating the requirement `_: std::marker::Sized`
--> src/db/mod.rs:117:3
|
117 | diesel::delete (table.filter (id.eq (pk))) .execute (&self.conn) ?;
| ^^^^^^^^^^^^^^
|
= help: consider adding a `#![recursion_limit="128"]` attribute to your crate
= note: required because of the requirements on the impl of `diesel::query_dsl::filter_dsl::FilterDsl<_>` for `<<<T as diesel::query_dsl::filter_dsl::FilterDsl<bool>>::Output as diesel::associations::HasTable>::Table as diesel::query_builder::AsQuery>::Query`
= note: required because of the requirements on the impl of `diesel::query_builder::IntoUpdateTarget` for `<T as diesel::query_dsl::filter_dsl::FilterDsl<bool>>::Output`
= note: required by `diesel::delete`

最佳答案

泛型并不容易。像 Diesel 这样高度通用的系统中的泛型甚至更难。

我更喜欢将步骤分解成非常的小部分,并尽可能避免链接。有了它,您基本上需要为每个步骤添加特征界限。一件好事是为非常复杂的特征边界使用/创建类型别名。 Diesel provides a number of these您可以根据自己的特殊用途制作自己的。

虽然我查看了生成的错误消息,但我主要查看了被调用的函数/方法所描述的类型范围。

逐点:

  1. .find来自FindDsl .
  2. delete需要 IntoUpdateTarget .
  3. 调用 delete 的结果类型是 DeleteStatement ,用 T::TableT::WhereClause 参数化。这是自定义类型别名 DeleteFindStatement
  4. .execute来自ExecuteDsl .
use diesel::{
associations::HasTable,
helper_types::Find,
query_builder::{DeleteStatement, IntoUpdateTarget},
query_dsl::methods::ExecuteDsl,
};

type DeleteFindStatement<F> =
DeleteStatement<<F as HasTable>::Table, <F as IntoUpdateTarget>::WhereClause>;

impl DB {
pub fn remove_row<Tbl, Pk>(&self, table: Tbl, pk: Pk) -> Result<(), Box<Error>>
where
Tbl: FindDsl<Pk>,
Find<Tbl, Pk>: IntoUpdateTarget,
DeleteFindStatement<Find<Tbl, Pk>>: ExecuteDsl<SqliteConnection>,
{
let find = table.find(pk);
let delete = diesel::delete(find);
delete.execute(&self.conn)?;
Ok(())
}
}

您需要自己尝试基于filter 的版本,因为您没有提供足够的代码来判断id 应该是什么;如您的错误消息所示。

另见:

is there a benefit in making the primary key generic, even if it is &str in all cases?

对我来说,使用泛型类型比插入一堆泛型生命周期参数更容易。

关于generics - 一般使用 Diesel 的查找或过滤器来执行删除,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55213466/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com