Skip to content
Permalink
Browse files
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.
  • Loading branch information
JoshInnis committed Mar 23, 2022
1 parent 2462000 commit 6df5efb628b3eac83d3d16c3877e991d66dff20f
Showing 5 changed files with 82 additions and 14 deletions.
@@ -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
@@ -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);
@@ -1663,19 +1663,23 @@ SELECT * FROM cypher('expr', $$ MATCH (v) RETURN v $$) AS (expression agtype);
SELECT * FROM cypher('expr', $$ MATCH ()-[e]-() RETURN e $$) AS (expression agtype);
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', $$
MATCH ()-[e]-() RETURN id(e)
$$) AS (id agtype);
id
------------------
1407374883553281
1407374883553281
1407374883553282
(2 rows)
1407374883553282
(4 rows)

SELECT * FROM cypher('expr', $$
MATCH (v) RETURN id(v)
@@ -1713,9 +1717,11 @@ SELECT * FROM cypher('expr', $$
$$) AS (start_id agtype);
start_id
------------------
1125899906842626
1125899906842626
1125899906842625
(2 rows)
1125899906842625
(4 rows)

-- should return null
SELECT * FROM cypher('expr', $$
@@ -1744,9 +1750,11 @@ SELECT * FROM cypher('expr', $$
$$) AS (end_id agtype);
end_id
------------------
1125899906842627
1125899906842627
1125899906842626
(2 rows)
1125899906842626
(4 rows)

-- should return null
SELECT * FROM cypher('expr', $$
@@ -1775,9 +1783,11 @@ SELECT * FROM cypher('expr', $$
$$) 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', $$
@@ -1806,9 +1816,11 @@ SELECT * FROM cypher('expr', $$
$$) 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
@@ -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
@@ -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;

0 comments on commit 6df5efb

Please sign in to comment.