如何在 Rust 中将 rusqlite Connection 和 Statement 对象存储在同一个结构中? [复制]

2024-01-03

我正在开发我的第一个 Rust 程序,并且与 Rust 所有权语义发生了冲突。我已经宣布了struct它将封装一个 SQLite 数据库连接,以便它维护一个Connection成员。出于性能原因,我还想保留一个准备好的语句,由Statement类型。这是我的代码的简化版本:

extern crate rusqlite; // 0.14.0

use rusqlite::{Connection, Statement};

pub struct Foo<'a> {
    conn: Connection,
    statement: Statement<'a>,
}

impl<'a> Foo<'a> {
    pub fn new() -> Foo<'a> {
        let conn = Connection::open(&":memory:").unwrap();
        let statement = conn
            .prepare("INSERT INTO Foo(name, hash) VALUES($1, $2)")
            .unwrap();
        Foo { conn, statement }
    }
}

我正在尝试转让所有权conn通过将变量存储在成员中来传递给被调用者Foo,但是当我尝试编译此代码时,它失败了:

error[E0597]: `conn` does not live long enough
  --> src/main.rs:13:25
   |
13 |         let statement = conn
   |                         ^^^^ borrowed value does not live long enough
...
17 |     }
   |     - borrowed value only lives until here
   |
note: borrowed value must be valid for the lifetime 'a as defined on the impl at 10:6...
  --> src/main.rs:10:6
   |
10 | impl<'a> Foo<'a> {
   |      ^^

由于某种原因,rusqlite::Connectiontype 不接受生命周期参数,因此我无法显式地将其生命周期与Statement实例。

我缺少什么?这种封装是一种非常常见的模式,我确信我遗漏了一些东西。


让我们看看Connection::prepare https://docs.rs/rusqlite/0.14.0/rusqlite/struct.Connection.html#method.prepare:

pub fn prepare<'a>(&'a self, sql: &str) -> Result<Statement<'a>>

如果我们忽略Result(这只是意味着这个函数可能会失败),这意味着“返回一个Statement其寿命不能超过Connection that prepare被召唤”。这可能是由于Statement包含对Connection.

但是,如果您有对某个项目的引用,则您无法再移动该项目,因为该引用将无效。使用该无效引用会导致内存不安全,因此应避免这种情况。

基本上,您需要在代码中镜像这些对象的生命周期和所有权,因此您不能捆绑Connection and Statement在相同的结构中。相反,一个可以引用另一个。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

如何在 Rust 中将 rusqlite Connection 和 Statement 对象存储在同一个结构中? [复制] 的相关文章

随机推荐