How AGE is executed on top of PostgreSQL
Tags: postgres, apacheage, age, database
Published: 2023-07-05 22:05:27


![Summary](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/yiayr403atnih47nvkmq.png)

### Hey everyone
Today I will explain to you how Apache AGE works in top of **Postgresql** it is considered as a complimentary part of the old blogs I have published before you can find them on my profile, lets get started!

First of all thanks to **Postgresql** being friendly with their extension they have taken into consideration that there are some **HOOKS** can be added to their source code one of them which is mainly used by **Apache AGE** is 
**post_parse_analyze_hook**

### What is post_parse_analyze_hook?
it is a function address assigned to **NULL** on Postgresql 

![Null starte](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/pvry2cffecnlz2fvbjvj.png)

And if it gets an address it will be called, i.e. when an extension is loaded on **Postgresql session** 
![Loadedsession](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/p115zm0dx4fmlh4cjn99.png)

And it has added an effect on that **Postgresql** variable when the queries are being executed that hook will be used.
When does it used? That's the decision of **PostgreSQL** not extensions' **decision** so that in the current time it is being called after the analyze and parse state.

![AGE](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/obaa5k4v4t943dk0se2g.png)


### What is attached to that function call? 

**ParseState** and **QueryTree** and **JumpleState**. If you miss any part of those terminologies you can find POSTS related to them on my blog also.


### What happens after Apache AGE gets that calling and what function is being used for that?
```C
	if (post_parse_analyze_hook)
		(*post_parse_analyze_hook) (pstate, query, jstate);

```
Apache AGE has set post_parse_analyze_hook to **post_parse_analyze**
Through the following code at `src/cypher/anaylze`
```C
void post_parse_analyze_init(void)
{
    prev_post_parse_analyze_hook = post_parse_analyze_hook;
    post_parse_analyze_hook = post_parse_analyze;
}
```

post_parse_analyze is a part of apache age and it's purpose is?

A: To change every cyhper call to subquery node 
Q: How?
Post parsing: i.e. second parsing.

- Go to every part of the query in the from statement (because our cypher call is being executed at the FROM part)

How to find them? In the parse state we can find them on field **RangeTblEntry**

For every entry of those we check them if it is 
- Function call
- Subquery

- If a function call it may be a cypher call so we need to make a check here [**Simply string matching**]

- **Got it**? but why do we need to check another **subqueries**? because their from list may consist of a cypher call (We are solving that recursively) 


What function does that **conversion**? **convert_cypher_walker**

find cypher() calls in **FROM** clauses and convert them to SELECT **subqueries**

![cypherwalker](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/wjh3k5tr1icyaqsohh72.png)

- KEEPS **CHECKING** a NODE if it is an **RTETblEntry** (the nodes on the FROM list)

```C
if (they are function as cypher is defined as function) { 
  // check if it is cypher or not 
  if (cypher) CONVERT TO SUB_QUERY
}
if there is real existing sub query check if it contains a cypher in their FROM list or not (i.e. RECURSIVE CALL)
```

**MISSION** : _UPDATES THE QUERY TREE TO ADD THE CYPHER SUB QUERIES INSTEAD OF CYPHER FUNCTION CALL_

Portion of the code of **convert_cypher_walker**
```C
static bool convert_cypher_walker(Node *node, ParseState *pstate)
{
    if (!node)
        return false;

    if (IsA(node, RangeTblEntry))
    {
        RangeTblEntry *rte = (RangeTblEntry *)node;

        switch (rte->rtekind)
        {
        case RTE_SUBQUERY:
            // traverse other RTE_SUBQUERYs
            return convert_cypher_walker((Node *)rte->subquery, pstate);
        case RTE_FUNCTION:
            if (is_rte_cypher(rte))
                convert_cypher_to_subquery(rte, pstate);
            return false;
        default:
            return false;
        }
    }
```


Thanks for reading till here I have reached to an end of today's blog I hope you feel it has given you good understanding of **Postgresql** extensions and AGE 

```sh
                        _ _                
   __ _  ___   ___   __| | |__  _   _  ___ 
  / _` |/ _ \ / _ \ / _` | '_ \| | | |/ _ \
 | (_| | (_) | (_) | (_| | |_) | |_| |  __/
  \__, |\___/ \___/ \__,_|_.__/ \__, |\___|
  |___/                         |___/      

```


### Resources & References

-     https://github.com/apache/age
-     https://age.apache.org/
-     https://github.com/postgres/postgres/