Borrow problems with compiled SQL statements

My program uses rusqlite to create a database from another data source. The database builds several tables in the same way, so I thought I would make a reuse function:

fn download_generic<Inserter>(table_name: &str, connection: &mut rusqlite::Connection, inserter: &mut Inserter) -> Result<(), String> where Inserter: FnMut(&str, &json::JsonValue) -> () {} 

inserter is a function that binds the correct values ​​from a previously prepared statement and makes an insert.

I call it this way:

 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("")]); }); 

However, I cannot pass &mut connection to download_generic because it is already borrowed by insert_stmt . Putting it into RefCell does not make sense, because I do not need extra time to complete this work.

I could try creating an insert_stmt generated by the lambda that you switch to download_generic , but then I get overwhelmed by the need to add timestamps everywhere, and still it seems unnatural.

+5
source share
1 answer

By design, Rust does not allow you to have immutable borrowed and variable borrowings on the same object at the same time. This is necessary to prevent dangling pointers and data calculations.

In the rusqlite API, some methods on Connection require mutable self , and some methods require only immutable self . However, some of the methods that require only immutable return objects are self , which keep this loan active; prepare is an example of this. Therefore, while one of these objects remains in scope, Rust will not allow you to use mutable borrowing on Connection .

This is probably the reason why some methods accept self using a mutable reference. Requiring a mutable link ensures that the caller has exclusive access to this object. If you think that this may not be the case for the methods that you need to use, or you think that there may be another way to solve this problem, you should report the problem to the library developers.

In relation to prepare in particular, you can bypass conflicting roles by calling prepare_cached inside the closure instead. To do this, you need to make download_generic pass Connection back as a parameter to close, otherwise you will have two mutable roles on Connection and this is not allowed.

+2
source

Source: https://habr.com/ru/post/1262847/


All Articles