#[cfg(any(test, feature = "pg_test"))]
#[pgx::pg_schema]
mod tests {
#[allow(unused_imports)]
use crate as pgx_tests;
use pgx::prelude::*;
use pgx::numeric::Error;
use serde::Deserialize;
#[pg_extern]
fn return_an_i32_numeric() -> AnyNumeric {
AnyNumeric::try_from(32).unwrap()
}
#[pg_extern]
fn return_a_f64_numeric() -> AnyNumeric {
AnyNumeric::try_from(64.64646464f64).unwrap()
}
#[pg_extern]
fn return_a_u64_numeric() -> AnyNumeric {
AnyNumeric::try_from(std::u64::MAX).unwrap()
}
#[pg_test]
fn test_return_an_i32_numeric() {
let result = Spi::get_one::<bool>("SELECT 32::numeric = tests.return_an_i32_numeric();");
assert_eq!(result, Ok(Some(true)));
}
#[pg_test]
fn test_return_a_f64_numeric() {
let result =
Spi::get_one::<bool>("SELECT 64.64646464::numeric = tests.return_a_f64_numeric();");
assert_eq!(result, Ok(Some(true)));
}
#[pg_test]
fn test_return_a_u64_numeric() {
let result = Spi::get_one::<bool>(
"SELECT 18446744073709551615::numeric = tests.return_a_u64_numeric();",
);
assert_eq!(result, Ok(Some(true)));
}
#[pg_test]
fn test_deserialize_numeric() {
use serde_json::json;
AnyNumeric::deserialize(&json!(42)).unwrap();
AnyNumeric::deserialize(&json!(42.4242)).unwrap();
AnyNumeric::deserialize(&json!(18446744073709551615u64)).unwrap();
AnyNumeric::deserialize(&json!("64.64646464")).unwrap();
let error = AnyNumeric::deserialize(&json!("foo")).err().unwrap().to_string();
assert_eq!("invalid input syntax for type numeric: \"foo\"", &error);
}
#[pg_test]
#[rustfmt::skip]
fn test_limits() {
assert_eq!(i8::try_from(AnyNumeric::try_from(i8::MIN).unwrap()).unwrap(), i8::MIN);
assert_eq!(i16::try_from(AnyNumeric::try_from(i16::MIN).unwrap()).unwrap(), i16::MIN);
assert_eq!(i32::try_from(AnyNumeric::try_from(i32::MIN).unwrap()).unwrap(), i32::MIN);
assert_eq!(i64::try_from(AnyNumeric::try_from(i64::MIN).unwrap()).unwrap(), i64::MIN);
assert_eq!(i128::try_from(AnyNumeric::try_from(i128::MIN).unwrap()).unwrap(), i128::MIN);
assert_eq!(isize::try_from(AnyNumeric::try_from(isize::MIN).unwrap()).unwrap(), isize::MIN);
assert_eq!(i8::try_from(AnyNumeric::try_from(i8::MAX).unwrap()).unwrap(), i8::MAX);
assert_eq!(i16::try_from(AnyNumeric::try_from(i16::MAX).unwrap()).unwrap(), i16::MAX);
assert_eq!(i32::try_from(AnyNumeric::try_from(i32::MAX).unwrap()).unwrap(), i32::MAX);
assert_eq!(i64::try_from(AnyNumeric::try_from(i64::MAX).unwrap()).unwrap(), i64::MAX);
assert_eq!(i128::try_from(AnyNumeric::try_from(i128::MAX).unwrap()).unwrap(), i128::MAX);
assert_eq!(isize::try_from(AnyNumeric::try_from(isize::MAX).unwrap()).unwrap(), isize::MAX);
assert_eq!(u8::try_from(AnyNumeric::try_from(u8::MIN).unwrap()).unwrap(), u8::MIN);
assert_eq!(u16::try_from(AnyNumeric::try_from(u16::MIN).unwrap()).unwrap(), u16::MIN);
assert_eq!(u32::try_from(AnyNumeric::try_from(u32::MIN).unwrap()).unwrap(), u32::MIN);
assert_eq!(u64::try_from(AnyNumeric::try_from(u64::MIN).unwrap()).unwrap(), u64::MIN);
assert_eq!(u128::try_from(AnyNumeric::try_from(u128::MIN).unwrap()).unwrap(), u128::MIN);
assert_eq!(usize::try_from(AnyNumeric::try_from(usize::MIN).unwrap()).unwrap(), usize::MIN);
assert_eq!(u8::try_from(AnyNumeric::try_from(u8::MAX).unwrap()).unwrap(), u8::MAX);
assert_eq!(u16::try_from(AnyNumeric::try_from(u16::MAX).unwrap()).unwrap(), u16::MAX);
assert_eq!(u32::try_from(AnyNumeric::try_from(u32::MAX).unwrap()).unwrap(), u32::MAX);
assert_eq!(u64::try_from(AnyNumeric::try_from(u64::MAX).unwrap()).unwrap(), u64::MAX);
assert_eq!(u128::try_from(AnyNumeric::try_from(u128::MAX).unwrap()).unwrap(), u128::MAX);
assert_eq!(usize::try_from(AnyNumeric::try_from(usize::MAX).unwrap()).unwrap(), usize::MAX);
#[cfg(any(feature = "pg11", feature = "pg12", feature = "pg13"))]
{
assert_eq!(AnyNumeric::try_from(f32::INFINITY).err(),
Some(pgx::numeric::Error::ConversionNotSupported(String::from("cannot convert infinity to numeric"))));
assert_eq!(AnyNumeric::try_from(f32::NEG_INFINITY).err(),
Some(pgx::numeric::Error::ConversionNotSupported(String::from("cannot convert infinity to numeric"))));
assert_eq!(AnyNumeric::try_from(f64::INFINITY).err(),
Some(pgx::numeric::Error::ConversionNotSupported(String::from("cannot convert infinity to numeric"))));
assert_eq!(AnyNumeric::try_from(f64::NEG_INFINITY).err(),
Some(pgx::numeric::Error::ConversionNotSupported(String::from("cannot convert infinity to numeric"))));
}
#[cfg(any(feature = "pg14", feature="pg15"))]
{
assert_eq!(f32::try_from(AnyNumeric::try_from(f32::INFINITY).unwrap()).unwrap(), f32::INFINITY);
assert_eq!(f64::try_from(AnyNumeric::try_from(f64::INFINITY).unwrap()).unwrap(), f64::INFINITY);
assert_eq!(f32::try_from(AnyNumeric::try_from(f32::NEG_INFINITY).unwrap()).unwrap(), f32::NEG_INFINITY);
assert_eq!(f64::try_from(AnyNumeric::try_from(f64::NEG_INFINITY).unwrap()).unwrap(), f64::NEG_INFINITY);
}
assert!(f32::try_from(AnyNumeric::try_from(f32::NAN).unwrap()).unwrap().is_nan());
assert!(f64::try_from(AnyNumeric::try_from(f64::NAN).unwrap()).unwrap().is_nan());
}
#[pg_test]
#[rustfmt::skip]
fn test_bad_conversions() {
let a = AnyNumeric::try_from(u128::MAX).unwrap();
let b = u64::try_from(a);
assert_eq!(b, Err(Error::OutOfRange(String::from("number too large to fit in target type"))));
let a = AnyNumeric::try_from(u128::MAX).unwrap();
let b = usize::try_from(a);
assert_eq!(b, Err(Error::OutOfRange(String::from("number too large to fit in target type"))));
let a = AnyNumeric::try_from(u128::MAX).unwrap();
let b = u32::try_from(a);
assert_eq!(b, Err(Error::OutOfRange(String::from("number too large to fit in target type"))));
let a = AnyNumeric::try_from(u128::MAX).unwrap();
let b = u16::try_from(a);
assert_eq!(b, Err(Error::OutOfRange(String::from("number too large to fit in target type"))));
let a = AnyNumeric::try_from(u128::MAX).unwrap();
let b = u8::try_from(a);
assert_eq!(b, Err(Error::OutOfRange(String::from("number too large to fit in target type"))));
let a = AnyNumeric::try_from(i128::MIN).unwrap();
let b = u8::try_from(a);
assert_eq!(b, Err(Error::OutOfRange(String::from("invalid digit found in string"))));
let a = AnyNumeric::try_from(f64::MAX).unwrap();
match f32::try_from(a) {
Err(Error::OutOfRange(_)) => {},
other => panic!("{:?}", other),
}
}
#[pg_test]
fn test_nan_ordering() {
let mut v = vec![
(1, AnyNumeric::try_from("nan").unwrap()),
(3, AnyNumeric::try_from("nan").unwrap()),
(2, AnyNumeric::try_from("nan").unwrap()),
];
v.sort_by(|a, b| a.1.cmp(&b.1));
assert_eq!(
v,
vec![
(1, AnyNumeric::try_from("nan").unwrap()),
(3, AnyNumeric::try_from("nan").unwrap()),
(2, AnyNumeric::try_from("nan").unwrap())
]
)
}
#[pg_test]
fn test_ordering() {
let mut v =
vec![(3, AnyNumeric::from(3)), (2, AnyNumeric::from(2)), (1, AnyNumeric::from(1))];
v.sort_by(|a, b| a.1.cmp(&b.1));
assert_eq!(
v,
vec![(1, AnyNumeric::from(1)), (2, AnyNumeric::from(2)), (3, AnyNumeric::from(3)),]
)
}
}