Fix apache#1513 - Invalid variable reuse in CREATE and MERGE clause (#1515)

Allow the reuse of a previously declared vertex variable only if the succeeding
CREATE/MERGE vertex has associated edges
i.e CREATE (n) CREATE (n)             -- invalid
    CREATE (n) CREATE (n)-[:edge]->() -- valid

Fixed another invalid variable reuse where in a CREATE path, edge variable
could be duplicated which resulted in ambiguous reference error

Added regression tests
diff --git a/regress/expected/cypher_create.out b/regress/expected/cypher_create.out
index 91b95d3..2388af8 100644
--- a/regress/expected/cypher_create.out
+++ b/regress/expected/cypher_create.out
@@ -714,7 +714,9 @@
 SELECT * FROM cypher('cypher_create', $$
 	CREATE p=() CREATE (p)
 $$) as (a agtype);
-ERROR:  agtype must resolve to a vertex
+ERROR:  variable p already exists
+LINE 2:  CREATE p=() CREATE (p)
+                             ^
 SELECT * FROM cypher('cypher_create', $$
 	CREATE p=(a)-[p:b]->(a)
 $$) as (a agtype);
@@ -748,7 +750,7 @@
 SELECT * FROM cypher('cypher_create', $$
 	CREATE (a)-[e:new]->(p)-[e]->(a)
 $$) as (a agtype);
