diff --git a/regress/expected/cypher_match.out b/regress/expected/cypher_match.out index 8f325cbe6..4888556d9 100644 --- a/regress/expected/cypher_match.out +++ b/regress/expected/cypher_match.out @@ -1256,6 +1256,25 @@ SELECT * FROM cypher('cypher_match', $$ "nobody" | | | "anybody" | | (12 rows) +-- Tests to catch match following optional match logic +-- this syntax is invalid in cypher +SELECT * FROM cypher('cypher_match', $$ + OPTIONAL MATCH (n) + MATCH (m) + RETURN n,m + $$) AS (n agtype, m agtype); +ERROR: MATCH cannot follow OPTIONAL MATCH +LINE 1: SELECT * FROM cypher('cypher_match', $$ + ^ +SELECT * FROM cypher('cypher_match', $$ + MATCH (n) + OPTIONAL MATCH (m) + MATCH (o) + RETURN n,m + $$) AS (n agtype, m agtype); +ERROR: MATCH cannot follow OPTIONAL MATCH +LINE 1: SELECT * FROM cypher('cypher_match', $$ + ^ -- -- Tests retrieving Var from some parent's cpstate during transformation -- diff --git a/regress/sql/cypher_match.sql b/regress/sql/cypher_match.sql index 70f638df2..344453e00 100644 --- a/regress/sql/cypher_match.sql +++ b/regress/sql/cypher_match.sql @@ -621,6 +621,20 @@ SELECT * FROM cypher('cypher_match', $$ ORDER BY n, p, m, q $$) AS (n agtype, r agtype, p agtype, m agtype, s agtype, q agtype); +-- Tests to catch match following optional match logic +-- this syntax is invalid in cypher +SELECT * FROM cypher('cypher_match', $$ + OPTIONAL MATCH (n) + MATCH (m) + RETURN n,m + $$) AS (n agtype, m agtype); + +SELECT * FROM cypher('cypher_match', $$ + MATCH (n) + OPTIONAL MATCH (m) + MATCH (o) + RETURN n,m + $$) AS (n agtype, m agtype); -- -- Tests retrieving Var from some parent's cpstate during transformation diff --git a/src/backend/parser/cypher_clause.c b/src/backend/parser/cypher_clause.c index e1e6c94be..294ebb064 100644 --- a/src/backend/parser/cypher_clause.c +++ b/src/backend/parser/cypher_clause.c @@ -2508,6 +2508,23 @@ static Query *transform_cypher_match_pattern(cypher_parsestate *cpstate, query = makeNode(Query); query->commandType = CMD_SELECT; + if(self->optional == true && clause->next) + { + cypher_clause *next = clause->next; + if (is_ag_node(next->self, cypher_match)) + { + cypher_match *next_self = (cypher_match *)next->self; + if (!next_self->optional) + { + ereport(ERROR, + (errcode(ERRCODE_SYNTAX_ERROR), + errmsg("MATCH cannot follow OPTIONAL MATCH"), + parser_errposition(pstate, + exprLocation((Node *) next_self)))); + } + } + } + // If there is no previous clause, transform to a general MATCH clause. if (self->optional == true && clause->prev != NULL) {