This is an automated email from the ASF dual-hosted git repository.
dehowef pushed a commit to branch PG14
in repository https://gitbox.apache.org/repos/asf/age.git
The following commit(s) were added to refs/heads/PG14 by this push:
new a118485f Fix issue 1393 - previous clause variables not seen with
EXISTS (#1426) (#1427)
a118485f is described below
commit a118485f0cd48fbd98e9b917c83d74e81e1f37ee
Author: John Gemignani <[email protected]>
AuthorDate: Tue Nov 28 17:00:49 2023 -0800
Fix issue 1393 - previous clause variables not seen with EXISTS (#1426)
(#1427)
Fixed issue 1393 - Unexpected error when matching nodes that are
connected to nodes resulted from a previous MATCH clause.
Basically, variables from the previous clauses where not seen when
using the EXISTS clause for path pattern matches. This only affected
EXISTS and only for the EXISTS (anonymous_path) grammar component.
The original issue was only with vertices, but this also affected
edges. Both cases are now fixed.
Fixed 1 regression test that was incorrect.
Added regression tests.
---
regress/expected/cypher_match.out | 379 +++++++++++++++++++++++++++++++++----
regress/sql/cypher_match.sql | 164 +++++++++++++---
src/backend/parser/cypher_clause.c | 69 +++++--
3 files changed, 537 insertions(+), 75 deletions(-)
diff --git a/regress/expected/cypher_match.out
b/regress/expected/cypher_match.out
index 8c427497..cef6dad9 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 483f0ef0..b211439e 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 dbae2704..6485fcff 100644
--- a/src/backend/parser/cypher_clause.c
+++ b/src/backend/parser/cypher_clause.c
@@ -4637,6 +4637,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;
@@ -4648,14 +4649,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;
@@ -4678,7 +4681,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),
@@ -4751,7 +4755,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),
@@ -4794,9 +4798,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);
@@ -4813,13 +4823,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;
}
}
@@ -4888,20 +4892,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;
@@ -4924,13 +4933,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
@@ -5039,6 +5060,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)
{
@@ -5053,10 +5080,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
*/