This is an automated email from the ASF dual-hosted git repository.

jgemignani pushed a commit to branch PG12
in repository https://gitbox.apache.org/repos/asf/age.git

commit e7e8c98d33c8d23d841ee2f09d437c439dd99071
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 234e3aad..3bc39cce 100644
--- a/src/backend/parser/cypher_clause.c
+++ b/src/backend/parser/cypher_clause.c
@@ -4361,20 +4361,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;
         }
     }
@@ -4453,7 +4462,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;
@@ -4510,22 +4519,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;
         }
     }

Reply via email to