如何将表示PostgreSQL数字列的原始字节片转换为f64?

时间:2019-11-18 09:18:45

标签: postgresql rust

我正在查询PostgreSQL的实例并选择一个十进制值的总和:

db=# SELECT SUM(distance) AS total_distance FROM table_name WHERE deleted_at IS NULL;
    total_distance
-----------------------
 3808.0666666666666578
(1 row)

当我尝试在Rust中执行此查询时:

extern crate postgres;
use postgres::{Connection, TlsMode};

fn main() {
    let conn = Connection::connect("postgresql://u:p@localhost:5432/db", TlsMode::None).unwrap();
    let query = "SELECT SUM(distance) AS total_distance FROM table_name WHERE deleted_at IS NULL;";
    for row in &conn.query(query, &[]).unwrap() {
        let total_distance: f64 = row.get("total_distance");
        println!("{}", total_distance);
    }
}

结果:

thread 'main' panicked at 'error retrieving column "total_distance": Error(Conversion(WrongType(Type(Numeric))))'

我在各种线程中看到Postgres板条箱不支持Numeric类型,因此我尝试创建自己的数字类型:

#[derive(Debug)]
struct Float64(f64);

impl FromSql for Float64 {
    fn from_sql(ty: &Type, raw: &[u8]) -> Result<Float64, Box<Error + Sync + Send>> {
        let bytes = raw.try_into().expect("failed!");
        Ok(Float64(f64::from_be_bytes(bytes)))
    }

    fn from_sql_null(ty: &Type) -> Result<Float64, Box<Error + Sync + Send>> {
        Ok(Float64(0.0))
    }

    fn from_sql_nullable(
        ty: &Type,
        raw: Option<&[u8]>,
    ) -> Result<Float64, Box<Error + Sync + Send>> {
        match raw {
            None => Ok(Float64(0.0)),
            Some(value) => Float64::from_sql(ty, value),
        }
    }

    fn accepts(ty: &Type) -> bool {
        NUMERIC.eq(ty)
    }
}

impl Display for Float64 {
    fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
        write!(f, "{}", self.to_string())
    }
}

但是由于原始字节无法解包,这仍然不起作用:

thread 'main' panicked at 'failed!: TryFromSliceError(())', src/libcore/result.rs:1165:5

raw: &[u8]的长度为18,这就是为什么它不能解包的原因。将18字节切片转换为f64的最佳方法是什么?

0 个答案:

没有答案