-ERROR:  relationships must be specify a label in CREATE.
+ERROR:  variable e already exists
 LINE 2:  CREATE (a)-[e:new]->(p)-[e]->(a)
                                  ^
 SELECT * FROM cypher('cypher_create', $$
@@ -794,12 +796,123 @@
 (1 row)
 
 --
+-- the following tests should fail due to invalid variable reuse (issue#1513)
+--
+SELECT * FROM cypher('cypher_create', $$
+  CREATE (n) CREATE (n) RETURN n
+$$) as (n agtype);
+ERROR:  variable n already exists
+LINE 2:   CREATE (n) CREATE (n) RETURN n
+                             ^
+SELECT * FROM cypher('cypher_create', $$
+  CREATE (n), (n) RETURN n
+$$) as (n agtype);
+ERROR:  variable n already exists
+LINE 2:   CREATE (n), (n) RETURN n
+                       ^
+SELECT * FROM cypher('cypher_create', $$
+  MATCH (n) CREATE (n) RETURN n
+$$) as (n agtype);
+ERROR:  variable n already exists
+LINE 2:   MATCH (n) CREATE (n) RETURN n
+                            ^
+SELECT * FROM cypher('cypher_create', $$
+  CREATE (n), (n)-[:edge]->(n), (n) RETURN n
+$$) as (n agtype);
+ERROR:  variable n already exists
+LINE 2:   CREATE (n), (n)-[:edge]->(n), (n) RETURN n
+                                         ^
+SELECT * FROM cypher('cypher_create', $$
+  CREATE (n)-[e:edge]->(m) CREATE (n), (m) RETURN n
+$$) as (n agtype);
+ERROR:  variable n already exists
+LINE 2:   CREATE (n)-[e:edge]->(m) CREATE (n), (m) RETURN n
+                                           ^
+SELECT * FROM cypher('cypher_create', $$
+  CREATE (n)-[e:edge]->(m) CREATE (), (m) RETURN m
+$$) as (m agtype);
+ERROR:  variable m already exists
+LINE 2:   CREATE (n)-[e:edge]->(m) CREATE (), (m) RETURN m
+                                               ^
+SELECT * FROM cypher('cypher_create', $$
+  CREATE (n)-[e:edge]->(m) CREATE (), (e) RETURN e
+$$) as (e agtype);
+ERROR:  variable e already exists
+LINE 2:   CREATE (n)-[e:edge]->(m) CREATE (), (e) RETURN e
+                                               ^
+SELECT * FROM cypher('cypher_create', $$
+  CREATE (n)-[e:edge]->(m) CREATE (n)-[e:edge]->(m) RETURN e
+$$) as (e agtype);
+ERROR:  variable e already exists
+LINE 2:   CREATE (n)-[e:edge]->(m) CREATE (n)-[e:edge]->(m) RETURN e
+                                              ^
+SELECT * FROM cypher('cypher_create', $$
+  WITH {id: 281474976710657, label: "", properties: {}}::vertex AS n CREATE (n) RETURN n
+$$) as (n agtype);
+ERROR:  variable n already exists
+LINE 2: ..., label: "", properties: {}}::vertex AS n CREATE (n) RETURN ...
+                                                             ^
+SELECT * FROM cypher('cypher_create', $$
+	CREATE (n)-[e:edge]->(n)-[e:edge]->(n) RETURN e
+$$) as (e agtype);
+ERROR:  variable e already exists
+LINE 2:  CREATE (n)-[e:edge]->(n)-[e:edge]->(n) RETURN e
+                                  ^
+SELECT * FROM cypher('cypher_create', $$
+	CREATE ()-[e:edge]->(), (n)-[e:edge]->(n)-[e:edge]->(n) RETURN e
+$$) as (e agtype);
+ERROR:  variable e already exists
+LINE 2:  CREATE ()-[e:edge]->(), (n)-[e:edge]->(n)-[e:edge]->(n) RET...
+                                     ^
+SELECT * FROM cypher('cypher_create', $$
+  CREATE (n)-[e:edge]->(m) CREATE (e)-[:edge]->() RETURN e
+$$) as (e agtype);
+ERROR:  variable e already exists
+LINE 2:   CREATE (n)-[e:edge]->(m) CREATE (e)-[:edge]->() RETURN e
+                                           ^
+SELECT * FROM cypher('cypher_create', $$
+	WITH {id: 1407374883553281, label: "edge", end_id: 281474976710658, start_id: 281474976710657, properties: {}}::edge AS e CREATE ()-[e:edge]->() RETURN e
+$$) as (e agtype);
+ERROR:  variable e already exists
+LINE 2: ...74976710657, properties: {}}::edge AS e CREATE ()-[e:edge]->...
+                                                             ^
+SELECT * FROM cypher('cypher_create', $$
+	CREATE (n) WITH n AS r CREATE (r) RETURN r
+$$) as (r agtype);
+ERROR:  variable r already exists
+LINE 2:  CREATE (n) WITH n AS r CREATE (r) RETURN r
+                                        ^
+-- valid variable reuse
+SELECT * FROM cypher('cypher_create', $$
+  CREATE (n)-[e1:edge]->(m) CREATE (n)-[e2:edge]->(m)
+$$) as (n agtype);
+ n 
+---
+(0 rows)
+
+SELECT * FROM cypher('cypher_create', $$
+	CREATE (n) WITH n AS r CREATE (r)-[e:edge]->() RETURN r
+$$) as (r agtype);
+                               r                                
+----------------------------------------------------------------
+ {"id": 281474976710685, "label": "", "properties": {}}::vertex
+(1 row)
+
+SELECT * FROM cypher('cypher_create', $$
+  CREATE (n), (m) WITH n AS r CREATE (m) RETURN m
+$$) as (m agtype);
+                               m                                
+----------------------------------------------------------------
+ {"id": 281474976710689, "label": "", "properties": {}}::vertex
+(1 row)
+
+--
 -- Clean up
 --
 DROP TABLE simple_path;
 DROP FUNCTION create_test;
 SELECT drop_graph('cypher_create', true);
-NOTICE:  drop cascades to 19 other objects
+NOTICE:  drop cascades to 20 other objects
 DETAIL:  drop cascades to table cypher_create._ag_label_vertex
 drop cascades to table cypher_create._ag_label_edge
 drop cascades to table cypher_create.v
