Yyunozor opened a new pull request, #2483:
URL: https://github.com/apache/age/pull/2483

   A query that begins with `OPTIONAL MATCH` returns no rows when the pattern 
matches nothing:
   
   ```
   SELECT * FROM cypher('g', $$ OPTIONAL MATCH (n:NoSuchLabel) RETURN n $$) AS 
(n agtype);
    n
   ---
   (0 rows)
   ```
   
   Cypher gives every `OPTIONAL MATCH` left join semantics. With no clause to 
its left it joins against the implicit single row that begins a query, so this 
has to return one row with `n = NULL` — that is what separates `OPTIONAL MATCH` 
from `MATCH`.
   
   `transform_cypher_match_pattern` builds the null-preserving LATERAL LEFT 
JOIN out of the previous clause, and falls through to the plain MATCH path when 
there is none ("If there is no previous clause, transform to a general MATCH 
clause"). A leading `OPTIONAL MATCH` has no previous clause, so it took the 
plain path. Any preceding clause, however trivial, already produced the right 
answer:
   
   ```
   $$ WITH 1 AS x OPTIONAL MATCH (n:NoSuchLabel) RETURN n $$    -- 1 row, n = 
NULL
   $$ UNWIND [1] AS x OPTIONAL MATCH (n:NoSuchLabel) RETURN n $$ -- 1 row, n = 
NULL
   ```
   
   The join was already right; only its left side was missing. This gives a 
leading `OPTIONAL MATCH` a previous clause that yields exactly one row, built 
the way `transform_cypher_with` already builds a synthesized `cypher_return`. 
Its lone column is named with the hidden variable prefix, so 
`expand_pnsi_attrs` keeps it out of `RETURN *` expansion.
   
   The clause is attached in `analyze_cypher` rather than in the transform. The 
transform temporarily clears `prev` to recurse into the join's right side and 
relies on `prev` being NULL there to take the plain MATCH path, so synthesizing 
a `prev` inside it re-arms that recursion until the stack runs out.
   
   Tests cover the no-match case for node and relationship patterns, a `WHERE` 
that no binding survives, that a matching pattern gains no extra null row, that 
`RETURN *` does not expose the internal column, that a leading `MATCH` still 
returns no rows, and that `MATCH` following `OPTIONAL MATCH` still errors. 
`make installcheck` passes 43/43 on this branch and on its parent; with only 
the two test files applied to the parent, `cypher_match` fails.
   
   Known limitation: a `UNION` branch beginning with `OPTIONAL MATCH` still 
returns no rows. Branches are assembled through 
`cypher_parse_sub_analyze_union`, not `analyze_cypher`, so they never reach 
this path. Placing the same unit clause there would be a natural follow-up.
   
   Closes #2473
   


-- 
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