You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@age.apache.org by jo...@apache.org on 2022/03/23 22:43:40 UTC

[incubator-age] branch master updated: Fix Simple Undirected MATCH Case

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

joshinnis pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/incubator-age.git


The following commit(s) were added to refs/heads/master by this push:
     new 6df5efb  Fix Simple Undirected MATCH Case
6df5efb is described below

commit 6df5efb628b3eac83d3d16c3877e991d66dff20f
Author: Josh Innis <Jo...@gmail.com>
AuthorDate: Wed Mar 23 15:39:59 2022 -0700

    Fix Simple Undirected MATCH Case
    
    When a MATCH has two vertices and an undirected edge, where no
    information was referenced in the two vertices, such as:
    
    MATCH ()-[e]-() RETURN e;
    
    Only half the number of rows were returned from what was expected.
    Every  edge should be included twice, once for each direction.
---
 regress/expected/cypher_match.out  | 11 +++++++++++
 regress/expected/cypher_remove.out |  6 ++++--
 regress/expected/expr.out          | 39 ++++++++++++++++++++++++++++----------
 regress/sql/cypher_match.sql       |  4 ++++
 src/backend/parser/cypher_clause.c | 36 +++++++++++++++++++++++++++++++++--
 5 files changed, 82 insertions(+), 14 deletions(-)

diff --git a/regress/expected/cypher_match.out b/regress/expected/cypher_match.out
index d2d387c..cf9ff79 100644
--- a/regress/expected/cypher_match.out
+++ b/regress/expected/cypher_match.out
@@ -127,6 +127,17 @@ $$) AS (a agtype);
  {"id": 1125899906842626, "label": "v1", "properties": {"id": "middle"}}::vertex
 (1 row)
 
