如何使用Diesel的PgNumeric类型插入十进制数?

时间:2016-07-03 23:41:40

标签: rust rust-diesel

我对如何使用signalAll()类型的十进制数字感到困惑。我在tests中注意到使用以下实例将PgNumeric1.0插入到表中:

-31.0

PgNumeric::Positive { weight: 0, scale: 1, digits: vec![1] } 

我似乎无法弄清楚如何将带小数点右边的数字(如PgNumeric::Negative {weight: 0, scale: 1, digits: vec![31] } )插入表中。

1 个答案:

答案 0 :(得分:3)

简短回答:PgNumeric::Positive { weight: 0, scale: 4, digits: [5, 4321] }

更多例子:

// 9.87654321::numeric
PgNumeric::Positive { weight: 0, scale: 8, digits: [9, 8765, 4321] }

// 12345.6789::numeric
PgNumeric::Positive { weight: 1, scale: 4, digits: [1, 2345, 6789] }

// 100000000.000000002::numeric
PgNumeric::Positive { weight: 2, scale: 9, digits: [1, 0, 0, 0, 0, 2000] }

// 0.3::numeric
PgNumeric::Positive { weight: -1, scale: 1, digits: [3000] }

看起来好像算法是:

  1. 将您的号码分组为从小数点开始并向外工作的4位数字块。这些是数字

  2. 计算表示整数部分所需的的数量并减去一个。这是重量

  3. 计算表示小数部分所需的位数。这是比例

  4. 测试工具

    这是我正在玩的代码,从测试中提取出来:

    extern crate diesel;
    
    use diesel::*;
    use diesel::types::*;
    
    use diesel::pg::data_types::PgNumeric;
    use diesel::pg::PgConnection;
    
     type PgBackend = <PgConnection as Connection>::Backend;
    
    fn main() {
        let query = "100000000.000000002::numeric";
        let expected_value = PgNumeric::Negative {
            digits: vec![31],
            weight: 0,
            scale: 1,
        };
        assert_eq!(expected_value, query_single_value::<Numeric, PgNumeric>(query));
    }
    
    fn query_single_value<T, U: Queryable<T, PgBackend>>(sql_str: &str) -> U
        where PgBackend: HasSqlType<T>,
    {
        use diesel::expression::dsl::sql;
        let connection = connection();
        select(sql::<T>(sql_str)).first(&connection).unwrap()
    }
    
    fn connection() -> PgConnection {
        let result = connection_without_transaction();
        result.begin_test_transaction().unwrap();
        result
    }
    
    fn connection_without_transaction() -> PgConnection {
        let connection_url = "postgres://localhost/some_db";
        ::diesel::pg::PgConnection::establish(&connection_url).unwrap()
    }
    

    潜在有用的背景信息

    来自Postgres docs

      

    数字的比例是小数点右侧小数部分的小数位数。数字的精度是整数中有效数字的总数,即小数点两边的位数。因此,数字23.5141的精度为6,比例为4。

    然而,Postgres code说:

    /*
     * In the NumericShort format, the remaining 14 bits of the header word
     * (n_short.n_header) are allocated as follows: 1 for sign (positive or
     * negative), 6 for dynamic scale, and 7 for weight.  In practice, most
     * commonly-encountered values can be represented this way.
     *
     * In the NumericLong format, the remaining 14 bits of the header word
     * (n_long.n_sign_dscale) represent the display scale; and the weight is
     * stored separately in n_weight.
     */