借用已编译的 SQL 语句的问题
Borrow problems with compiled SQL statements
我的程序使用 rusqlite 从另一个数据源构建数据库。数据库以相同的方式构建多个表,所以我想我会做一个可重用的函数来这样做:
fn download_generic<Inserter>(table_name: &str,
connection: &mut rusqlite::Connection,
inserter: &mut Inserter)
-> Result<(), String>
where Inserter: FnMut(&str, &json::JsonValue) -> ()
{}
inserter
是一个函数,它从先前准备的语句中绑定正确的值并进行插入。
我这样称呼它:
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("")]);
});
但是我无法将 &mut connection
传递给 download_generic
,因为它已经被 insert_stmt
借用了。将它放入 RefCell
中是没有意义的,因为我不需要运行时开销来完成这项工作。
我可以尝试让 insert_stmt
由您传递给 download_generic
的 lambda 生成,但后来我不得不在各处添加生命周期标记而不知所措,而且这看起来很不自然。
根据设计,Rust 会阻止您同时激活同一对象上的不可变借用和可变借用。这是为了防止悬挂指针和数据竞争。
在 rusqlite 的 API 中,Connection
上的一些方法需要一个可变的 self
,而一些方法只需要一个不可变的 self
。然而,一些方法只需要一个不可变的 self
return 对象来保持借用; prepare
就是一个例子。因此,只要这些对象之一留在范围内,Rust 就不允许您在 Connection
.
上进行可变借用
有些方法通过可变引用获取 self
可能是有原因的。要求可变引用可确保被调用方拥有对该对象的独占访问权。如果您认为您需要使用的方法可能不是这种情况,或者您认为可能有另一种方法来解决这个问题,您应该向库的维护者报告问题。
具体来说 prepare
,您可以通过从闭包中调用 prepare_cached
来解决借用冲突。为了做到这一点,你必须让 download_generic
将 connection
作为参数传回闭包,否则你会在 connection
上有两个可变借用,这是不允许的.
我的程序使用 rusqlite 从另一个数据源构建数据库。数据库以相同的方式构建多个表,所以我想我会做一个可重用的函数来这样做:
fn download_generic<Inserter>(table_name: &str,
connection: &mut rusqlite::Connection,
inserter: &mut Inserter)
-> Result<(), String>
where Inserter: FnMut(&str, &json::JsonValue) -> ()
{}
inserter
是一个函数,它从先前准备的语句中绑定正确的值并进行插入。
我这样称呼它:
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("")]);
});
但是我无法将 &mut connection
传递给 download_generic
,因为它已经被 insert_stmt
借用了。将它放入 RefCell
中是没有意义的,因为我不需要运行时开销来完成这项工作。
我可以尝试让 insert_stmt
由您传递给 download_generic
的 lambda 生成,但后来我不得不在各处添加生命周期标记而不知所措,而且这看起来很不自然。
根据设计,Rust 会阻止您同时激活同一对象上的不可变借用和可变借用。这是为了防止悬挂指针和数据竞争。
在 rusqlite 的 API 中,Connection
上的一些方法需要一个可变的 self
,而一些方法只需要一个不可变的 self
。然而,一些方法只需要一个不可变的 self
return 对象来保持借用; prepare
就是一个例子。因此,只要这些对象之一留在范围内,Rust 就不允许您在 Connection
.
有些方法通过可变引用获取 self
可能是有原因的。要求可变引用可确保被调用方拥有对该对象的独占访问权。如果您认为您需要使用的方法可能不是这种情况,或者您认为可能有另一种方法来解决这个问题,您应该向库的维护者报告问题。
具体来说 prepare
,您可以通过从闭包中调用 prepare_cached
来解决借用冲突。为了做到这一点,你必须让 download_generic
将 connection
作为参数传回闭包,否则你会在 connection
上有两个可变借用,这是不允许的.