< 返回版块

坚果修补匠 发表于 2021-11-19 18:17

问题是这样的,今天我在用 SQLx 连接数据库时,用到了 SQLx 提供的 query_with 这么一个函数,它要求传入的 sqlarguments 的生命周期一致。而当我编写下面的代码时,却报出了生命周期不够长的问题。

pub type SQLArgs<'a> = sqlx::any::AnyArguments<'a>;
pub fn build_where<'a>(condition: Condition) -> (String, SQLArgs<'a>)

pub fn query_with<'q, DB, A>(sql: &'q str, arguments: A) -> Query<'q, DB, A> 
where
    DB: Database,
    A: IntoArguments<'q, DB>, 

        // Check sql statment
        let select = DMLBuilder::build_wildcard_select("Genshin_characters");
        let (where_, existed_args) = DMLBuilder::build_where(complicated_condition);
        let limit = DMLBuilder::build_limit(1);
        let query_xp_character = format!("{}{}{}", select, where_, limit);
        assert_eq!(
            query_xp_character,
            r#"SELECT * FROM `Genshin_characters` WHERE ((`SEX` = ?) AND (`Region` IN (?, ?)) AND (`Vision` = ?)) OR (`Name` = ?) LIMIT 1"#
        );
        
        let mut conn = sqlx::AnyConnection::connect("sqlite://:memory:").await.unwrap();
        conn.execute(
            r#"
            CREATE TABLE `Genshin_characters` (
                id Integer Primary Key,
                SEX varchar(20),
                Region varchar(20),
                Vision varchar(20),
                Name varchar(20)
            );
            INSERT INTO `Genshin_characters` (SEX, Region, Vision, Name) VALUES
            ("FEMALE", "Liyue", "Pyro", "Xiangling")
        "#,
        )
        .await
        .unwrap();
        let res = sqlx::query_with(&query_xp_character, existed_args)
            .fetch_optional(&mut conn)
            .await
            .unwrap();
        assert!(res.is_some());
        let row = res.unwrap();
        assert_eq!("Xiangling", row.get::<&str, &str>("Name"));
error[E0597]: `query_xp_character` does not live long enough
   --> colos-rs-server/src/dao/sql/dml_builder.rs:292:36
    |
292 |         let res = sqlx::query_with(&query_xp_character, existed_args)
    |                                    ^^^^^^^^^^^^^^^^^^^ borrowed value does not live long enough
...
299 |     }
    |     -
    |     |
    |     `query_xp_character` dropped here while still borrowed
    |     borrow might be used here, when `existed_args` is dropped and runs the destructor for type `AnyArguments<'_>`
    |
    = note: values in a scope are dropped in the opposite order they are defined

根据我的理解,query_xp_character 这个 String 的生命周期与这个函数一致,existed_args 的生命周期也是一样。并没法理解这个问题出在那里。

评论区

写评论
作者 坚果修补匠 2021-11-20 10:20

哦哦😯

--
👇
lan: 变量们会依照声明顺序的倒序drop,你这里的代码中有俩借用产生了依赖,调整声明顺序让被借用者后drop即可。

lan 2021-11-19 20:39

变量们会依照声明顺序的倒序drop,你这里的代码中有俩借用产生了依赖,调整声明顺序让被借用者后drop即可。

作者 坚果修补匠 2021-11-19 18:22

PS: 如果我这么写就可以通过编译

        let (query_xp_character, existed_args) = {
            // Check sql statment
            let select = DMLBuilder::build_wildcard_select("Genshin_characters");
            let (where_, existed_args) = DMLBuilder::build_where(complicated_condition);
            let limit = DMLBuilder::build_limit(1);
            let query_xp_character = format!("{}{}{}", select, where_, limit);
            (query_xp_character, existed_args)
        };
1 共 3 条评论, 1 页