@@ -819,6 +932,7 @@
 drop cascades to table cypher_create."CREATE"
 drop cascades to table cypher_create."create"
 drop cascades to table cypher_create."CrEaTe"
+drop cascades to table cypher_create.edge
 NOTICE:  graph "cypher_create" has been dropped
  drop_graph 
 ------------
diff --git a/regress/expected/cypher_merge.out b/regress/expected/cypher_merge.out
index 7427c8e..39690e7 100644
--- a/regress/expected/cypher_merge.out
+++ b/regress/expected/cypher_merge.out
@@ -817,7 +817,9 @@
 
 --test query
 SELECT * FROM cypher('cypher_merge', $$MATCH (n) OPTIONAL MATCH (n)-[:e]->(m) MERGE (m)$$) AS (a agtype);
-ERROR:  Existing variable m cannot be NULL in MERGE clause
+ERROR:  variable m already exists
+LINE 1: ..., $$MATCH (n) OPTIONAL MATCH (n)-[:e]->(m) MERGE (m)$$) AS (...
+                                                             ^
 -- validate only 1 vertex exits
 SELECT * FROM cypher('cypher_merge', $$MATCH (n) RETURN n$$) AS (a agtype);
                                a                                
@@ -1182,6 +1184,85 @@
  
 (1 row)
 
+--
+-- the following tests should fail due to invalid variable reuse (issue#1513)
+--
+SELECT * FROM cypher('cypher_merge', $$
+  MERGE (n) MERGE (n) RETURN n
+$$) as (a agtype);
+ERROR:  variable n already exists
+LINE 2:   MERGE (n) MERGE (n) RETURN n
+                           ^
+SELECT * FROM cypher('cypher_merge', $$
+  MATCH (n) MERGE (n) RETURN n
+$$) as (a agtype);
+ERROR:  variable n already exists
+LINE 2:   MATCH (n) MERGE (n) RETURN n
+                           ^
+SELECT * FROM cypher('cypher_merge', $$
+  CREATE (n) MERGE (n) RETURN n
+$$) as (a agtype);
+ERROR:  variable n already exists
+LINE 2:   CREATE (n) MERGE (n) RETURN n
+                            ^
+SELECT * FROM cypher('cypher_merge', $$
+  MATCH (n) WITH n AS r MERGE (r) RETURN r
+$$) as (a agtype);
+ERROR:  variable r already exists
+LINE 2:   MATCH (n) WITH n AS r MERGE (r) RETURN r
+                                       ^
+SELECT * FROM cypher('cypher_merge', $$
+  WITH {id: 281474976710657, label: "", properties: {}}::vertex AS n MERGE (n) RETURN n
+$$) as (a agtype);
+ERROR:  variable n already exists
+LINE 2: ...7, label: "", properties: {}}::vertex AS n MERGE (n) RETURN ...
+                                                             ^
+SELECT * FROM cypher('cypher_merge', $$
+	MERGE (n)-[e:edge]->(n)-[e1:edge]->(n) MERGE(n) RETURN e
+$$) as (a agtype);
+ERROR:  variable n already exists
+LINE 2:  MERGE (n)-[e:edge]->(n)-[e1:edge]->(n) MERGE(n) RETURN e
+                                                      ^
+SELECT * FROM cypher('cypher_merge', $$
+  MERGE (n)-[e:edge]->(m) MERGE (e)-[:edge]->() RETURN e
+$$) as (a agtype);
+ERROR:  variable 'e' is for an edge
+LINE 2:   MERGE (n)-[e:edge]->(m) MERGE (e)-[:edge]->() RETURN e
+                                         ^
+SELECT * FROM cypher('cypher_merge', $$
+	WITH {id: 1407374883553281, label: "edge", end_id: 281474976710658, start_id: 281474976710657, properties: {}}::edge AS e MERGE ()-[e:edge]->() RETURN e
+$$) as (a agtype);
+ERROR:  variable e already exists
+LINE 2: ...474976710657, properties: {}}::edge AS e MERGE ()-[e:edge]->...
+                                                             ^
+SELECT * FROM cypher('cypher_merge', $$
+  MATCH (n) WITH n AS r MERGE (r) RETURN r
+$$) as (a agtype);
+ERROR:  variable r already exists
+LINE 2:   MATCH (n) WITH n AS r MERGE (r) RETURN r
+                                       ^
+-- valid variable reuse
+SELECT * FROM cypher('cypher_merge', $$
+  MERGE (n)-[e1:edge]->(m) MERGE (n)-[e2:edge]->()
+$$) as (n agtype);
+ n 
+---
+(0 rows)
+
+SELECT * FROM cypher('cypher_merge', $$
+  MERGE (n) WITH n AS r MERGE (r)-[e:edge]->()
+$$) as (a agtype);
+ a 
+---
+(0 rows)
+
+SELECT * FROM cypher('cypher_merge', $$
+  CREATE (n), (m) WITH n AS r MERGE (m)
+$$) as (a agtype);
+ a 
+---
+(0 rows)
+
 --clean up
 SELECT * FROM cypher('cypher_merge', $$MATCH (n) DETACH DELETE n $$) AS (a agtype);
  a 
