mod common;
use anyhow::Result;
async fn query_bool(container: &testcontainers::ContainerAsync<testcontainers_modules::postgres::Postgres>, sql: &str) -> Result<bool> {
let host = container.get_host().await?;
let port = container.get_host_port_ipv4(5432).await?;
let (client, connection) =
tokio_postgres::connect(&format!("host={host} port={port} user=postgres password=postgres dbname=ankurah"), tokio_postgres::NoTls)
.await?;
tokio::spawn(async move {
if let Err(e) = connection.await {
eprintln!("connection error: {}", e);
}
});
let row = client.query_one(sql, &[]).await?;
let result: bool = row.get(0);
Ok(result)
}
#[tokio::test]
async fn test_jsonb_numeric_comparison_is_numeric() -> Result<()> {
let (container, _storage) = common::create_postgres_container().await?;
let result = query_bool(&container, "SELECT '9'::jsonb > '10'::jsonb").await?;
assert!(!result, "JSONB numeric comparison should be numeric, not lexicographic: 9 > 10 should be false");
let result = query_bool(&container, "SELECT '9'::jsonb < '10'::jsonb").await?;
assert!(result, "9 < 10 should be true");
let result = query_bool(&container, "SELECT '100'::jsonb > '9'::jsonb").await?;
assert!(result, "100 > 9 should be true");
Ok(())
}
#[tokio::test]
async fn test_jsonb_string_comparison_is_lexicographic() -> Result<()> {
let (container, _storage) = common::create_postgres_container().await?;
let result = query_bool(&container, r#"SELECT '"9"'::jsonb > '"10"'::jsonb"#).await?;
assert!(result, "String '9' > '10' lexicographically");
let result = query_bool(&container, r#"SELECT '"abc"'::jsonb < '"abd"'::jsonb"#).await?;
assert!(result, "String 'abc' < 'abd'");
Ok(())
}
#[tokio::test]
async fn test_jsonb_cross_type_comparison_returns_false() -> Result<()> {
let (container, _storage) = common::create_postgres_container().await?;
let result = query_bool(&container, r#"SELECT '9'::jsonb = '"9"'::jsonb"#).await?;
assert!(!result, "Number 9 should not equal string '9'");
let result = query_bool(&container, "SELECT '9'::jsonb = 'true'::jsonb").await?;
assert!(!result, "Number 9 should not equal boolean true");
let result = query_bool(&container, r#"SELECT '"true"'::jsonb = 'true'::jsonb"#).await?;
assert!(!result, "String 'true' should not equal boolean true");
Ok(())
}
#[tokio::test]
async fn test_jsonb_float_int_comparison() -> Result<()> {
let (container, _storage) = common::create_postgres_container().await?;
let result = query_bool(&container, "SELECT '9'::jsonb = '9.0'::jsonb").await?;
assert!(result, "Integer 9 should equal float 9.0");
let result = query_bool(&container, "SELECT '9.5'::jsonb > '9'::jsonb").await?;
assert!(result, "9.5 > 9 should be true");
let result = query_bool(&container, "SELECT '9'::jsonb < '9.1'::jsonb").await?;
assert!(result, "9 < 9.1 should be true");
Ok(())
}
#[tokio::test]
async fn test_jsonb_null_comparison() -> Result<()> {
let (container, _storage) = common::create_postgres_container().await?;
let result = query_bool(&container, "SELECT 'null'::jsonb = 'null'::jsonb").await?;
assert!(result, "JSONB null should equal JSONB null");
let result = query_bool(&container, "SELECT 'null'::jsonb = '0'::jsonb").await?;
assert!(!result, "JSONB null should not equal 0");
let result = query_bool(&container, r#"SELECT 'null'::jsonb = '""'::jsonb"#).await?;
assert!(!result, "JSONB null should not equal empty string");
Ok(())
}
#[tokio::test]
async fn test_jsonb_path_extraction_with_comparison() -> Result<()> {
let (container, _storage) = common::create_postgres_container().await?;
let result = query_bool(&container, r#"SELECT ('{"count": 9}'::jsonb)->'count' > '10'::jsonb"#).await?;
assert!(!result, "JSON count 9 > 10 should be false");
let result = query_bool(&container, r#"SELECT ('{"count": 100}'::jsonb)->'count' > '10'::jsonb"#).await?;
assert!(result, "JSON count 100 > 10 should be true");
let result = query_bool(&container, r#"SELECT ('{"status": "active"}'::jsonb)->'status' = '"active"'::jsonb"#).await?;
assert!(result, "JSON status = 'active' should match");
let result = query_bool(&container, r#"SELECT ('{"count": 9}'::jsonb)->'count' = '"9"'::jsonb"#).await?;
assert!(!result, "JSON number 9 should not equal JSON string '9'");
Ok(())
}