Skip to content

Commit 42e8e76

Browse files
killercuprubdos
authored andcommitted
Cut T'Sql into pieces
It's a PR of that sort Refactoration Some squeezing With some luck see CI succeeding
1 parent 9140577 commit 42e8e76

1 file changed

Lines changed: 52 additions & 34 deletions

File tree

diesel/src/pg/types/numeric.rs

Lines changed: 52 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -18,10 +18,58 @@ mod bigdecimal {
1818
use pg::data_types::PgNumeric;
1919
use types::{self, FromSql, ToSql, IsNull};
2020

21+
type Digits = Vec<i16>;
22+
23+
fn bigdec_add_integer_part(digits: &mut Digits, absolute: &BigDecimal) -> i16 {
24+
let mut weight = 0;
25+
let ten_k = BigInt::from(10000);
26+
27+
let mut integer_part = absolute.to_bigint().expect("Can always take integer part of BigDecimal");
28+
29+
while ten_k < integer_part {
30+
weight += 1;
31+
// digit is integer_part REM 10_000
32+
let (div, digit) = integer_part.div_rem(&ten_k);
33+
digits.push(digit.to_u16().expect("digit < 10000, but cannot fit in i16") as i16);
34+
integer_part = div;
35+
}
36+
digits.push(integer_part.to_string().parse::<i16>().expect("digit < 10000, but cannot fit in i16"));
37+
38+
digits.reverse();
39+
40+
weight
41+
}
42+
43+
fn bigdec_add_decimal_part(digits: &mut Digits, absolute: &BigDecimal) -> u16 {
44+
use std::str::FromStr;
45+
46+
let ten_k = BigDecimal::from_str("10000").expect("Could not parse into BigDecimal");
47+
48+
let decimal_part = absolute;
49+
let mut decimal_part = decimal_part - absolute.with_scale(0);
50+
// scale is the amount of digits to print. to_string() includes a "0.",
51+
// that's why the -2 is there.
52+
let scale = if decimal_part == Zero::zero() {
53+
0
54+
} else {
55+
decimal_part.to_string().len() as u16 - 2
56+
};
57+
58+
while decimal_part != BigDecimal::zero() {
59+
decimal_part *= &ten_k;
60+
let digit = decimal_part.to_bigint().expect("Can always take integer part of BigDecimal");
61+
62+
// This can be simplified when github.com/akubera/bigdecimal-rs/issues/13 gets
63+
// solved; decimal_part -= &digit; should suffice by then.
64+
decimal_part -= BigDecimal::new(digit.clone(), 0);
65+
digits.push(digit.to_u16().expect("digit < 10000, but cannot fit in i16") as i16);
66+
}
67+
68+
scale
69+
}
70+
2171
impl ToSql<types::Numeric, Pg> for BigDecimal {
2272
fn to_sql<W: Write>(&self, out: &mut W) -> Result<IsNull, Box<Error + Send + Sync>> {
23-
use std::str::FromStr;
24-
2573
// The encoding of the BigDecimal type for PostgreSQL is a bit complicated:
2674
// PostgreSQL expects the data in base-10000 (so two bytes per 10k),
2775
// and the decimal point should lie on a boundary (as per definition of "base-10000").
@@ -33,43 +81,13 @@ mod bigdecimal {
3381
// the sign, the (integer) part before the decimal, and the part after the decimal.
3482

3583
let absolute = self.abs();
36-
3784
let mut digits = vec![];
38-
let ten_k = BigInt::from(10000);
39-
let mut integer_part = absolute.to_bigint().expect("Can always take integer part of BigDecimal");
40-
let decimal_part = &absolute;
41-
let mut decimal_part = decimal_part - absolute.with_scale(0);
42-
// scale is the amount of digits to print. to_string() includes a "0.",
43-
// that's why the -2 is there.
44-
let scale = if decimal_part == Zero::zero() {
45-
0
46-
} else {
47-
decimal_part.to_string().len() as u16 - 2
48-
};
49-
let mut weight = 0;
5085

5186
// Encode the integer part
52-
while ten_k < integer_part {
53-
weight += 1;
54-
// digit is integer_part REM 10_000
55-
let (div, digit) = integer_part.div_rem(&ten_k);
56-
digits.push(digit.to_u16().expect("digit < 10000, but cannot fit in i16") as i16);
57-
integer_part = div;
58-
}
59-
digits.push(integer_part.to_string().parse::<i16>().expect("digit < 10000, but cannot fit in i16"));
60-
61-
digits.reverse();
87+
let weight = bigdec_add_integer_part(&mut digits, &absolute);
6288

6389
// Encode the decimal part
64-
let ten_k = BigDecimal::from_str("10000").expect("Could not parse into BigDecimal");
65-
while decimal_part != BigDecimal::zero() {
66-
decimal_part *= &ten_k;
67-
let digit = decimal_part.to_bigint().expect("Can always take integer part of BigDecimal");
68-
// This can be simplified when github.com/akubera/bigdecimal-rs/issues/13 gets
69-
// solved; decimal_part -= &digit; should suffice by then.
70-
decimal_part -= BigDecimal::new(digit.clone(), 0);
71-
digits.push(digit.to_u16().expect("digit < 10000, but cannot fit in i16") as i16);
72-
}
90+
let scale = bigdec_add_decimal_part(&mut digits, &absolute);
7391

7492
let numeric = match self.sign() {
7593
Sign::Plus => PgNumeric::Positive {

0 commit comments

Comments
 (0)