[Age label inheritance] - VLE edge inheritance: regression tests (#789)
* Added inheritance to create_vlabel function
* Only two parameters to create_vlabel function, inheritance works as -> child_name:parent_name
* create_vlabel receives 3 arguments, the third is a list of parent labels
* Elements in the array are fetched properly
* Error when merging multiple inherited definitions fixed, but still needs to fix the testing
* Changed how create_vlabel handles if there is a parent name in the array
* Added some checking with the is_inheriting variable to see if the label is inheriting
* Added inheritance to create_elabel
* Changed create_label function calls
* changes to match new needed arguments (boolean is_inheriting).
* Tests for edge and vertex label inheritance added for the cypher_create.sql file
* Regression test for VLE edge inheritance
* VLE finds child of child edge
* cypher_vle test passed.
---------
Co-authored-by: Marco A S <aureliojuniorcmrj@hotmail.com>
diff --git a/regress/expected/cypher_vle.out b/regress/expected/cypher_vle.out
index 5f8f922..79876a3 100644
--- a/regress/expected/cypher_vle.out
+++ b/regress/expected/cypher_vle.out
@@ -762,6 +762,242 @@
(1 row)
--
+-- Test VLE for edge inheritance
+--
+SELECT create_graph('vle_inheritance_graph');
+NOTICE: graph "vle_inheritance_graph" has been created
+ create_graph
+--------------
+
+(1 row)
+
+SELECT create_vlabel('vle_inheritance_graph', 'Head');
+NOTICE: VLabel "Head" has been created
+ create_vlabel
+---------------
+
+(1 row)
+
+SELECT create_vlabel('vle_inheritance_graph', 'Tail');
+NOTICE: VLabel "Tail" has been created
+ create_vlabel
+---------------
+
+(1 row)
+
+SELECT create_vlabel('vle_inheritance_graph', 'Node');
+NOTICE: VLabel "Node" has been created
+ create_vlabel
+---------------
+
+(1 row)
+
+SELECT create_elabel('vle_inheritance_graph', 'PARENT_EDGE_A');
+NOTICE: ELabel "PARENT_EDGE_A" has been created
+ create_elabel
+---------------
+
+(1 row)
+
+SELECT create_elabel('vle_inheritance_graph', 'PARENT_EDGE_B');
+NOTICE: ELabel "PARENT_EDGE_B" has been created
+ create_elabel
+---------------
+
+(1 row)
+
+SELECT create_elabel('vle_inheritance_graph', 'CHILD_EDGE_A', ARRAY['PARENT_EDGE_A']);
+NOTICE: ELabel CHILD_EDGE_A will inherit from PARENT_EDGE_A
+NOTICE: merging column "id" with inherited definition
+NOTICE: merging column "start_id" with inherited definition
+NOTICE: merging column "end_id" with inherited definition
+NOTICE: merging column "properties" with inherited definition
+NOTICE: ELabel "CHILD_EDGE_A" has been created
+ create_elabel
+---------------
+
+(1 row)
+
+SELECT create_elabel('vle_inheritance_graph', 'CHILD_EDGE_B', ARRAY['PARENT_EDGE_B']);
+NOTICE: ELabel CHILD_EDGE_B will inherit from PARENT_EDGE_B
+NOTICE: merging column "id" with inherited definition
+NOTICE: merging column "start_id" with inherited definition
+NOTICE: merging column "end_id" with inherited definition
+NOTICE: merging column "properties" with inherited definition
+NOTICE: ELabel "CHILD_EDGE_B" has been created
+ create_elabel
+---------------
+
+(1 row)
+
+SELECT create_elabel('vle_inheritance_graph', 'CHILD_EDGE_C', ARRAY['CHILD_EDGE_B']);
+NOTICE: ELabel CHILD_EDGE_C will inherit from CHILD_EDGE_B
+NOTICE: merging column "id" with inherited definition
+NOTICE: merging column "start_id" with inherited definition
+NOTICE: merging column "end_id" with inherited definition
+NOTICE: merging column "properties" with inherited definition
+NOTICE: ELabel "CHILD_EDGE_C" has been created
+ create_elabel
+---------------
+
+(1 row)
+
+SELECT * FROM cypher('vle_inheritance_graph', $$
+ CREATE (:Head {id: 1})-[:PARENT_EDGE_A]->(:Node {id: 2})-[:CHILD_EDGE_A]->(:Node {id: 3})-[:PARENT_EDGE_A]->(:Tail {id: 4}),
+ (:Head {id: 5})-[:PARENT_EDGE_B]->(:Node {id: 6})-[:CHILD_EDGE_B]->(:Node {id: 7})-[:PARENT_EDGE_B]->(:Tail {id: 8}),
+ (:Head {id: 9})-[:CHILD_EDGE_C]->(:Tail {id: 10})
+ $$) AS (a agtype);
+ a
+---
+(0 rows)
+
+--
+-- VLE with the PARENT_EDGEs
+--
+-- should find 6 rows
+SELECT * FROM cypher('vle_inheritance_graph', $$
+ MATCH (a)-[:PARENT_EDGE_A*]->(b)
+ RETURN a.id, b.id
+$$) AS (a_id agtype, b_id agtype);
+ a_id | b_id
+------+------
+ 1 | 2
+ 1 | 3
+ 1 | 4
+ 2 | 3
+ 2 | 4
+ 3 | 4
+(6 rows)
+
+-- should find 3 rows
+SELECT * FROM cypher('vle_inheritance_graph', $$
+ MATCH (a)-[:PARENT_EDGE_A*1]->(b)
+ RETURN a.id, b.id
+$$) AS (a_id agtype, b_id agtype);
+ a_id | b_id
+------+------
+ 1 | 2
+ 2 | 3
+ 3 | 4
+(3 rows)
+
+-- should find 2 rows
+SELECT * FROM cypher('vle_inheritance_graph', $$
+ MATCH (a)-[:PARENT_EDGE_A*2]->(b)
+ RETURN a.id, b.id
+$$) AS (a_id agtype, b_id agtype);
+ a_id | b_id
+------+------
+ 1 | 3
+ 2 | 4
+(2 rows)
+
+-- should find 1 row
+SELECT * FROM cypher('vle_inheritance_graph', $$
+ MATCH (a)-[:PARENT_EDGE_A*3]->(b)
+ RETURN a.id, b.id
+$$) AS (a_id agtype, b_id agtype);
+ a_id | b_id
+------+------
+ 1 | 4
+(1 row)
+
+-- should find 7 rows
+SELECT * FROM cypher('vle_inheritance_graph', $$
+ MATCH (a)-[:PARENT_EDGE_B*]->(b)
+ RETURN a.id, b.id
+$$) AS (a_id agtype, b_id agtype);
+ a_id | b_id
+------+------
+ 5 | 6
+ 5 | 7
+ 5 | 8
+ 9 | 10
+ 6 | 7
+ 6 | 8
+ 7 | 8
+(7 rows)
+
+-- should find 4 rows
+SELECT * FROM cypher('vle_inheritance_graph', $$
+ MATCH (a)-[:PARENT_EDGE_B*1]->(b)
+ RETURN a.id, b.id
+$$) AS (a_id agtype, b_id agtype);
+ a_id | b_id
+------+------
+ 5 | 6
+ 9 | 10
+ 6 | 7
+ 7 | 8
+(4 rows)
+
+-- should find 2 rows
+SELECT * FROM cypher('vle_inheritance_graph', $$
+ MATCH (a)-[:PARENT_EDGE_B*2]->(b)
+ RETURN a.id, b.id
+$$) AS (a_id agtype, b_id agtype);
+ a_id | b_id
+------+------
+ 5 | 7
+ 6 | 8
+(2 rows)
+
+-- should find 1 row
+SELECT * FROM cypher('vle_inheritance_graph', $$
+ MATCH (a)-[:PARENT_EDGE_B*3]->(b)
+ RETURN a.id, b.id
+$$) AS (a_id agtype, b_id agtype);
+ a_id | b_id
+------+------
+ 5 | 8
+(1 row)
+
+--
+-- VLE with the CHILD_EDGEs
+--
+-- should find 1 row
+SELECT * FROM cypher('vle_inheritance_graph', $$
+ MATCH (a)-[:CHILD_EDGE_A*]->(b)
+ RETURN a.id, b.id
+$$) AS (a_id agtype, b_id agtype);
+ a_id | b_id
+------+------
+ 2 | 3
+(1 row)
+
+-- should find 1 row
+SELECT * FROM cypher('vle_inheritance_graph', $$
+ MATCH (a)-[:CHILD_EDGE_A*1]->(b)
+ RETURN a.id, b.id
+$$) AS (a_id agtype, b_id agtype);
+ a_id | b_id
+------+------
+ 2 | 3
+(1 row)
+
+-- should find 2 row
+SELECT * FROM cypher('vle_inheritance_graph', $$
+ MATCH (a)-[:CHILD_EDGE_B*]->(b)
+ RETURN a.id, b.id
+$$) AS (a_id agtype, b_id agtype);
+ a_id | b_id
+------+------
+ 9 | 10
+ 6 | 7
+(2 rows)
+
+-- should find 2 row
+SELECT * FROM cypher('vle_inheritance_graph', $$
+ MATCH (a)-[:CHILD_EDGE_B*1]->(b)
+ RETURN a.id, b.id
+$$) AS (a_id agtype, b_id agtype);
+ a_id | b_id
+------+------
+ 9 | 10
+ 6 | 7
+(2 rows)
+
+--
-- Clean up
--
DROP TABLE start_and_end_points;
@@ -782,6 +1018,24 @@
(1 row)
+SELECT drop_graph('vle_inheritance_graph', true)
--
-- End
--
+NOTICE: drop cascades to 10 other objects
+DETAIL: drop cascades to table vle_inheritance_graph._ag_label_vertex
+drop cascades to table vle_inheritance_graph._ag_label_edge
+drop cascades to table vle_inheritance_graph."Head"
+drop cascades to table vle_inheritance_graph."Tail"
+drop cascades to table vle_inheritance_graph."Node"
+drop cascades to table vle_inheritance_graph."PARENT_EDGE_A"
+drop cascades to table vle_inheritance_graph."PARENT_EDGE_B"
+drop cascades to table vle_inheritance_graph."CHILD_EDGE_A"
+drop cascades to table vle_inheritance_graph."CHILD_EDGE_B"
+drop cascades to table vle_inheritance_graph."CHILD_EDGE_C"
+NOTICE: graph "vle_inheritance_graph" has been dropped
+ drop_graph
+------------
+
+(1 row)
+
diff --git a/regress/sql/cypher_vle.sql b/regress/sql/cypher_vle.sql
index 468135e..5dc5d8f 100644
--- a/regress/sql/cypher_vle.sql
+++ b/regress/sql/cypher_vle.sql
@@ -290,6 +290,108 @@
SELECT drop_graph('mygraph', true);
+
+--
+-- Test VLE for edge inheritance
+--
+
+SELECT create_graph('vle_inheritance_graph');
+SELECT create_vlabel('vle_inheritance_graph', 'Head');
+SELECT create_vlabel('vle_inheritance_graph', 'Tail');
+SELECT create_vlabel('vle_inheritance_graph', 'Node');
+SELECT create_elabel('vle_inheritance_graph', 'PARENT_EDGE_A');
+SELECT create_elabel('vle_inheritance_graph', 'PARENT_EDGE_B');
+SELECT create_elabel('vle_inheritance_graph', 'CHILD_EDGE_A', ARRAY['PARENT_EDGE_A']);
+SELECT create_elabel('vle_inheritance_graph', 'CHILD_EDGE_B', ARRAY['PARENT_EDGE_B']);
+SELECT create_elabel('vle_inheritance_graph', 'CHILD_EDGE_C', ARRAY['CHILD_EDGE_B']);
+
+
+SELECT * FROM cypher('vle_inheritance_graph', $$
+ CREATE (:Head {id: 1})-[:PARENT_EDGE_A]->(:Node {id: 2})-[:CHILD_EDGE_A]->(:Node {id: 3})-[:PARENT_EDGE_A]->(:Tail {id: 4}),
+ (:Head {id: 5})-[:PARENT_EDGE_B]->(:Node {id: 6})-[:CHILD_EDGE_B]->(:Node {id: 7})-[:PARENT_EDGE_B]->(:Tail {id: 8}),
+ (:Head {id: 9})-[:CHILD_EDGE_C]->(:Tail {id: 10})
+ $$) AS (a agtype);
+
+--
+-- VLE with the PARENT_EDGEs
+--
+
+-- should find 6 rows
+SELECT * FROM cypher('vle_inheritance_graph', $$
+ MATCH (a)-[:PARENT_EDGE_A*]->(b)
+ RETURN a.id, b.id
+$$) AS (a_id agtype, b_id agtype);
+
+-- should find 3 rows
+SELECT * FROM cypher('vle_inheritance_graph', $$
+ MATCH (a)-[:PARENT_EDGE_A*1]->(b)
+ RETURN a.id, b.id
+$$) AS (a_id agtype, b_id agtype);
+
+-- should find 2 rows
+SELECT * FROM cypher('vle_inheritance_graph', $$
+ MATCH (a)-[:PARENT_EDGE_A*2]->(b)
+ RETURN a.id, b.id
+$$) AS (a_id agtype, b_id agtype);
+
+-- should find 1 row
+SELECT * FROM cypher('vle_inheritance_graph', $$
+ MATCH (a)-[:PARENT_EDGE_A*3]->(b)
+ RETURN a.id, b.id
+$$) AS (a_id agtype, b_id agtype);
+
+-- should find 7 rows
+SELECT * FROM cypher('vle_inheritance_graph', $$
+ MATCH (a)-[:PARENT_EDGE_B*]->(b)
+ RETURN a.id, b.id
+$$) AS (a_id agtype, b_id agtype);
+
+-- should find 4 rows
+SELECT * FROM cypher('vle_inheritance_graph', $$
+ MATCH (a)-[:PARENT_EDGE_B*1]->(b)
+ RETURN a.id, b.id
+$$) AS (a_id agtype, b_id agtype);
+
+-- should find 2 rows
+SELECT * FROM cypher('vle_inheritance_graph', $$
+ MATCH (a)-[:PARENT_EDGE_B*2]->(b)
+ RETURN a.id, b.id
+$$) AS (a_id agtype, b_id agtype);
+
+-- should find 1 row
+SELECT * FROM cypher('vle_inheritance_graph', $$
+ MATCH (a)-[:PARENT_EDGE_B*3]->(b)
+ RETURN a.id, b.id
+$$) AS (a_id agtype, b_id agtype);
+
+--
+-- VLE with the CHILD_EDGEs
+--
+
+-- should find 1 row
+SELECT * FROM cypher('vle_inheritance_graph', $$
+ MATCH (a)-[:CHILD_EDGE_A*]->(b)
+ RETURN a.id, b.id
+$$) AS (a_id agtype, b_id agtype);
+
+-- should find 1 row
+SELECT * FROM cypher('vle_inheritance_graph', $$
+ MATCH (a)-[:CHILD_EDGE_A*1]->(b)
+ RETURN a.id, b.id
+$$) AS (a_id agtype, b_id agtype);
+
+-- should find 2 row
+SELECT * FROM cypher('vle_inheritance_graph', $$
+ MATCH (a)-[:CHILD_EDGE_B*]->(b)
+ RETURN a.id, b.id
+$$) AS (a_id agtype, b_id agtype);
+
+-- should find 2 row
+SELECT * FROM cypher('vle_inheritance_graph', $$
+ MATCH (a)-[:CHILD_EDGE_B*1]->(b)
+ RETURN a.id, b.id
+$$) AS (a_id agtype, b_id agtype);
+
--
-- Clean up
--
@@ -298,6 +400,8 @@
SELECT drop_graph('cypher_vle', true);
+SELECT drop_graph('vle_inheritance_graph', true)
+
--
-- End
--
diff --git a/src/backend/utils/adt/age_global_graph.c b/src/backend/utils/adt/age_global_graph.c
index 6f7562a..ef5f84b 100644
--- a/src/backend/utils/adt/age_global_graph.c
+++ b/src/backend/utils/adt/age_global_graph.c
@@ -490,11 +490,14 @@
/* get the specific graph OID and namespace (schema) OID */
graph_oid = ggctx->graph_oid;
graph_namespace_oid = get_namespace_oid(ggctx->graph_name, false);
+
/* get the active snapshot */
snapshot = GetActiveSnapshot();
+
/* get the names of all of the edge label tables */
edge_label_names = get_ag_labels_names(snapshot, graph_oid,
LABEL_TYPE_EDGE);
+
/* go through all edge label tables in list */
foreach (lc, edge_label_names)
{
@@ -507,14 +510,18 @@
/* get the edge label name */
edge_label_name = lfirst(lc);
+
/* get the edge label name's OID */
edge_label_table_oid = get_relname_relid(edge_label_name,
graph_namespace_oid);
+
/* open the relation (table) and begin the scan */
graph_edge_label = heap_open(edge_label_table_oid, ShareLock);
scan_desc = heap_beginscan(graph_edge_label, snapshot, 0, NULL);
+
/* get the tupdesc - we don't need to release this one */
tupdesc = RelationGetDescr(graph_edge_label);
+
/* bail if the number of columns differs */
if (tupdesc->natts != 4)
{
@@ -990,60 +997,34 @@
return ee->end_vertex_id;
}
-List* getChildren(GRAPH_global_context *ggctx)
+/* Function to return all the child edges from the given parent edge */
+List* get_child_edges(GRAPH_global_context *ggctx, char* edge_label_name)
{
-
- Oid graph_oid;
Oid graph_namespace_oid;
- Snapshot snapshot;
- List *edge_label_names = NIL;
- ListCell *lc;
- List *children = NIL;
+ Oid edge_label_table_oid;
+ List *child_edges_oid = NIL;
+
+ /* return the empty list */
+ if (edge_label_name == NULL)
+ {
+ return child_edges_oid;
+ }
/* get the specific graph OID and namespace (schema) OID */
- graph_oid = ggctx->graph_oid;
graph_namespace_oid = get_namespace_oid(ggctx->graph_name, false);
- /* get the active snapshot */
- snapshot = GetActiveSnapshot();
- /* get the names of all of the edge label tables */
- edge_label_names = get_ag_labels_names(snapshot, graph_oid,
- LABEL_TYPE_EDGE);
- /* go through all edge label tables in list */
- foreach (lc, edge_label_names)
+
+ /* get the edge label name's OID */
+ edge_label_table_oid = get_relname_relid(edge_label_name,
+ graph_namespace_oid);
+
+ /* verify if the current edge has child edges */
+ if(has_subclass(edge_label_table_oid))
{
- Relation graph_edge_label;
- HeapScanDesc scan_desc;
- HeapTuple tuple;
- char *edge_label_name;
- Oid edge_label_table_oid;
- TupleDesc tupdesc;
-
-
- /* get the edge label name */
- edge_label_name = lfirst(lc);
-
- /* get the edge label name's OID */
- edge_label_table_oid = get_relname_relid(edge_label_name,
- graph_namespace_oid);
-
- List *child_edges_oid_temp = NIL;
-
- if( has_subclass(edge_label_table_oid))
- {
- child_edges_oid_temp = find_inheritance_children(edge_label_table_oid, NoLock);
-
- //loop through the child edges
- ListCell *lc1;
- foreach (lc1, child_edges_oid_temp)
- {
- Oid child_edge_oid = lfirst_oid(lc1);
- children = lappend_oid(children, child_edge_oid);
- }
- }
-
+ /* get the edge's child labels OIDs */
+ child_edges_oid = find_all_inheritors(edge_label_table_oid, NoLock, NULL);
}
-
- return children;
+
+ return child_edges_oid;
}
/* PostgreSQL SQL facing functions */
diff --git a/src/backend/utils/adt/age_vle.c b/src/backend/utils/adt/age_vle.c
index b123d26..7feaf69 100644
--- a/src/backend/utils/adt/age_vle.c
+++ b/src/backend/utils/adt/age_vle.c
@@ -335,7 +335,8 @@
int num_edge_property_constraints = 0;
int num_edge_properties = 0;
List *child_oid_list = NIL;
- bool isChild = false;
+ ListCell *lc;
+ bool is_child = false;
GRAPH_global_context *ggctx = NULL;
/*get the graph global context */
@@ -363,11 +364,14 @@
/* get the edge label name from the oid */
edge_label_name = get_rel_name(get_edge_entry_label_table_oid(ee));
+
/* get our edge's properties */
edge_property = DATUM_GET_AGTYPE_P(get_edge_entry_properties(ee));
+
/* get the containers */
agtc_edge_property_constraint = &vlelctx->edge_property_constraint->root;
agtc_edge_property = &edge_property->root;
+
/* get the number of properties in the edge to be matched */
num_edge_properties = AGTYPE_CONTAINER_SIZE(agtc_edge_property);
@@ -381,18 +385,18 @@
return false;
}
- /* get the children list of the current VLE_local_context*/
- child_oid_list = getChildren(ggctx);
- ListCell *lc;
- /* check if child exists or not*/
+ /* get the children list of the current VLE_local_context edge label name */
+ child_oid_list = get_child_edges(ggctx, vlelctx->edge_label_name);
+
+ /* check if child exists or not */
foreach(lc, child_oid_list)
{
Oid child_oid = lfirst_oid(lc);
char *child_name = get_rel_name(child_oid);
if (strcmp(edge_label_name, child_name) == 0)
{
- isChild = true;
+ is_child = true;
}
}
@@ -400,7 +404,7 @@
* Check for a label constraint. If the label name is NULL, there isn't one.
*/
if (vlelctx->edge_label_name != NULL &&
- strcmp(vlelctx->edge_label_name, edge_label_name) != 0 && !isChild)
+ strcmp(vlelctx->edge_label_name, edge_label_name) != 0 && !is_child)
{
return false;
}
diff --git a/src/include/utils/age_global_graph.h b/src/include/utils/age_global_graph.h
index 7801141..46b14cc 100644
--- a/src/include/utils/age_global_graph.h
+++ b/src/include/utils/age_global_graph.h
@@ -60,5 +60,5 @@
Datum get_edge_entry_properties(edge_entry *ee);
graphid get_edge_entry_start_vertex_id(edge_entry *ee);
graphid get_edge_entry_end_vertex_id(edge_entry *ee);
-List* getChildren(GRAPH_global_context *ggctx);
+List* get_child_edges(GRAPH_global_context *ggctx, char* edge_label_name);
#endif