1 use crate::constants::MAX_PRECISION;
2 use crate::{
3     ops::array::{div_by_u32, is_all_zero, mul_by_u32},
4     Decimal,
5 };
6 use core::{convert::TryInto, fmt};
7 use std::error;
8 
9 #[derive(Debug, Clone)]
10 pub struct InvalidDecimal {
11     inner: Option<String>,
12 }
13 
14 impl fmt::Display for InvalidDecimal {
fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result15     fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
16         if let Some(ref msg) = self.inner {
17             fmt.write_fmt(format_args!("Invalid Decimal: {}", msg))
18         } else {
19             fmt.write_str("Invalid Decimal")
20         }
21     }
22 }
23 
24 impl error::Error for InvalidDecimal {}
25 
26 struct PostgresDecimal<D> {
27     neg: bool,
28     weight: i16,
29     scale: u16,
30     digits: D,
31 }
32 
33 impl Decimal {
34     fn from_postgres<D: ExactSizeIterator<Item = u16>>(
35         PostgresDecimal {
36             neg,
37             scale,
38             digits,
39             weight,
40         }: PostgresDecimal<D>,
41     ) -> Self {
42         let mut digits = digits.into_iter().collect::<Vec<_>>();
43 
44         let fractionals_part_count = digits.len() as i32 + (-weight as i32) - 1;
45         let integers_part_count = weight as i32 + 1;
46 
47         let mut result = Decimal::ZERO;
48         // adding integer part
49         if integers_part_count > 0 {
50             let (start_integers, last) = if integers_part_count > digits.len() as i32 {
51                 (integers_part_count - digits.len() as i32, digits.len() as i32)
52             } else {
53                 (0, integers_part_count)
54             };
55             let integers: Vec<_> = digits.drain(..last as usize).collect();
56             for digit in integers {
57                 result *= Decimal::from_i128_with_scale(10i128.pow(4), 0);
58                 result += Decimal::new(digit as i64, 0);
59             }
60             result *= Decimal::from_i128_with_scale(10i128.pow(4 * start_integers as u32), 0);
61         }
62         // adding fractional part
63         if fractionals_part_count > 0 {
64             let dec: Vec<_> = digits.into_iter().collect();
65             let start_fractionals = if weight < 0 { (-weight as u32) - 1 } else { 0 };
66             for (i, digit) in dec.into_iter().enumerate() {
67                 let fract_pow = 4 * (i as u32 + 1 + start_fractionals);
68                 if fract_pow <= MAX_PRECISION {
69                     result += Decimal::new(digit as i64, 0) / Decimal::from_i128_with_scale(10i128.pow(fract_pow), 0);
70                 } else if fract_pow == MAX_PRECISION + 4 {
71                     // rounding last digit
72                     if digit >= 5000 {
73                         result += Decimal::new(1_i64, 0) / Decimal::from_i128_with_scale(10i128.pow(MAX_PRECISION), 0);
74                     }
75                 }
76             }
77         }
78 
79         result.set_sign_negative(neg);
80         // Rescale to the postgres value, automatically rounding as needed.
81         result.rescale(scale as u32);
82         result
83     }
84 
to_postgres(self) -> PostgresDecimal<Vec<i16>>85     fn to_postgres(self) -> PostgresDecimal<Vec<i16>> {
86         if self.is_zero() {
87             return PostgresDecimal {
88                 neg: false,
89                 weight: 0,
90                 scale: 0,
91                 digits: vec![0],
92             };
93         }
94         let scale = self.scale() as u16;
95 
96         let groups_diff = scale & 0x3; // groups_diff = scale % 4
97 
98         let mut mantissa = self.mantissa_array4();
99 
100         if groups_diff > 0 {
101             let remainder = 4 - groups_diff;
102             let power = 10u32.pow(u32::from(remainder));
103             mul_by_u32(&mut mantissa, power);
104         }
105 
106         // array to store max mantissa of Decimal in Postgres decimal format
107         const MAX_GROUP_COUNT: usize = 8;
108         let mut digits = Vec::with_capacity(MAX_GROUP_COUNT);
109 
110         while !is_all_zero(&mantissa) {
111             let digit = div_by_u32(&mut mantissa, 10000) as u16;
112             digits.push(digit.try_into().unwrap());
113         }
114         digits.reverse();
115         let digits_after_decimal = (scale + 3) as u16 / 4;
116         let weight = digits.len() as i16 - digits_after_decimal as i16 - 1;
117 
118         let unnecessary_zeroes = if weight >= 0 {
119             let index_of_decimal = (weight + 1) as usize;
120             digits
121                 .get(index_of_decimal..)
122                 .expect("enough digits exist")
123                 .iter()
124                 .rev()
125                 .take_while(|i| **i == 0)
126                 .count()
127         } else {
128             0
129         };
130         let relevant_digits = digits.len() - unnecessary_zeroes;
131         digits.truncate(relevant_digits);
132 
133         PostgresDecimal {
134             neg: self.is_sign_negative(),
135             digits,
136             scale,
137             weight,
138         }
139     }
140 }
141 
142 #[cfg(feature = "diesel")]
143 mod diesel {
144     use super::*;
145     use ::diesel::{
146         deserialize::{self, FromSql},
147         pg::data_types::PgNumeric,
148         pg::Pg,
149         serialize::{self, Output, ToSql},
150         sql_types::Numeric,
151     };
152     use core::convert::{TryFrom, TryInto};
153     use std::io::Write;
154 
155     impl<'a> TryFrom<&'a PgNumeric> for Decimal {
156         type Error = Box<dyn error::Error + Send + Sync>;
157 
try_from(numeric: &'a PgNumeric) -> deserialize::Result<Self>158         fn try_from(numeric: &'a PgNumeric) -> deserialize::Result<Self> {
159             let (neg, weight, scale, digits) = match *numeric {
160                 PgNumeric::Positive {
161                     weight,
162                     scale,
163                     ref digits,
164                 } => (false, weight, scale, digits),
165                 PgNumeric::Negative {
166                     weight,
167                     scale,
168                     ref digits,
169                 } => (true, weight, scale, digits),
170                 PgNumeric::NaN => return Err(Box::from("NaN is not supported in Decimal")),
171             };
172 
173             Ok(Self::from_postgres(PostgresDecimal {
174                 neg,
175                 weight,
176                 scale,
177                 digits: digits.iter().copied().map(|v| v.try_into().unwrap()),
178             }))
179         }
180     }
181 
182     impl TryFrom<PgNumeric> for Decimal {
183         type Error = Box<dyn error::Error + Send + Sync>;
184 
try_from(numeric: PgNumeric) -> deserialize::Result<Self>185         fn try_from(numeric: PgNumeric) -> deserialize::Result<Self> {
186             (&numeric).try_into()
187         }
188     }
189 
190     impl<'a> From<&'a Decimal> for PgNumeric {
from(decimal: &'a Decimal) -> Self191         fn from(decimal: &'a Decimal) -> Self {
192             let PostgresDecimal {
193                 neg,
194                 weight,
195                 scale,
196                 digits,
197             } = decimal.to_postgres();
198 
199             if neg {
200                 PgNumeric::Negative { digits, scale, weight }
201             } else {
202                 PgNumeric::Positive { digits, scale, weight }
203             }
204         }
205     }
206 
207     impl From<Decimal> for PgNumeric {
from(bigdecimal: Decimal) -> Self208         fn from(bigdecimal: Decimal) -> Self {
209             (&bigdecimal).into()
210         }
211     }
212 
213     impl ToSql<Numeric, Pg> for Decimal {
to_sql<W: Write>(&self, out: &mut Output<W, Pg>) -> serialize::Result214         fn to_sql<W: Write>(&self, out: &mut Output<W, Pg>) -> serialize::Result {
215             let numeric = PgNumeric::from(self);
216             ToSql::<Numeric, Pg>::to_sql(&numeric, out)
217         }
218     }
219 
220     impl FromSql<Numeric, Pg> for Decimal {
from_sql(numeric: Option<&[u8]>) -> deserialize::Result<Self>221         fn from_sql(numeric: Option<&[u8]>) -> deserialize::Result<Self> {
222             PgNumeric::from_sql(numeric)?.try_into()
223         }
224     }
225 
226     #[cfg(test)]
227     mod pg_tests {
228         use super::*;
229         use core::str::FromStr;
230 
231         #[test]
test_unnecessary_zeroes()232         fn test_unnecessary_zeroes() {
233             fn extract(value: &str) -> Decimal {
234                 Decimal::from_str(value).unwrap()
235             }
236 
237             let tests = &[
238                 ("0.000001660"),
239                 ("41.120255926293000"),
240                 ("0.5538973300"),
241                 ("08883.55986854293100"),
242                 ("0.0000_0000_0016_6000_00"),
243                 ("0.00000166650000"),
244                 ("1666500000000"),
245                 ("1666500000000.0000054500"),
246                 ("8944.000000000000"),
247             ];
248 
249             for &value in tests {
250                 let value = extract(value);
251                 let pg = PgNumeric::from(value);
252                 let dec = Decimal::try_from(pg).unwrap();
253                 assert_eq!(dec, value);
254             }
255         }
256 
257         #[test]
decimal_to_pgnumeric_converts_digits_to_base_10000()258         fn decimal_to_pgnumeric_converts_digits_to_base_10000() {
259             let decimal = Decimal::from_str("1").unwrap();
260             let expected = PgNumeric::Positive {
261                 weight: 0,
262                 scale: 0,
263                 digits: vec![1],
264             };
265             assert_eq!(expected, decimal.into());
266 
267             let decimal = Decimal::from_str("10").unwrap();
268             let expected = PgNumeric::Positive {
269                 weight: 0,
270                 scale: 0,
271                 digits: vec![10],
272             };
273             assert_eq!(expected, decimal.into());
274 
275             let decimal = Decimal::from_str("10000").unwrap();
276             let expected = PgNumeric::Positive {
277                 weight: 1,
278                 scale: 0,
279                 digits: vec![1, 0],
280             };
281             assert_eq!(expected, decimal.into());
282 
283             let decimal = Decimal::from_str("10001").unwrap();
284             let expected = PgNumeric::Positive {
285                 weight: 1,
286                 scale: 0,
287                 digits: vec![1, 1],
288             };
289             assert_eq!(expected, decimal.into());
290 
291             let decimal = Decimal::from_str("100000000").unwrap();
292             let expected = PgNumeric::Positive {
293                 weight: 2,
294                 scale: 0,
295                 digits: vec![1, 0, 0],
296             };
297             assert_eq!(expected, decimal.into());
298         }
299 
300         #[test]
decimal_to_pg_numeric_properly_adjusts_scale()301         fn decimal_to_pg_numeric_properly_adjusts_scale() {
302             let decimal = Decimal::from_str("1").unwrap();
303             let expected = PgNumeric::Positive {
304                 weight: 0,
305                 scale: 0,
306                 digits: vec![1],
307             };
308             assert_eq!(expected, decimal.into());
309 
310             let decimal = Decimal::from_str("1.0").unwrap();
311             let expected = PgNumeric::Positive {
312                 weight: 0,
313                 scale: 1,
314                 digits: vec![1],
315             };
316             assert_eq!(expected, decimal.into());
317 
318             let decimal = Decimal::from_str("1.1").unwrap();
319             let expected = PgNumeric::Positive {
320                 weight: 0,
321                 scale: 1,
322                 digits: vec![1, 1000],
323             };
324             assert_eq!(expected, decimal.into());
325 
326             let decimal = Decimal::from_str("1.10").unwrap();
327             let expected = PgNumeric::Positive {
328                 weight: 0,
329                 scale: 2,
330                 digits: vec![1, 1000],
331             };
332             assert_eq!(expected, decimal.into());
333 
334             let decimal = Decimal::from_str("100000000.0001").unwrap();
335             let expected = PgNumeric::Positive {
336                 weight: 2,
337                 scale: 4,
338                 digits: vec![1, 0, 0, 1],
339             };
340             assert_eq!(expected, decimal.into());
341 
342             let decimal = Decimal::from_str("0.1").unwrap();
343             let expected = PgNumeric::Positive {
344                 weight: -1,
345                 scale: 1,
346                 digits: vec![1000],
347             };
348             assert_eq!(expected, decimal.into());
349         }
350 
351         #[test]
352         #[cfg(feature = "unstable")]
decimal_to_pg_numeric_retains_sign()353         fn decimal_to_pg_numeric_retains_sign() {
354             let decimal = Decimal::from_str("123.456").unwrap();
355             let expected = PgNumeric::Positive {
356                 weight: 0,
357                 scale: 3,
358                 digits: vec![123, 4560],
359             };
360             assert_eq!(expected, decimal.into());
361 
362             let decimal = Decimal::from_str("-123.456").unwrap();
363             let expected = PgNumeric::Negative {
364                 weight: 0,
365                 scale: 3,
366                 digits: vec![123, 4560],
367             };
368             assert_eq!(expected, decimal.into());
369         }
370 
371         #[test]
pg_numeric_to_decimal_works()372         fn pg_numeric_to_decimal_works() {
373             let expected = Decimal::from_str("50").unwrap();
374             let pg_numeric = PgNumeric::Positive {
375                 weight: 0,
376                 scale: 0,
377                 digits: vec![50],
378             };
379             let res: Decimal = pg_numeric.try_into().unwrap();
380             assert_eq!(res, expected);
381             let expected = Decimal::from_str("123.456").unwrap();
382             let pg_numeric = PgNumeric::Positive {
383                 weight: 0,
384                 scale: 3,
385                 digits: vec![123, 4560],
386             };
387             let res: Decimal = pg_numeric.try_into().unwrap();
388             assert_eq!(res, expected);
389 
390             let expected = Decimal::from_str("-56.78").unwrap();
391             let pg_numeric = PgNumeric::Negative {
392                 weight: 0,
393                 scale: 2,
394                 digits: vec![56, 7800],
395             };
396             let res: Decimal = pg_numeric.try_into().unwrap();
397             assert_eq!(res, expected);
398 
399             // Verify no trailing zeroes are lost.
400 
401             let expected = Decimal::from_str("1.100").unwrap();
402             let pg_numeric = PgNumeric::Positive {
403                 weight: 0,
404                 scale: 3,
405                 digits: vec![1, 1000],
406             };
407             let res: Decimal = pg_numeric.try_into().unwrap();
408             assert_eq!(res.to_string(), expected.to_string());
409 
410             // To represent 5.00, Postgres can return either [5, 0] as the list of digits.
411             let expected = Decimal::from_str("5.00").unwrap();
412             let pg_numeric = PgNumeric::Positive {
413                 weight: 0,
414                 scale: 2,
415 
416                 digits: vec![5, 0],
417             };
418             let res: Decimal = pg_numeric.try_into().unwrap();
419             assert_eq!(res.to_string(), expected.to_string());
420 
421             // To represent 5.00, Postgres can return [5] as the list of digits.
422             let expected = Decimal::from_str("5.00").unwrap();
423             let pg_numeric = PgNumeric::Positive {
424                 weight: 0,
425                 scale: 2,
426                 digits: vec![5],
427             };
428             let res: Decimal = pg_numeric.try_into().unwrap();
429             assert_eq!(res.to_string(), expected.to_string());
430 
431             let expected = Decimal::from_str("3.1415926535897932384626433833").unwrap();
432             let pg_numeric = PgNumeric::Positive {
433                 weight: 0,
434                 scale: 30,
435                 digits: vec![3, 1415, 9265, 3589, 7932, 3846, 2643, 3832, 7950, 2800],
436             };
437             let res: Decimal = pg_numeric.try_into().unwrap();
438             assert_eq!(res.to_string(), expected.to_string());
439 
440             let expected = Decimal::from_str("3.1415926535897932384626433833").unwrap();
441             let pg_numeric = PgNumeric::Positive {
442                 weight: 0,
443                 scale: 34,
444                 digits: vec![3, 1415, 9265, 3589, 7932, 3846, 2643, 3832, 7950, 2800],
445             };
446 
447             let res: Decimal = pg_numeric.try_into().unwrap();
448             assert_eq!(res.to_string(), expected.to_string());
449 
450             let expected = Decimal::from_str("1.2345678901234567890123456790").unwrap();
451             let pg_numeric = PgNumeric::Positive {
452                 weight: 0,
453                 scale: 34,
454                 digits: vec![1, 2345, 6789, 0123, 4567, 8901, 2345, 6789, 5000, 0],
455             };
456 
457             let res: Decimal = pg_numeric.try_into().unwrap();
458             assert_eq!(res.to_string(), expected.to_string());
459         }
460     }
461 }
462 
463 #[cfg(feature = "postgres")]
464 mod postgres {
465     use super::*;
466     use ::postgres::types::{to_sql_checked, FromSql, IsNull, ToSql, Type};
467     use byteorder::{BigEndian, ReadBytesExt};
468     use bytes::{BufMut, BytesMut};
469     use std::io::Cursor;
470 
471     impl<'a> FromSql<'a> for Decimal {
472         // Decimals are represented as follows:
473         // Header:
474         //  u16 numGroups
475         //  i16 weightFirstGroup (10000^weight)
476         //  u16 sign (0x0000 = positive, 0x4000 = negative, 0xC000 = NaN)
477         //  i16 dscale. Number of digits (in base 10) to print after decimal separator
478         //
479         //  Pseudo code :
480         //  const Decimals [
481         //          0.0000000000000000000000000001,
482         //          0.000000000000000000000001,
483         //          0.00000000000000000001,
484         //          0.0000000000000001,
485         //          0.000000000001,
486         //          0.00000001,
487         //          0.0001,
488         //          1,
489         //          10000,
490         //          100000000,
491         //          1000000000000,
492         //          10000000000000000,
493         //          100000000000000000000,
494         //          1000000000000000000000000,
495         //          10000000000000000000000000000
496         //  ]
497         //  overflow = false
498         //  result = 0
499         //  for i = 0, weight = weightFirstGroup + 7; i < numGroups; i++, weight--
500         //    group = read.u16
501         //    if weight < 0 or weight > MaxNum
502         //       overflow = true
503         //    else
504         //       result += Decimals[weight] * group
505         //  sign == 0x4000 ? -result : result
506 
507         // So if we were to take the number: 3950.123456
508         //
509         //  Stored on Disk:
510         //    00 03 00 00 00 00 00 06 0F 6E 04 D2 15 E0
511         //
512         //  Number of groups: 00 03
513         //  Weight of first group: 00 00
514         //  Sign: 00 00
515         //  DScale: 00 06
516         //
517         // 0F 6E = 3950
518         //   result = result + 3950 * 1;
519         // 04 D2 = 1234
520         //   result = result + 1234 * 0.0001;
521         // 15 E0 = 5600
522         //   result = result + 5600 * 0.00000001;
523         //
524 
from_sql(_: &Type, raw: &[u8]) -> Result<Decimal, Box<dyn error::Error + 'static + Sync + Send>>525         fn from_sql(_: &Type, raw: &[u8]) -> Result<Decimal, Box<dyn error::Error + 'static + Sync + Send>> {
526             let mut raw = Cursor::new(raw);
527             let num_groups = raw.read_u16::<BigEndian>()?;
528             let weight = raw.read_i16::<BigEndian>()?; // 10000^weight
529                                                        // Sign: 0x0000 = positive, 0x4000 = negative, 0xC000 = NaN
530             let sign = raw.read_u16::<BigEndian>()?;
531             // Number of digits (in base 10) to print after decimal separator
532             let scale = raw.read_u16::<BigEndian>()?;
533 
534             // Read all of the groups
535             let mut groups = Vec::new();
536             for _ in 0..num_groups as usize {
537                 groups.push(raw.read_u16::<BigEndian>()?);
538             }
539 
540             Ok(Self::from_postgres(PostgresDecimal {
541                 neg: sign == 0x4000,
542                 weight,
543                 scale,
544                 digits: groups.into_iter(),
545             }))
546         }
547 
accepts(ty: &Type) -> bool548         fn accepts(ty: &Type) -> bool {
549             matches!(*ty, Type::NUMERIC)
550         }
551     }
552 
553     impl ToSql for Decimal {
to_sql( &self, _: &Type, out: &mut BytesMut, ) -> Result<IsNull, Box<dyn error::Error + 'static + Sync + Send>>554         fn to_sql(
555             &self,
556             _: &Type,
557             out: &mut BytesMut,
558         ) -> Result<IsNull, Box<dyn error::Error + 'static + Sync + Send>> {
559             let PostgresDecimal {
560                 neg,
561                 weight,
562                 scale,
563                 digits,
564             } = self.to_postgres();
565 
566             let num_digits = digits.len();
567 
568             // Reserve bytes
569             out.reserve(8 + num_digits * 2);
570 
571             // Number of groups
572             out.put_u16(num_digits.try_into().unwrap());
573             // Weight of first group
574             out.put_i16(weight);
575             // Sign
576             out.put_u16(if neg { 0x4000 } else { 0x0000 });
577             // DScale
578             out.put_u16(scale);
579             // Now process the number
580             for digit in digits[0..num_digits].iter() {
581                 out.put_i16(*digit);
582             }
583 
584             Ok(IsNull::No)
585         }
586 
accepts(ty: &Type) -> bool587         fn accepts(ty: &Type) -> bool {
588             matches!(*ty, Type::NUMERIC)
589         }
590 
591         to_sql_checked!();
592     }
593 
594     #[cfg(test)]
595     mod test {
596         use super::*;
597         use ::postgres::{Client, NoTls};
598         use core::str::FromStr;
599 
600         /// Gets the URL for connecting to PostgreSQL for testing. Set the POSTGRES_URL
601         /// environment variable to change from the default of "postgres://postgres@localhost".
get_postgres_url() -> String602         fn get_postgres_url() -> String {
603             if let Ok(url) = std::env::var("POSTGRES_URL") {
604                 return url;
605             }
606             "postgres://postgres@localhost".to_string()
607         }
608 
609         pub static TEST_DECIMALS: &[(u32, u32, &str, &str)] = &[
610             // precision, scale, sent, expected
611             (35, 6, "3950.123456", "3950.123456"),
612             (35, 2, "3950.123456", "3950.12"),
613             (35, 2, "3950.1256", "3950.13"),
614             (10, 2, "3950.123456", "3950.12"),
615             (35, 6, "3950", "3950.000000"),
616             (4, 0, "3950", "3950"),
617             (35, 6, "0.1", "0.100000"),
618             (35, 6, "0.01", "0.010000"),
619             (35, 6, "0.001", "0.001000"),
620             (35, 6, "0.0001", "0.000100"),
621             (35, 6, "0.00001", "0.000010"),
622             (35, 6, "0.000001", "0.000001"),
623             (35, 6, "1", "1.000000"),
624             (35, 6, "-100", "-100.000000"),
625             (35, 6, "-123.456", "-123.456000"),
626             (35, 6, "119996.25", "119996.250000"),
627             (35, 6, "1000000", "1000000.000000"),
628             (35, 6, "9999999.99999", "9999999.999990"),
629             (35, 6, "12340.56789", "12340.567890"),
630             // Scale is only 28 since that is the maximum we can represent.
631             (65, 30, "1.2", "1.2000000000000000000000000000"),
632             // Pi - rounded at scale 28
633             (
634                 65,
635                 30,
636                 "3.141592653589793238462643383279",
637                 "3.1415926535897932384626433833",
638             ),
639             (
640                 65,
641                 34,
642                 "3.1415926535897932384626433832795028",
643                 "3.1415926535897932384626433833",
644             ),
645             // Unrounded number
646             (
647                 65,
648                 34,
649                 "1.234567890123456789012345678950000",
650                 "1.2345678901234567890123456790",
651             ),
652             (
653                 65,
654                 34, // No rounding due to 49999 after significant digits
655                 "1.234567890123456789012345678949999",
656                 "1.2345678901234567890123456789",
657             ),
658             // 0xFFFF_FFFF_FFFF_FFFF_FFFF_FFFF (96 bit)
659             (35, 0, "79228162514264337593543950335", "79228162514264337593543950335"),
660             // 0x0FFF_FFFF_FFFF_FFFF_FFFF_FFFF (95 bit)
661             (35, 1, "4951760157141521099596496895", "4951760157141521099596496895.0"),
662             // 0x1000_0000_0000_0000_0000_0000
663             (35, 1, "4951760157141521099596496896", "4951760157141521099596496896.0"),
664             (35, 6, "18446744073709551615", "18446744073709551615.000000"),
665             (35, 6, "-18446744073709551615", "-18446744073709551615.000000"),
666             (35, 6, "0.10001", "0.100010"),
667             (35, 6, "0.12345", "0.123450"),
668         ];
669 
670         #[test]
test_null()671         fn test_null() {
672             let mut client = match Client::connect(&get_postgres_url(), NoTls) {
673                 Ok(x) => x,
674                 Err(err) => panic!("{:#?}", err),
675             };
676 
677             // Test NULL
678             let result: Option<Decimal> = match client.query("SELECT NULL::numeric", &[]) {
679                 Ok(x) => x.iter().next().unwrap().get(0),
680                 Err(err) => panic!("{:#?}", err),
681             };
682             assert_eq!(None, result);
683         }
684 
685         #[tokio::test]
686         #[cfg(feature = "tokio-pg")]
async_test_null()687         async fn async_test_null() {
688             use futures::future::FutureExt;
689             use tokio_postgres::connect;
690 
691             let (client, connection) = connect(&get_postgres_url(), NoTls).await.unwrap();
692             let connection = connection.map(|e| e.unwrap());
693             tokio::spawn(connection);
694 
695             let statement = client.prepare(&"SELECT NULL::numeric").await.unwrap();
696             let rows = client.query(&statement, &[]).await.unwrap();
697             let result: Option<Decimal> = rows.iter().next().unwrap().get(0);
698 
699             assert_eq!(None, result);
700         }
701 
702         #[test]
read_numeric_type()703         fn read_numeric_type() {
704             let mut client = match Client::connect(&get_postgres_url(), NoTls) {
705                 Ok(x) => x,
706                 Err(err) => panic!("{:#?}", err),
707             };
708             for &(precision, scale, sent, expected) in TEST_DECIMALS.iter() {
709                 let result: Decimal =
710                     match client.query(&*format!("SELECT {}::NUMERIC({}, {})", sent, precision, scale), &[]) {
711                         Ok(x) => x.iter().next().unwrap().get(0),
712                         Err(err) => panic!("SELECT {}::NUMERIC({}, {}), error - {:#?}", sent, precision, scale, err),
713                     };
714                 assert_eq!(
715                     expected,
716                     result.to_string(),
717                     "NUMERIC({}, {}) sent: {}",
718                     precision,
719                     scale,
720                     sent
721                 );
722             }
723         }
724 
725         #[tokio::test]
726         #[cfg(feature = "tokio-pg")]
async_read_numeric_type()727         async fn async_read_numeric_type() {
728             use futures::future::FutureExt;
729             use tokio_postgres::connect;
730 
731             let (client, connection) = connect(&get_postgres_url(), NoTls).await.unwrap();
732             let connection = connection.map(|e| e.unwrap());
733             tokio::spawn(connection);
734             for &(precision, scale, sent, expected) in TEST_DECIMALS.iter() {
735                 let statement = client
736                     .prepare(&*format!("SELECT {}::NUMERIC({}, {})", sent, precision, scale))
737                     .await
738                     .unwrap();
739                 let rows = client.query(&statement, &[]).await.unwrap();
740                 let result: Decimal = rows.iter().next().unwrap().get(0);
741 
742                 assert_eq!(expected, result.to_string(), "NUMERIC({}, {})", precision, scale);
743             }
744         }
745 
746         #[test]
write_numeric_type()747         fn write_numeric_type() {
748             let mut client = match Client::connect(&get_postgres_url(), NoTls) {
749                 Ok(x) => x,
750                 Err(err) => panic!("{:#?}", err),
751             };
752             for &(precision, scale, sent, expected) in TEST_DECIMALS.iter() {
753                 let number = Decimal::from_str(sent).unwrap();
754                 let result: Decimal =
755                     match client.query(&*format!("SELECT $1::NUMERIC({}, {})", precision, scale), &[&number]) {
756                         Ok(x) => x.iter().next().unwrap().get(0),
757                         Err(err) => panic!("{:#?}", err),
758                     };
759                 assert_eq!(expected, result.to_string(), "NUMERIC({}, {})", precision, scale);
760             }
761         }
762 
763         #[tokio::test]
764         #[cfg(feature = "tokio-pg")]
async_write_numeric_type()765         async fn async_write_numeric_type() {
766             use futures::future::FutureExt;
767             use tokio_postgres::connect;
768 
769             let (client, connection) = connect(&get_postgres_url(), NoTls).await.unwrap();
770             let connection = connection.map(|e| e.unwrap());
771             tokio::spawn(connection);
772 
773             for &(precision, scale, sent, expected) in TEST_DECIMALS.iter() {
774                 let statement = client
775                     .prepare(&*format!("SELECT $1::NUMERIC({}, {})", precision, scale))
776                     .await
777                     .unwrap();
778                 let number = Decimal::from_str(sent).unwrap();
779                 let rows = client.query(&statement, &[&number]).await.unwrap();
780                 let result: Decimal = rows.iter().next().unwrap().get(0);
781 
782                 assert_eq!(expected, result.to_string(), "NUMERIC({}, {})", precision, scale);
783             }
784         }
785 
786         #[test]
numeric_overflow()787         fn numeric_overflow() {
788             let tests = [(4, 4, "3950.1234")];
789             let mut client = match Client::connect(&get_postgres_url(), NoTls) {
790                 Ok(x) => x,
791                 Err(err) => panic!("{:#?}", err),
792             };
793             for &(precision, scale, sent) in tests.iter() {
794                 match client.query(&*format!("SELECT {}::NUMERIC({}, {})", sent, precision, scale), &[]) {
795                     Ok(_) => panic!(
796                         "Expected numeric overflow for {}::NUMERIC({}, {})",
797                         sent, precision, scale
798                     ),
799                     Err(err) => {
800                         assert_eq!("22003", err.code().unwrap().code(), "Unexpected error code");
801                     }
802                 };
803             }
804         }
805 
806         #[tokio::test]
807         #[cfg(feature = "tokio-pg")]
async_numeric_overflow()808         async fn async_numeric_overflow() {
809             use futures::future::FutureExt;
810             use tokio_postgres::connect;
811 
812             let tests = [(4, 4, "3950.1234")];
813             let (client, connection) = connect(&get_postgres_url(), NoTls).await.unwrap();
814             let connection = connection.map(|e| e.unwrap());
815             tokio::spawn(connection);
816 
817             for &(precision, scale, sent) in tests.iter() {
818                 let statement = client
819                     .prepare(&*format!("SELECT {}::NUMERIC({}, {})", sent, precision, scale))
820                     .await
821                     .unwrap();
822 
823                 match client.query(&statement, &[]).await {
824                     Ok(_) => panic!(
825                         "Expected numeric overflow for {}::NUMERIC({}, {})",
826                         sent, precision, scale
827                     ),
828                     Err(err) => assert_eq!("22003", err.code().unwrap().code(), "Unexpected error code"),
829                 }
830             }
831         }
832     }
833 }
834