1

I was working on the internals or architecture of Apache-Age and i know that how graph, vertex, or edge is created in Apache-Age but i am confused how it's been assigned an graphid in the memory.

For Graph Creation:

SELECT create_graph('graph_name');

For vertex creation:

SELECT * 
FROM cypher('graph_name', $$
    CREATE (n)
$$) as (v agtype);

For edge Creation:

SELECT * 
FROM cypher('graph_name', $$
    MATCH (a:label), (b:label)
    WHERE a.property = 'Node A' AND b.property = 'Node B'
    CREATE (a)-[e:RELTYPE]->(b)
    RETURN e
$$) as (e agtype);

Now, i am confused that what happens inside the memory like how graph is assigned the memory and then how vertex and edges are assign these graphids in the memory. Also share the data structures used by Apache-Age in storing that graph database in the memory and how other properties are given graphid.

2 Answers2

1

The vertex and edge are assigned to the graphid based on the cypher query is being called (i.e. the first parameter) it is checked on the backend and gets the Object ID of that graph with the matched graph name and assigning that to them.
You need to check the source code to get everything connected.

In your queries:

1- A graph named 'graph_name' has got a unique Object ID and get added to the graphs table as well as it is stored in a hash-table for quick-accessing the current exiting tables

SELECT create_graph('graph_name');

2- Get the Object ID of the graph with name 'graph_name' and create a vertex and connect them together and store it

SELECT * 
FROM cypher('graph_name', $$
    CREATE (n)
$$) as (v agtype);

3- Do similar.

AGE uses a custom data type called agtype, which is the only data type returned by AGE. Agtype is a superset of Json and a custom implementation of JsonB. Here is the data-structure used, also you can check that on the source code on github.


/*
 * agtype_value: In-memory representation of agtype.  This is a convenient
 * deserialized representation, that can easily support using the "val"
 * union across underlying types during manipulation.  The agtype on-disk
 * representation has various alignment considerations.
 */
struct agtype_value
{
    enum agtype_value_type type; /* Influences sort order */

    union
    {
        int64 int_value; /* Cypher 8 byte Integer */
        float8 float_value; /* Cypher 8 byte Float */
        Numeric numeric;
        bool boolean;
        struct
        {
            int len;
            char *val; /* Not necessarily null-terminated */
        } string; /* String primitive type */

        struct
        {
            int num_elems;
            agtype_value *elems;
            bool raw_scalar; /* Top-level "raw scalar" array? */
        } array; /* Array container type */

        struct
        {
            int num_pairs; /* 1 pair, 2 elements */
            agtype_pair *pairs;
        } object; /* Associative container type */

        struct
        {
            int len;
            agtype_container *data;
        } binary; /* Array or object, in on-disk format */
    } val;
};

References:

0

The graphid.c file deals with graphid operations, check it on this link

https://github.com/apache/age/blob/master/src/backend/utils/adt/graphid.c

It has the make_graphid function that does a operation which will always return the same graphid, given the same arguments:

graphid make_graphid(const int32 label_id, const int64 entry_id)
{
    uint64 tmp;

    if (!label_id_is_valid(label_id))
    {
        ereport(ERROR, (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
                        errmsg("label_id must be %d .. %d",
                               LABEL_ID_MIN, LABEL_ID_MAX)));
    }
    if (!entry_id_is_valid(entry_id))
    {
        ereport(ERROR,
                (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
                 errmsg("entry_id must be " INT64_FORMAT " .. " INT64_FORMAT,
                        ENTRY_ID_MIN, ENTRY_ID_MAX)));
    }

    tmp = (((uint64)label_id) << ENTRY_ID_BITS) |
          (((uint64)entry_id) & ENTRY_ID_MASK);

    return (graphid)tmp;
}
Marco Souza
  • 296
  • 7