Order comparisons between values of different types may return a boolean instead of `null`.
- Dominant language
- C
- Stars
- 4.8k
- Forks
- 523
- Avg merge
- 1d 2h
- Merged PRs (30d)
- 9
Description
**Describe the bug**
Order comparisons between values of different types may return a boolean instead of `null`.
In the minimized repro below, Apache AGE evaluates `30 > 'Rex'` as `true` and `30 < 'Rex'` as `false`.
On both Neo4j and Memgraph, the same expressions evaluate to `null`.
This suggests Apache AGE is applying a cross-type ordering for `>` / `<` comparisons where other Cypher implementations treat the comparison result as null.
**How are you accessing AGE (Command line, driver, etc.)?**
- PostgreSQL `cypher(...)` wrapper through the local Python differential-testing harness
- Reproducible directly in `psql` inside the Docker container
**What data setup do we need to do?**
No graph data is required beyond creating an empty graph:
```pgsql
SELECT create_graph('fuzz_graph');
```
**What is the necessary configuration info needed?**
- Plain Apache AGE Docker image was enough
- Docker image in local repro: `apache/age`
- AGE extension version: `1.7.0`
- PostgreSQL version: `18.1`
- Graph name used in repro: `fuzz_graph`
- No extra extensions or special configuration were required
**What is the command that caused the error?**
```pgsql
SELECT * FROM cypher('fuzz_graph', $$
RETURN 30 > 'Rex' AS gt,
30 < 'Rex' AS lt,
30 = 'Rex' AS eq
$$) AS (gt agtype, lt agtype, eq agtype);
```
Returned result on AGE:
```text
gt | lt | eq
-----+-------+------
true | false | false
```
**Expected behavior**
The equality result `30 = 'Rex'` being `false` is fine, but the ordering comparisons should evaluate to `null` rather than `true` / `false`.
Expected result:
```text
gt | lt | eq
-----+------+------
null | null | false
```
Neo4j returns:
```text
gt | lt | eq
-----+------+------
null | null | false
```
Memgraph returns the same result.
**Environment (please complete the following information):**
- Version: Apache AGE `1.7.0`
- PostgreSQL: `18.1`
- Host OS: Windows
- Architecture: x86_64
- Deployment: Docker
**Additional context**
The same difference also reproduces when the values come from graph properties instead of literals:
```pgsql
SELECT * FROM cypher('fuzz_graph', $$
CREATE (:Person {name:'Alice', age:30}),
(:Dog {name:'Rex'})
$$) AS (v agtype);
SELECT * FROM cypher('fuzz_graph', $$
MATCH (person:Person), (dog:Dog)
WHERE person.name = 'Alice' AND dog.name = 'Rex'
RETURN person.age > dog.name AS v
$$) AS (v agtype);
```
Apache AGE returns:
```text
true
```
while Neo4j and Memgraph both return:
```text
null
```
This issue was first found during automated Neo4j-vs-AGE differential testing in a larger query:
```cypher
MATCH (person:Person)
WHERE COUNT { (person)-[:HAS_DOG]->(dog:Dog) WHERE person.age > dog.name } > 0
OPTIONAL MATCH (person)-[:HAS_DOG]->(dog:Dog)
RETURN DISTINCT person.name AS name, collect(dog.name) AS dogNames
ORDER BY name
LIMIT 2
```
After minimization, the same semantic difference still reproduces with the direct literal comparison above.
Contributor guide
Assessment
This issue has not been assessed yet.