crdv7 opened a new issue, #2487:
URL: https://github.com/apache/age/issues/2487
**Describe the bug**
When a `MATCH` produces the same entity in multiple result rows, a writable
expression that depends on the entity's previous property value is evaluated
from the original entity state carried by each row.
In the example below, the same vertex appears in two rows and reaches the
`SET` clause twice, but its stored value is only incremented once. I would
like to confirm whether this is the intended AGE behavior or a correctness
issue.
**How are you accessing AGE (Command line, driver, etc.)?**
- `psql`
**What data setup do we need to do?**
```pgsql
LOAD 'age';
SET search_path = ag_catalog, "$user", public;
SELECT create_graph('repeated_row_set');
SELECT * FROM cypher('repeated_row_set', $$
CREATE (n:T {cnt: 0})-[:R]->(:M {v: 1}),
(n)-[:R]->(:M {v: 2})
$$) AS (a agtype);
```
The same `T` vertex is now matched once for each outgoing `R` relationship.
**What is the necessary configuration info needed?**
- No additional extension or non-default AGE configuration is required.
**What is the command that caused the error?**
```pgsql
SELECT * FROM cypher('repeated_row_set', $$
MATCH (n:T)-[:R]->(m:M)
SET n.cnt = n.cnt + 1
RETURN n.cnt, m.v
$$) AS (cnt agtype, mv agtype);
```
Observed result:
```text
cnt | mv
-----+----
1 | 1
1 | 2
```
Reading the stored value:
```pgsql
SELECT * FROM cypher('repeated_row_set', $$
MATCH (n:T)
RETURN n.cnt
$$) AS (cnt agtype);
```
produces:
```text
cnt
-----
1
```
**Expected behavior**
There are two plausible interpretations:
1. If `SET` is applied to each matched row in turn and a later row observes
the write made for an earlier row, both rows should increment `cnt`:
```text
row 1: 0 + 1 -> 1
row 2: 1 + 1 -> 2
```
The final stored value would be `2`.
2. If right-hand-side expressions are evaluated from the input state of the
`SET` clause without writes becoming visible between its input rows, both
rows may compute `0 + 1` and the final stored value may remain `1`.
Could the community confirm which interpretation is intended? Whichever
behavior is chosen should be deterministic and documented. If AGE intends
the first interpretation, the observed result is a correctness bug.
The
[Cypher clause-composition
documentation](https://neo4j.com/docs/cypher-manual/current/clauses/clause-composition/)
states that most clauses are applied to each row of the intermediate result
table in turn, but it does not explicitly resolve multiple input rows that
refer to the same entity within one writable clause. For comparison, the
equivalent query in Neo4j accumulates both updates and stores a final `cnt`
value of `2`.
PostgreSQL takes a different approach for
[`UPDATE ... FROM`](https://www.postgresql.org/docs/18/sql-update.html):
when multiple join rows identify the same target row, only one join row is
used for the update. AGE is implemented on PostgreSQL but exposes Cypher, so
neither precedent alone establishes the intended AGE semantics.
**Environment (please complete the following information):**
- AGE baseline commit: `801417404978823bd8732452c3f7959017584785`
- PostgreSQL: 18.4
- Access method: `psql`
- OS: Linux x86-64
**Additional context**
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: [email protected]
For queries about this service, please contact Infrastructure at:
[email protected]