DEV Community

Mohamed Mokhtar
Mohamed Mokhtar

Posted on

2 1 1 1 1

Under the hood of create_graph at Apache AGE

Introduction

The following article I am going to let you know more about what is going inside the Apache AGE back-end from the perspective of PostgreSQL and give you a brief introduction about the graph creation on PostgreSQL using Apache AGE.

under-the-hood

Let's

Prerequisites

  • PostgreSQL
  • Apache AGE

if you don't have them visit my blogs and you will learn how to install them

The beginning

Mostly everything in Apache AGE is a function that is written in C and being loaded to PostgreSQL as any PL/SQL function

So, create_graph is a function and it is defined on age--1.3.0.sql for example (varies based on version being used)

That how does it look like

CREATE FUNCTION ag_catalog.create_graph(graph_name name)
RETURNS void
LANGUAGE c
AS 'MODULE_PATHNAME';
Enter fullscreen mode Exit fullscreen mode

How it is implemented?


PG_FUNCTION_INFO_V1(create_graph);

/* function that is evoked for creating a graph */
Datum create_graph(PG_FUNCTION_ARGS)
{
    char *graph;
    Name graph_name;
    char *graph_name_str;
    Oid nsp_id;

    //if no argument is passed with the function, graph name cannot be null
    if (PG_ARGISNULL(0))
    {
        ereport(ERROR, (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
                        errmsg("graph name can not be NULL")));
    }

    //gets graph name as function argument
    graph_name = PG_GETARG_NAME(0);  

    graph_name_str = NameStr(*graph_name);

    //checking if the name of the graph falls under the pre-decided graph naming conventions(regex)
    if (!is_valid_graph_name(graph_name_str))
    {
        ereport(ERROR, (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
                        errmsg("graph name is invalid")));
    }

    //graph name must be unique, a graph with the same name should not exist
    if (graph_exists(graph_name_str))
    {
        ereport(ERROR,
                (errcode(ERRCODE_UNDEFINED_SCHEMA),
                 errmsg("graph \"%s\" already exists", graph_name_str)));
    }

    nsp_id = create_schema_for_graph(graph_name);

    //inserts the graph info into the relation which has all the other existing graphs info
    insert_graph(graph_name, nsp_id);  

    //Increment the Command counter before create the generic labels.
    CommandCounterIncrement();

    //Create the default label tables
    graph = graph_name->data;
    create_label(graph, AG_DEFAULT_LABEL_VERTEX, LABEL_TYPE_VERTEX, NIL);
    create_label(graph, AG_DEFAULT_LABEL_EDGE, LABEL_TYPE_EDGE, NIL);

    ereport(NOTICE,
            (errmsg("graph \"%s\" has been created", NameStr(*graph_name))));

    //according to postgres specification of c-language functions if function returns void this is the syntax
    PG_RETURN_VOID(); 
}
Enter fullscreen mode Exit fullscreen mode

What are the most interesting parts

  • Creating a namespace (schema) for that graph
    /*
     * This is the same with running the following SQL statement.
     *
     * CREATE SCHEMA `graph_name`
     *   CREATE SEQUENCE `LABEL_ID_SEQ_NAME`
     *     AS integer
     *     MAXVALUE `LABEL_ID_MAX`
     *     CYCLE
     * The sequence will be used to assign a unique id to a label in the graph.
     *
     * schemaname doesn't have to be graph_name but the same name is used so
     * that users can find the backed schema for a graph only by its name.
     *
     * ProcessUtilityContext of this command is PROCESS_UTILITY_SUBCOMMAND
     * so the event trigger will not be fired.
     */

    nsp_id = create_schema_for_graph(graph_name);
Enter fullscreen mode Exit fullscreen mode
  • Creates new entry on the ag_catalog at the graphs table
// INSERT INTO ag_catalog.ag_graph VALUES (graph_name, nsp_id)
// = 
    insert_graph(graph_name, nsp_id);  
Enter fullscreen mode Exit fullscreen mode
  • The following statements creates a table for holding the labels of (vertex and edges)
    graph = graph_name->data;
    create_label(graph, AG_DEFAULT_LABEL_VERTEX, LABEL_TYPE_VERTEX, NIL);
    create_label(graph, AG_DEFAULT_LABEL_EDGE, LABEL_TYPE_EDGE, NIL);
Enter fullscreen mode Exit fullscreen mode

Conclusion

  • Create namespace (schema)
  • Insert into ag_catalog graphs table a new entry for it
  • Create Vertex labels table inside the create namespace
  • Create Edge labels table inside the create namespace

See you in next AGE statement under the hood

Resources and References

API Trace View

How I Cut 22.3 Seconds Off an API Call with Sentry

Struggling with slow API calls? Dan Mindru walks through how he used Sentry's new Trace View feature to shave off 22.3 seconds from an API call.

Get a practical walkthrough of how to identify bottlenecks, split tasks into multiple parallel tasks, identify slow AI model calls, and more.

Read more →

Top comments (0)

The Most Contextual AI Development Assistant

Pieces.app image

Our centralized storage agent works on-device, unifying various developer tools to proactively capture and enrich useful materials, streamline collaboration, and solve complex problems through a contextual understanding of your unique workflow.

👥 Ideal for solo developers, teams, and cross-company projects

Learn more