postgresql 在rust中,有没有办法从`sqlx::query_with`返回`rows_affected`沿着行本身?

rsaldnfx  于 2023-10-18  发布在  PostgreSQL
关注(0)|答案(1)|浏览(140)

sqlx文档如下所示:
execute查询终结器返回受影响的行数(如果有),并丢弃所有收到的结果。此外,还有fetchfetch_onefetch_optionalfetch_all接收结果。
sqlx::query返回的Query类型将从数据库返回Row<'conn>。列值可以通过序号或名称row.get()访问。由于Row在连接上保留了一个不可变的借用,因此一次只能存在一个Row
有没有办法同时得到rows_affected和行本身?
我尝试在一个事务中运行相同的查询两次,我故意回滚,但当我收到sql语句时,我已经在一个事务的中间,我不能并行运行两个事务。
有没有办法不跑两次?
我使用rust,最新的sqlx和postgres作为数据库。

neekobn8

neekobn81#

您还需要futures crate:

[dependencies]
futures = { version = "0.3.28", default-features = false }
sqlx = { version = "0.7.2", features = ["runtime-tokio", "postgres"] }

然后你可以做这样的恶作剧:

use futures::stream::StreamExt;
use sqlx::{postgres::PgPoolOptions, Either, PgPool, Row};

#[tokio::main]
async fn main() {
    # ...

    do_query(
        &pool,
        "INSERT INTO todos (description) VALUES ('One'), ('Two') RETURNING id",
    )
    .await;
    do_query(&pool, "DELETE FROM todos").await;
}

async fn do_query(pool: &PgPool, query: &str) {
    let prefix = query.split_whitespace().next().unwrap();

    let mut results = sqlx::query(query).fetch_many(pool);

    while let Some(result) = results.next().await {
        let either = result.unwrap();
        match either {
            Either::Left(res) => {
                let num = res.rows_affected();
                println!("[{prefix}] affected {num} rows");
            }
            Either::Right(row) => {
                let num = row.len();
                println!("[{prefix}] fetched {num} rows");
            }
        }
    }
}

这将返回

[INSERT] fetched 1 rows
[INSERT] fetched 1 rows
[INSERT] affected 2 rows
[DELETE] affected 2 rows

相关问题