Now that we saw how to develop a function to create a complete graph on Apache AGE, we are going to create a function to develop a Barbell graph - two complete graphs (cliques) connected by a bridge path. We will guide you through each step, explaining the components of the function to help you understand how it works.
We start by declaring our function with the macro PG_FUNCTION_INFO_V1
. This is used in PostgreSQL to bind our C function to SQL commands. In our case, we're defining a function called age_create_barbell_graph
.
PG_FUNCTION_INFO_V1(age_create_barbell_graph);
This function takes a graph name, the number of vertices in each complete graph (m), the number of vertices in the bridge path (n), labels for vertices and edges, and properties for vertices and edges.
Our main function is age_create_barbell_graph
, and it uses the PG_FUNCTION_ARGS
macro as a shortcut to pass arguments from SQL commands to our C function.
Datum age_create_barbell_graph(PG_FUNCTION_ARGS)
We need to declare all variables in the beginning of the function, otherwise it will issue an warning when compiling: ISO C90 forbids mixed declarations and code [-Wdeclaration-after-statement]
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;
We have to check if any mandatory arguments are null. This is essential because it prevents any errors from occurring later in our function. For example, if the graph name or size is null or invalid, the function throws an error.
Here we check the arguments and process it immediately after:
// Checking for possible NULL arguments
// Name graph_name
if (PG_ARGISNULL(0))
{
ereport(ERROR, (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
errmsg("Graph name cannot be NULL")));
}
graph_name = PG_GETARG_NAME(0);
graph_name_str = NameStr(*graph_name);
// int graph size (number of nodes in each complete graph)
if (PG_ARGISNULL(1) && PG_GETARG_INT32(1) < 3)
{
ereport(ERROR, (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
errmsg("Graph size cannot be NULL or lower than 3")));
}
/*
* 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 cannot 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);
/*
* Name edge_label
*/
if (PG_ARGISNULL(5))
{
ereport(ERROR, (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
errmsg("edge label can not be NULL")));
}
edge_label_name = PG_GETARG_NAME(5);
edge_label_str = NameStr(*edge_label_name);
We use DirectFunctionCall4
to call the function create_complete_graph
twice - once for each complete graph in our Barbell Graph. This function creates a complete graph with a given name, size, edge label, and vertex label.
DirectFunctionCall4(create_complete_graph, arguments->arg[0],
arguments->arg[1],
arguments->arg[5],
arguments->arg[3]);
We need to get the unique identifiers (oid
) for our graph and labels. This is done using the get_graph_oid
and get_label_id
functions.
graph_oid = get_graph_oid(graph_name_str);
node_label_id = get_label_id(node_label_str, graph_oid);
edge_label_id = get_label_id(edge_label_str, graph_oid);
The graph and edge caches are then searched to provide access to necessary nodes to be connected with edges later.
graph_cache = search_graph_name_cache(graph_name_str);
edge_cache = search_label_name_graph_cache(edge_label_str,graph_oid);
We use the get_nextval_internal
function to get the next internal value in the graph, so a new object (node or edge) graph id can be composed.
nextval = get_nextval_internal(graph_cache, edge_cache);
Finally, we use the insert_edge_simple
function to connect two nodes - one from each complete graph. This creates the bridge that links our two complete graphs into a Barbell Graph.
insert_edge_simple(graph_oid, edge_label_str,
object_graph_id, start_node_graph_id,
end_node_graph_id, properties);
And that's it! Our function ends by returning void using PG_RETURN_VOID()
, meaning it doesn't return any value. The graph is directly created in the database.
Including the Function in the PostgreSQL Catalog
The function you've just created needs to be recognized and executed by PostgreSQL. To achieve this, we have to add a corresponding entry in PostgreSQL's catalog. This is done by including the function in the age--1.3.0.sql
file. This file is the SQL script that sets up the PostgreSQL functions when Apache AGE is installed.
Here's the code you need to add to the age--1.3.0.sql
file:
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';
This CREATE FUNCTION
command adds our age_create_barbell_graph
function to the ag_catalog
, which is the PostgreSQL catalog for Apache AGE.
The structure of the CREATE FUNCTION
command matches the structure of the C function we've defined earlier. The parameters, their types, and their default values are all listed here, along with the function's return type (void
).
LANGUAGE c
specifies that the function is written in C.
CALLED ON NULL INPUT
means the function will still be called even if some of its arguments are null.
PARALLEL SAFE
indicates that this function can be safely run in parallel mode by PostgreSQL.
Finally, 'MODULE_PATHNAME'
is a placeholder for the shared library where the C function is located.
After adding this to the age--1.3.0.sql
file and installing Apache AGE, PostgreSQL will recognize and be able to execute your age_create_barbell_graph
function. Now you can use this function to create barbell graphs directly from your SQL commands!
Calling the Function from the psql Interface
Now that our function is defined and registered with PostgreSQL, let's go over how to call it from the psql
interface.
Here are the commands to load the Apache AGE extension and set the search path:
CREATE EXTENSION age;
LOAD 'age';
SET search_path TO ag_catalog;
SET search_path TO ag_catalog;
is setting the search path to ag_catalog
, the PostgreSQL catalog for Apache AGE. This means that the function we're going to call is located in this catalog.
Now we can call our age_create_barbell_graph
function. Here's the command to do so:
SELECT age_create_barbell_graph('barbell',5,0,'vlabel',NULL,'elabel',NULL);
We use a SELECT
statement to call the function. The parameters passed are the name of the graph ('barbell'), the number of vertices in each complete graph (5), the number of vertices in the bridge path (0), and the labels for the vertices and edges ('vlabel' and 'elabel', respectively). We're passing NULL
for the properties of vertices and edges as we haven't defined any.
As you might notice, the bridge size and properties arguments are not implemented in this function. That's an exercise for you - try modifying the function to include these features, to further enhance the functionality and flexibility of your barbell graphs!
This concludes our guide on developing a Barbell graph function using Apache AGE. Remember that practice is key in mastering these concepts, so don't hesitate to experiment and try implementing additional features yourself!
I make these posts in order to guide people into the development of a new technology. If you find anything incorrect, I urge you to comment below so I can fix it. Thanks!
Check Apache AGE: https://age.apache.org/.
Overview — Apache AGE master documentation: https://age.apache.org/age-manual/master/intro/overview.html.
GitHub - apache/age: https://github.com/apache/age
Top comments (0)