design-patternsrustrusqlite

What's the idiomatic way to pass types in Rust?


I create a connection type, i.e.

let mut conn = Connection::open("sqlite.db").unwrap();

And then I pass that type to my save_all function along with a vector, like this:

pub fn save_all(conn: &mut Connection,
                vehicles: Vec<Vehicle>) -> Result<(), Error> {
    let tx = conn.transaction()?;
    for v in vehicles {
        let sql: &str =
            "INSERT INTO local_edits (vehicle_id, make, model, color)
                 VALUES (:vehicle_id, :make, :model, :color)";
        let mut statement = tx.prepare(sql)?;
        statement.execute(named_params! {
                ":vehicle_id": v.vehicle_id,
                ":make": v.make,
                ":model": v.model,
                ":color": v.color})?;
    };
    tx.commit()?;
    return Ok(());
}

This code seems to work okay. Is this code actually correct?

If I don't make my conn type &mut Connection in the save_all function, the code doesn't compile for me. It tells me:

Cannot borrow immutable local variable `conn` as mutable

I'm not quite sure how to understand this.

And is the right pattern to pass conn's "reference" to my save_all function?

I don’t want to transfer ownership to this function. I think I just want to let the function borrow the connection.


Solution

  • Cannot borrow immutable local variable conn as mutable

    The mut in &mut Connection is necessary because you are calling transaction on conn which requires a mutable reference. See also the documentation for this API callI which expects a &mut self.

    Borrowing vs. transfer of ownership

    Borrowing seems like the right way to do this in case you want to re-use the connection later again. If you would transfer ownership of the connection you'd have to return it again as part of the result in order to re-use it later (because of how affine types in rust work). This would be less-ergonomic to work with than just borrowing the connection.