use anyhow::Result;
use uni_db::Uni;
use uni_query::Value;
async fn create_test_db() -> Result<Uni> {
use uni_db::DataType;
let db = Uni::in_memory().build().await?;
db.schema()
.label("Person")
.property_nullable("name", DataType::String)
.property_nullable("tags", DataType::CypherValue) .property_nullable("scores", DataType::List(Box::new(DataType::Int64)))
.property_nullable("values", DataType::List(Box::new(DataType::Int64)))
.property_nullable("items", DataType::List(Box::new(DataType::Int64)))
.property_nullable("errors", DataType::List(Box::new(DataType::Int64)))
.property_nullable("numbers", DataType::List(Box::new(DataType::Int64)))
.property_nullable("data", DataType::CypherValue) .apply()
.await?;
Ok(db)
}
#[tokio::test]
async fn test_quantifier_all_e2e() -> Result<()> {
let db = create_test_db().await?;
let tx = db.session().tx().await?;
tx.execute("CREATE (p:Person {name: 'Alice', tags: [1, 2, 3], scores: [85, 90, 95]})")
.await?;
tx.execute("CREATE (p:Person {name: 'Bob', tags: [0, -1, 5], scores: [60, 70, 80]})")
.await?;
tx.commit().await?;
db.flush().await?;
let result = db
.session()
.query("MATCH (p:Person) WHERE ALL(x IN p.tags WHERE x > 0) RETURN p.name")
.await?;
assert_eq!(result.len(), 1);
let name: String = result.rows()[0].get("p.name")?;
assert_eq!(name, "Alice");
Ok(())
}
#[tokio::test]
async fn test_quantifier_any_e2e() -> Result<()> {
let db = create_test_db().await?;
let tx = db.session().tx().await?;
tx.execute("CREATE (p:Person {name: 'Alice', values: [1, 2, 3]})")
.await?;
tx.execute("CREATE (p:Person {name: 'Bob', values: [10, 20, 30]})")
.await?;
tx.commit().await?;
db.flush().await?;
let result = db
.session()
.query(
"MATCH (p:Person) WHERE ANY(x IN p.values WHERE x >= 20) RETURN p.name ORDER BY p.name",
)
.await?;
assert_eq!(result.len(), 1);
let name: String = result.rows()[0].get("p.name")?;
assert_eq!(name, "Bob");
Ok(())
}
#[tokio::test]
async fn test_quantifier_single_e2e() -> Result<()> {
let db = create_test_db().await?;
let tx = db.session().tx().await?;
tx.execute("CREATE (p:Person {name: 'Charlie', items: [5]})")
.await?;
tx.execute("CREATE (p:Person {name: 'David', items: [5, 5, 5]})")
.await?;
tx.commit().await?;
db.flush().await?;
let result = db
.session()
.query("MATCH (p:Person) WHERE SINGLE(x IN p.items WHERE x = 5) RETURN p.name")
.await?;
assert_eq!(result.len(), 1);
let name: String = result.rows()[0].get("p.name")?;
assert_eq!(name, "Charlie");
Ok(())
}
#[tokio::test]
async fn test_quantifier_none_e2e() -> Result<()> {
let db = create_test_db().await?;
let tx = db.session().tx().await?;
tx.execute("CREATE (p:Person {name: 'Eve', errors: [1, 2, 3]})")
.await?;
tx.execute("CREATE (p:Person {name: 'Frank', errors: [-1, -2]})")
.await?;
tx.commit().await?;
db.flush().await?;
let result = db
.session()
.query("MATCH (p:Person) WHERE NONE(x IN p.errors WHERE x < 0) RETURN p.name")
.await?;
assert_eq!(result.len(), 1);
let name: String = result.rows()[0].get("p.name")?;
assert_eq!(name, "Eve");
Ok(())
}
#[tokio::test]
async fn test_quantifier_in_return_e2e() -> Result<()> {
let db = create_test_db().await?;
let tx = db.session().tx().await?;
tx.execute("CREATE (p:Person {name: 'Grace', numbers: [10, 20, 30]})")
.await?;
tx.commit().await?;
db.flush().await?;
let result = db
.session().query("MATCH (p:Person {name: 'Grace'}) RETURN ALL(x IN p.numbers WHERE x >= 10) AS all_valid")
.await?;
assert_eq!(result.len(), 1);
let all_valid: bool = result.rows()[0].get("all_valid")?;
assert!(all_valid);
Ok(())
}
#[tokio::test]
async fn test_quantifier_with_literal_list_e2e() -> Result<()> {
let db = create_test_db().await?;
let result = db
.session()
.query("RETURN ALL(x IN [1, 2, 3, 4, 5] WHERE x > 0) AS result")
.await?;
assert_eq!(result.len(), 1);
let res: bool = result.rows()[0].get("result")?;
assert!(res);
Ok(())
}
#[tokio::test]
async fn test_quantifier_empty_list_e2e() -> Result<()> {
let db = create_test_db().await?;
let tx = db.session().tx().await?;
tx.execute("CREATE (p:Person {name: 'Empty', items: []})")
.await?;
tx.commit().await?;
db.flush().await?;
let result_all = db
.session()
.query("MATCH (p:Person {name: 'Empty'}) RETURN ALL(x IN p.items WHERE x > 0) AS result")
.await?;
let res: bool = result_all.rows()[0].get("result")?;
assert!(res);
let result_any = db
.session()
.query("MATCH (p:Person {name: 'Empty'}) RETURN ANY(x IN p.items WHERE x > 0) AS result")
.await?;
let res: bool = result_any.rows()[0].get("result")?;
assert!(!res);
let result_none = db
.session()
.query("MATCH (p:Person {name: 'Empty'}) RETURN NONE(x IN p.items WHERE x > 0) AS result")
.await?;
let res: bool = result_none.rows()[0].get("result")?;
assert!(res);
Ok(())
}
#[tokio::test]
async fn test_array_indexing_e2e() -> Result<()> {
let db = create_test_db().await?;
let tx = db.session().tx().await?;
tx.execute("CREATE (p:Person {name: 'Helen', tags: ['a', 'b', 'c', 'd']})")
.await?;
tx.commit().await?;
db.flush().await?;
let result = db
.session()
.query("MATCH (p:Person {name: 'Helen'}) RETURN p.tags[0] AS first, p.tags[2] AS third")
.await?;
assert_eq!(result.len(), 1);
let first: String = result.rows()[0].get("first")?;
let third: String = result.rows()[0].get("third")?;
assert_eq!(first, "a");
assert_eq!(third, "c");
Ok(())
}
#[tokio::test]
async fn test_array_slicing_e2e() -> Result<()> {
let db = create_test_db().await?;
let tx = db.session().tx().await?;
tx.execute("CREATE (p:Person {name: 'Ivan', numbers: [10, 20, 30, 40, 50]})")
.await?;
tx.commit().await?;
db.flush().await?;
let result = db
.session()
.query("MATCH (p:Person {name: 'Ivan'}) RETURN p.numbers[1..3] AS slice")
.await?;
assert_eq!(result.len(), 1);
let slice: Vec<i64> = result.rows()[0].get("slice")?;
assert_eq!(slice, vec![20, 30]);
Ok(())
}
#[tokio::test]
async fn test_combined_quantifier_and_array_ops_e2e() -> Result<()> {
let db = create_test_db().await?;
let tx = db.session().tx().await?;
tx.execute("CREATE (p:Person {name: 'Jane', data: [[1, 2], [3, 4], [5, 6]]})")
.await?;
tx.commit().await?;
db.flush().await?;
let result = db
.session()
.query(
"MATCH (p:Person {name: 'Jane'})
WHERE ALL(row IN p.data WHERE row[0] > 0)
RETURN p.name",
)
.await?;
assert_eq!(result.len(), 1);
let name: String = result.rows()[0].get("p.name")?;
assert_eq!(name, "Jane");
Ok(())
}
async fn eval(db: &Uni, cypher: &str) -> Value {
let result = db.session().query(cypher).await.unwrap();
result.rows()[0].value("result").unwrap().clone()
}
async fn assert_bool(db: &Uni, cypher: &str, expected: bool) {
let val = eval(db, cypher).await;
assert_eq!(
val,
Value::Bool(expected),
"Expected Bool({expected}) for: {cypher}"
);
}
async fn assert_null(db: &Uni, cypher: &str) {
let val = eval(db, cypher).await;
assert_eq!(val, Value::Null, "Expected Null for: {cypher}");
}
#[tokio::test]
async fn test_empty_list_all_quantifier() {
let db = Uni::in_memory().build().await.unwrap();
assert_bool(&db, "RETURN all(x IN [] WHERE x > 0) AS result", true).await;
assert_bool(&db, "RETURN all(x IN [] WHERE true) AS result", true).await;
assert_bool(&db, "RETURN all(x IN [] WHERE false) AS result", true).await;
}
#[tokio::test]
async fn test_empty_list_any_quantifier() {
let db = Uni::in_memory().build().await.unwrap();
assert_bool(&db, "RETURN any(x IN [] WHERE x > 0) AS result", false).await;
assert_bool(&db, "RETURN any(x IN [] WHERE true) AS result", false).await;
assert_bool(&db, "RETURN any(x IN [] WHERE false) AS result", false).await;
}
#[tokio::test]
async fn test_empty_list_none_quantifier() {
let db = Uni::in_memory().build().await.unwrap();
assert_bool(&db, "RETURN none(x IN [] WHERE x > 0) AS result", true).await;
assert_bool(&db, "RETURN none(x IN [] WHERE true) AS result", true).await;
assert_bool(&db, "RETURN none(x IN [] WHERE false) AS result", true).await;
}
#[tokio::test]
async fn test_empty_list_single_quantifier() {
let db = Uni::in_memory().build().await.unwrap();
assert_bool(&db, "RETURN single(x IN [] WHERE x > 0) AS result", false).await;
assert_bool(&db, "RETURN single(x IN [] WHERE true) AS result", false).await;
assert_bool(&db, "RETURN single(x IN [] WHERE false) AS result", false).await;
}
#[tokio::test]
async fn test_quantifier_booleans() {
let db = Uni::in_memory().build().await.unwrap();
assert_bool(&db, "RETURN all(x IN [true, true] WHERE x) AS result", true).await;
assert_bool(
&db,
"RETURN all(x IN [true, false] WHERE x) AS result",
false,
)
.await;
assert_bool(
&db,
"RETURN any(x IN [true, false] WHERE x) AS result",
true,
)
.await;
assert_bool(
&db,
"RETURN any(x IN [false, false] WHERE x) AS result",
false,
)
.await;
assert_bool(
&db,
"RETURN none(x IN [false, false] WHERE x) AS result",
true,
)
.await;
assert_bool(
&db,
"RETURN none(x IN [true, false] WHERE x) AS result",
false,
)
.await;
assert_bool(
&db,
"RETURN single(x IN [true, false] WHERE x) AS result",
true,
)
.await;
assert_bool(
&db,
"RETURN single(x IN [true, true] WHERE x) AS result",
false,
)
.await;
}
#[tokio::test]
async fn test_quantifier_integers() {
let db = Uni::in_memory().build().await.unwrap();
assert_bool(
&db,
"RETURN all(x IN [2, 2, 2] WHERE x = 2) AS result",
true,
)
.await;
assert_bool(
&db,
"RETURN all(x IN [1, 2, 3] WHERE x = 2) AS result",
false,
)
.await;
assert_bool(
&db,
"RETURN any(x IN [1, 2, 3, 4] WHERE x > 3) AS result",
true,
)
.await;
assert_bool(
&db,
"RETURN any(x IN [1, 2, 3] WHERE x > 10) AS result",
false,
)
.await;
assert_bool(
&db,
"RETURN single(x IN [1, 2, 3, 4] WHERE x = 3) AS result",
true,
)
.await;
assert_bool(
&db,
"RETURN single(x IN [3, 3, 4] WHERE x = 3) AS result",
false,
)
.await;
assert_bool(
&db,
"RETURN none(x IN [1, 2, 3] WHERE x < 0) AS result",
true,
)
.await;
assert_bool(
&db,
"RETURN none(x IN [1, -2, 3] WHERE x < 0) AS result",
false,
)
.await;
}
#[tokio::test]
async fn test_quantifier_floats() {
let db = Uni::in_memory().build().await.unwrap();
assert_bool(
&db,
"RETURN all(x IN [1.1, 2.2, 3.3] WHERE x > 0.0) AS result",
true,
)
.await;
assert_bool(
&db,
"RETURN any(x IN [1.1, 2.2, 3.5] WHERE x = 3.5) AS result",
true,
)
.await;
assert_bool(
&db,
"RETURN none(x IN [1.1, 2.2, 3.5] WHERE x < 0.0) AS result",
true,
)
.await;
assert_bool(
&db,
"RETURN single(x IN [1.1, 2.2, 3.5] WHERE x > 3.0) AS result",
true,
)
.await;
}
#[tokio::test]
async fn test_quantifier_strings() {
let db = Uni::in_memory().build().await.unwrap();
assert_bool(
&db,
"RETURN all(x IN ['abc', 'def', 'ghi'] WHERE size(x) = 3) AS result",
true,
)
.await;
assert_bool(
&db,
"RETURN all(x IN ['abc', 'de'] WHERE size(x) = 3) AS result",
false,
)
.await;
assert_bool(
&db,
"RETURN any(x IN ['abc', 'de'] WHERE size(x) = 3) AS result",
true,
)
.await;
assert_bool(
&db,
"RETURN single(x IN ['abc', 'de'] WHERE size(x) = 3) AS result",
true,
)
.await;
assert_bool(
&db,
"RETURN none(x IN ['ab', 'de'] WHERE size(x) = 3) AS result",
true,
)
.await;
}
#[tokio::test]
async fn test_quantifier_nested_lists() {
let db = Uni::in_memory().build().await.unwrap();
assert_bool(
&db,
"RETURN all(x IN [[1, 2, 3], [4, 5, 6]] WHERE size(x) = 3) AS result",
true,
)
.await;
assert_bool(
&db,
"RETURN any(x IN [[1, 2, 3], ['a']] WHERE size(x) = 3) AS result",
true,
)
.await;
assert_bool(
&db,
"RETURN single(x IN [[1, 2, 3], ['a']] WHERE size(x) = 3) AS result",
true,
)
.await;
assert_bool(
&db,
"RETURN none(x IN [['a'], ['b']] WHERE size(x) = 3) AS result",
true,
)
.await;
}
#[tokio::test]
async fn test_quantifier_maps() {
let db = Uni::in_memory().build().await.unwrap();
assert_bool(
&db,
"RETURN all(x IN [{a: 2}, {a: 2}] WHERE x.a = 2) AS result",
true,
)
.await;
assert_bool(
&db,
"RETURN any(x IN [{a: 2}, {a: 4}] WHERE x.a = 2) AS result",
true,
)
.await;
assert_bool(
&db,
"RETURN single(x IN [{a: 2}, {a: 4}] WHERE x.a = 2) AS result",
true,
)
.await;
assert_bool(
&db,
"RETURN none(x IN [{a: 3}, {a: 4}] WHERE x.a = 2) AS result",
true,
)
.await;
}
#[tokio::test]
async fn test_quantifier_static_predicates() {
let db = Uni::in_memory().build().await.unwrap();
assert_bool(&db, "RETURN all(x IN [1, 2, 3] WHERE true) AS result", true).await;
assert_bool(&db, "RETURN any(x IN [1, 2, 3] WHERE true) AS result", true).await;
assert_bool(
&db,
"RETURN none(x IN [1, 2, 3] WHERE true) AS result",
false,
)
.await;
assert_bool(
&db,
"RETURN single(x IN [1, 2, 3] WHERE true) AS result",
false,
)
.await;
assert_bool(&db, "RETURN single(x IN [42] WHERE true) AS result", true).await;
assert_bool(
&db,
"RETURN all(x IN [1, 2, 3] WHERE false) AS result",
false,
)
.await;
assert_bool(
&db,
"RETURN any(x IN [1, 2, 3] WHERE false) AS result",
false,
)
.await;
assert_bool(
&db,
"RETURN none(x IN [1, 2, 3] WHERE false) AS result",
true,
)
.await;
assert_bool(
&db,
"RETURN single(x IN [1, 2, 3] WHERE false) AS result",
false,
)
.await;
}
#[tokio::test]
async fn test_quantifier_single_element_list() {
let db = Uni::in_memory().build().await.unwrap();
assert_bool(&db, "RETURN all(x IN [5] WHERE x = 5) AS result", true).await;
assert_bool(&db, "RETURN all(x IN [5] WHERE x = 6) AS result", false).await;
assert_bool(&db, "RETURN any(x IN [5] WHERE x = 5) AS result", true).await;
assert_bool(&db, "RETURN any(x IN [5] WHERE x = 6) AS result", false).await;
assert_bool(&db, "RETURN single(x IN [5] WHERE x = 5) AS result", true).await;
assert_bool(&db, "RETURN single(x IN [5] WHERE x = 6) AS result", false).await;
assert_bool(&db, "RETURN none(x IN [5] WHERE x = 5) AS result", false).await;
assert_bool(&db, "RETURN none(x IN [5] WHERE x = 6) AS result", true).await;
}
#[tokio::test]
async fn test_none_null_semantics() {
let db = Uni::in_memory().build().await.unwrap();
assert_null(&db, "RETURN none(x IN [null] WHERE x = 2) AS result").await;
assert_bool(
&db,
"RETURN none(x IN [2, null] WHERE x = 2) AS result",
false,
)
.await;
assert_null(&db, "RETURN none(x IN [0, null] WHERE x = 2) AS result").await;
assert_bool(&db, "RETURN none(x IN [0, 1] WHERE x = 2) AS result", true).await;
assert_bool(&db, "RETURN none(x IN [2, 1] WHERE x = 2) AS result", false).await;
assert_null(&db, "RETURN none(x IN [null, null] WHERE x = 2) AS result").await;
assert_null(&db, "RETURN none(x IN [1, null, 3] WHERE x = 2) AS result").await;
assert_bool(
&db,
"RETURN none(x IN [1, null, 2] WHERE x = 2) AS result",
false,
)
.await;
}
#[tokio::test]
async fn test_single_null_semantics() {
let db = Uni::in_memory().build().await.unwrap();
assert_null(&db, "RETURN single(x IN [null] WHERE x = 2) AS result").await;
assert_null(&db, "RETURN single(x IN [2, null] WHERE x = 2) AS result").await;
assert_null(&db, "RETURN single(x IN [0, null] WHERE x = 2) AS result").await;
assert_bool(&db, "RETURN single(x IN [2] WHERE x = 2) AS result", true).await;
assert_bool(
&db,
"RETURN single(x IN [2, 2] WHERE x = 2) AS result",
false,
)
.await;
assert_bool(
&db,
"RETURN single(x IN [2, 2, null] WHERE x = 2) AS result",
false,
)
.await;
assert_bool(
&db,
"RETURN single(x IN [0, 1] WHERE x = 2) AS result",
false,
)
.await;
assert_bool(
&db,
"RETURN single(x IN [0, 2, 1] WHERE x = 2) AS result",
true,
)
.await;
}
#[tokio::test]
async fn test_any_null_semantics() {
let db = Uni::in_memory().build().await.unwrap();
assert_null(&db, "RETURN any(x IN [null] WHERE x = 2) AS result").await;
assert_bool(
&db,
"RETURN any(x IN [2, null] WHERE x = 2) AS result",
true,
)
.await;
assert_null(&db, "RETURN any(x IN [0, null] WHERE x = 2) AS result").await;
assert_bool(&db, "RETURN any(x IN [0, 1] WHERE x = 2) AS result", false).await;
assert_bool(&db, "RETURN any(x IN [0, 2] WHERE x = 2) AS result", true).await;
assert_null(&db, "RETURN any(x IN [null, null] WHERE x = 2) AS result").await;
assert_bool(
&db,
"RETURN any(x IN [null, 2, null] WHERE x = 2) AS result",
true,
)
.await;
}
#[tokio::test]
async fn test_all_null_semantics() {
let db = Uni::in_memory().build().await.unwrap();
assert_null(&db, "RETURN all(x IN [null] WHERE x = 2) AS result").await;
assert_null(&db, "RETURN all(x IN [2, null] WHERE x = 2) AS result").await;
assert_bool(
&db,
"RETURN all(x IN [0, null] WHERE x = 2) AS result",
false,
)
.await;
assert_bool(&db, "RETURN all(x IN [2, 2] WHERE x = 2) AS result", true).await;
assert_bool(&db, "RETURN all(x IN [0, 1] WHERE x = 2) AS result", false).await;
assert_null(
&db,
"RETURN all(x IN [2, null, null] WHERE x = 2) AS result",
)
.await;
assert_bool(
&db,
"RETURN all(x IN [null, 0, null] WHERE x = 2) AS result",
false,
)
.await;
}
#[tokio::test]
async fn test_none_is_null_predicate() {
let db = Uni::in_memory().build().await.unwrap();
assert_bool(
&db,
"RETURN none(x IN [null] WHERE x IS NULL) AS result",
false,
)
.await;
assert_bool(
&db,
"RETURN none(x IN [1, null] WHERE x IS NULL) AS result",
false,
)
.await;
assert_bool(
&db,
"RETURN none(x IN [1, 2] WHERE x IS NULL) AS result",
true,
)
.await;
assert_bool(
&db,
"RETURN none(x IN [null] WHERE x IS NOT NULL) AS result",
true,
)
.await;
assert_bool(
&db,
"RETURN none(x IN [1, null] WHERE x IS NOT NULL) AS result",
false,
)
.await;
assert_bool(
&db,
"RETURN none(x IN [1, 2] WHERE x IS NOT NULL) AS result",
false,
)
.await;
}
#[tokio::test]
async fn test_single_is_null_predicate() {
let db = Uni::in_memory().build().await.unwrap();
assert_bool(
&db,
"RETURN single(x IN [null] WHERE x IS NULL) AS result",
true,
)
.await;
assert_bool(
&db,
"RETURN single(x IN [0, null] WHERE x IS NULL) AS result",
true,
)
.await;
assert_bool(
&db,
"RETURN single(x IN [null, null] WHERE x IS NULL) AS result",
false,
)
.await;
assert_bool(
&db,
"RETURN single(x IN [1, 2] WHERE x IS NULL) AS result",
false,
)
.await;
assert_bool(
&db,
"RETURN single(x IN [null] WHERE x IS NOT NULL) AS result",
false,
)
.await;
assert_bool(
&db,
"RETURN single(x IN [1, null] WHERE x IS NOT NULL) AS result",
true,
)
.await;
assert_bool(
&db,
"RETURN single(x IN [1, 2] WHERE x IS NOT NULL) AS result",
false,
)
.await;
}
#[tokio::test]
async fn test_any_is_null_predicate() {
let db = Uni::in_memory().build().await.unwrap();
assert_bool(
&db,
"RETURN any(x IN [null] WHERE x IS NULL) AS result",
true,
)
.await;
assert_bool(
&db,
"RETURN any(x IN [1, null] WHERE x IS NULL) AS result",
true,
)
.await;
assert_bool(
&db,
"RETURN any(x IN [1, 2] WHERE x IS NULL) AS result",
false,
)
.await;
assert_bool(
&db,
"RETURN any(x IN [null, null] WHERE x IS NOT NULL) AS result",
false,
)
.await;
assert_bool(
&db,
"RETURN any(x IN [null, 1] WHERE x IS NOT NULL) AS result",
true,
)
.await;
assert_bool(
&db,
"RETURN any(x IN [1, 2] WHERE x IS NOT NULL) AS result",
true,
)
.await;
}
#[tokio::test]
async fn test_all_is_null_predicate() {
let db = Uni::in_memory().build().await.unwrap();
assert_bool(
&db,
"RETURN all(x IN [null] WHERE x IS NULL) AS result",
true,
)
.await;
assert_bool(
&db,
"RETURN all(x IN [null, null] WHERE x IS NULL) AS result",
true,
)
.await;
assert_bool(
&db,
"RETURN all(x IN [1, null] WHERE x IS NULL) AS result",
false,
)
.await;
assert_bool(
&db,
"RETURN all(x IN [1, 2] WHERE x IS NULL) AS result",
false,
)
.await;
assert_bool(
&db,
"RETURN all(x IN [null] WHERE x IS NOT NULL) AS result",
false,
)
.await;
assert_bool(
&db,
"RETURN all(x IN [null, null] WHERE x IS NOT NULL) AS result",
false,
)
.await;
assert_bool(
&db,
"RETURN all(x IN [1, 2] WHERE x IS NOT NULL) AS result",
true,
)
.await;
assert_bool(
&db,
"RETURN all(x IN [1, null] WHERE x IS NOT NULL) AS result",
false,
)
.await;
}
#[tokio::test]
async fn test_mixed_null_is_null_multiple_elements() {
let db = Uni::in_memory().build().await.unwrap();
assert_bool(
&db,
"RETURN none(x IN [null, null, null] WHERE x IS NULL) AS result",
false,
)
.await;
assert_bool(
&db,
"RETURN all(x IN [null, null, null] WHERE x IS NULL) AS result",
true,
)
.await;
assert_bool(
&db,
"RETURN single(x IN [1, null, 2] WHERE x IS NULL) AS result",
true,
)
.await;
assert_bool(
&db,
"RETURN single(x IN [1, null, null] WHERE x IS NULL) AS result",
false,
)
.await;
assert_bool(
&db,
"RETURN any(x IN [1, 2, 3] WHERE x IS NULL) AS result",
false,
)
.await;
}
#[tokio::test]
async fn test_is_null_on_empty_list() {
let db = Uni::in_memory().build().await.unwrap();
assert_bool(&db, "RETURN all(x IN [] WHERE x IS NULL) AS result", true).await;
assert_bool(&db, "RETURN any(x IN [] WHERE x IS NULL) AS result", false).await;
assert_bool(&db, "RETURN none(x IN [] WHERE x IS NULL) AS result", true).await;
assert_bool(
&db,
"RETURN single(x IN [] WHERE x IS NULL) AS result",
false,
)
.await;
}
#[tokio::test]
async fn test_is_null_on_all_non_null_list() {
let db = Uni::in_memory().build().await.unwrap();
assert_bool(
&db,
"RETURN none(x IN [1, 2, 3] WHERE x IS NULL) AS result",
true,
)
.await;
assert_bool(
&db,
"RETURN all(x IN [1, 2, 3] WHERE x IS NOT NULL) AS result",
true,
)
.await;
}
#[tokio::test]
async fn test_nested_quantifier_on_nested_lists() {
let db = Uni::in_memory().build().await.unwrap();
assert_bool(
&db,
"RETURN none(x IN [['abc'], ['abc', 'def']] WHERE none(y IN x WHERE y = 'abc')) AS result",
true,
)
.await;
assert_bool(
&db,
"RETURN all(x IN [['abc'], ['abc', 'def']] WHERE any(y IN x WHERE y = 'abc')) AS result",
true,
)
.await;
assert_bool(
&db,
"RETURN single(x IN [[1, 2, 3], [4, 5, 6], [7, 8, 9]] WHERE all(y IN x WHERE y > 5)) AS result",
true,
)
.await;
assert_bool(
&db,
"RETURN any(x IN [[1], [2, 3], [4, 5, 6]] WHERE single(y IN x WHERE y > 0)) AS result",
true,
)
.await;
}
#[tokio::test]
async fn test_nested_quantifier_on_same_list() {
let db = Uni::in_memory().build().await.unwrap();
assert_bool(
&db,
"WITH [1, 2, 3, 4, 5, 6, 7, 8, 9] AS list RETURN single(x IN list WHERE none(y IN list WHERE x < y)) AS result",
true,
)
.await;
assert_bool(
&db,
"WITH [1, 2, 3, 4, 5, 6, 7, 8, 9] AS list RETURN single(x IN list WHERE none(y IN list WHERE y < x)) AS result",
true,
)
.await;
}
#[tokio::test]
async fn test_nested_quantifier_all_any() {
let db = Uni::in_memory().build().await.unwrap();
assert_bool(
&db,
"RETURN all(x IN [[1, 2], [3, 4]] WHERE any(y IN x WHERE y % 2 = 0)) AS result",
true,
)
.await;
assert_bool(
&db,
"RETURN all(x IN [[1, 3], [5, 7]] WHERE any(y IN x WHERE y % 2 = 0)) AS result",
false,
)
.await;
}
#[tokio::test]
async fn test_nested_quantifier_with_nulls() {
let db = Uni::in_memory().build().await.unwrap();
assert_bool(
&db,
"RETURN any(x IN [[null, 1], [2, 3]] WHERE all(y IN x WHERE y > 0)) AS result",
true,
)
.await;
assert_bool(
&db,
"RETURN none(x IN [[null, 1], [2, 3]] WHERE all(y IN x WHERE y > 0)) AS result",
false,
)
.await;
}
#[tokio::test]
async fn test_none_equivalences() {
let db = Uni::in_memory().build().await.unwrap();
let list = "[1, 2, 3, 4, 5, 6, 7, 8, 9]";
assert_bool(
&db,
&format!(
"RETURN none(x IN {list} WHERE x = 2) = (NOT any(x IN {list} WHERE x = 2)) AS result"
),
true,
)
.await;
assert_bool(
&db,
&format!(
"RETURN none(x IN {list} WHERE x = 2) = all(x IN {list} WHERE NOT (x = 2)) AS result"
),
true,
)
.await;
assert_bool(
&db,
&format!(
"RETURN none(x IN {list} WHERE x % 2 = 0) = (NOT any(x IN {list} WHERE x % 2 = 0)) AS result"
),
true,
)
.await;
assert_bool(
&db,
&format!(
"RETURN none(x IN {list} WHERE x % 2 = 0) = all(x IN {list} WHERE NOT (x % 2 = 0)) AS result"
),
true,
)
.await;
assert_bool(
&db,
&format!(
"RETURN none(x IN {list} WHERE x > 100) = (NOT any(x IN {list} WHERE x > 100)) AS result"
),
true,
)
.await;
assert_bool(
&db,
&format!(
"RETURN none(x IN {list} WHERE x > 100) = all(x IN {list} WHERE NOT (x > 100)) AS result"
),
true,
)
.await;
}
#[tokio::test]
async fn test_any_equivalences() {
let db = Uni::in_memory().build().await.unwrap();
let list = "[1, 2, 3, 4, 5, 6, 7, 8, 9]";
assert_bool(
&db,
&format!(
"RETURN any(x IN {list} WHERE x = 2) = (NOT none(x IN {list} WHERE x = 2)) AS result"
),
true,
)
.await;
assert_bool(
&db,
&format!(
"RETURN any(x IN {list} WHERE x = 2) = (NOT all(x IN {list} WHERE NOT (x = 2))) AS result"
),
true,
)
.await;
assert_bool(
&db,
&format!(
"RETURN any(x IN {list} WHERE x % 3 = 0) = (NOT none(x IN {list} WHERE x % 3 = 0)) AS result"
),
true,
)
.await;
assert_bool(
&db,
&format!(
"RETURN any(x IN {list} WHERE x % 3 = 0) = (NOT all(x IN {list} WHERE NOT (x % 3 = 0))) AS result"
),
true,
)
.await;
assert_bool(
&db,
&format!(
"RETURN any(x IN {list} WHERE x > 100) = (NOT none(x IN {list} WHERE x > 100)) AS result"
),
true,
)
.await;
}
#[tokio::test]
async fn test_all_equivalences() {
let db = Uni::in_memory().build().await.unwrap();
let list = "[1, 2, 3, 4, 5, 6, 7, 8, 9]";
assert_bool(
&db,
&format!(
"RETURN all(x IN {list} WHERE x > 0) = none(x IN {list} WHERE NOT (x > 0)) AS result"
),
true,
)
.await;
assert_bool(
&db,
&format!(
"RETURN all(x IN {list} WHERE x > 0) = (NOT any(x IN {list} WHERE NOT (x > 0))) AS result"
),
true,
)
.await;
assert_bool(
&db,
&format!(
"RETURN all(x IN {list} WHERE x < 7) = none(x IN {list} WHERE NOT (x < 7)) AS result"
),
true,
)
.await;
assert_bool(
&db,
&format!(
"RETURN all(x IN {list} WHERE x < 7) = (NOT any(x IN {list} WHERE NOT (x < 7))) AS result"
),
true,
)
.await;
assert_bool(
&db,
&format!(
"RETURN all(x IN {list} WHERE x >= 3) = none(x IN {list} WHERE NOT (x >= 3)) AS result"
),
true,
)
.await;
assert_bool(
&db,
&format!(
"RETURN all(x IN {list} WHERE x >= 3) = (NOT any(x IN {list} WHERE NOT (x >= 3))) AS result"
),
true,
)
.await;
}
#[tokio::test]
async fn test_equivalence_identities_cross_check() {
let db = Uni::in_memory().build().await.unwrap();
let list = "[1, 2, 3, 4, 5]";
assert_bool(
&db,
&format!("RETURN none(x IN {list} WHERE x = 3) AS result"),
false,
)
.await;
assert_bool(
&db,
&format!("RETURN any(x IN {list} WHERE x = 3) AS result"),
true,
)
.await;
assert_bool(
&db,
&format!("RETURN all(x IN {list} WHERE x = 3) AS result"),
false,
)
.await;
assert_bool(
&db,
&format!("RETURN single(x IN {list} WHERE x = 3) AS result"),
true,
)
.await;
assert_bool(
&db,
&format!("RETURN none(x IN {list} WHERE x > 0) AS result"),
false,
)
.await;
assert_bool(
&db,
&format!("RETURN any(x IN {list} WHERE x > 0) AS result"),
true,
)
.await;
assert_bool(
&db,
&format!("RETURN all(x IN {list} WHERE x > 0) AS result"),
true,
)
.await;
assert_bool(
&db,
&format!("RETURN single(x IN {list} WHERE x > 0) AS result"),
false,
)
.await;
assert_bool(
&db,
&format!("RETURN none(x IN {list} WHERE x > 100) AS result"),
true,
)
.await;
assert_bool(
&db,
&format!("RETURN any(x IN {list} WHERE x > 100) AS result"),
false,
)
.await;
assert_bool(
&db,
&format!("RETURN all(x IN {list} WHERE x > 100) AS result"),
false,
)
.await;
assert_bool(
&db,
&format!("RETURN single(x IN {list} WHERE x > 100) AS result"),
false,
)
.await;
}
#[tokio::test]
async fn test_none_size_equivalence() {
let db = Uni::in_memory().build().await.unwrap();
let list = "[1, 2, 3, 4, 5, 6, 7, 8, 9]";
assert_bool(
&db,
&format!(
"RETURN none(x IN {list} WHERE x > 100) = (size([x IN {list} WHERE x > 100 | x]) = 0) AS result"
),
true,
)
.await;
assert_bool(
&db,
&format!(
"RETURN none(x IN {list} WHERE x = 5) = (size([x IN {list} WHERE x = 5 | x]) = 0) AS result"
),
true,
)
.await;
assert_bool(
&db,
&format!(
"RETURN none(x IN {list} WHERE x % 2 = 0) = (size([x IN {list} WHERE x % 2 = 0 | x]) = 0) AS result"
),
true,
)
.await;
}
#[tokio::test]
async fn test_single_size_equivalence() {
let db = Uni::in_memory().build().await.unwrap();
let list = "[1, 2, 3, 4, 5, 6, 7, 8, 9]";
assert_bool(
&db,
&format!(
"RETURN single(x IN {list} WHERE x = 5) = (size([x IN {list} WHERE x = 5 | x]) = 1) AS result"
),
true,
)
.await;
assert_bool(
&db,
&format!(
"RETURN single(x IN {list} WHERE x % 2 = 0) = (size([x IN {list} WHERE x % 2 = 0 | x]) = 1) AS result"
),
true,
)
.await;
assert_bool(
&db,
&format!(
"RETURN single(x IN {list} WHERE x > 100) = (size([x IN {list} WHERE x > 100 | x]) = 1) AS result"
),
true,
)
.await;
}
#[tokio::test]
async fn test_any_size_equivalence() {
let db = Uni::in_memory().build().await.unwrap();
let list = "[1, 2, 3, 4, 5, 6, 7, 8, 9]";
assert_bool(
&db,
&format!(
"RETURN any(x IN {list} WHERE x = 5) = (size([x IN {list} WHERE x = 5 | x]) > 0) AS result"
),
true,
)
.await;
assert_bool(
&db,
&format!(
"RETURN any(x IN {list} WHERE x > 100) = (size([x IN {list} WHERE x > 100 | x]) > 0) AS result"
),
true,
)
.await;
assert_bool(
&db,
&format!(
"RETURN any(x IN {list} WHERE x % 3 = 0) = (size([x IN {list} WHERE x % 3 = 0 | x]) > 0) AS result"
),
true,
)
.await;
}
#[tokio::test]
async fn test_all_size_equivalence() {
let db = Uni::in_memory().build().await.unwrap();
let list = "[1, 2, 3, 4, 5, 6, 7, 8, 9]";
assert_bool(
&db,
&format!(
"RETURN all(x IN {list} WHERE x > 0) = (size([x IN {list} WHERE x > 0 | x]) = size({list})) AS result"
),
true,
)
.await;
assert_bool(
&db,
&format!(
"RETURN all(x IN {list} WHERE x < 7) = (size([x IN {list} WHERE x < 7 | x]) = size({list})) AS result"
),
true,
)
.await;
assert_bool(
&db,
&format!(
"RETURN all(x IN {list} WHERE x > 100) = (size([x IN {list} WHERE x > 100 | x]) = size({list})) AS result"
),
true,
)
.await;
}
#[tokio::test]
async fn test_implication_single_all_implies_any() {
let db = Uni::in_memory().build().await.unwrap();
let list = "[1, 2, 3, 4, 5, 6, 7, 8, 9]";
assert_bool(
&db,
&format!(
"RETURN (NOT (single(x IN {list} WHERE x = 5) OR all(x IN {list} WHERE x = 5)) OR any(x IN {list} WHERE x = 5)) AS result"
),
true,
)
.await;
assert_bool(
&db,
&format!(
"RETURN (NOT (single(x IN {list} WHERE x > 0) OR all(x IN {list} WHERE x > 0)) OR any(x IN {list} WHERE x > 0)) AS result"
),
true,
)
.await;
assert_bool(
&db,
&format!(
"RETURN (NOT (single(x IN {list} WHERE x > 100) OR all(x IN {list} WHERE x > 100)) OR any(x IN {list} WHERE x > 100)) AS result"
),
true,
)
.await;
assert_bool(
&db,
&format!(
"RETURN (NOT (single(x IN {list} WHERE x % 2 = 0) OR all(x IN {list} WHERE x % 2 = 0)) OR any(x IN {list} WHERE x % 2 = 0)) AS result"
),
true,
)
.await;
assert_bool(
&db,
&format!(
"RETURN (NOT (single(x IN {list} WHERE x = 1) OR all(x IN {list} WHERE x = 1)) OR any(x IN {list} WHERE x = 1)) AS result"
),
true,
)
.await;
}