use spg_engine::{Engine, QueryResult};
fn t(e: &mut Engine, sql: &str) -> String {
match e.execute(sql).unwrap() {
QueryResult::Rows { rows, .. } => match &rows[0].values[0] {
spg_storage::Value::Text(s) => s.to_string(),
v => format!("{v:?}"),
},
_ => panic!("rows"),
}
}
#[test]
fn numeric_beyond_i128() {
let mut e = Engine::new();
assert_eq!(
t(
&mut e,
"SELECT (12345678901234567890123456789012345678 * 98765432109876543210)::text"
),
"1219326311370217952249657064224965706333485749112223746380"
);
assert_eq!(
t(
&mut e,
"SELECT (123456789012345678901234567890123456789::numeric * 2)::text"
),
"246913578024691357802469135780246913578"
);
assert_eq!(
t(
&mut e,
"SELECT (99999999999999999999999999999999999999 * 99999999999999999999999999999999999999 + 1)::text"
),
"9999999999999999999999999999999999999800000000000000000000000000000000000002"
);
assert_eq!(
t(&mut e, "SELECT (10000000000000000000 * 2)::text"),
"20000000000000000000"
);
assert_eq!(
t(
&mut e,
"SELECT (123456789012345678901234567890123456789012345)::text"
),
"123456789012345678901234567890123456789012345"
);
assert_eq!(
t(
&mut e,
"SELECT (99999999999999999999999999999999999999.5 + 0.5)::text"
),
"100000000000000000000000000000000000000.0"
);
}
#[test]
fn numeric_bignum_compare() {
let mut e = Engine::new();
let b = |e: &mut Engine, sql: &str| {
matches!(
e.execute(sql).unwrap(),
QueryResult::Rows { ref rows, .. } if matches!(rows[0].values[0], spg_storage::Value::Bool(true))
)
};
assert!(b(
&mut e,
"SELECT (99999999999999999999999999999999999999 * 2) > (99999999999999999999999999999999999999 * 1)"
));
assert!(b(
&mut e,
"SELECT (99999999999999999999999999999999999999 * 2) = (99999999999999999999999999999999999999 + 99999999999999999999999999999999999999)"
));
assert!(!b(
&mut e,
"SELECT (99999999999999999999999999999999999999 * 2) < 5"
));
}
#[test]
fn numeric_bignum_divide() {
let mut e = Engine::new();
assert_eq!(
t(
&mut e,
"SELECT (99999999999999999999999999999999999999 * 99999999999999999999999999999999999999 / 3)::text"
),
"3333333333333333333333333333333333333266666666666666666666666666666666666667"
);
assert_eq!(
t(
&mut e,
"SELECT (123456789012345678901234567890123456789012345 / 7)::text"
),
"17636684144620811271604938270017636684144621"
);
assert_eq!(
t(
&mut e,
"SELECT (99999999999999999999999999999999999999999 / 100000000000000000000)::text"
),
"1000000000000000000000"
);
assert_eq!(
t(
&mut e,
"SELECT (123456789012345678901234567890123456789012345 % 7)::text"
),
"5"
);
assert!(
e.execute("SELECT 99999999999999999999999999999999999999 / 0")
.is_err()
);
}
#[test]
fn numeric_sqrt_stays_numeric() {
let mut e = Engine::new();
assert_eq!(
t(&mut e, "SELECT sqrt(2::numeric)::text"),
"1.414213562373095"
);
assert_eq!(
t(&mut e, "SELECT sqrt(10::numeric)::text"),
"3.162277660168379"
);
assert_eq!(
t(&mut e, "SELECT sqrt(9::numeric)::text"),
"3.000000000000000"
);
assert_eq!(
t(&mut e, "SELECT sqrt(1000000::numeric)::text"),
"1000.0000000000000"
);
assert_eq!(t(&mut e, "SELECT sqrt(2.25)::text"), "1.500000000000000");
assert_eq!(t(&mut e, "SELECT sqrt(0.01)::text"), "0.10000000000000000");
assert_eq!(
t(
&mut e,
"SELECT sqrt(99999999999999999999999999999999999999::numeric)::text"
),
"10000000000000000000"
);
assert_eq!(
t(
&mut e,
"SELECT sqrt(152415787532388367501905199875019052100::numeric)::text"
),
"12345678901234567890"
);
assert_eq!(
t(&mut e, "SELECT pg_typeof(sqrt(2::numeric))::text"),
"numeric"
);
assert!(e.execute("SELECT sqrt((-4)::numeric)").is_err());
}
#[test]
fn numeric_bignum_order_by() {
let mut e = Engine::new();
e.execute("CREATE TABLE bo(x numeric)").unwrap();
e.execute(
"INSERT INTO bo VALUES \
(123456789012345678901234567890123456789012345), (5), \
(999999999999999999999999999999999999999999999), \
((-888888888888888888888888888888888888888888888))",
)
.unwrap();
let order = match e.execute("SELECT x::text FROM bo ORDER BY bo.x").unwrap() {
QueryResult::Rows { rows, .. } => rows
.iter()
.map(|r| match &r.values[0] {
spg_storage::Value::Text(s) => s.to_string(),
v => format!("{v:?}"),
})
.collect::<Vec<_>>()
.join(","),
_ => panic!("rows"),
};
assert_eq!(
order,
"-888888888888888888888888888888888888888888888,\
5,\
123456789012345678901234567890123456789012345,\
999999999999999999999999999999999999999999999"
);
let text_order = match e.execute("SELECT x::text FROM bo ORDER BY x").unwrap() {
QueryResult::Rows { rows, .. } => rows
.iter()
.map(|r| match &r.values[0] {
spg_storage::Value::Text(s) => s.to_string(),
v => format!("{v:?}"),
})
.collect::<Vec<_>>()
.join(","),
_ => panic!("rows"),
};
assert_eq!(
text_order,
"-888888888888888888888888888888888888888888888,\
123456789012345678901234567890123456789012345,\
5,\
999999999999999999999999999999999999999999999"
);
assert_eq!(
t(&mut e, "SELECT max(x)::text FROM bo"),
"999999999999999999999999999999999999999999999"
);
assert_eq!(
t(&mut e, "SELECT min(x)::text FROM bo"),
"-888888888888888888888888888888888888888888888"
);
}