This is an automated email from the ASF dual-hosted git repository.
dehowef pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/age.git
The following commit(s) were added to refs/heads/master by this push:
new 0ef2dc27 Fix property constraints against resolved variables (#724)
(#751)
0ef2dc27 is described below
commit 0ef2dc27a0b4c328f819077a8c8c26ae2c0fb4de
Author: John Gemignani <[email protected]>
AuthorDate: Wed Mar 22 10:08:57 2023 -0700
Fix property constraints against resolved variables (#724) (#751)
Fixed an issue where an already resolved variable, when used for
a property constraint, errored out. See #724 for more details.
This is the second part of the fix for the match property constraint
bug regarding variable reuse. The prior fix addressed clause-to-clause,
this fix addresses within a clause.
Adjusted and added additional regression tests.
Co-authored-by: Dehowe Feng <[email protected]>
---
regress/expected/cypher_match.out | 118 +++++++++++++++++++++++++++++++++----
regress/sql/cypher_match.sql | 40 ++++++++++---
src/backend/parser/cypher_clause.c | 68 ++++++++++++++-------
3 files changed, 186 insertions(+), 40 deletions(-)
diff --git a/regress/expected/cypher_match.out
b/regress/expected/cypher_match.out
index f3817a50..0e596406 100644
--- a/regress/expected/cypher_match.out
+++ b/regress/expected/cypher_match.out
@@ -502,25 +502,45 @@ SELECT * FROM cypher('cypher_match', $$MATCH (n:v)$$) AS
(a agtype);
ERROR: syntax error at end of input
LINE 1: SELECT * FROM cypher('cypher_match', $$MATCH (n:v)$$) AS (a ...
^
---Invalid Variables
+--invalid variable reuse, these should fail
SELECT * FROM cypher('cypher_match', $$
MATCH (a)-[]-()-[]-(a:v1) RETURN a
$$) AS (a agtype);
-ERROR: variable a already exists
+ERROR: multiple labels for variable 'a' are not supported
LINE 2: MATCH (a)-[]-()-[]-(a:v1) RETURN a
^
+SELECT * FROM cypher('cypher_match', $$
+ MATCH (a)-[]-(a:v2)-[]-(a) RETURN a
+$$) AS (a agtype);
+ERROR: multiple labels for variable 'a' are not supported
+LINE 2: MATCH (a)-[]-(a:v2)-[]-(a) RETURN a
+ ^
+SELECT * FROM cypher('cypher_match', $$
+ MATCH (a)-[]-(a:v1) RETURN a
+$$) AS (a agtype);
+ERROR: multiple labels for variable 'a' are not supported
+LINE 2: MATCH (a)-[]-(a:v1) RETURN a
+ ^
+SELECT * FROM cypher('cypher_match', $$
+ MATCH (a)-[]-(a)-[]-(a:v1) RETURN a
+$$) AS (a agtype);
+ERROR: multiple labels for variable 'a' are not supported
+LINE 2: MATCH (a)-[]-(a)-[]-(a:v1) RETURN a
+ ^
+--Valid variable reuse, although why would you want to do it this way?
SELECT * FROM cypher('cypher_match', $$
MATCH (a:v1)-[]-()-[a]-() RETURN a
$$) AS (a agtype);
-ERROR: variable a already exists
+ERROR: variable 'a' is for a vertex
LINE 2: MATCH (a:v1)-[]-()-[a]-() RETURN a
^
SELECT * FROM cypher('cypher_match', $$
- MATCH (a:v1)-[]-()-[]-(a {id:'will_fail'}) RETURN a
+ MATCH (a:v1)-[]-()-[]-(a {id:'will_not_fail'}) RETURN a
$$) AS (a agtype);
-ERROR: variable a already exists
-LINE 2: MATCH (a:v1)-[]-()-[]-(a {id:'will_fail'}) RETURN a
- ^
+ a
+---
+(0 rows)
+
--Incorrect Labels
SELECT * FROM cypher('cypher_match', $$MATCH (n)-[:v]-() RETURN n$$) AS (n
agtype);
n
@@ -1509,14 +1529,14 @@ SELECT * FROM cypher('cypher_match', $$
(1 row)
SELECT * FROM cypher('cypher_match', $$
- MATCH (a),(b) WHERE a.age = 4 AND a.name = "T" AND b.age = 6 CREATE
+ MATCH (a),(b) WHERE a.age = 4 AND a.name = "T" AND b.age = 6 CREATE
(a)-[:knows {relationship: "friends", years: 3}]->(b) $$) as (r agtype);
r
---
(0 rows)
SELECT * FROM cypher('cypher_match', $$
- MATCH (a),(b) WHERE a.age = 4 AND a.name = "orphan" AND b.age = 6
CREATE
+ MATCH (a),(b) WHERE a.age = 4 AND a.name = "orphan" AND b.age = 6 CREATE
(a)-[:knows {relationship: "enemies", years: 4}]->(b) $$) as (r agtype);
r
---
@@ -1534,7 +1554,7 @@ SELECT * FROM cypher('cypher_match', $$
{"id": 1407374883553283, "label": "e1", "end_id": 281474976710661,
"start_id": 281474976710660, "properties": {}}::edge
(6 rows)
--- check reuse of 'a'
+-- check reuse of 'a' clause-to-clause - vertices
SELECT * FROM cypher('cypher_match', $$
MATCH (a {age:4}) RETURN a $$) as (a agtype);
a
@@ -1614,7 +1634,7 @@ SELECT * FROM cypher('cypher_match', $$
{"id": 281474976710666, "label": "", "properties": {"age": 6}}::vertex
(2 rows)
--- check reuse of 'r'
+-- check reuse of 'r' clause-to-clause - edges
SELECT * FROM cypher('cypher_match', $$
MATCH ()-[r]-() RETURN r $$) as (r agtype);
r
@@ -1672,6 +1692,82 @@ SELECT * FROM cypher('cypher_match', $$
---
(0 rows)
+-- check reuse within clause - vertices
+SELECT * FROM cypher('cypher_match', $$ CREATE (u {name:
"Dave"})-[:knows]->({name: "John"})-[:knows]->(u) RETURN u $$) as (u agtype);
+ u
+------------------------------------------------------------------------------
+ {"id": 281474976710667, "label": "", "properties": {"name": "Dave"}}::vertex
+(1 row)
+
+SELECT * FROM cypher('cypher_match', $$ MATCH p=(u)-[]-()-[]-(u) RETURN p
$$)as (p agtype);
+
p
+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
+ [{"id": 281474976710667, "label": "", "properties": {"name":
"Dave"}}::vertex, {"id": 4785074604081155, "label": "knows", "end_id":
281474976710667, "start_id": 281474976710668, "properties": {}}::edge, {"id":
281474976710668, "label": "", "properties": {"name": "John"}}::vertex, {"id":
4785074604081156, "label": "knows", "end_id": 281474976710668, "start_id":
281474976710667, "properties": {}}::edge, {"id": 281474976710667, "label": "",
"properties": {"name": "Dave"}}::vertex]::path
+ [{"id": 281474976710668, "label": "", "properties": {"name":
"John"}}::vertex, {"id": 4785074604081155, "label": "knows", "end_id":
281474976710667, "start_id": 281474976710668, "properties": {}}::edge, {"id":
281474976710667, "label": "", "properties": {"name": "Dave"}}::vertex, {"id":
4785074604081156, "label": "knows", "end_id": 281474976710668, "start_id":
281474976710667, "properties": {}}::edge, {"id": 281474976710668, "label": "",
"properties": {"name": "John"}}::vertex]::path
+ [{"id": 281474976710667, "label": "", "properties": {"name":
"Dave"}}::vertex, {"id": 4785074604081156, "label": "knows", "end_id":
281474976710668, "start_id": 281474976710667, "properties": {}}::edge, {"id":
281474976710668, "label": "", "properties": {"name": "John"}}::vertex, {"id":
4785074604081155, "label": "knows", "end_id": 281474976710667, "start_id":
281474976710668, "properties": {}}::edge, {"id": 281474976710667, "label": "",
"properties": {"name": "Dave"}}::vertex]::path
+ [{"id": 281474976710668, "label": "", "properties": {"name":
"John"}}::vertex, {"id": 4785074604081156, "label": "knows", "end_id":
281474976710668, "start_id": 281474976710667, "properties": {}}::edge, {"id":
281474976710667, "label": "", "properties": {"name": "Dave"}}::vertex, {"id":
4785074604081155, "label": "knows", "end_id": 281474976710667, "start_id":
281474976710668, "properties": {}}::edge, {"id": 281474976710668, "label": "",
"properties": {"name": "John"}}::vertex]::path
+(4 rows)
+
+SELECT * FROM cypher('cypher_match', $$ MATCH p=(u)-[]->()-[]->(u) RETURN p
$$)as (p agtype);
+
p
+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
+ [{"id": 281474976710668, "label": "", "properties": {"name":
"John"}}::vertex, {"id": 4785074604081155, "label": "knows", "end_id":
281474976710667, "start_id": 281474976710668, "properties": {}}::edge, {"id":
281474976710667, "label": "", "properties": {"name": "Dave"}}::vertex, {"id":
4785074604081156, "label": "knows", "end_id": 281474976710668, "start_id":
281474976710667, "properties": {}}::edge, {"id": 281474976710668, "label": "",
"properties": {"name": "John"}}::vertex]::path
+ [{"id": 281474976710667, "label": "", "properties": {"name":
"Dave"}}::vertex, {"id": 4785074604081156, "label": "knows", "end_id":
281474976710668, "start_id": 281474976710667, "properties": {}}::edge, {"id":
281474976710668, "label": "", "properties": {"name": "John"}}::vertex, {"id":
4785074604081155, "label": "knows", "end_id": 281474976710667, "start_id":
281474976710668, "properties": {}}::edge, {"id": 281474976710667, "label": "",
"properties": {"name": "Dave"}}::vertex]::path
+(2 rows)
+
+SELECT * FROM cypher('cypher_match', $$ MATCH p=(a)-[]->()-[]->(a {name:
"Dave"}) RETURN p $$)as (p agtype);
+
p
+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
+ [{"id": 281474976710667, "label": "", "properties": {"name":
"Dave"}}::vertex, {"id": 4785074604081156, "label": "knows", "end_id":
281474976710668, "start_id": 281474976710667, "properties": {}}::edge, {"id":
281474976710668, "label": "", "properties": {"name": "John"}}::vertex, {"id":
4785074604081155, "label": "knows", "end_id": 281474976710667, "start_id":
281474976710668, "properties": {}}::edge, {"id": 281474976710667, "label": "",
"properties": {"name": "Dave"}}::vertex]::path
+(1 row)
+
+SELECT * FROM cypher('cypher_match', $$ MATCH p=(a)-[]->()-[]->(a {name:
"John"}) RETURN p $$)as (p agtype);
+
p
+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
+ [{"id": 281474976710668, "label": "", "properties": {"name":
"John"}}::vertex, {"id": 4785074604081155, "label": "knows", "end_id":
281474976710667, "start_id": 281474976710668, "properties": {}}::edge, {"id":
281474976710667, "label": "", "properties": {"name": "Dave"}}::vertex, {"id":
4785074604081156, "label": "knows", "end_id": 281474976710668, "start_id":
281474976710667, "properties": {}}::edge, {"id": 281474976710668, "label": "",
"properties": {"name": "John"}}::vertex]::path
+(1 row)
+
+SELECT * FROM cypher('cypher_match', $$ MATCH p=(a {name:
"Dave"})-[]->()-[]->(a {name: "Dave"}) RETURN p $$)as (p agtype);
+
p
+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
+ [{"id": 281474976710667, "label": "", "properties": {"name":
"Dave"}}::vertex, {"id": 4785074604081156, "label": "knows", "end_id":
281474976710668, "start_id": 281474976710667, "properties": {}}::edge, {"id":
281474976710668, "label": "", "properties": {"name": "John"}}::vertex, {"id":
4785074604081155, "label": "knows", "end_id": 281474976710667, "start_id":
281474976710668, "properties": {}}::edge, {"id": 281474976710667, "label": "",
"properties": {"name": "Dave"}}::vertex]::path
+(1 row)
+
+SELECT * FROM cypher('cypher_match', $$ MATCH p=(a {name:
"John"})-[]->()-[]->(a {name: "John"}) RETURN p $$)as (p agtype);
+
p
+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
+ [{"id": 281474976710668, "label": "", "properties": {"name":
"John"}}::vertex, {"id": 4785074604081155, "label": "knows", "end_id":
281474976710667, "start_id": 281474976710668, "properties": {}}::edge, {"id":
281474976710667, "label": "", "properties": {"name": "Dave"}}::vertex, {"id":
4785074604081156, "label": "knows", "end_id": 281474976710668, "start_id":
281474976710667, "properties": {}}::edge, {"id": 281474976710668, "label": "",
"properties": {"name": "John"}}::vertex]::path
+(1 row)
+
+SELECT * FROM cypher('cypher_match', $$ MATCH p=(a {name:
"Dave"})-[]->()-[]->(a) RETURN p $$)as (p agtype);
+
p
+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
+ [{"id": 281474976710667, "label": "", "properties": {"name":
"Dave"}}::vertex, {"id": 4785074604081156, "label": "knows", "end_id":
281474976710668, "start_id": 281474976710667, "properties": {}}::edge, {"id":
281474976710668, "label": "", "properties": {"name": "John"}}::vertex, {"id":
4785074604081155, "label": "knows", "end_id": 281474976710667, "start_id":
281474976710668, "properties": {}}::edge, {"id": 281474976710667, "label": "",
"properties": {"name": "Dave"}}::vertex]::path
+(1 row)
+
+SELECT * FROM cypher('cypher_match', $$ MATCH p=(a {name:
"John"})-[]->()-[]->(a) RETURN p $$)as (p agtype);
+
p
+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
+ [{"id": 281474976710668, "label": "", "properties": {"name":
"John"}}::vertex, {"id": 4785074604081155, "label": "knows", "end_id":
281474976710667, "start_id": 281474976710668, "properties": {}}::edge, {"id":
281474976710667, "label": "", "properties": {"name": "Dave"}}::vertex, {"id":
4785074604081156, "label": "knows", "end_id": 281474976710668, "start_id":
281474976710667, "properties": {}}::edge, {"id": 281474976710668, "label": "",
"properties": {"name": "John"}}::vertex]::path
+(1 row)
+
+-- these are illegal and should fail
+SELECT * FROM cypher('cypher_match', $$ MATCH p=(a)-[b]->()-[b]->(a) RETURN p
$$)as (p agtype);
+ERROR: duplicate edge variable 'b' within a clause
+LINE 1: ...ROM cypher('cypher_match', $$ MATCH p=(a)-[b]->()-[b]->(a) R...
+ ^
+SELECT * FROM cypher('cypher_match', $$ MATCH p=(a)-[b]->()-[b:knows]->(a)
RETURN p $$)as (p agtype);
+ERROR: duplicate edge variable 'b' within a clause
+LINE 1: ...ROM cypher('cypher_match', $$ MATCH p=(a)-[b]->()-[b:knows]-...
+ ^
+SELECT * FROM cypher('cypher_match', $$ MATCH
p=(a)-[b:knows]->()-[b:knows]->(a) RETURN p $$)as (p agtype);
+ERROR: duplicate edge variable 'b' within a clause
+LINE 1: ...pher('cypher_match', $$ MATCH p=(a)-[b:knows]->()-[b:knows]-...
+ ^
+SELECT * FROM cypher('cypher_match', $$ MATCH p=(a)-[b:knows]->()-[b]->(a)
RETURN p $$)as (p agtype);
+ERROR: duplicate edge variable 'b' within a clause
+LINE 1: ...pher('cypher_match', $$ MATCH p=(a)-[b:knows]->()-[b]->(a) R...
+ ^
--
-- Clean up
--
diff --git a/regress/sql/cypher_match.sql b/regress/sql/cypher_match.sql
index f08f8dfb..b05e79c5 100644
--- a/regress/sql/cypher_match.sql
+++ b/regress/sql/cypher_match.sql
@@ -271,17 +271,27 @@ EXECUTE property_ps(agtype_build_map('props',
-- need a following RETURN clause (should fail)
SELECT * FROM cypher('cypher_match', $$MATCH (n:v)$$) AS (a agtype);
---Invalid Variables
+--invalid variable reuse, these should fail
SELECT * FROM cypher('cypher_match', $$
MATCH (a)-[]-()-[]-(a:v1) RETURN a
$$) AS (a agtype);
+SELECT * FROM cypher('cypher_match', $$
+ MATCH (a)-[]-(a:v2)-[]-(a) RETURN a
+$$) AS (a agtype);
+SELECT * FROM cypher('cypher_match', $$
+ MATCH (a)-[]-(a:v1) RETURN a
+$$) AS (a agtype);
+SELECT * FROM cypher('cypher_match', $$
+ MATCH (a)-[]-(a)-[]-(a:v1) RETURN a
+$$) AS (a agtype);
+--Valid variable reuse, although why would you want to do it this way?
SELECT * FROM cypher('cypher_match', $$
MATCH (a:v1)-[]-()-[a]-() RETURN a
$$) AS (a agtype);
SELECT * FROM cypher('cypher_match', $$
- MATCH (a:v1)-[]-()-[]-(a {id:'will_fail'}) RETURN a
+ MATCH (a:v1)-[]-()-[]-(a {id:'will_not_fail'}) RETURN a
$$) AS (a agtype);
--Incorrect Labels
@@ -750,20 +760,19 @@ SELECT * FROM cypher('cypher_match', $$
SELECT * FROM cypher('cypher_match', $$
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
RETURN a,b $$) as (a agtype, b agtype);
SELECT * FROM cypher('cypher_match', $$
- MATCH (a),(b) WHERE a.age = 4 AND a.name = "T" AND b.age = 6 CREATE
+ MATCH (a),(b) WHERE a.age = 4 AND a.name = "T" AND b.age = 6 CREATE
(a)-[:knows {relationship: "friends", years: 3}]->(b) $$) as (r agtype);
SELECT * FROM cypher('cypher_match', $$
- MATCH (a),(b) WHERE a.age = 4 AND a.name = "orphan" AND b.age = 6
CREATE
+ MATCH (a),(b) WHERE a.age = 4 AND a.name = "orphan" AND b.age = 6 CREATE
(a)-[:knows {relationship: "enemies", years: 4}]->(b) $$) as (r agtype);
SELECT * FROM cypher('cypher_match', $$
MATCH (a)-[r]-(b) RETURN r $$) as (r agtype);
--- check reuse of 'a'
+-- check reuse of 'a' clause-to-clause - vertices
SELECT * FROM cypher('cypher_match', $$
MATCH (a {age:4}) RETURN a $$) as (a agtype);
SELECT * FROM cypher('cypher_match', $$
@@ -790,7 +799,7 @@ SELECT * FROM cypher('cypher_match', $$
SELECT * FROM cypher('cypher_match', $$
MATCH (a) WHERE exists(a.age) AND NOT exists(a.name) RETURN a $$) as (a
agtype);
--- check reuse of 'r'
+-- check reuse of 'r' clause-to-clause - edges
SELECT * FROM cypher('cypher_match', $$
MATCH ()-[r]-() RETURN r $$) as (r agtype);
SELECT * FROM cypher('cypher_match', $$
@@ -807,6 +816,23 @@ SELECT * FROM cypher('cypher_match', $$
SELECT * FROM cypher('cypher_match', $$
MATCH ()-[r {relationship:"enemies"}]-() MATCH ()-[r
{relationship:"friends"}]-() RETURN r $$) as (r agtype);
+-- check reuse within clause - vertices
+SELECT * FROM cypher('cypher_match', $$ CREATE (u {name:
"Dave"})-[:knows]->({name: "John"})-[:knows]->(u) RETURN u $$) as (u agtype);
+SELECT * FROM cypher('cypher_match', $$ MATCH p=(u)-[]-()-[]-(u) RETURN p
$$)as (p agtype);
+SELECT * FROM cypher('cypher_match', $$ MATCH p=(u)-[]->()-[]->(u) RETURN p
$$)as (p agtype);
+SELECT * FROM cypher('cypher_match', $$ MATCH p=(a)-[]->()-[]->(a {name:
"Dave"}) RETURN p $$)as (p agtype);
+SELECT * FROM cypher('cypher_match', $$ MATCH p=(a)-[]->()-[]->(a {name:
"John"}) RETURN p $$)as (p agtype);
+SELECT * FROM cypher('cypher_match', $$ MATCH p=(a {name:
"Dave"})-[]->()-[]->(a {name: "Dave"}) RETURN p $$)as (p agtype);
+SELECT * FROM cypher('cypher_match', $$ MATCH p=(a {name:
"John"})-[]->()-[]->(a {name: "John"}) RETURN p $$)as (p agtype);
+SELECT * FROM cypher('cypher_match', $$ MATCH p=(a {name:
"Dave"})-[]->()-[]->(a) RETURN p $$)as (p agtype);
+SELECT * FROM cypher('cypher_match', $$ MATCH p=(a {name:
"John"})-[]->()-[]->(a) RETURN p $$)as (p agtype);
+
+-- these are illegal and should fail
+SELECT * FROM cypher('cypher_match', $$ MATCH p=(a)-[b]->()-[b]->(a) RETURN p
$$)as (p agtype);
+SELECT * FROM cypher('cypher_match', $$ MATCH p=(a)-[b]->()-[b:knows]->(a)
RETURN p $$)as (p agtype);
+SELECT * FROM cypher('cypher_match', $$ MATCH
p=(a)-[b:knows]->()-[b:knows]->(a) RETURN p $$)as (p agtype);
+SELECT * FROM cypher('cypher_match', $$ MATCH p=(a)-[b:knows]->()-[b]->(a)
RETURN p $$)as (p agtype);
+
--
-- Clean up
--
diff --git a/src/backend/parser/cypher_clause.c
b/src/backend/parser/cypher_clause.c
index 01b33605..ad876d8c 100644
--- a/src/backend/parser/cypher_clause.c
+++ b/src/backend/parser/cypher_clause.c
@@ -4352,20 +4352,29 @@ static Expr *transform_cypher_edge(cypher_parsestate
*cpstate,
transform_entity *entity = find_variable(cpstate, rel->name);
/*
- * TODO: openCypher allows a variable to be used before it
- * is properly declared. This logic is not satifactory
- * for that and must be better developed.
+ * If the variable already exists, verify that it is for an edge.
+ * You cannot have the same edge repeated in a path.
+ * You cannot have an variable that is for a vertex.
*/
- if (entity != NULL &&
- (entity->type != ENT_EDGE ||
- !IS_DEFAULT_LABEL_EDGE(rel->label) ||
- rel->props))
+ if (entity != NULL)
{
- ereport(ERROR,
- (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
- errmsg("variable %s already exists", rel->name),
- parser_errposition(pstate, rel->location)));
+ if (entity->type == ENT_EDGE)
+ {
+ ereport(ERROR,
+ (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
+ errmsg("duplicate edge variable '%s' within a
clause",
+ rel->name),
+ parser_errposition(pstate, rel->location)));
+ }
+ if (entity->type == ENT_VERTEX)
+ {
+ ereport(ERROR,
+ (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
+ errmsg("variable '%s' is for a vertex",
rel->name),
+ parser_errposition(pstate, rel->location)));
+ }
}
+
return te->expr;
}
}
@@ -4444,7 +4453,7 @@ static Expr *transform_cypher_node(cypher_parsestate
*cpstate,
* segmentation faults, and other errors.
*
* Update: Nonexistent and mismatched labels now return a NULL value
to
- * prevent segmentation faults, and other errors. We can also
consider
+ * prevent segmentation faults, and other errors. We can also consider
* if an all-purpose label would be useful.
*/
node->label = NULL;
@@ -4501,22 +4510,37 @@ static Expr *transform_cypher_node(cypher_parsestate
*cpstate,
{
transform_entity *entity = find_variable(cpstate, node->name);
- /*
- * TODO: openCypher allows a variable to be used before it
- * is properly declared. This logic is not satifactory
- * for that and must be better developed.
- */
- if (entity != NULL &&
- (entity->type != ENT_VERTEX ||
- !IS_DEFAULT_LABEL_VERTEX(node->label) ||
- node->props))
+ /* If the variable already exists, verify that it is for a vertex
*/
+ if (entity != NULL && (entity->type != ENT_VERTEX))
{
ereport(ERROR,
(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
- errmsg("variable %s already exists", node->name),
+ errmsg("variable '%s' is for a edge", node->name),
parser_errposition(pstate, node->location)));
}
+ /*
+ * If the variable already exists, verify that any label specified
+ * is of the same name or scope. Reject those that aren't.
+ */
+ if (entity != NULL)
+ {
+ cypher_node *cnode = (cypher_node *)entity->entity.node;
+
+ if (cnode != NULL &&
+ node != NULL &&
+ /* allow node using a default label against resolved var */
+ pg_strcasecmp(node->label, AG_DEFAULT_LABEL_VERTEX) != 0 &&
+ /* allow labels with the same name */
+ pg_strcasecmp(cnode->label, node->label) != 0)
+ {
+ ereport(ERROR,
+ (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
+ errmsg("multiple labels for variable '%s' are not
supported", node->name),
+ parser_errposition(pstate, node->location)));
+ }
+ }
+
return te->expr;
}
}