Mój program używa rusqlite do zbudowania bazy danych z innego źródła danych. Baza buduje wielu tabel w taki sam sposób, więc pomyślałem, że zrobię wielokrotnego użytku funkcji, aby to zrobić:Problemy z wypożyczaniem ze skompilowanymi instrukcjami SQL
fn download_generic<Inserter>(table_name: &str,
connection: &mut rusqlite::Connection,
inserter: &mut Inserter)
-> Result<(), String>
where Inserter: FnMut(&str, &json::JsonValue) ->()
{}
inserter
to funkcja, która wiąże się prawidłowe wartości z wcześniej przygotowanym oświadczeniu i nie wstawianie .
nazywam go tak:
let mut insert_stmt = connection
.prepare("insert or replace into categories values(?,?);")
.unwrap();
download_generic("categories",
&mut connection,
&mut |uuid, jsonproperties| {
insert_stmt.execute(&[&uuid, &jsonproperties["name"].as_str().unwrap_or("")]);
});
Jednak nie mogę przejść &mut connection
do download_generic
bo to już pożyczone przez insert_stmt
. Umieszczenie go w RefCell
nie ma sensu, ponieważ nie powinienem potrzebować narzutu środowiska wykonawczego, aby to działało.
Mogę spróbować wygenerować insert_stmt
wygenerowany przez lambdę, którą przechodzisz na download_generic
, ale wtedy jestem przytłoczony koniecznością dodawania znaczników życia wszędzie, i tak czy inaczej wydaje się to nienaturalne.
Umieszczenie go w "RefCell" nie zadziałałoby: 'RefCell' po prostu sprawdza w czasie wykonywania zamiast kompilacji, ale wykonuje to samo podstawowe sprawdzenie => ** Aliasing XOR Mutability **. Oczywiste pytanie brzmi: czy nie możesz po prostu pożyczyć (niezmiennie) tego samego połączenia? Jeśli pojedynczy wymagany kredyt jest zmienny, oznacza to, że nie masz szczęścia. –
Czy nie mogę po prostu przenieść insert_stmt do lambda w jakiś sposób, aby 'download_generic' zachował to? – njaard
Czy zamiast tego możesz użyć "przygotować_cached" zamiast "przygotować", aby uzyskać gotowe oświadczenie w zamknięciu? Musiałbyś jawnie przekazać 'połączenie' do zamknięcia, aby uniknąć konfliktu pożyczek. –