如何使用 Diesel 的 Pg 数字类型插入小数?
How to insert a decimal number with Diesel's PgNumeric type?
我对如何将 PgNumeric
类型用于十进制数字感到困惑。我在 tests 中注意到 1.0
和 -31.0
使用以下实例插入到 table 中:
PgNumeric::Positive { weight: 0, scale: 1, digits: vec![1] }
和
PgNumeric::Negative {weight: 0, scale: 1, digits: vec![31] }
我似乎无法弄清楚如何将小数点右侧带有数字的值(如 5.4321
)插入 table。
简答: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] }
看起来好像算法是:
将您的号码分组为 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()
}
可能有用的背景信息
The scale of a numeric is the count of decimal digits in the fractional part, to the right of the decimal point. The precision of a numeric is the total count of significant digits in the whole number, that is, the number of digits to both sides of the decimal point. So the number 23.5141 has a precision of 6 and a scale of 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.
*/
我对如何将 PgNumeric
类型用于十进制数字感到困惑。我在 tests 中注意到 1.0
和 -31.0
使用以下实例插入到 table 中:
PgNumeric::Positive { weight: 0, scale: 1, digits: vec![1] }
和
PgNumeric::Negative {weight: 0, scale: 1, digits: vec![31] }
我似乎无法弄清楚如何将小数点右侧带有数字的值(如 5.4321
)插入 table。
简答: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] }
看起来好像算法是:
将您的号码分组为 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()
}
可能有用的背景信息
The scale of a numeric is the count of decimal digits in the fractional part, to the right of the decimal point. The precision of a numeric is the total count of significant digits in the whole number, that is, the number of digits to both sides of the decimal point. So the number 23.5141 has a precision of 6 and a scale of 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.
*/