+SELECT * FROM cypher('cypher_match', $$
+    MATCH p=()-[e]-() RETURN e
+$$) AS (a agtype);
+                                                             a                                                             
+---------------------------------------------------------------------------------------------------------------------------
+ {"id": 1407374883553282, "label": "e1", "end_id": 1125899906842626, "start_id": 1125899906842625, "properties": {}}::edge
+ {"id": 1407374883553282, "label": "e1", "end_id": 1125899906842626, "start_id": 1125899906842625, "properties": {}}::edge
+ {"id": 1407374883553281, "label": "e1", "end_id": 1125899906842627, "start_id": 1125899906842626, "properties": {}}::edge
+ {"id": 1407374883553281, "label": "e1", "end_id": 1125899906842627, "start_id": 1125899906842626, "properties": {}}::edge
+(4 rows)
+
 -- Right Path Test
 SELECT * FROM cypher('cypher_match', $$
 	MATCH (a:v1)-[:e1]->(b:v1)-[:e1]->(c:v1) RETURN a, b, c
diff --git a/regress/expected/cypher_remove.out b/regress/expected/cypher_remove.out
index 8129cad..ca2b94a 100644
--- a/regress/expected/cypher_remove.out
+++ b/regress/expected/cypher_remove.out
@@ -447,13 +447,15 @@ SELECT * FROM cypher('cypher_remove', $$MATCH ()-[e:edge_multi_property]-() RETU
                                                                             a                                                                            
 ---------------------------------------------------------------------------------------------------------------------------------------------------------
  {"id": 3659174697238529, "label": "edge_multi_property", "end_id": 281474976710664, "start_id": 281474976710663, "properties": {"i": 5, "j": 20}}::edge
-(1 row)
+ {"id": 3659174697238529, "label": "edge_multi_property", "end_id": 281474976710664, "start_id": 281474976710663, "properties": {"i": 5, "j": 20}}::edge
+(2 rows)
 
 SELECT * FROM cypher('cypher_remove', $$MATCH ()-[e:edge_multi_property]-() REMOVE e.i, e.j RETURN e$$) AS (a agtype);
                                                                     a                                                                     
 ------------------------------------------------------------------------------------------------------------------------------------------
  {"id": 3659174697238529, "label": "edge_multi_property", "end_id": 281474976710664, "start_id": 281474976710663, "properties": {}}::edge
-(1 row)
+ {"id": 3659174697238529, "label": "edge_multi_property", "end_id": 281474976710664, "start_id": 281474976710663, "properties": {}}::edge
+(2 rows)
 
 --Errors
 SELECT * FROM cypher('cypher_remove', $$REMOVE n.i$$) AS (a agtype);
diff --git a/regress/expected/expr.out b/regress/expected/expr.out
index aac5b29..f4fdc4b 100644
--- a/regress/expected/expr.out
+++ b/regress/expected/expr.out
@@ -1664,8 +1664,10 @@ SELECT * FROM cypher('expr', $$ MATCH ()-[e]-() RETURN e $$) AS (expression agty
                                                         expression                                                         
 ---------------------------------------------------------------------------------------------------------------------------
  {"id": 1407374883553281, "label": "e1", "end_id": 1125899906842627, "start_id": 1125899906842626, "properties": {}}::edge
+ {"id": 1407374883553281, "label": "e1", "end_id": 1125899906842627, "start_id": 1125899906842626, "properties": {}}::edge
  {"id": 1407374883553282, "label": "e1", "end_id": 1125899906842626, "start_id": 1125899906842625, "properties": {}}::edge
-(2 rows)
+ {"id": 1407374883553282, "label": "e1", "end_id": 1125899906842626, "start_id": 1125899906842625, "properties": {}}::edge
+(4 rows)
 
 -- id()
 SELECT * FROM cypher('expr', $$
@@ -1674,8 +1676,10 @@ $$) AS (id agtype);
         id        
 ------------------
  1407374883553281
+ 1407374883553281
  1407374883553282
-(2 rows)
+ 1407374883553282
+(4 rows)
 
 SELECT * FROM cypher('expr', $$
     MATCH (v) RETURN id(v)
@@ -1714,8 +1718,10 @@ $$) AS (start_id agtype);
      start_id     
 ------------------
  1125899906842626
+ 1125899906842626
  1125899906842625
-(2 rows)
+ 1125899906842625
+(4 rows)
 
 -- should return null
 SELECT * FROM cypher('expr', $$
@@ -1745,8 +1751,10 @@ $$) AS (end_id agtype);
       end_id      
 ------------------
  1125899906842627
+ 1125899906842627
  1125899906842626
-(2 rows)
+ 1125899906842626
+(4 rows)
 
 -- should return null
 SELECT * FROM cypher('expr', $$
@@ -1776,8 +1784,10 @@ $$) AS (id agtype, start_id agtype, startNode agtype);
         id        |     start_id     |                                    startnode                                     
 ------------------+------------------+----------------------------------------------------------------------------------
  1407374883553281 | 1125899906842626 | {"id": 1125899906842626, "label": "v1", "properties": {"id": "middle"}}::vertex
+ 1407374883553281 | 1125899906842626 | {"id": 1125899906842626, "label": "v1", "properties": {"id": "middle"}}::vertex
  1407374883553282 | 1125899906842625 | {"id": 1125899906842625, "label": "v1", "properties": {"id": "initial"}}::vertex
-(2 rows)
+ 1407374883553282 | 1125899906842625 | {"id": 1125899906842625, "label": "v1", "properties": {"id": "initial"}}::vertex
+(4 rows)
 
 -- should return null
 SELECT * FROM cypher('expr', $$
@@ -1807,8 +1817,10 @@ $$) AS (id agtype, end_id agtype, endNode agtype);
         id        |      end_id      |                                     endnode                                     
 ------------------+------------------+---------------------------------------------------------------------------------
  1407374883553281 | 1125899906842627 | {"id": 1125899906842627, "label": "v1", "properties": {"id": "end"}}::vertex
+ 1407374883553281 | 1125899906842627 | {"id": 1125899906842627, "label": "v1", "properties": {"id": "end"}}::vertex
  1407374883553282 | 1125899906842626 | {"id": 1125899906842626, "label": "v1", "properties": {"id": "middle"}}::vertex
-(2 rows)
+ 1407374883553282 | 1125899906842626 | {"id": 1125899906842626, "label": "v1", "properties": {"id": "middle"}}::vertex
+(4 rows)
 
 -- should return null
 SELECT * FROM cypher('expr', $$
@@ -1839,7 +1851,9 @@ $$) AS (type agtype);
 ------
  "e1"
  "e1"
-(2 rows)
+ "e1"
+ "e1"
+(4 rows)
 
 -- should return null
 SELECT * FROM cypher('expr', $$
@@ -2094,7 +2108,9 @@ $$) AS (properties agtype);
 ------------
  {}
  {}
-(2 rows)
+ {}
+ {}
+(4 rows)
 
 -- should return null
 SELECT * FROM cypher('expr', $$
@@ -5641,10 +5657,13 @@ SELECT * FROM cypher('keys', $$MATCH (v) RETURN keys(v)$$) AS (vertex_keys agtyp
 SELECT * FROM cypher('keys', $$MATCH ()-[e]-() RETURN keys(e)$$) AS (edge_keys agtype);
  edge_keys 
 -----------
+ []
+ []
  ["song"]
  ["song"]
- []
-(3 rows)
+ ["song"]
+ ["song"]
+(6 rows)
 
 SELECT * FROM cypher('keys', $$RETURN keys({a:1,b:'two',c:[1,2,3]})$$) AS (keys agtype);
       keys       
diff --git a/regress/sql/cypher_match.sql b/regress/sql/cypher_match.sql
index 1ccc316..057e27a 100644
--- a/regress/sql/cypher_match.sql
+++ b/regress/sql/cypher_match.sql
@@ -64,6 +64,10 @@ SELECT * FROM cypher('cypher_match', $$
 	MATCH (a:v1)-[]->(), ()-[]->(a) RETURN a
 $$) AS (a agtype);
 
+SELECT * FROM cypher('cypher_match', $$
+    MATCH p=()-[e]-() RETURN e
+$$) AS (a agtype);
+
 -- Right Path Test
 SELECT * FROM cypher('cypher_match', $$
 	MATCH (a:v1)-[:e1]->(b:v1)-[:e1]->(c:v1) RETURN a, b, c
diff --git a/src/backend/parser/cypher_clause.c b/src/backend/parser/cypher_clause.c
index 2eb738d..92d049d 100644
--- a/src/backend/parser/cypher_clause.c
+++ b/src/backend/parser/cypher_clause.c
@@ -3413,6 +3413,7 @@ static List *transform_match_entities(cypher_parsestate *cpstate, Query *query,
     List *entities = NIL;
     int i = 0;
     bool node_declared_in_prev_clause = false;
+    transform_entity *prev_entity = NULL;
 
     /*
      * Iterate through every node in the path, construct the expr node
@@ -3466,11 +3467,14 @@ static List *transform_match_entities(cypher_parsestate *cpstate, Query *query,
 
                 n = create_property_constraint_function(cpstate, entity,
                                                         node->props);
-                cpstate->property_constraint_quals = lappend(cpstate->property_constraint_quals, n);
+                cpstate->property_constraint_quals =
+                    lappend(cpstate->property_constraint_quals, n);
             }
 
             cpstate->entities = lappend(cpstate->entities, entity);
             entities = lappend(entities, entity);
+
+            prev_entity = entity;
         }
         /* odd increments of i are edges */
         else
@@ -3487,6 +3491,29 @@ static List *transform_match_entities(cypher_parsestate *cpstate, Query *query,
             /* if it is a regular edge */
             if (rel->varlen == NULL)
             {
+                /*
+                 * In the case where the MATCH is one edge and two vertices, the
+                 * edge is bidirectional, and neither vertex is included in the
+                 * join tree, we need to force one of the vertices into the join
+                 * tree to ensure the output is generated correctly.
+                 */
+                if (list_length(path->path) == 3 &&
+                        rel->dir == CYPHER_REL_DIR_NONE &&
+                        !prev_entity->in_join_tree)
+                {
+                    cypher_node *node = (cypher_node *)lfirst(lnext(lc));
+
+                    if (!INCLUDE_NODE_IN_JOIN_TREE(path, node))
+                    {
+                        /*
+                         * Assigning a variable name here will ensure that when
+                         * the next vertex is processed, the vertex will be
+                         * included in the join tree.
+                         */
+                        node->name = get_next_default_alias(cpstate);
+                    }
+                }
+
                 expr = transform_cypher_edge(cpstate, rel, &query->targetList);
 
                 entity = make_transform_entity(cpstate, ENT_EDGE, (Node *)rel,
@@ -3499,10 +3526,13 @@ static List *transform_match_entities(cypher_parsestate *cpstate, Query *query,
                     Node *n = create_property_constraint_function(cpstate,
                                                                   entity,
                                                                   rel->props);
-                    cpstate->property_constraint_quals = lappend(cpstate->property_constraint_quals, n);
+                    cpstate->property_constraint_quals =
+                        lappend(cpstate->property_constraint_quals, n);
                 }
 
                 entities = lappend(entities, entity);
+
+                prev_entity = entity;
             }
             /* if we have a VLE edge */
             else
@@ -3534,6 +3564,8 @@ static List *transform_match_entities(cypher_parsestate *cpstate, Query *query,
                 /* add the entity in */
                 cpstate->entities = lappend(cpstate->entities, vle_entity);
                 entities = lappend(entities, vle_entity);
+
+                prev_entity = entity;
             }
 
             node_declared_in_prev_clause = false;