diff --git a/regress/expected/cypher_match.out b/regress/expected/cypher_match.out index 8c427497d..cef6dad94 100644 --- a/regress/expected/cypher_match.out +++ b/regress/expected/cypher_match.out @@ -1192,20 +1192,6 @@ AS (exists agtype); true (15 rows) -SELECT * FROM cypher('cypher_match', - $$MATCH p=(u)-[e]->(v) RETURN EXISTS((p)) $$) -AS (exists agtype); - exists --------- - true - true - true - true - true - true - true -(7 rows) - SELECT * FROM cypher('cypher_match', $$MATCH (u)-[e]->(v) RETURN EXISTS((u)-[e]->(v)-[e]->(u))$$) AS (exists agtype); @@ -1235,6 +1221,13 @@ AS (u agtype, e agtype, v agtype); ERROR: variable `x` does not exist LINE 2: $$MATCH (u)-[e]->(v) WHERE EXISTS((u)-[e]->(x)) RETURN u, e... ^ +-- path variable not allowed in EXISTS +SELECT * FROM cypher('cypher_match', + $$MATCH p=(u)-[e]->(v) RETURN EXISTS((p)) $$) +AS (exists agtype); +ERROR: a path variable 'p' is not allowed here +LINE 2: $$MATCH p=(u)-[e]->(v) RETURN EXISTS((p)) $$) + ^ -- -- Tests for EXISTS(property) -- @@ -1965,7 +1958,7 @@ SELECT * FROM cypher('cypher_match', $$ (8 rows) SELECT * FROM cypher('cypher_match', $$ - MATCH (a) WHERE exists(a.name) RETURN a $$) as (a agtype); + MATCH (a) WHERE EXISTS(a.name) RETURN a $$) as (a agtype); a -------------------------------------------------------------------------------- {"id": 281474976710659, "label": "", "properties": {"name": "orphan"}}::vertex @@ -1974,7 +1967,7 @@ SELECT * FROM cypher('cypher_match', $$ (3 rows) SELECT * FROM cypher('cypher_match', $$ - MATCH (a) WHERE exists(a.name) SET a.age = 4 RETURN a $$) as (a agtype); + MATCH (a) WHERE EXISTS(a.name) SET a.age = 4 RETURN a $$) as (a agtype); a ------------------------------------------------------------------------------------------ {"id": 281474976710659, "label": "", "properties": {"age": 4, "name": "orphan"}}::vertex @@ -2080,7 +2073,7 @@ SELECT * FROM cypher('cypher_match', $$ (1 row) SELECT * FROM cypher('cypher_match', $$ - MATCH (a) WHERE exists(a.age) AND exists(a.name) RETURN a $$) as (a agtype); + MATCH (a) WHERE EXISTS(a.age) AND EXISTS(a.name) RETURN a $$) as (a agtype); a ------------------------------------------------------------------------------------------ {"id": 281474976710660, "label": "", "properties": {"age": 4, "name": "F"}}::vertex @@ -2089,7 +2082,7 @@ SELECT * FROM cypher('cypher_match', $$ (3 rows) SELECT * FROM cypher('cypher_match', $$ - MATCH (a) WHERE exists(a.age) AND NOT exists(a.name) RETURN a $$) as (a agtype); + MATCH (a) WHERE EXISTS(a.age) AND NOT EXISTS(a.name) RETURN a $$) as (a agtype); a ------------------------------------------------------------------------ {"id": 281474976710665, "label": "", "properties": {"age": 4}}::vertex @@ -2842,7 +2835,7 @@ NOTICE: graph "issue_1399" has been created -- this is an empty graph so these should return 0 SELECT * FROM cypher('issue_1399', $$ MATCH (foo) - WHERE exists((foo)-[]->()) + WHERE EXISTS((foo)-[]->()) RETURN foo $$) as (c agtype); c @@ -2851,7 +2844,7 @@ $$) as (c agtype); SELECT * FROM cypher('issue_1399', $$ MATCH (foo) - WHERE NOT exists((foo)-[]->()) + WHERE NOT EXISTS((foo)-[]->()) RETURN foo $$) as (c agtype); c @@ -2860,7 +2853,7 @@ $$) as (c agtype); SELECT * FROM cypher('issue_1399', $$ MATCH (foo) - WHERE exists((foo)-[:BAR]->()) + WHERE EXISTS((foo)-[:BAR]->()) RETURN foo $$) as (c agtype); c @@ -2869,7 +2862,7 @@ $$) as (c agtype); SELECT * FROM cypher('issue_1399', $$ MATCH (foo) - WHERE NOT exists((foo)-[:BAR]->()) + WHERE NOT EXISTS((foo)-[:BAR]->()) RETURN foo $$) as (c agtype); c @@ -2879,7 +2872,7 @@ $$) as (c agtype); -- this is an empty graph so these should return false SELECT * FROM cypher('issue_1399', $$ MATCH (foo) - WHERE exists((foo)-[]->()) + WHERE EXISTS((foo)-[]->()) RETURN count(foo) > 0 $$) as (c agtype); c @@ -2889,7 +2882,7 @@ $$) as (c agtype); SELECT * FROM cypher('issue_1399', $$ MATCH (foo) - WHERE NOT exists((foo)-[]->()) + WHERE NOT EXISTS((foo)-[]->()) RETURN count(foo) > 0 $$) as (c agtype); c @@ -2899,7 +2892,7 @@ $$) as (c agtype); SELECT * FROM cypher('issue_1399', $$ MATCH (foo) - WHERE exists((foo)-[:BAR]->()) + WHERE EXISTS((foo)-[:BAR]->()) RETURN count(foo) > 0 $$) as (c agtype); c @@ -2909,7 +2902,7 @@ $$) as (c agtype); SELECT * FROM cypher('issue_1399', $$ MATCH (foo) - WHERE NOT exists((foo)-[:BAR]->()) + WHERE NOT EXISTS((foo)-[:BAR]->()) RETURN count(foo) > 0 $$) as (c agtype); c @@ -2930,7 +2923,7 @@ $$) as (c agtype); -- only one vertex can match. SELECT * FROM cypher('issue_1399', $$ MATCH (foo) - WHERE exists((foo)-[]->()) + WHERE EXISTS((foo)-[]->()) RETURN foo $$) as (c agtype); c @@ -2940,7 +2933,7 @@ $$) as (c agtype); SELECT * FROM cypher('issue_1399', $$ MATCH (foo) - WHERE NOT exists((foo)-[]->()) + WHERE NOT EXISTS((foo)-[]->()) RETURN foo $$) as (c agtype); c @@ -2950,7 +2943,7 @@ $$) as (c agtype); SELECT * FROM cypher('issue_1399', $$ MATCH (foo) - WHERE exists((foo)-[:BAR]->()) + WHERE EXISTS((foo)-[:BAR]->()) RETURN foo $$) as (c agtype); c @@ -2960,7 +2953,7 @@ $$) as (c agtype); SELECT * FROM cypher('issue_1399', $$ MATCH (foo) - WHERE NOT exists((foo)-[:BAR]->()) + WHERE NOT EXISTS((foo)-[:BAR]->()) RETURN foo $$) as (c agtype); c @@ -2971,7 +2964,7 @@ $$) as (c agtype); -- this should return 0 rows as it can't exist - that path isn't in BAR2 SELECT * FROM cypher('issue_1399', $$ MATCH (foo) - WHERE exists((foo)-[:BAR2]->()) + WHERE EXISTS((foo)-[:BAR2]->()) RETURN foo $$) as (c agtype); c @@ -2981,7 +2974,7 @@ $$) as (c agtype); -- this should return 2 rows as they all exist SELECT * FROM cypher('issue_1399', $$ MATCH (foo) - WHERE NOT exists((foo)-[:BAR2]->()) + WHERE NOT EXISTS((foo)-[:BAR2]->()) RETURN foo $$) as (c agtype); c @@ -2990,6 +2983,316 @@ $$) as (c agtype); {"id": 281474976710658, "label": "", "properties": {}}::vertex (2 rows) +-- Issue 1393 EXISTS doesn't see previous clauses' variables +SELECT FROM create_graph('issue_1393'); +NOTICE: graph "issue_1393" has been created +-- +(1 row) + +SELECT * FROM cypher('issue_1393', $$ + CREATE (n1:Object) RETURN n1 +$$) AS (n1 agtype); + n1 +---------------------------------------------------------------------- + {"id": 844424930131969, "label": "Object", "properties": {}}::vertex +(1 row) + +-- vertex cases +SELECT * FROM cypher('issue_1393', $$ + MATCH (n1:Object) MATCH (n2:Object) WHERE EXISTS((n1)-[]->(n2)) RETURN n1,n2 +$$) AS (n1 agtype, n2 agtype); + n1 | n2 +----+---- +(0 rows) + +SELECT * FROM cypher('issue_1393', $$ + MATCH (n1:Object) MATCH (n2:Object) WHERE EXISTS((n1:Object)-[]->(n2:Object)) RETURN n1,n2 +$$) AS (n1 agtype, n2 agtype); + n1 | n2 +----+---- +(0 rows) + +SELECT * FROM cypher('issue_1393', $$ + MATCH (n1:Object) MATCH (n2:Object) WHERE NOT EXISTS((n1)-[]->(n2)) RETURN n1,n2 +$$) AS (n1 agtype, n2 agtype); + n1 | n2 +----------------------------------------------------------------------+---------------------------------------------------------------------- + {"id": 844424930131969, "label": "Object", "properties": {}}::vertex | {"id": 844424930131969, "label": "Object", "properties": {}}::vertex +(1 row) + +SELECT * FROM cypher('issue_1393', $$ + MATCH (n1:Object) MATCH (n2:Object) WHERE NOT EXISTS((n1:Object)-[]->(n2:Object)) RETURN n1,n2 +$$) AS (n1 agtype, n2 agtype); + n1 | n2 +----------------------------------------------------------------------+---------------------------------------------------------------------- + {"id": 844424930131969, "label": "Object", "properties": {}}::vertex | {"id": 844424930131969, "label": "Object", "properties": {}}::vertex +(1 row) + +SELECT * FROM cypher('issue_1393', $$ + MATCH (n1:Object) MATCH (n2:Object) WHERE EXISTS((n1)-[]->()) RETURN n1,n2 +$$) AS (n1 agtype, n2 agtype); + n1 | n2 +----+---- +(0 rows) + +SELECT * FROM cypher('issue_1393', $$ + MATCH (n1:Object) MATCH (n2:Object) WHERE NOT EXISTS((n1)-[]->()) RETURN n1,n2 +$$) AS (n1 agtype, n2 agtype); + n1 | n2 +----------------------------------------------------------------------+---------------------------------------------------------------------- + {"id": 844424930131969, "label": "Object", "properties": {}}::vertex | {"id": 844424930131969, "label": "Object", "properties": {}}::vertex +(1 row) + +SELECT * FROM cypher('issue_1393', $$ + CREATE (n1:Object)-[e:knows]->(n2:Object) RETURN n1, e, n2 +$$) AS (n1 agtype, e agtype, n2 agtype); + n1 | e | n2 +----------------------------------------------------------------------+----------------------------------------------------------------------------------------------------------------------------+---------------------------------------------------------------------- + {"id": 844424930131970, "label": "Object", "properties": {}}::vertex | {"id": 1125899906842625, "label": "knows", "end_id": 844424930131971, "start_id": 844424930131970, "properties": {}}::edge | {"id": 844424930131971, "label": "Object", "properties": {}}::vertex +(1 row) + +SELECT * FROM cypher('issue_1393', $$ + MATCH (n1:Object) MATCH (n2:Object) WHERE EXISTS((n1)-[]->(n2)) RETURN n1,n2 +$$) AS (n1 agtype, n2 agtype); + n1 | n2 +----------------------------------------------------------------------+---------------------------------------------------------------------- + {"id": 844424930131970, "label": "Object", "properties": {}}::vertex | {"id": 844424930131971, "label": "Object", "properties": {}}::vertex +(1 row) + +SELECT * FROM cypher('issue_1393', $$ + MATCH (n1:Object) MATCH (n2:Object) WHERE EXISTS((n1:Object)-[]->(n2:Object)) RETURN n1,n2 +$$) AS (n1 agtype, n2 agtype); + n1 | n2 +----------------------------------------------------------------------+---------------------------------------------------------------------- + {"id": 844424930131970, "label": "Object", "properties": {}}::vertex | {"id": 844424930131971, "label": "Object", "properties": {}}::vertex +(1 row) + +SELECT * FROM cypher('issue_1393', $$ + MATCH (n1:Object) MATCH (n2:Object) WHERE NOT EXISTS((n1)-[]->(n2)) RETURN n1,n2 +$$) AS (n1 agtype, n2 agtype); + n1 | n2 +----------------------------------------------------------------------+---------------------------------------------------------------------- + {"id": 844424930131969, "label": "Object", "properties": {}}::vertex | {"id": 844424930131969, "label": "Object", "properties": {}}::vertex + {"id": 844424930131969, "label": "Object", "properties": {}}::vertex | {"id": 844424930131970, "label": "Object", "properties": {}}::vertex + {"id": 844424930131969, "label": "Object", "properties": {}}::vertex | {"id": 844424930131971, "label": "Object", "properties": {}}::vertex + {"id": 844424930131970, "label": "Object", "properties": {}}::vertex | {"id": 844424930131969, "label": "Object", "properties": {}}::vertex + {"id": 844424930131970, "label": "Object", "properties": {}}::vertex | {"id": 844424930131970, "label": "Object", "properties": {}}::vertex + {"id": 844424930131971, "label": "Object", "properties": {}}::vertex | {"id": 844424930131969, "label": "Object", "properties": {}}::vertex + {"id": 844424930131971, "label": "Object", "properties": {}}::vertex | {"id": 844424930131970, "label": "Object", "properties": {}}::vertex + {"id": 844424930131971, "label": "Object", "properties": {}}::vertex | {"id": 844424930131971, "label": "Object", "properties": {}}::vertex +(8 rows) + +SELECT * FROM cypher('issue_1393', $$ + MATCH (n1:Object) MATCH (n2:Object) WHERE NOT EXISTS((n1:Object)-[]->(n2:Object)) RETURN n1,n2 +$$) AS (n1 agtype, n2 agtype); + n1 | n2 +----------------------------------------------------------------------+---------------------------------------------------------------------- + {"id": 844424930131969, "label": "Object", "properties": {}}::vertex | {"id": 844424930131969, "label": "Object", "properties": {}}::vertex + {"id": 844424930131969, "label": "Object", "properties": {}}::vertex | {"id": 844424930131970, "label": "Object", "properties": {}}::vertex + {"id": 844424930131969, "label": "Object", "properties": {}}::vertex | {"id": 844424930131971, "label": "Object", "properties": {}}::vertex + {"id": 844424930131970, "label": "Object", "properties": {}}::vertex | {"id": 844424930131969, "label": "Object", "properties": {}}::vertex + {"id": 844424930131970, "label": "Object", "properties": {}}::vertex | {"id": 844424930131970, "label": "Object", "properties": {}}::vertex + {"id": 844424930131971, "label": "Object", "properties": {}}::vertex | {"id": 844424930131969, "label": "Object", "properties": {}}::vertex + {"id": 844424930131971, "label": "Object", "properties": {}}::vertex | {"id": 844424930131970, "label": "Object", "properties": {}}::vertex + {"id": 844424930131971, "label": "Object", "properties": {}}::vertex | {"id": 844424930131971, "label": "Object", "properties": {}}::vertex +(8 rows) + +SELECT * FROM cypher('issue_1393', $$ + MATCH (n1:Object) MATCH (n2:Object) WHERE EXISTS((n1)-[]->()) RETURN n1,n2 +$$) AS (n1 agtype, n2 agtype); + n1 | n2 +----------------------------------------------------------------------+---------------------------------------------------------------------- + {"id": 844424930131970, "label": "Object", "properties": {}}::vertex | {"id": 844424930131969, "label": "Object", "properties": {}}::vertex + {"id": 844424930131970, "label": "Object", "properties": {}}::vertex | {"id": 844424930131970, "label": "Object", "properties": {}}::vertex + {"id": 844424930131970, "label": "Object", "properties": {}}::vertex | {"id": 844424930131971, "label": "Object", "properties": {}}::vertex +(3 rows) + +SELECT * FROM cypher('issue_1393', $$ + MATCH (n1:Object) MATCH (n2:Object) WHERE NOT EXISTS((n1)-[]->()) RETURN n1,n2 +$$) AS (n1 agtype, n2 agtype); + n1 | n2 +----------------------------------------------------------------------+---------------------------------------------------------------------- + {"id": 844424930131969, "label": "Object", "properties": {}}::vertex | {"id": 844424930131969, "label": "Object", "properties": {}}::vertex + {"id": 844424930131971, "label": "Object", "properties": {}}::vertex | {"id": 844424930131969, "label": "Object", "properties": {}}::vertex + {"id": 844424930131969, "label": "Object", "properties": {}}::vertex | {"id": 844424930131970, "label": "Object", "properties": {}}::vertex + {"id": 844424930131971, "label": "Object", "properties": {}}::vertex | {"id": 844424930131970, "label": "Object", "properties": {}}::vertex + {"id": 844424930131969, "label": "Object", "properties": {}}::vertex | {"id": 844424930131971, "label": "Object", "properties": {}}::vertex + {"id": 844424930131971, "label": "Object", "properties": {}}::vertex | {"id": 844424930131971, "label": "Object", "properties": {}}::vertex +(6 rows) + +SELECT * FROM cypher('issue_1393', $$ + MATCH (n1:Object) MATCH (n2:Object) WHERE EXISTS((n1:Object)-[]->()) RETURN n1,n2 +$$) AS (n1 agtype, n2 agtype); + n1 | n2 +----------------------------------------------------------------------+---------------------------------------------------------------------- + {"id": 844424930131970, "label": "Object", "properties": {}}::vertex | {"id": 844424930131969, "label": "Object", "properties": {}}::vertex + {"id": 844424930131970, "label": "Object", "properties": {}}::vertex | {"id": 844424930131970, "label": "Object", "properties": {}}::vertex + {"id": 844424930131970, "label": "Object", "properties": {}}::vertex | {"id": 844424930131971, "label": "Object", "properties": {}}::vertex +(3 rows) + +SELECT * FROM cypher('issue_1393', $$ + MATCH (n1:Object) MATCH (n2:Object) WHERE NOT EXISTS((n1:Object)-[]->()) RETURN n1,n2 +$$) AS (n1 agtype, n2 agtype); + n1 | n2 +----------------------------------------------------------------------+---------------------------------------------------------------------- + {"id": 844424930131969, "label": "Object", "properties": {}}::vertex | {"id": 844424930131969, "label": "Object", "properties": {}}::vertex + {"id": 844424930131971, "label": "Object", "properties": {}}::vertex | {"id": 844424930131969, "label": "Object", "properties": {}}::vertex + {"id": 844424930131969, "label": "Object", "properties": {}}::vertex | {"id": 844424930131970, "label": "Object", "properties": {}}::vertex + {"id": 844424930131971, "label": "Object", "properties": {}}::vertex | {"id": 844424930131970, "label": "Object", "properties": {}}::vertex + {"id": 844424930131969, "label": "Object", "properties": {}}::vertex | {"id": 844424930131971, "label": "Object", "properties": {}}::vertex + {"id": 844424930131971, "label": "Object", "properties": {}}::vertex | {"id": 844424930131971, "label": "Object", "properties": {}}::vertex +(6 rows) + +-- should error +SELECT * FROM cypher('issue_1393', $$ + MATCH (n1:Object) MATCH (n2:Object) WHERE EXISTS((n1:object)-[]->()) RETURN n1,n2 +$$) AS (n1 agtype, n2 agtype); +ERROR: multiple labels for variable 'n1' are not supported +LINE 2: ...MATCH (n1:Object) MATCH (n2:Object) WHERE EXISTS((n1:object)... + ^ +SELECT * FROM cypher('issue_1393', $$ + MATCH (n1:Object) MATCH (n2:Object) WHERE NOT EXISTS((n1:object)-[]->()) RETURN n1,n2 +$$) AS (n1 agtype, n2 agtype); +ERROR: multiple labels for variable 'n1' are not supported +LINE 2: ...H (n1:Object) MATCH (n2:Object) WHERE NOT EXISTS((n1:object)... + ^ +SELECT * FROM cypher('issue_1393', $$ + MATCH (n1:Object) MATCH (n2:Object) WHERE NOT EXISTS((n1)-[e]->()) RETURN n1,n2,e +$$) AS (n1 agtype, n2 agtype, e agtype); +ERROR: variable `e` does not exist +LINE 2: ...1:Object) MATCH (n2:Object) WHERE NOT EXISTS((n1)-[e]->()) R... + ^ +-- edge cases +SELECT * FROM cypher('issue_1393', $$ + MATCH (n1:Object)-[e1:knows]->() MATCH (n2:Object) WHERE EXISTS((n1)-[e1]->(n2)) RETURN e1 +$$) AS (e1 agtype); + e1 +---------------------------------------------------------------------------------------------------------------------------- + {"id": 1125899906842625, "label": "knows", "end_id": 844424930131971, "start_id": 844424930131970, "properties": {}}::edge +(1 row) + +SELECT * FROM cypher('issue_1393', $$ + MATCH (n1:Object)-[e1:knows]->() MATCH (n2:Object) WHERE EXISTS((n1:Object)-[e1:knows]->(n2:Object)) RETURN e1 +$$) AS (e1 agtype); + e1 +---------------------------------------------------------------------------------------------------------------------------- + {"id": 1125899906842625, "label": "knows", "end_id": 844424930131971, "start_id": 844424930131970, "properties": {}}::edge +(1 row) + +SELECT * FROM cypher('issue_1393', $$ + MATCH (n1:Object)-[e1:knows]->() MATCH (n2:Object) WHERE NOT EXISTS((n1)-[e1]->(n2)) RETURN e1 +$$) AS (e1 agtype); + e1 +---------------------------------------------------------------------------------------------------------------------------- + {"id": 1125899906842625, "label": "knows", "end_id": 844424930131971, "start_id": 844424930131970, "properties": {}}::edge + {"id": 1125899906842625, "label": "knows", "end_id": 844424930131971, "start_id": 844424930131970, "properties": {}}::edge +(2 rows) + +SELECT * FROM cypher('issue_1393', $$ + MATCH (n1:Object)-[e1:knows]->() MATCH (n2:Object) WHERE NOT EXISTS((n1:Object)-[e1:knows]->(n2:Object)) RETURN e1 +$$) AS (e1 agtype); + e1 +---------------------------------------------------------------------------------------------------------------------------- + {"id": 1125899906842625, "label": "knows", "end_id": 844424930131971, "start_id": 844424930131970, "properties": {}}::edge + {"id": 1125899906842625, "label": "knows", "end_id": 844424930131971, "start_id": 844424930131970, "properties": {}}::edge +(2 rows) + +SELECT * FROM cypher('issue_1393', $$ + MATCH (n1:Object)-[e1:knows]->() MATCH (n2:Object) WHERE EXISTS((n1)-[e1]->()) RETURN e1 +$$) AS (e1 agtype); + e1 +---------------------------------------------------------------------------------------------------------------------------- + {"id": 1125899906842625, "label": "knows", "end_id": 844424930131971, "start_id": 844424930131970, "properties": {}}::edge + {"id": 1125899906842625, "label": "knows", "end_id": 844424930131971, "start_id": 844424930131970, "properties": {}}::edge + {"id": 1125899906842625, "label": "knows", "end_id": 844424930131971, "start_id": 844424930131970, "properties": {}}::edge +(3 rows) + +SELECT * FROM cypher('issue_1393', $$ + MATCH (n1:Object)-[e1:knows]->() MATCH (n2:Object) WHERE EXISTS((n1:Object)-[e1:knows]->(n2:Object)) RETURN e1 +$$) AS (e1 agtype); + e1 +---------------------------------------------------------------------------------------------------------------------------- + {"id": 1125899906842625, "label": "knows", "end_id": 844424930131971, "start_id": 844424930131970, "properties": {}}::edge +(1 row) + +SELECT * FROM cypher('issue_1393', $$ + MATCH (n1:Object)-[e1:knows]->() MATCH (n2:Object) WHERE NOT EXISTS((n1)-[e1]->()) RETURN e1 +$$) AS (e1 agtype); + e1 +---- +(0 rows) + +SELECT * FROM cypher('issue_1393', $$ + MATCH (n1:Object)-[e1:knows]->() MATCH (n2:Object) WHERE NOT EXISTS((n1:Object)-[e1:knows]->(n2:Object)) RETURN e1 +$$) AS (e1 agtype); + e1 +---------------------------------------------------------------------------------------------------------------------------- + {"id": 1125899906842625, "label": "knows", "end_id": 844424930131971, "start_id": 844424930131970, "properties": {}}::edge + {"id": 1125899906842625, "label": "knows", "end_id": 844424930131971, "start_id": 844424930131970, "properties": {}}::edge +(2 rows) + +-- should error +SELECT * FROM cypher('issue_1393', $$ + MATCH (n1:Object)-[e1:knows]->() MATCH (n2:Object) WHERE EXISTS((n1:Object)-[e1:Knows]->(n2:Object)) RETURN e1 +$$) AS (e1 agtype); +ERROR: multiple labels for variable 'e1' are not supported +LINE 2: ...s]->() MATCH (n2:Object) WHERE EXISTS((n1:Object)-[e1:Knows]... + ^ +SELECT * FROM cypher('issue_1393', $$ + MATCH (n1:Object)-[e1:knows]->() MATCH (n2:Object) WHERE NOT EXISTS((n1:Object)-[e1:Knows]->(n2:Object)) RETURN e1 +$$) AS (e1 agtype); +ERROR: multiple labels for variable 'e1' are not supported +LINE 2: ...() MATCH (n2:Object) WHERE NOT EXISTS((n1:Object)-[e1:Knows]... + ^ +SELECT * FROM cypher('issue_1393', $$ + MATCH (n1:Object)-[e1:knows]->() MATCH (n2:Object) WHERE EXISTS((e1:Object)-[e1:Knows]->(n2:Object)) RETURN e1 +$$) AS (e1 agtype); +ERROR: variable 'e1' is for an edge +LINE 2: ...t)-[e1:knows]->() MATCH (n2:Object) WHERE EXISTS((e1:Object)... + ^ +SELECT * FROM cypher('issue_1393', $$ + MATCH (n1:Object)-[e1:knows]->() MATCH (n2:Object) WHERE NOT EXISTS((n1:Object)-[e1:knows]->(e1)) RETURN e1 +$$) AS (e1 agtype); +ERROR: variable 'e1' is for an edge +LINE 2: ...Object) WHERE NOT EXISTS((n1:Object)-[e1:knows]->(e1)) RETUR... + ^ +SELECT * FROM cypher('issue_1393', $$ + MATCH (n1:Object)-[e1:knows]->() MATCH (n2:Object) WHERE NOT EXISTS((n1:Object)-[e1:knows]->(e2)) RETURN e1 +$$) AS (e1 agtype); +ERROR: variable `e2` does not exist +LINE 2: ...Object) WHERE NOT EXISTS((n1:Object)-[e1:knows]->(e2)) RETUR... + ^ +SELECT * FROM cypher('issue_1393', $$ + MATCH p=(n1:Object)-[e1:knows]->() MATCH (n2:Object) WHERE EXISTS((n1:Object)-[p]->(e2)) RETURN e1 +$$) AS (e1 agtype); +ERROR: variable 'p' is for a path +LINE 2: ...s]->() MATCH (n2:Object) WHERE EXISTS((n1:Object)-[p]->(e2))... + ^ +SELECT * FROM cypher('issue_1393', $$ + MATCH p=(n1)-[e1]->() MATCH (n2) WHERE EXISTS((n1)-[p]->(e2)) RETURN p +$$) AS (e1 agtype); +ERROR: variable 'p' is for a path +LINE 2: ...ATCH p=(n1)-[e1]->() MATCH (n2) WHERE EXISTS((n1)-[p]->(e2))... + ^ +-- long cases +SELECT * FROM cypher('issue_1393', $$ + MATCH (n1) MATCH (n2) MATCH (n1)-[e1]->() MATCH (n2)<-[e2]-(n1) MATCH (n3) + WHERE EXISTS((n3)-[e1]->(n2)) RETURN n1,n2,n3,e1 +$$) AS (n1 agtype, n2 agtype, n3 agtype, e1 agtype); + n1 | n2 | n3 | e1 +----------------------------------------------------------------------+----------------------------------------------------------------------+----------------------------------------------------------------------+---------------------------------------------------------------------------------------------------------------------------- + {"id": 844424930131970, "label": "Object", "properties": {}}::vertex | {"id": 844424930131971, "label": "Object", "properties": {}}::vertex | {"id": 844424930131970, "label": "Object", "properties": {}}::vertex | {"id": 1125899906842625, "label": "knows", "end_id": 844424930131971, "start_id": 844424930131970, "properties": {}}::edge +(1 row) + +SELECT * FROM cypher('issue_1393', $$ + MATCH (n1:Object) MATCH (n2:Object) MATCH (n1)-[e1:knows]->() MATCH (n2)<-[e2:knows]-(n1) MATCH (n3:Object) + WHERE EXISTS((n3:Object)-[e1:knows]->(n2:Object)) RETURN n1,n2,n3,e1 +$$) AS (n1 agtype, n2 agtype, n3 agtype, e1 agtype); + n1 | n2 | n3 | e1 +----------------------------------------------------------------------+----------------------------------------------------------------------+----------------------------------------------------------------------+---------------------------------------------------------------------------------------------------------------------------- + {"id": 844424930131970, "label": "Object", "properties": {}}::vertex | {"id": 844424930131971, "label": "Object", "properties": {}}::vertex | {"id": 844424930131970, "label": "Object", "properties": {}}::vertex | {"id": 1125899906842625, "label": "knows", "end_id": 844424930131971, "start_id": 844424930131970, "properties": {}}::edge +(1 row) + -- -- Clean up -- @@ -3064,6 +3367,18 @@ NOTICE: graph "issue_1399" has been dropped (1 row) +SELECT drop_graph('issue_1393', true); +NOTICE: drop cascades to 4 other objects +DETAIL: drop cascades to table issue_1393._ag_label_vertex +drop cascades to table issue_1393._ag_label_edge +drop cascades to table issue_1393."Object" +drop cascades to table issue_1393.knows +NOTICE: graph "issue_1393" has been dropped + drop_graph +------------ + +(1 row) + -- -- End -- diff --git a/regress/sql/cypher_match.sql b/regress/sql/cypher_match.sql index 483f0ef04..b211439ea 100644 --- a/regress/sql/cypher_match.sql +++ b/regress/sql/cypher_match.sql @@ -561,10 +561,6 @@ SELECT * FROM cypher('cypher_match', $$MATCH (u) RETURN EXISTS((u)-[]->()) $$) AS (exists agtype); -SELECT * FROM cypher('cypher_match', - $$MATCH p=(u)-[e]->(v) RETURN EXISTS((p)) $$) -AS (exists agtype); - SELECT * FROM cypher('cypher_match', $$MATCH (u)-[e]->(v) RETURN EXISTS((u)-[e]->(v)-[e]->(u))$$) AS (exists agtype); @@ -580,6 +576,11 @@ SELECT * FROM cypher('cypher_match', $$MATCH (u)-[e]->(v) WHERE EXISTS((u)-[e]->(x)) RETURN u, e, v $$) AS (u agtype, e agtype, v agtype); +-- path variable not allowed in EXISTS +SELECT * FROM cypher('cypher_match', + $$MATCH p=(u)-[e]->(v) RETURN EXISTS((p)) $$) +AS (exists agtype); + -- -- Tests for EXISTS(property) -- @@ -950,9 +951,9 @@ SELECT * FROM cypher('cypher_match', $$ SELECT * FROM cypher('cypher_match', $$ MATCH (a) RETURN a $$) as (a agtype); SELECT * FROM cypher('cypher_match', $$ - MATCH (a) WHERE exists(a.name) RETURN a $$) as (a agtype); + MATCH (a) WHERE EXISTS(a.name) RETURN a $$) as (a agtype); SELECT * FROM cypher('cypher_match', $$ - MATCH (a) WHERE exists(a.name) SET a.age = 4 RETURN a $$) as (a agtype); + MATCH (a) WHERE EXISTS(a.name) SET a.age = 4 RETURN a $$) as (a agtype); SELECT * FROM cypher('cypher_match', $$ MATCH (a),(b) WHERE a.age = 4 AND a.name = "T" AND b.age = 6 @@ -988,10 +989,10 @@ SELECT * FROM cypher('cypher_match', $$ MATCH (a {name: "orphan"}) MATCH (a {age:3}) RETURN a $$) as (a agtype); SELECT * FROM cypher('cypher_match', $$ - MATCH (a) WHERE exists(a.age) AND exists(a.name) RETURN a $$) as (a agtype); + MATCH (a) WHERE EXISTS(a.age) AND EXISTS(a.name) RETURN a $$) as (a agtype); SELECT * FROM cypher('cypher_match', $$ - MATCH (a) WHERE exists(a.age) AND NOT exists(a.name) RETURN a $$) as (a agtype); + MATCH (a) WHERE EXISTS(a.age) AND NOT EXISTS(a.name) RETURN a $$) as (a agtype); -- check reuse of 'r' clause-to-clause - edges SELECT * FROM cypher('cypher_match', $$ @@ -1185,43 +1186,43 @@ SELECT create_graph('issue_1399'); -- this is an empty graph so these should return 0 SELECT * FROM cypher('issue_1399', $$ MATCH (foo) - WHERE exists((foo)-[]->()) + WHERE EXISTS((foo)-[]->()) RETURN foo $$) as (c agtype); SELECT * FROM cypher('issue_1399', $$ MATCH (foo) - WHERE NOT exists((foo)-[]->()) + WHERE NOT EXISTS((foo)-[]->()) RETURN foo $$) as (c agtype); SELECT * FROM cypher('issue_1399', $$ MATCH (foo) - WHERE exists((foo)-[:BAR]->()) + WHERE EXISTS((foo)-[:BAR]->()) RETURN foo $$) as (c agtype); SELECT * FROM cypher('issue_1399', $$ MATCH (foo) - WHERE NOT exists((foo)-[:BAR]->()) + WHERE NOT EXISTS((foo)-[:BAR]->()) RETURN foo $$) as (c agtype); -- this is an empty graph so these should return false SELECT * FROM cypher('issue_1399', $$ MATCH (foo) - WHERE exists((foo)-[]->()) + WHERE EXISTS((foo)-[]->()) RETURN count(foo) > 0 $$) as (c agtype); SELECT * FROM cypher('issue_1399', $$ MATCH (foo) - WHERE NOT exists((foo)-[]->()) + WHERE NOT EXISTS((foo)-[]->()) RETURN count(foo) > 0 $$) as (c agtype); SELECT * FROM cypher('issue_1399', $$ MATCH (foo) - WHERE exists((foo)-[:BAR]->()) + WHERE EXISTS((foo)-[:BAR]->()) RETURN count(foo) > 0 $$) as (c agtype); SELECT * FROM cypher('issue_1399', $$ MATCH (foo) - WHERE NOT exists((foo)-[:BAR]->()) + WHERE NOT EXISTS((foo)-[:BAR]->()) RETURN count(foo) > 0 $$) as (c agtype); -- create 1 path @@ -1232,37 +1233,155 @@ $$) as (c agtype); -- only one vertex can match. SELECT * FROM cypher('issue_1399', $$ MATCH (foo) - WHERE exists((foo)-[]->()) + WHERE EXISTS((foo)-[]->()) RETURN foo $$) as (c agtype); SELECT * FROM cypher('issue_1399', $$ MATCH (foo) - WHERE NOT exists((foo)-[]->()) + WHERE NOT EXISTS((foo)-[]->()) RETURN foo $$) as (c agtype); SELECT * FROM cypher('issue_1399', $$ MATCH (foo) - WHERE exists((foo)-[:BAR]->()) + WHERE EXISTS((foo)-[:BAR]->()) RETURN foo $$) as (c agtype); SELECT * FROM cypher('issue_1399', $$ MATCH (foo) - WHERE NOT exists((foo)-[:BAR]->()) + WHERE NOT EXISTS((foo)-[:BAR]->()) RETURN foo $$) as (c agtype); -- this should return 0 rows as it can't exist - that path isn't in BAR2 SELECT * FROM cypher('issue_1399', $$ MATCH (foo) - WHERE exists((foo)-[:BAR2]->()) + WHERE EXISTS((foo)-[:BAR2]->()) RETURN foo $$) as (c agtype); -- this should return 2 rows as they all exist SELECT * FROM cypher('issue_1399', $$ MATCH (foo) - WHERE NOT exists((foo)-[:BAR2]->()) + WHERE NOT EXISTS((foo)-[:BAR2]->()) RETURN foo $$) as (c agtype); +-- Issue 1393 EXISTS doesn't see previous clauses' variables +SELECT FROM create_graph('issue_1393'); +SELECT * FROM cypher('issue_1393', $$ + CREATE (n1:Object) RETURN n1 +$$) AS (n1 agtype); +-- vertex cases +SELECT * FROM cypher('issue_1393', $$ + MATCH (n1:Object) MATCH (n2:Object) WHERE EXISTS((n1)-[]->(n2)) RETURN n1,n2 +$$) AS (n1 agtype, n2 agtype); +SELECT * FROM cypher('issue_1393', $$ + MATCH (n1:Object) MATCH (n2:Object) WHERE EXISTS((n1:Object)-[]->(n2:Object)) RETURN n1,n2 +$$) AS (n1 agtype, n2 agtype); +SELECT * FROM cypher('issue_1393', $$ + MATCH (n1:Object) MATCH (n2:Object) WHERE NOT EXISTS((n1)-[]->(n2)) RETURN n1,n2 +$$) AS (n1 agtype, n2 agtype); +SELECT * FROM cypher('issue_1393', $$ + MATCH (n1:Object) MATCH (n2:Object) WHERE NOT EXISTS((n1:Object)-[]->(n2:Object)) RETURN n1,n2 +$$) AS (n1 agtype, n2 agtype); +SELECT * FROM cypher('issue_1393', $$ + MATCH (n1:Object) MATCH (n2:Object) WHERE EXISTS((n1)-[]->()) RETURN n1,n2 +$$) AS (n1 agtype, n2 agtype); +SELECT * FROM cypher('issue_1393', $$ + MATCH (n1:Object) MATCH (n2:Object) WHERE NOT EXISTS((n1)-[]->()) RETURN n1,n2 +$$) AS (n1 agtype, n2 agtype); +SELECT * FROM cypher('issue_1393', $$ + CREATE (n1:Object)-[e:knows]->(n2:Object) RETURN n1, e, n2 +$$) AS (n1 agtype, e agtype, n2 agtype); +SELECT * FROM cypher('issue_1393', $$ + MATCH (n1:Object) MATCH (n2:Object) WHERE EXISTS((n1)-[]->(n2)) RETURN n1,n2 +$$) AS (n1 agtype, n2 agtype); +SELECT * FROM cypher('issue_1393', $$ + MATCH (n1:Object) MATCH (n2:Object) WHERE EXISTS((n1:Object)-[]->(n2:Object)) RETURN n1,n2 +$$) AS (n1 agtype, n2 agtype); +SELECT * FROM cypher('issue_1393', $$ + MATCH (n1:Object) MATCH (n2:Object) WHERE NOT EXISTS((n1)-[]->(n2)) RETURN n1,n2 +$$) AS (n1 agtype, n2 agtype); +SELECT * FROM cypher('issue_1393', $$ + MATCH (n1:Object) MATCH (n2:Object) WHERE NOT EXISTS((n1:Object)-[]->(n2:Object)) RETURN n1,n2 +$$) AS (n1 agtype, n2 agtype); +SELECT * FROM cypher('issue_1393', $$ + MATCH (n1:Object) MATCH (n2:Object) WHERE EXISTS((n1)-[]->()) RETURN n1,n2 +$$) AS (n1 agtype, n2 agtype); +SELECT * FROM cypher('issue_1393', $$ + MATCH (n1:Object) MATCH (n2:Object) WHERE NOT EXISTS((n1)-[]->()) RETURN n1,n2 +$$) AS (n1 agtype, n2 agtype); +SELECT * FROM cypher('issue_1393', $$ + MATCH (n1:Object) MATCH (n2:Object) WHERE EXISTS((n1:Object)-[]->()) RETURN n1,n2 +$$) AS (n1 agtype, n2 agtype); +SELECT * FROM cypher('issue_1393', $$ + MATCH (n1:Object) MATCH (n2:Object) WHERE NOT EXISTS((n1:Object)-[]->()) RETURN n1,n2 +$$) AS (n1 agtype, n2 agtype); +-- should error +SELECT * FROM cypher('issue_1393', $$ + MATCH (n1:Object) MATCH (n2:Object) WHERE EXISTS((n1:object)-[]->()) RETURN n1,n2 +$$) AS (n1 agtype, n2 agtype); +SELECT * FROM cypher('issue_1393', $$ + MATCH (n1:Object) MATCH (n2:Object) WHERE NOT EXISTS((n1:object)-[]->()) RETURN n1,n2 +$$) AS (n1 agtype, n2 agtype); +SELECT * FROM cypher('issue_1393', $$ + MATCH (n1:Object) MATCH (n2:Object) WHERE NOT EXISTS((n1)-[e]->()) RETURN n1,n2,e +$$) AS (n1 agtype, n2 agtype, e agtype); +-- edge cases +SELECT * FROM cypher('issue_1393', $$ + MATCH (n1:Object)-[e1:knows]->() MATCH (n2:Object) WHERE EXISTS((n1)-[e1]->(n2)) RETURN e1 +$$) AS (e1 agtype); +SELECT * FROM cypher('issue_1393', $$ + MATCH (n1:Object)-[e1:knows]->() MATCH (n2:Object) WHERE EXISTS((n1:Object)-[e1:knows]->(n2:Object)) RETURN e1 +$$) AS (e1 agtype); +SELECT * FROM cypher('issue_1393', $$ + MATCH (n1:Object)-[e1:knows]->() MATCH (n2:Object) WHERE NOT EXISTS((n1)-[e1]->(n2)) RETURN e1 +$$) AS (e1 agtype); +SELECT * FROM cypher('issue_1393', $$ + MATCH (n1:Object)-[e1:knows]->() MATCH (n2:Object) WHERE NOT EXISTS((n1:Object)-[e1:knows]->(n2:Object)) RETURN e1 +$$) AS (e1 agtype); +SELECT * FROM cypher('issue_1393', $$ + MATCH (n1:Object)-[e1:knows]->() MATCH (n2:Object) WHERE EXISTS((n1)-[e1]->()) RETURN e1 +$$) AS (e1 agtype); +SELECT * FROM cypher('issue_1393', $$ + MATCH (n1:Object)-[e1:knows]->() MATCH (n2:Object) WHERE EXISTS((n1:Object)-[e1:knows]->(n2:Object)) RETURN e1 +$$) AS (e1 agtype); +SELECT * FROM cypher('issue_1393', $$ + MATCH (n1:Object)-[e1:knows]->() MATCH (n2:Object) WHERE NOT EXISTS((n1)-[e1]->()) RETURN e1 +$$) AS (e1 agtype); +SELECT * FROM cypher('issue_1393', $$ + MATCH (n1:Object)-[e1:knows]->() MATCH (n2:Object) WHERE NOT EXISTS((n1:Object)-[e1:knows]->(n2:Object)) RETURN e1 +$$) AS (e1 agtype); +-- should error +SELECT * FROM cypher('issue_1393', $$ + MATCH (n1:Object)-[e1:knows]->() MATCH (n2:Object) WHERE EXISTS((n1:Object)-[e1:Knows]->(n2:Object)) RETURN e1 +$$) AS (e1 agtype); +SELECT * FROM cypher('issue_1393', $$ + MATCH (n1:Object)-[e1:knows]->() MATCH (n2:Object) WHERE NOT EXISTS((n1:Object)-[e1:Knows]->(n2:Object)) RETURN e1 +$$) AS (e1 agtype); +SELECT * FROM cypher('issue_1393', $$ + MATCH (n1:Object)-[e1:knows]->() MATCH (n2:Object) WHERE EXISTS((e1:Object)-[e1:Knows]->(n2:Object)) RETURN e1 +$$) AS (e1 agtype); +SELECT * FROM cypher('issue_1393', $$ + MATCH (n1:Object)-[e1:knows]->() MATCH (n2:Object) WHERE NOT EXISTS((n1:Object)-[e1:knows]->(e1)) RETURN e1 +$$) AS (e1 agtype); +SELECT * FROM cypher('issue_1393', $$ + MATCH (n1:Object)-[e1:knows]->() MATCH (n2:Object) WHERE NOT EXISTS((n1:Object)-[e1:knows]->(e2)) RETURN e1 +$$) AS (e1 agtype); +SELECT * FROM cypher('issue_1393', $$ + MATCH p=(n1:Object)-[e1:knows]->() MATCH (n2:Object) WHERE EXISTS((n1:Object)-[p]->(e2)) RETURN e1 +$$) AS (e1 agtype); +SELECT * FROM cypher('issue_1393', $$ + MATCH p=(n1)-[e1]->() MATCH (n2) WHERE EXISTS((n1)-[p]->(e2)) RETURN p +$$) AS (e1 agtype); +-- long cases +SELECT * FROM cypher('issue_1393', $$ + MATCH (n1) MATCH (n2) MATCH (n1)-[e1]->() MATCH (n2)<-[e2]-(n1) MATCH (n3) + WHERE EXISTS((n3)-[e1]->(n2)) RETURN n1,n2,n3,e1 +$$) AS (n1 agtype, n2 agtype, n3 agtype, e1 agtype); +SELECT * FROM cypher('issue_1393', $$ + MATCH (n1:Object) MATCH (n2:Object) MATCH (n1)-[e1:knows]->() MATCH (n2)<-[e2:knows]-(n1) MATCH (n3:Object) + WHERE EXISTS((n3:Object)-[e1:knows]->(n2:Object)) RETURN n1,n2,n3,e1 +$$) AS (n1 agtype, n2 agtype, n3 agtype, e1 agtype); + -- -- Clean up -- @@ -1271,6 +1390,7 @@ SELECT drop_graph('test_retrieve_var', true); SELECT drop_graph('test_enable_containment', true); SELECT drop_graph('issue_945', true); SELECT drop_graph('issue_1399', true); +SELECT drop_graph('issue_1393', true); -- -- End diff --git a/src/backend/parser/cypher_clause.c b/src/backend/parser/cypher_clause.c index e60fc2813..ba51d5fed 100644 --- a/src/backend/parser/cypher_clause.c +++ b/src/backend/parser/cypher_clause.c @@ -4638,6 +4638,7 @@ static Expr *transform_cypher_edge(cypher_parsestate *cpstate, transform_entity *entity = NULL; cypher_relationship *cr = NULL; Node *expr = NULL; + Var *previous_clause_var = NULL; bool refs_var = false; ParseNamespaceItem *pnsi = NULL; @@ -4649,14 +4650,16 @@ static Expr *transform_cypher_edge(cypher_parsestate *cpstate, { te = findTarget(*target_list, rel->name); entity = find_variable(cpstate, rel->name); - expr = colNameToVar(pstate, rel->name, false, rel->location); + previous_clause_var = (Var *)colNameToVar(pstate, rel->name, false, + rel->location); /* * If we have a valid entity and te for this rel name, go ahead and get * the cypher relationship as we will need this for later and flag that * we have a variable reference. */ - if (te != NULL && entity != NULL) + if ((te != NULL && entity != NULL) || + (entity != NULL && previous_clause_var != NULL)) { cr = (cypher_relationship *)entity->entity.rel; refs_var = true; @@ -4679,7 +4682,8 @@ static Expr *transform_cypher_edge(cypher_parsestate *cpstate, errmsg("variable '%s' is for a VLE edge", rel->name), parser_errposition(pstate, rel->location))); } - else if (entity->type == ENT_PATH) + else if (entity->type == ENT_PATH && + pstate->p_expr_kind != EXPR_KIND_SELECT_TARGET) { ereport(ERROR, (errcode(ERRCODE_DUPLICATE_ALIAS), @@ -4752,7 +4756,7 @@ static Expr *transform_cypher_edge(cypher_parsestate *cpstate, * Variables for edges are not allowed to be used multiple times within the * same clause. */ - if (expr == NULL && refs_var) + if (previous_clause_var == NULL && refs_var) { ereport(ERROR, (errcode(ERRCODE_DUPLICATE_ALIAS), @@ -4795,9 +4799,15 @@ static Expr *transform_cypher_edge(cypher_parsestate *cpstate, * If expr_kind is WHERE, the expressions are in the parent's * parent's parsestate, due to the way we transform sublinks. */ - transform_entity *tentity = find_variable(parent_cpstate, - rel->name); + transform_entity *tentity = NULL; + /* if we have the referenced var, just return it */ + if (previous_clause_var != NULL) + { + return (Expr *)previous_clause_var; + } + + tentity = find_variable(parent_cpstate, rel->name); if (tentity != NULL) { return get_relative_expr(tentity, 2); @@ -4814,13 +4824,7 @@ static Expr *transform_cypher_edge(cypher_parsestate *cpstate, /* if this vertex is referencing an existing te var, return its expr */ if (refs_var) { - return te->expr; - } - - /* if this vertex is referencing an existing col var, return its expr */ - if (expr != NULL) - { - return (Expr *)expr; + return (te != NULL) ? te->expr : (Expr *)previous_clause_var; } } @@ -4889,20 +4893,25 @@ static Expr *transform_cypher_node(cypher_parsestate *cpstate, transform_entity *entity = NULL; cypher_node *cn = NULL; bool refs_var = false; - ParseNamespaceItem *pnsi; + ParseNamespaceItem *pnsi = NULL; + Var *previous_clause_var = NULL; /* if we have a node name, get any potential variable references */ if (node->name != NULL) { te = findTarget(*target_list, node->name); entity = find_variable(cpstate, node->name); + previous_clause_var = (Var *)colNameToVar(pstate, node->name, false, + node->location); /* - * If we have a valid entity and te for this rel name, go ahead and get - * the cypher relationship as we will need this for later and flag that - * we have a variable reference. + * If we have a valid entity and te or a valid entity and a previous var + * ref for this rel name, go ahead and get the cypher relationship. We + * will need this information for later. Additionally, flag that we have + * a variable reference. */ - if (te != NULL && entity != NULL) + if ((te != NULL && entity != NULL) || + (entity != NULL && previous_clause_var != NULL)) { cn = (cypher_node *)entity->entity.node; refs_var = true; @@ -4925,13 +4934,25 @@ static Expr *transform_cypher_node(cypher_parsestate *cpstate, errmsg("variable '%s' is for a VLE edge", node->name), parser_errposition(pstate, node->location))); } - else if (entity->type == ENT_PATH) + /* gets non EXISTS cases */ + else if (entity->type == ENT_PATH && + pstate->p_expr_kind != EXPR_KIND_SELECT_TARGET) { ereport(ERROR, (errcode(ERRCODE_DUPLICATE_ALIAS), errmsg("variable '%s' is for a path", node->name), parser_errposition(pstate, node->location))); } + /* gets EXISTS cases */ + else if (entity->type == ENT_PATH && + pstate->p_expr_kind == EXPR_KIND_SELECT_TARGET) + { + ereport(ERROR, + (errcode(ERRCODE_DUPLICATE_ALIAS), + errmsg("a path variable '%s' is not allowed here", + node->name), + parser_errposition(pstate, node->location))); + } } /* If their is a te but no entity, it implies that their is @@ -5040,6 +5061,12 @@ static Expr *transform_cypher_node(cypher_parsestate *cpstate, */ transform_entity *tentity = NULL; + /* if we have the referenced var, just return it */ + if (previous_clause_var != NULL) + { + return (Expr *)previous_clause_var; + } + tentity = find_variable(parent_cpstate, node->name); if (tentity != NULL) { @@ -5054,10 +5081,10 @@ static Expr *transform_cypher_node(cypher_parsestate *cpstate, } } - /* if this vertex is referencing an existing te var, return its expr */ + /* if this vertex is referencing an existing var, return its expr */ if (refs_var) { - return te->expr; + return (te != NULL) ? te->expr : (Expr *)previous_clause_var; } /* if this vertex is referencing an existing col var, return its expr */