@@ -1192,7 +1273,7 @@
  * Clean up graph
  */
 SELECT drop_graph('cypher_merge', true);
-NOTICE:  drop cascades to 18 other objects
+NOTICE:  drop cascades to 19 other objects
 DETAIL:  drop cascades to table cypher_merge._ag_label_vertex
 drop cascades to table cypher_merge._ag_label_edge
 drop cascades to table cypher_merge.e
@@ -1211,6 +1292,7 @@
 drop cascades to table cypher_merge."Q"
 drop cascades to table cypher_merge."R"
 drop cascades to table cypher_merge."E1"
+drop cascades to table cypher_merge.edge
 NOTICE:  graph "cypher_merge" has been dropped
  drop_graph 
 ------------
diff --git a/regress/sql/cypher_create.sql b/regress/sql/cypher_create.sql
index 8c9ac89..0093dc4 100644
--- a/regress/sql/cypher_create.sql
+++ b/regress/sql/cypher_create.sql
@@ -404,6 +404,78 @@
 $$) as (a agtype);
 
 --
+-- the following tests should fail due to invalid variable reuse (issue#1513)
+--
+SELECT * FROM cypher('cypher_create', $$
+  CREATE (n) CREATE (n) RETURN n
+$$) as (n agtype);
+
+SELECT * FROM cypher('cypher_create', $$
+  CREATE (n), (n) RETURN n
+$$) as (n agtype);
+
+SELECT * FROM cypher('cypher_create', $$
+  MATCH (n) CREATE (n) RETURN n
+$$) as (n agtype);
+
+SELECT * FROM cypher('cypher_create', $$
+  CREATE (n), (n)-[:edge]->(n), (n) RETURN n
+$$) as (n agtype);
+
+SELECT * FROM cypher('cypher_create', $$
+  CREATE (n)-[e:edge]->(m) CREATE (n), (m) RETURN n
+$$) as (n agtype);
+
+SELECT * FROM cypher('cypher_create', $$
+  CREATE (n)-[e:edge]->(m) CREATE (), (m) RETURN m
+$$) as (m agtype);
+
+SELECT * FROM cypher('cypher_create', $$
+  CREATE (n)-[e:edge]->(m) CREATE (), (e) RETURN e
+$$) as (e agtype);
+
+SELECT * FROM cypher('cypher_create', $$
+  CREATE (n)-[e:edge]->(m) CREATE (n)-[e:edge]->(m) RETURN e
+$$) as (e agtype);
+
+SELECT * FROM cypher('cypher_create', $$
+  WITH {id: 281474976710657, label: "", properties: {}}::vertex AS n CREATE (n) RETURN n
+$$) as (n agtype);
+
+SELECT * FROM cypher('cypher_create', $$
+	CREATE (n)-[e:edge]->(n)-[e:edge]->(n) RETURN e
+$$) as (e agtype);
+
+SELECT * FROM cypher('cypher_create', $$
+	CREATE ()-[e:edge]->(), (n)-[e:edge]->(n)-[e:edge]->(n) RETURN e
+$$) as (e agtype);
+
+SELECT * FROM cypher('cypher_create', $$
+  CREATE (n)-[e:edge]->(m) CREATE (e)-[:edge]->() RETURN e
+$$) as (e agtype);
+
+SELECT * FROM cypher('cypher_create', $$
+	WITH {id: 1407374883553281, label: "edge", end_id: 281474976710658, start_id: 281474976710657, properties: {}}::edge AS e CREATE ()-[e:edge]->() RETURN e
+$$) as (e agtype);
+
+SELECT * FROM cypher('cypher_create', $$
+	CREATE (n) WITH n AS r CREATE (r) RETURN r
+$$) as (r agtype);
+
+-- valid variable reuse
+SELECT * FROM cypher('cypher_create', $$
+  CREATE (n)-[e1:edge]->(m) CREATE (n)-[e2:edge]->(m)
+$$) as (n agtype);
+
+SELECT * FROM cypher('cypher_create', $$
+	CREATE (n) WITH n AS r CREATE (r)-[e:edge]->() RETURN r
+$$) as (r agtype);
+
+SELECT * FROM cypher('cypher_create', $$
+  CREATE (n), (m) WITH n AS r CREATE (m) RETURN m
+$$) as (m agtype);
+
+--
 -- Clean up
 --
 DROP TABLE simple_path;
diff --git a/regress/sql/cypher_merge.sql b/regress/sql/cypher_merge.sql
index 81d965a..f6aceea 100644
--- a/regress/sql/cypher_merge.sql
+++ b/regress/sql/cypher_merge.sql
@@ -554,6 +554,58 @@
 SELECT * FROM cypher('issue_1219', $$ MATCH ()-[e]->() RETURN e $$) as (result agtype);
 SELECT drop_graph('issue_1219', true);
 
+--
+-- the following tests should fail due to invalid variable reuse (issue#1513)
+--
+SELECT * FROM cypher('cypher_merge', $$
+  MERGE (n) MERGE (n) RETURN n
+$$) as (a agtype);
+
+SELECT * FROM cypher('cypher_merge', $$
+  MATCH (n) MERGE (n) RETURN n
+$$) as (a agtype);
+
+SELECT * FROM cypher('cypher_merge', $$
+  CREATE (n) MERGE (n) RETURN n
+$$) as (a agtype);
+
+SELECT * FROM cypher('cypher_merge', $$
+  MATCH (n) WITH n AS r MERGE (r) RETURN r
+$$) as (a agtype);
+
+SELECT * FROM cypher('cypher_merge', $$
+  WITH {id: 281474976710657, label: "", properties: {}}::vertex AS n MERGE (n) RETURN n
+$$) as (a agtype);
+
+SELECT * FROM cypher('cypher_merge', $$
+	MERGE (n)-[e:edge]->(n)-[e1:edge]->(n) MERGE(n) RETURN e
+$$) as (a agtype);
+
+SELECT * FROM cypher('cypher_merge', $$
+  MERGE (n)-[e:edge]->(m) MERGE (e)-[:edge]->() RETURN e
+$$) as (a agtype);
+
+SELECT * FROM cypher('cypher_merge', $$
+	WITH {id: 1407374883553281, label: "edge", end_id: 281474976710658, start_id: 281474976710657, properties: {}}::edge AS e MERGE ()-[e:edge]->() RETURN e
+$$) as (a agtype);
+
+SELECT * FROM cypher('cypher_merge', $$
+  MATCH (n) WITH n AS r MERGE (r) RETURN r
+$$) as (a agtype);
+
+-- valid variable reuse
+SELECT * FROM cypher('cypher_merge', $$
+  MERGE (n)-[e1:edge]->(m) MERGE (n)-[e2:edge]->()
+$$) as (n agtype);
+
+SELECT * FROM cypher('cypher_merge', $$
+  MERGE (n) WITH n AS r MERGE (r)-[e:edge]->()
+$$) as (a agtype);
+
+SELECT * FROM cypher('cypher_merge', $$
+  CREATE (n), (m) WITH n AS r MERGE (m)
+$$) as (a agtype);
+
 --clean up
 SELECT * FROM cypher('cypher_merge', $$MATCH (n) DETACH DELETE n $$) AS (a agtype);
 
diff --git a/src/backend/parser/cypher_clause.c b/src/backend/parser/cypher_clause.c
index 212cd26..c164e19 100644
--- a/src/backend/parser/cypher_clause.c
+++ b/src/backend/parser/cypher_clause.c
@@ -181,7 +181,7 @@
                              cypher_path *cp);
 static cypher_target_node *
 transform_create_cypher_node(cypher_parsestate *cpstate, List **target_list,
-                             cypher_node *node);
+                             cypher_node *node, bool has_edge);
 static cypher_target_node *
 transform_create_cypher_new_node(cypher_parsestate *cpstate,
                                  List **target_list, cypher_node *node);
