use hyperdb_api::{Interval, Numeric, ToSqlParam};
mod common;
use common::TestConnection;
#[test]
fn test_json_param() {
let test = TestConnection::new().expect("Failed to create test connection");
let json_value = serde_json::json!({"a": 1, "b": [2, 3]});
let result = test
.connection
.query_params("SELECT $1 AS v", &[&json_value as &dyn ToSqlParam])
.expect("query_params failed");
let rows = result.collect_rows().expect("collect_rows failed");
assert_eq!(rows.len(), 1, "Expected exactly one row");
let returned_str: Option<String> = rows[0].get(0);
assert!(returned_str.is_some(), "Expected non-NULL JSON value");
let returned_json: serde_json::Value =
serde_json::from_str(&returned_str.unwrap()).expect("Failed to parse returned JSON");
assert_eq!(
returned_json, json_value,
"Returned JSON doesn't match original"
);
}
#[test]
fn test_interval_param() {
let test = TestConnection::new().expect("Failed to create test connection");
let interval = Interval::new(2, 5, 0); let result = test
.connection
.query_params(
"SELECT CAST($1 AS text) AS v",
&[&interval as &dyn ToSqlParam],
)
.expect("query_params failed");
let rows = result.collect_rows().expect("collect_rows failed");
assert_eq!(rows.len(), 1, "Expected exactly one row");
let returned: String = rows[0].get(0).expect("Expected non-NULL Interval value");
assert_eq!(
returned, "P2M5D",
"interval should decode to 2 months + 5 days (ISO-8601), got: {returned}"
);
}
#[test]
fn test_option_numeric_param() {
let test = TestConnection::new().expect("Failed to create test connection");
let some_n: Option<Numeric> = Some(Numeric::new(7, 0));
let none_n: Option<Numeric> = None;
let rows = test
.connection
.query_params(
"SELECT $1 AS a, $2 AS b",
&[&some_n as &dyn ToSqlParam, &none_n as &dyn ToSqlParam],
)
.expect("query_params failed")
.collect_rows()
.expect("collect_rows failed");
assert_eq!(rows.len(), 1);
assert_eq!(rows[0].get::<i64>(0), Some(7), "Some(Numeric(7,0)) → 7");
assert_eq!(rows[0].get::<i64>(1), None, "None → SQL NULL");
}
#[test]
fn test_numeric_scale0_param() {
let test = TestConnection::new().expect("Failed to create test connection");
let numeric = Numeric::new(42, 0); let result = test
.connection
.query_params("SELECT $1 AS v", &[&numeric as &dyn ToSqlParam])
.expect("query_params failed");
let rows = result.collect_rows().expect("collect_rows failed");
assert_eq!(rows.len(), 1, "Expected exactly one row");
let returned: Option<i64> = rows[0].get(0);
assert_eq!(
returned,
Some(42),
"Expected Numeric(42,0) to round-trip as 42"
);
}
#[test]
fn test_numeric_scaled_rejected_fail_fast() {
let test = TestConnection::new().expect("Failed to create test connection");
let numeric = Numeric::new(123, 2); let result = test
.connection
.query_params("SELECT $1 AS v", &[&numeric as &dyn ToSqlParam])
.expect("query_params itself should not error");
let err = result
.collect_rows()
.expect_err("scale>0 Numeric must be rejected by the server, not silently truncated");
let msg = err.to_string();
assert!(
msg.contains("0A000") || msg.contains("cannot handle truncation when reading numerics"),
"expected Hyper's NUMERIC truncation error (fail-fast), got: {msg}"
);
}