You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Rust中postgres::Error错误处理失败,寻求解决方案

处理postgres::Error时的编译错误解决方法

我在处理postgres::Error时遇到问题,尝试用SqlState或DbError都没效果,怀疑postgres::error的错误处理有局限,或是自己遗漏了要点。以下是我的Rust代码:

extern crate postgres;
use postgres::{Client, NoTls};
use postgres::error::Error as PgError;

pub async fn get_metadata(client: &Client, db: String, schema: String) -> Result<serde_json::Value, PgError> {

    let query = r#"
        select row_to_json(Tb) as tbls from(
        . . . .         
        WHERE table_schema=$1) Tb;
    "#;

    // Execute the query and collect the results
    let rows = client.query(query, &[&schema])?;

    // Assuming you expect only one row as a result
    if let Some(row) = rows.iter().next() {
        // Extract the JSON response from the "tbls" column
        let json_response: Option<serde_json::Value> = row.get(0);

        
        // You can now work with the JSON response
        match json_response {
            Some(json) => {
                return Ok(json);
            }
            None => {
                eprintln!("No JSON response found in the result.");
                // Return an error here
                return Err(_);
            }
        }
    }

    // Return an error if no row is found
    Err(PgError.into_source())
}

运行代码后出现以下编译错误:

error[E0061]: this function takes 1 argument but 0 arguments were supplied
   --> src/main.rs:64:9
    |
64  |     Err(PgError::into_source())
    |         ^^^^^^^^^^^^^^^^^^^^-- an argument of type `postgres::Error` is missing
    |
note: method defined here
   --> /home/afidegnum/.cargo/registry/src/index.crates.io-6f17d22bba15001f/tokio-postgres-0.7.10/src/error/mod.rs:417:12
    |
417 |     pub fn into_source(self) -> Option<Box<dyn error::Error + Sync + Send>> {
    |            ^^^^^^^^^^^
help: provide the argument
    |
64  |     Err(PgError::into_source(/* postgres::Error */))
    |                             ~~~~~~~~~~~~~~~~~~~~~~~

error[E0308]: mismatched types
   --> src/main.rs:64:9
    |
64  |     Err(PgError::into_source())
    |     --- ^^^^^^^^^^^^^^^^^^^^^^ expected `Error`, found `Option<Box<...>>`
    |     |
    |     arguments to this enum variant are incorrect
    |
    = note: expected struct `postgres::Error`
                 found enum `Option<Box<(dyn std::error::Error + Send + Sync + 'static)>>`
help: the type constructed contains `Option<Box<(dyn std::error::Error + Send + Sync + 'static)>>` due to the type of the argument passed
   --> src/main.rs:64:5
    |
64  |     Err(PgError::into_source())
    |     ^^^^----------------------^
    |         |
    |         this argument influences the type of `Err`
note: tuple variant defined here
   --> /home/afidegnum/.rustup/toolchains/stable-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/result.rs:511:5
    |
511 |     Err(#[stable(feature = "rust1", since = "1.0.0")] E),
    |     ^^^

尝试使用std::io::Error也无法解决该问题。


问题分析

编译错误的核心是两处误用:

  1. into_source()方法调用错误:into_source()是postgres::Error实例的方法,需要通过具体错误对象调用,而非作为静态方法直接调用。而且它返回的是Option<Box<dyn Error + Sync + Send>>,和你函数声明的返回错误类型PgError不匹配。
  2. 自定义错误返回缺失:当JSON值为空或无查询结果时,你没有构造合法的PgError实例,而是用Err(_)这种无效写法。

解决方案

方案1:改用通用错误类型(推荐)

将函数返回的错误类型改为Box<dyn Error>,这样可以灵活返回任意实现了Error trait的错误,包括postgres原生错误和自定义错误:

extern crate postgres;
use postgres::{Client, NoTls};
use postgres::error::Error as PgError;
use std::error::Error;

pub async fn get_metadata(client: &Client, db: String, schema: String) -> Result<serde_json::Value, Box<dyn Error>> {
    let query = r#"
        select row_to_json(Tb) as tbls from(
        . . . .         
        WHERE table_schema=$1) Tb;
    "#;

    // 执行查询,postgres错误会自动转为Box<dyn Error>
    let rows = client.query(query, &[&schema])?;

    if let Some(row) = rows.iter().next() {
        let json_response: Option<serde_json::Value> = row.get(0);

        match json_response {
            Some(json) => Ok(json),
            None => {
                eprintln!("No JSON response found in the result.");
                // 返回自定义字符串错误
                Err("No JSON response found in query result".into())
            }
        }
    } else {
        // 返回自定义无结果错误
        Err("No rows returned for the specified schema".into())
    }
}

方案2:构造PgError实例(若必须返回PgError)

如果业务要求必须返回PgError,可以手动构造DbError并包装成PgError:

extern crate postgres;
use postgres::{Client, NoTls};
use postgres::error::{Error as PgError, DbError, SqlState};

pub async fn get_metadata(client: &Client, db: String, schema: String) -> Result<serde_json::Value, PgError> {
    let query = r#"
        select row_to_json(Tb) as tbls from(
        . . . .         
        WHERE table_schema=$1) Tb;
    "#;

    let rows = client.query(query, &[&schema])?;

    if let Some(row) = rows.iter().next() {
        let json_response: Option<serde_json::Value> = row.get(0);

        match json_response {
            Some(json) => Ok(json),
            None => {
                eprintln!("No JSON response found in the result.");
                // 构造DbError实例
                let db_err = DbError::new(
                    SqlState::NO_DATA,
                    "No JSON value found in result row".to_string(),
                    None,
                    vec![],
                );
                Err(PgError::Db(db_err))
            }
        }
    } else {
        // 构造无结果的DbError
        let db_err = DbError::new(
            SqlState::NO_DATA,
            "No rows returned for schema".to_string(),
            None,
            vec![],
        );
        Err(PgError::Db(db_err))
    }
}

关键说明

  • into_source()是用来从已有的PgError实例中提取底层错误来源的,不是用来创建新错误的方法。
  • 通用错误类型Box<dyn Error>在Rust错误处理中更灵活,适合大多数场景,避免被特定错误类型绑定。

内容的提问来源于stack exchange,提问作者alexander

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.09 22:35:27