This is an automated email from the ASF dual-hosted git repository.
jgemignani pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/age.git
The following commit(s) were added to refs/heads/master by this push:
new 7628c85 Barbell graph generation (#648)
7628c85 is described below
commit 7628c85edbb95bbb6cf7caa7501f12c1aa40c9f2
Author: Marco Aurélio Silva de Souza Júnior
<[email protected]>
AuthorDate: Fri Feb 17 15:45:05 2023 -0300
Barbell graph generation (#648)
* Added function to create a Barbell Graph
* Created auxiliary function to get_next_val_internal;
* Currently creates a bridge of no vertexes between graphs,
will be implemented next.
* Added signature to age_create_barbell_graph
* Moved bracket to next line to macth code standards
* Fixed patterns to match code standards
* moved PG_FUNCTION_INFO_V1(age_create_barbell_graph) next to
age_create_barbell_graph function;
* added brackets to if/else conditions if just one line;
* moved get_nextval_internal auxiliary function to the beggining of
the file.
---
age--1.2.0.sql | 13 +++
src/backend/utils/graph_generation.c | 156 ++++++++++++++++++++++++++++++++++-
2 files changed, 165 insertions(+), 4 deletions(-)
diff --git a/age--1.2.0.sql b/age--1.2.0.sql
index 3075824..e34b3c9 100644
--- a/age--1.2.0.sql
+++ b/age--1.2.0.sql
@@ -4182,6 +4182,19 @@ CALLED ON NULL INPUT
PARALLEL SAFE
AS 'MODULE_PATHNAME';
+CREATE FUNCTION ag_catalog.age_create_barbell_graph(graph_name name,
+ graph_size int,
+ bridge_size int,
+ node_label name = NULL,
+ node_properties agtype = NULL,
+ edge_label name = NULL,
+ edge_properties agtype = NULL)
+RETURNS void
+LANGUAGE c
+CALLED ON NULL INPUT
+PARALLEL SAFE
+AS 'MODULE_PATHNAME';
+
CREATE FUNCTION ag_catalog.age_prepare_cypher(cstring, cstring)
RETURNS boolean
LANGUAGE c
diff --git a/src/backend/utils/graph_generation.c
b/src/backend/utils/graph_generation.c
index 49da5f8..80ef85f 100644
--- a/src/backend/utils/graph_generation.c
+++ b/src/backend/utils/graph_generation.c
@@ -41,14 +41,35 @@
#include "catalog/ag_graph.h"
#include "catalog/ag_label.h"
+#include "commands/graph_commands.h"
#include "commands/label_commands.h"
#include "utils/graphid.h"
-#include "commands/graph_commands.h"
#include "utils/load/age_load.h"
#include "utils/load/ag_load_edges.h"
#include "utils/load/ag_load_labels.h"
+int64 get_nextval_internal(graph_cache_data* graph_cache,
+ label_cache_data* label_cache);
+/*
+ * Auxiliary function to get the next internal value in the graph,
+ * so a new object (node or edge) graph id can be composed.
+ */
+
+int64 get_nextval_internal(graph_cache_data* graph_cache,
+ label_cache_data* label_cache)
+{
+ Oid obj_seq_id;
+ char* label_seq_name_str;
+
+ label_seq_name_str = NameStr(label_cache->seq_name);
+ obj_seq_id = get_relname_relid(label_seq_name_str,
+ graph_cache->namespace);
+
+ return nextval_internal(obj_seq_id, true);
+}
+
+
PG_FUNCTION_INFO_V1(create_complete_graph);
/*
@@ -125,7 +146,6 @@ Datum create_complete_graph(PG_FUNCTION_ARGS)
if (!graph_exists(graph_name_str))
{
DirectFunctionCall1(create_graph, CStringGetDatum(graph_name));
-
}
graph_id = get_graph_oid(graph_name_str);
@@ -194,10 +214,138 @@ Datum create_complete_graph(PG_FUNCTION_ARGS)
insert_edge_simple(graph_id, edge_name_str,
object_graph_id, start_vertex_graph_id,
end_vertex_graph_id, props);
-
}
}
-
PG_RETURN_VOID();
}
+
+PG_FUNCTION_INFO_V1(age_create_barbell_graph);
+
+/*
+ * The barbell graph is two complete graphs connected by a bridge path
+ * Syntax:
+ * ag_catalog.age_create_barbell_graph(graph_name Name,
+ * m int,
+ * n int,
+ * vertex_label_name Name DEFAULT = NULL,
+ * vertex_properties agtype DEFAULT = NULL,
+ * edge_label_name Name DEAULT = NULL,
+ * edge_properties agtype DEFAULT = NULL)
+ * Input:
+ *
+ * graph_name - Name of the graph to be created.
+ * m - number of vertices in one complete graph.
+ * n - number of vertices in the bridge path.
+ * vertex_label_name - Name of the label to assign each vertex to.
+ * vertex_properties - Property values to assign each vertex. Default is NULL
+ * edge_label_name - Name of the label to assign each edge to.
+ * edge_properties - Property values to assign each edge. Default is NULL
+ *
+ * https://en.wikipedia.org/wiki/Barbell_graph
+ */
+
+Datum age_create_barbell_graph(PG_FUNCTION_ARGS)
+{
+ FunctionCallInfo arguments;
+ Oid graph_oid;
+ Name graph_name;
+ char* graph_name_str;
+
+ int64 start_node_index, end_node_index, nextval;
+
+ Name node_label_name = NULL;
+ int32 node_label_id;
+ char* node_label_str;
+
+ Name edge_label_name;
+ int32 edge_label_id;
+ char* edge_label_str;
+
+ graphid object_graph_id;
+ graphid start_node_graph_id;
+ graphid end_node_graph_id;
+
+ graph_cache_data* graph_cache;
+ label_cache_data* edge_cache;
+
+ agtype* properties = NULL;
+
+ arguments = fcinfo;
+
+ // create two separate complete graphs
+ DirectFunctionCall4(create_complete_graph, arguments->arg[0],
+ arguments->arg[1],
+ arguments->arg[5],
+ arguments->arg[3]);
+ DirectFunctionCall4(create_complete_graph, arguments->arg[0],
+ arguments->arg[1],
+ arguments->arg[5],
+ arguments->arg[3]);
+
+ // Handling remaining arguments
+ /*
+ * graph_name: doesn't need to validate, since the create_complete_graph
+ * function already does that.
+ */
+ graph_name = PG_GETARG_NAME(0);
+ graph_name_str = NameStr(*graph_name);
+ graph_oid = get_graph_oid(graph_name_str);
+
+ /*
+ * int64 bridge_size: currently only stays at zero.
+ * to do: implement bridge with variable number of nodes.
+ */
+ if (PG_ARGISNULL(2) || PG_GETARG_INT32(2) < 0 )
+ {
+ ereport(ERROR, (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
+ errmsg("Bridge size must not be NULL or lower than 0")));
+ }
+
+ // node label: if null, gets default label, which is "_ag_label_vertex"
+ if (PG_ARGISNULL(3))
+ {
+ namestrcpy(node_label_name, AG_DEFAULT_LABEL_VERTEX);
+ }
+ else
+ {
+ node_label_name = PG_GETARG_NAME(3);
+ }
+ node_label_str = NameStr(*node_label_name);
+ node_label_id = get_label_id(node_label_str, graph_oid);
+
+ /*
+ * edge_label: doesn't need to validate, since the create_complete_graph
+ * function already does that.
+ */
+ edge_label_name = PG_GETARG_NAME(5);
+ edge_label_str = NameStr(*edge_label_name);
+ edge_label_id = get_label_id(edge_label_str, graph_oid);
+
+ /*
+ * Fetching caches to get next values for graph id's, and access nodes
+ * to be connected with edges.
+ */
+ graph_cache = search_graph_name_cache(graph_name_str);
+ edge_cache = search_label_name_graph_cache(edge_label_str,graph_oid);
+
+ // connect a node from each graph
+ start_node_index = 1; // first created node, from the first complete graph
+ end_node_index = arguments->arg[1]*2; // last created node, second graph
+
+ // next index to be assigned to a node or edge
+ nextval = get_nextval_internal(graph_cache, edge_cache);
+
+ // build the graph id's of the edge to be created
+ object_graph_id = make_graphid(edge_label_id, nextval);
+ start_node_graph_id = make_graphid(node_label_id, start_node_index);
+ end_node_graph_id = make_graphid(node_label_id, end_node_index);
+ properties = create_empty_agtype();
+
+ // connect two nodes
+ insert_edge_simple(graph_oid, edge_label_str,
+ object_graph_id, start_node_graph_id,
+ end_node_graph_id, properties);
+
+ PG_RETURN_VOID();
+}