mirror of
https://github.com/launchbadge/sqlx.git
synced 2025-10-02 15:25:32 +00:00
fix: bigdecimal decoding ob1 for positive weight multiples of 4
This commit is contained in:
parent
f85920acaf
commit
84e8ed0d4c
@ -99,7 +99,8 @@ impl TryFrom<&'_ BigDecimal> for PgNumeric {
|
|||||||
let weight: i16 = if weight_10 <= 0 {
|
let weight: i16 = if weight_10 <= 0 {
|
||||||
weight_10 / 4 - 1
|
weight_10 / 4 - 1
|
||||||
} else {
|
} else {
|
||||||
weight_10 / 4
|
// the `-1` is a fix for an off by 1 error (4 digits should still be 0 weight)
|
||||||
|
(weight_10 - 1) / 4
|
||||||
}
|
}
|
||||||
.try_into()?;
|
.try_into()?;
|
||||||
|
|
||||||
@ -109,11 +110,7 @@ impl TryFrom<&'_ BigDecimal> for PgNumeric {
|
|||||||
base_10.len() / 4
|
base_10.len() / 4
|
||||||
};
|
};
|
||||||
|
|
||||||
let offset = if weight_10 < 0 {
|
let offset = weight_10.rem_euclid(4) as usize;
|
||||||
4 - (-weight_10) % 4
|
|
||||||
} else {
|
|
||||||
weight_10 % 4
|
|
||||||
} as usize;
|
|
||||||
|
|
||||||
let mut digits = Vec::with_capacity(digits_len);
|
let mut digits = Vec::with_capacity(digits_len);
|
||||||
|
|
||||||
@ -173,127 +170,238 @@ impl Decode<'_, Postgres> for BigDecimal {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[cfg(test)]
|
||||||
fn test_bigdecimal_to_pgnumeric() {
|
mod bigdecimal_to_pgnumeric {
|
||||||
let one: BigDecimal = "1".parse().unwrap();
|
use super::{BigDecimal, PgNumeric, PgNumericSign};
|
||||||
assert_eq!(
|
use std::convert::TryFrom;
|
||||||
PgNumeric::try_from(&one).unwrap(),
|
|
||||||
PgNumeric::Number {
|
|
||||||
sign: PgNumericSign::Positive,
|
|
||||||
scale: 0,
|
|
||||||
weight: 0,
|
|
||||||
digits: vec![1]
|
|
||||||
}
|
|
||||||
);
|
|
||||||
|
|
||||||
let ten: BigDecimal = "10".parse().unwrap();
|
#[test]
|
||||||
assert_eq!(
|
fn zero() {
|
||||||
PgNumeric::try_from(&ten).unwrap(),
|
let zero: BigDecimal = "0".parse().unwrap();
|
||||||
PgNumeric::Number {
|
|
||||||
sign: PgNumericSign::Positive,
|
|
||||||
scale: 0,
|
|
||||||
weight: 0,
|
|
||||||
digits: vec![10]
|
|
||||||
}
|
|
||||||
);
|
|
||||||
|
|
||||||
let one_hundred: BigDecimal = "100".parse().unwrap();
|
assert_eq!(
|
||||||
assert_eq!(
|
PgNumeric::try_from(&zero).unwrap(),
|
||||||
PgNumeric::try_from(&one_hundred).unwrap(),
|
PgNumeric::Number {
|
||||||
PgNumeric::Number {
|
sign: PgNumericSign::Positive,
|
||||||
sign: PgNumericSign::Positive,
|
scale: 0,
|
||||||
scale: 0,
|
weight: 0,
|
||||||
weight: 0,
|
digits: vec![]
|
||||||
digits: vec![100]
|
}
|
||||||
}
|
);
|
||||||
);
|
}
|
||||||
|
|
||||||
// BigDecimal doesn't normalize here
|
#[test]
|
||||||
let ten_thousand: BigDecimal = "10000".parse().unwrap();
|
fn one() {
|
||||||
assert_eq!(
|
let one: BigDecimal = "1".parse().unwrap();
|
||||||
PgNumeric::try_from(&ten_thousand).unwrap(),
|
assert_eq!(
|
||||||
PgNumeric::Number {
|
PgNumeric::try_from(&one).unwrap(),
|
||||||
sign: PgNumericSign::Positive,
|
PgNumeric::Number {
|
||||||
scale: 0,
|
sign: PgNumericSign::Positive,
|
||||||
weight: 1,
|
scale: 0,
|
||||||
digits: vec![1]
|
weight: 0,
|
||||||
}
|
digits: vec![1]
|
||||||
);
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
let two_digits: BigDecimal = "12345".parse().unwrap();
|
#[test]
|
||||||
assert_eq!(
|
fn ten() {
|
||||||
PgNumeric::try_from(&two_digits).unwrap(),
|
let ten: BigDecimal = "10".parse().unwrap();
|
||||||
PgNumeric::Number {
|
assert_eq!(
|
||||||
sign: PgNumericSign::Positive,
|
PgNumeric::try_from(&ten).unwrap(),
|
||||||
scale: 0,
|
PgNumeric::Number {
|
||||||
weight: 1,
|
sign: PgNumericSign::Positive,
|
||||||
digits: vec![1, 2345]
|
scale: 0,
|
||||||
}
|
weight: 0,
|
||||||
);
|
digits: vec![10]
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
let one_tenth: BigDecimal = "0.1".parse().unwrap();
|
#[test]
|
||||||
assert_eq!(
|
fn one_hundred() {
|
||||||
PgNumeric::try_from(&one_tenth).unwrap(),
|
let one_hundred: BigDecimal = "100".parse().unwrap();
|
||||||
PgNumeric::Number {
|
assert_eq!(
|
||||||
sign: PgNumericSign::Positive,
|
PgNumeric::try_from(&one_hundred).unwrap(),
|
||||||
scale: 1,
|
PgNumeric::Number {
|
||||||
weight: -1,
|
sign: PgNumericSign::Positive,
|
||||||
digits: vec![1000]
|
scale: 0,
|
||||||
}
|
weight: 0,
|
||||||
);
|
digits: vec![100]
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
let decimal: BigDecimal = "1.2345".parse().unwrap();
|
#[test]
|
||||||
assert_eq!(
|
fn ten_thousand() {
|
||||||
PgNumeric::try_from(&decimal).unwrap(),
|
// BigDecimal doesn't normalize here
|
||||||
PgNumeric::Number {
|
let ten_thousand: BigDecimal = "10000".parse().unwrap();
|
||||||
sign: PgNumericSign::Positive,
|
assert_eq!(
|
||||||
scale: 4,
|
PgNumeric::try_from(&ten_thousand).unwrap(),
|
||||||
weight: 0,
|
PgNumeric::Number {
|
||||||
digits: vec![1, 2345]
|
sign: PgNumericSign::Positive,
|
||||||
}
|
scale: 0,
|
||||||
);
|
weight: 1,
|
||||||
|
digits: vec![1]
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
let decimal: BigDecimal = "0.12345".parse().unwrap();
|
#[test]
|
||||||
assert_eq!(
|
fn two_digits() {
|
||||||
PgNumeric::try_from(&decimal).unwrap(),
|
let two_digits: BigDecimal = "12345".parse().unwrap();
|
||||||
PgNumeric::Number {
|
assert_eq!(
|
||||||
sign: PgNumericSign::Positive,
|
PgNumeric::try_from(&two_digits).unwrap(),
|
||||||
scale: 5,
|
PgNumeric::Number {
|
||||||
weight: -1,
|
sign: PgNumericSign::Positive,
|
||||||
digits: vec![1234, 5000]
|
scale: 0,
|
||||||
}
|
weight: 1,
|
||||||
);
|
digits: vec![1, 2345]
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
let decimal: BigDecimal = "0.01234".parse().unwrap();
|
#[test]
|
||||||
assert_eq!(
|
fn one_tenth() {
|
||||||
PgNumeric::try_from(&decimal).unwrap(),
|
let one_tenth: BigDecimal = "0.1".parse().unwrap();
|
||||||
PgNumeric::Number {
|
assert_eq!(
|
||||||
sign: PgNumericSign::Positive,
|
PgNumeric::try_from(&one_tenth).unwrap(),
|
||||||
scale: 5,
|
PgNumeric::Number {
|
||||||
weight: -1,
|
sign: PgNumericSign::Positive,
|
||||||
digits: vec![0123, 4000]
|
scale: 1,
|
||||||
}
|
weight: -1,
|
||||||
);
|
digits: vec![1000]
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
let decimal: BigDecimal = "12345.67890".parse().unwrap();
|
#[test]
|
||||||
assert_eq!(
|
fn decimal_1() {
|
||||||
PgNumeric::try_from(&decimal).unwrap(),
|
let decimal: BigDecimal = "1.2345".parse().unwrap();
|
||||||
PgNumeric::Number {
|
assert_eq!(
|
||||||
sign: PgNumericSign::Positive,
|
PgNumeric::try_from(&decimal).unwrap(),
|
||||||
scale: 5,
|
PgNumeric::Number {
|
||||||
weight: 1,
|
sign: PgNumericSign::Positive,
|
||||||
digits: vec![1, 2345, 6789]
|
scale: 4,
|
||||||
}
|
weight: 0,
|
||||||
);
|
digits: vec![1, 2345]
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
let one_digit_decimal: BigDecimal = "0.00001234".parse().unwrap();
|
#[test]
|
||||||
assert_eq!(
|
fn decimal_2() {
|
||||||
PgNumeric::try_from(&one_digit_decimal).unwrap(),
|
let decimal: BigDecimal = "0.12345".parse().unwrap();
|
||||||
PgNumeric::Number {
|
assert_eq!(
|
||||||
sign: PgNumericSign::Positive,
|
PgNumeric::try_from(&decimal).unwrap(),
|
||||||
scale: 8,
|
PgNumeric::Number {
|
||||||
weight: -2,
|
sign: PgNumericSign::Positive,
|
||||||
digits: vec![1234]
|
scale: 5,
|
||||||
}
|
weight: -1,
|
||||||
);
|
digits: vec![1234, 5000]
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn decimal_3() {
|
||||||
|
let decimal: BigDecimal = "0.01234".parse().unwrap();
|
||||||
|
assert_eq!(
|
||||||
|
PgNumeric::try_from(&decimal).unwrap(),
|
||||||
|
PgNumeric::Number {
|
||||||
|
sign: PgNumericSign::Positive,
|
||||||
|
scale: 5,
|
||||||
|
weight: -1,
|
||||||
|
digits: vec![0123, 4000]
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn decimal_4() {
|
||||||
|
let decimal: BigDecimal = "12345.67890".parse().unwrap();
|
||||||
|
assert_eq!(
|
||||||
|
PgNumeric::try_from(&decimal).unwrap(),
|
||||||
|
PgNumeric::Number {
|
||||||
|
sign: PgNumericSign::Positive,
|
||||||
|
scale: 5,
|
||||||
|
weight: 1,
|
||||||
|
digits: vec![1, 2345, 6789]
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn one_digit_decimal() {
|
||||||
|
let one_digit_decimal: BigDecimal = "0.00001234".parse().unwrap();
|
||||||
|
assert_eq!(
|
||||||
|
PgNumeric::try_from(&one_digit_decimal).unwrap(),
|
||||||
|
PgNumeric::Number {
|
||||||
|
sign: PgNumericSign::Positive,
|
||||||
|
scale: 8,
|
||||||
|
weight: -2,
|
||||||
|
digits: vec![1234]
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn issue_423_four_digit() {
|
||||||
|
// This is a regression test for https://github.com/launchbadge/sqlx/issues/423
|
||||||
|
let four_digit: BigDecimal = "1234".parse().unwrap();
|
||||||
|
assert_eq!(
|
||||||
|
PgNumeric::try_from(&four_digit).unwrap(),
|
||||||
|
PgNumeric::Number {
|
||||||
|
sign: PgNumericSign::Positive,
|
||||||
|
scale: 0,
|
||||||
|
weight: 0,
|
||||||
|
digits: vec![1234]
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn issue_423_negative_four_digit() {
|
||||||
|
// This is a regression test for https://github.com/launchbadge/sqlx/issues/423
|
||||||
|
let negative_four_digit: BigDecimal = "-1234".parse().unwrap();
|
||||||
|
assert_eq!(
|
||||||
|
PgNumeric::try_from(&negative_four_digit).unwrap(),
|
||||||
|
PgNumeric::Number {
|
||||||
|
sign: PgNumericSign::Negative,
|
||||||
|
scale: 0,
|
||||||
|
weight: 0,
|
||||||
|
digits: vec![1234]
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn issue_423_eight_digit() {
|
||||||
|
// This is a regression test for https://github.com/launchbadge/sqlx/issues/423
|
||||||
|
let eight_digit: BigDecimal = "12345678".parse().unwrap();
|
||||||
|
assert_eq!(
|
||||||
|
PgNumeric::try_from(&eight_digit).unwrap(),
|
||||||
|
PgNumeric::Number {
|
||||||
|
sign: PgNumericSign::Positive,
|
||||||
|
scale: 0,
|
||||||
|
weight: 1,
|
||||||
|
digits: vec![1234, 5678]
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn issue_423_negative_eight_digit() {
|
||||||
|
// This is a regression test for https://github.com/launchbadge/sqlx/issues/423
|
||||||
|
let negative_eight_digit: BigDecimal = "-12345678".parse().unwrap();
|
||||||
|
assert_eq!(
|
||||||
|
PgNumeric::try_from(&negative_eight_digit).unwrap(),
|
||||||
|
PgNumeric::Number {
|
||||||
|
sign: PgNumericSign::Negative,
|
||||||
|
scale: 0,
|
||||||
|
weight: 1,
|
||||||
|
digits: vec![1234, 5678]
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user