@@ -255,7 +255,7 @@
                             cypher_relationship *edge);
 static cypher_target_node *
 transform_merge_cypher_node(cypher_parsestate *cpstate, List **target_list,
-                            cypher_node *node);
+                            cypher_node *node, bool has_edge);
 static Node *transform_clause_for_join(cypher_parsestate *cpstate,
                                        cypher_clause *clause,
                                        RangeTblEntry **rte,
@@ -5336,7 +5336,7 @@
                              cypher_path *path)
 {
     ParseState *pstate = (ParseState *)cpstate;
-    ListCell *lc;
+    ListCell *lc, *prev_node = NULL;
     List *transformed_path = NIL;
     cypher_create_path *ccp = make_ag_node(cypher_create_path);
     bool in_path = path->var_name != NULL;
@@ -5361,9 +5361,11 @@
         {
             cypher_node *node = lfirst(lc);
             transform_entity *entity;
+            ListCell *next_node = lnext(path->path, lc);
 
             cypher_target_node *rel =
-                transform_create_cypher_node(cpstate, target_list, node);
+                transform_create_cypher_node(cpstate, target_list, node,
+                                             (next_node || prev_node));
 
             if (in_path)
             {
@@ -5418,6 +5420,7 @@
             ereport(ERROR,
                     (errmsg_internal("unrecognized node in create pattern")));
         }
+        prev_node = lc;
     }
 
     ccp->target_nodes = transformed_path;
@@ -5489,7 +5492,7 @@
 
         entity = find_variable(cpstate, edge->name);
 
-        if ((entity && entity->type != ENT_EDGE) || variable_exists(cpstate, edge->name))
+        if (entity || variable_exists(cpstate, edge->name))
         {
                 ereport(ERROR,
                         (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
@@ -5602,7 +5605,7 @@
 // transform nodes, check to see if the variable name already exists.
 static cypher_target_node *
 transform_create_cypher_node(cypher_parsestate *cpstate, List **target_list,
-                             cypher_node *node)
+                             cypher_node *node, bool has_edge)
 {
     ParseState *pstate = (ParseState *)cpstate;
 
@@ -5636,7 +5639,7 @@
          */
         if (entity && te)
         {
-            if (entity->type != ENT_VERTEX)
+            if (entity->type != ENT_VERTEX || !has_edge)
             {
                 ereport(ERROR,
                         (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
@@ -5649,6 +5652,13 @@
         }
         else if (te)
         {
+            if (!has_edge)
+            {
+                ereport(ERROR,
+                        (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
+                         errmsg("variable %s already exists", node->name),
+                         parser_errposition(pstate, node->location)));
+            }
             /*
              * Here we are not sure if the te is a vertex, path or something
              * else. So we will let it pass and the execution stage will catch
@@ -6682,7 +6692,7 @@
                             cypher_path *path)
 {
     ParseState *pstate = (ParseState *)cpstate;
-    ListCell *lc;
+    ListCell *lc, *prev_node = NULL;
     List *transformed_path = NIL;
     cypher_create_path *ccp = make_ag_node(cypher_create_path);
     bool in_path = path->var_name != NULL;
@@ -6695,6 +6705,7 @@
         {
             cypher_node *node = lfirst(lc);
             cypher_target_node *rel = NULL;
+            ListCell *next_node = lnext(path->path, lc);
 
             if (path->var_name != NULL && node->name != NULL &&
                 strcmp(path->var_name, node->name) == 0)
@@ -6716,7 +6727,8 @@
             /* if there wasn't a transformed variable, transform the node */
             if (rel == NULL)
             {
-                rel = transform_merge_cypher_node(cpstate, target_list, node);
+                rel = transform_merge_cypher_node(cpstate, target_list, node,
+                                                  (next_node || prev_node));
             }
 
             if (in_path)
@@ -6772,6 +6784,7 @@
             ereport(ERROR,
                     (errmsg_internal("unrecognized node in create pattern")));
         }
+        prev_node = lc;
     }
 
     // store the path's variable name
@@ -6807,7 +6820,7 @@
                                                          ENT_EDGE);
 
         // We found a variable with this variable name, throw an error.
-        if (entity != NULL)
+        if (entity || variable_exists(cpstate, edge->name))
         {
             ereport(ERROR,
                 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
@@ -6906,8 +6919,9 @@
  */
 static cypher_target_node *
 transform_merge_cypher_node(cypher_parsestate *cpstate, List **target_list,
-                            cypher_node *node)
+                            cypher_node *node, bool has_edge)
 {
+    ParseState *pstate = (ParseState *)cpstate;
     cypher_target_node *rel = make_ag_node(cypher_target_node);
     Relation label_relation;
     RangeVar *rv;
@@ -6918,19 +6932,35 @@
     {
         transform_entity *entity = find_transform_entity(cpstate, node->name,
                                                          ENT_VERTEX);
+        bool var_exists = variable_exists(cpstate, node->name);
         /*
          *  the vertex was previously declared, we do not need to do any setup
          *  to create the node.
          */
-        if (entity != NULL)
+        if (entity && var_exists)
         {
-                rel->type = LABEL_KIND_VERTEX;
-                rel->tuple_position = InvalidAttrNumber;
-                rel->variable_name = node->name;
-                rel->resultRelInfo = NULL;
+            if (!has_edge)
+            {
+                ereport(ERROR,
+                        (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
+                         errmsg("variable %s already exists", node->name),
+                         parser_errposition(pstate, node->location)));
+            }
 
-                rel->flags |= CYPHER_TARGET_NODE_MERGE_EXISTS;
-                return rel;
+            rel->type = LABEL_KIND_VERTEX;
+            rel->tuple_position = InvalidAttrNumber;
+            rel->variable_name = node->name;
+            rel->resultRelInfo = NULL;
+
+            rel->flags |= CYPHER_TARGET_NODE_MERGE_EXISTS;
+            return rel;
+        }
+        else if (var_exists && !has_edge)
+        {
+            ereport(ERROR,
+                        (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
+                         errmsg("variable %s already exists", node->name),
+                         parser_errposition(pstate, node->location)));
         }
         rel->flags |= CYPHER_TARGET_NODE_IS_VAR;
     }