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]

Reply via email to