У меня есть следующая схема в базе данных Postgres:
Table A {
ID
Name
}
Table B {
ID FOREIGN KEY (A.ID)
}
Я пытаюсь написать следующий запрос в Diesel:
DELETE FROM B
WHERE B.ID in (SELECT ID from A WHERE A.Name = $VAR)
$VAR
является переменная, переданная моим приложением.
Моя первая попытка написать это была следующая:
fn deleteB(conn: &PgConnection, n: &str) {
use schema::A::dsl::*;
use schema::A;
use schema::B;
let res = A::table
.filter(Name.eq(n))
.select(ID);
.load(conn)
.unwrap();
assert!(res.len() < 2);
let b_id: i32 = *res.iter().nth(1).unwrap_or(&0);
let _rows = diesel::delete(
B::table
.filter(ID.eq(n_id))
)
.execute(conn)
.unwrap();
}
Это компилируется, но не работает: оператор SELECT
для идентификатора всегда возвращает 0. Он не соответствует ни одной из вставленных записей в A, хотя я проверял вручную, что они там есть. Я уверен, что у меня есть ошибка в процессе сопоставления (&str
против &String
может быть?), Но я решил попробовать другое решение, так как оно мне не понравилось, так как оно должно выполняться два отдельных утверждения против базы данных.
Моя вторая попытка выглядит следующим образом:
fn deleteB(conn: &PgConnection, n: &str) {
use schema::A::dsl::*;
use schema::A;
use schema::B;
let source = B::table.inner_join(A::table)
.filter(Name.eq(n));
let s = delete(source)
.execute(conn)
.unwrap();
}
Мне это кажется более дизельным-идиоматическим c (предупреждение о спойлере, я почти не знаю фреймворк) но, конечно же, он не компилируется:
|
410 | let s = delete(source)
| ^^^^^^ the trait `diesel::query_builder::IntoUpdateTarget` is not implemented for `diesel::query_builder::SelectStatement<diesel::query_source::joins::JoinOn<diesel::query_source::joins::Join<mobility2::schema::B::table...` (very long error)
Я изучал вышеупомянутую черту, когда понял, что это кажется тривиальной операцией (само удаление), и мне, вероятно, лучше обратиться за помощью ,
Как правильно написать идиоматический c дизельный код для выполнения оператора удаления, который я хочу выполнить?