<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Marco Aurélio Silva de Souza Júnior</title>
    <description>The latest articles on DEV Community by Marco Aurélio Silva de Souza Júnior (@markgomer).</description>
    <link>https://dev.to/markgomer</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F1018237%2F701414bb-a5c9-48d3-9c91-0d66f9193430.jpeg</url>
      <title>DEV Community: Marco Aurélio Silva de Souza Júnior</title>
      <link>https://dev.to/markgomer</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/markgomer"/>
    <language>en</language>
    <item>
      <title>How to use the official Apache AGE docker image</title>
      <dc:creator>Marco Aurélio Silva de Souza Júnior</dc:creator>
      <pubDate>Thu, 10 Aug 2023 15:11:31 +0000</pubDate>
      <link>https://dev.to/markgomer/how-to-use-the-official-apache-age-docker-image-5baf</link>
      <guid>https://dev.to/markgomer/how-to-use-the-official-apache-age-docker-image-5baf</guid>
      <description>&lt;h2&gt;
  
  
  Pre-requisites
&lt;/h2&gt;

&lt;p&gt;For this guide I'll be using Windows 11 with Arch Linux installed on WSL2, and Docker integrated. Docker Desktop needs to be installed on Windows. &lt;br&gt;
This may work on anything that runs Docker, though.&lt;/p&gt;


&lt;h2&gt;
  
  
  Getting the image
&lt;/h2&gt;

&lt;p&gt;Make sure docker daemon is running by starting Docker Desktop.&lt;/p&gt;

&lt;p&gt;If you issue &lt;code&gt;docker ps&lt;/code&gt; and it doesn't throw an error, you may be good to go.&lt;/p&gt;

&lt;p&gt;Now go to the official &lt;a href="https://hub.docker.com/r/apache/age" rel="noopener noreferrer"&gt;Apache AGE docker hub page&lt;/a&gt; and copy the command:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;docker pull apache/age
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Run it on WSL terminal and it should appear in the list of docker images:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;docker image ls
REPOSITORY          TAG           IMAGE ID       CREATED        SIZE
apache/age          latest        dc3b65a4c6fc   44 hours ago   1.34GB
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  Running the container
&lt;/h2&gt;

&lt;p&gt;Now that you have the image, you need to run a container of it, but it needs very specific variables as per user documentation. From WSL terminal paste:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;docker run \
    --name age  \
    -p 5455:5432 \
    -e POSTGRES_USER=postgresUser \
    -e POSTGRES_PASSWORD=postgresPW \
    -e POSTGRES_DB=postgresDB \
    -d \
    apache/age
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Let me break down the command:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;&lt;code&gt;docker run&lt;/code&gt;: This is the basic command to start a new Docker container.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code&gt;--name age&lt;/code&gt;: Assigns the name &lt;code&gt;age&lt;/code&gt; to the container. This name can be used to reference the container in other Docker commands.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code&gt;-p 5455:5432&lt;/code&gt;: Maps port 5432 inside the Docker container to port 5455 on the host machine (WSL). This is useful for connecting to the PostgreSQL service running inside the container from the host system.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code&gt;-e POSTGRES_USER=postgresUser&lt;/code&gt;: Sets an environment variable &lt;code&gt;POSTGRES_USER&lt;/code&gt; inside the container, assigning it the value &lt;code&gt;postgresUser&lt;/code&gt;. This is the username used to connect to the PostgreSQL database.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code&gt;-e POSTGRES_PASSWORD=postgresPW&lt;/code&gt;: Sets an environment variable &lt;code&gt;POSTGRES_PASSWORD&lt;/code&gt; inside the container, assigning it the value &lt;code&gt;postgresPW&lt;/code&gt;. This is the password used to connect to the PostgreSQL database.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code&gt;-e POSTGRES_DB=postgresDB&lt;/code&gt;: Sets an environment variable &lt;code&gt;POSTGRES_DB&lt;/code&gt; inside the container, assigning it the value &lt;code&gt;postgresDB&lt;/code&gt;. This is the name of the database to which connections will be made by default.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code&gt;-d&lt;/code&gt;: Runs the container in detached mode. This means that the container will run in the background, and you won't see its output in the terminal.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code&gt;apache/age&lt;/code&gt;: This is the name of the Docker image to be used for the container. It refers to a specific image that has Apache AGE installed and configured.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;With that there will be a running container on background:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fcgg9ew6ej8eg5ekov3c4.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fcgg9ew6ej8eg5ekov3c4.png" alt="Docker Desktop Containers"&gt;&lt;/a&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  Using Apache AGE from container
&lt;/h2&gt;

&lt;p&gt;Now on Docker Desktop, click on age, the recently created container.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fnrypojg97iv15h4eij0v.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fnrypojg97iv15h4eij0v.png" alt="Container name "&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Now click "Terminal" and "Open in external terminal"&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F3kwd466ubje671koe5eq.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F3kwd466ubje671koe5eq.png" alt="Open Container in external terminal"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;It will open your default terminal logged in to root.&lt;/p&gt;

&lt;p&gt;Now run the command:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;psql -h 0.0.0.0 -p 5432 -d postgresDB -U postgresUser
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Immediately you will be inside psql, logged in to "postgresUser" in the "postgresDB" database, which were created upon the prior docker run command.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# psql -h 0.0.0.0 -p 5432 -d postgresDB -U postgresUser
psql (14.8 (Debian 14.8-1.pgdg120+1))
Type "help" for help.

postgresDB=#
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Apache AGE comes already loaded, so you can start using it right away:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;postgresDB=# SET search_path TO ag_catalog;
SET
postgresDB=# SELECT * FROM ag_graph;
 graphid | name | namespace
---------+------+-----------
   16950 | test | test
(1 row)

postgresDB=# SELECT * FROM ag_label;
       name       | graph | id | kind |       relation        |        seq_name
------------------+-------+----+------+-----------------------+-------------------------
 _ag_label_vertex | 16950 |  1 | v    | test._ag_label_vertex | _ag_label_vertex_id_seq
 _ag_label_edge   | 16950 |  2 | e    | test._ag_label_edge   | _ag_label_edge_id_seq
(2 rows)

postgresDB=#
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And that's a wrap! Have fun!&lt;/p&gt;




&lt;p&gt;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!&lt;/p&gt;




&lt;p&gt;Check Apache AGE: &lt;a href="https://age.apache.org/" rel="noopener noreferrer"&gt;https://age.apache.org/&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Overview — Apache AGE master documentation: &lt;a href="https://age.apache.org/age-manual/master/intro/overview.html" rel="noopener noreferrer"&gt;https://age.apache.org/age-manual/master/intro/overview.html&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;GitHub - apache/age: &lt;a href="https://github.com/apache/age" rel="noopener noreferrer"&gt;https://github.com/apache/age&lt;/a&gt;&lt;/p&gt;

</description>
      <category>apacheage</category>
      <category>postgres</category>
      <category>docker</category>
    </item>
    <item>
      <title>How to Install PostgreSQL from Source</title>
      <dc:creator>Marco Aurélio Silva de Souza Júnior</dc:creator>
      <pubDate>Fri, 28 Jul 2023 19:15:55 +0000</pubDate>
      <link>https://dev.to/markgomer/how-to-install-postgresql-from-source-3jd8</link>
      <guid>https://dev.to/markgomer/how-to-install-postgresql-from-source-3jd8</guid>
      <description>&lt;p&gt;Welcome to this guide on installing PostgreSQL from source on your machine. PostgreSQL is a powerful, open-source object-relational database system. Today, we'll walk through the process of setting it up from scratch.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Prerequisites&lt;/strong&gt;
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;apt update &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; apt upgrade &lt;span class="nt"&gt;--yes&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; apt &lt;span class="nb"&gt;install sudo &lt;/span&gt;locales &lt;span class="nt"&gt;--yes&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This command will update the list of packages and their versions on your machine (&lt;code&gt;apt update&lt;/code&gt;), upgrade your system's installed packages (&lt;code&gt;apt upgrade --yes&lt;/code&gt;), and then install &lt;code&gt;sudo&lt;/code&gt; and &lt;code&gt;locales&lt;/code&gt; (&lt;code&gt;apt install sudo locales --yes&lt;/code&gt;). &lt;/p&gt;

&lt;p&gt;The &lt;code&gt;sudo&lt;/code&gt; package provides ordinary users with root permissions for specific commands, and &lt;code&gt;locales&lt;/code&gt; is a system software package that supports localization - the adaptation of a product to meet the language, cultural and other requirements of a specific locale.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;dpkg-reconfigure tzdata
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This command reconfigures the timezone data on your machine. It's important to set this correctly to ensure all time-related processes on your system follow your local timezone.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;adduser &amp;lt;username&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This command creates a new user. Replace &lt;code&gt;&amp;lt;username&amp;gt;&lt;/code&gt; with your preferred username.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"&amp;lt;username&amp;gt; ALL=PASSWD: ALL"&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; /etc/sudoers.d/&amp;lt;username&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This line adds the newly created user to the &lt;code&gt;sudoers&lt;/code&gt; file, which controls which users can run what software on which machines and as which users.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;su - &amp;lt;username&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This command switches the current user to the newly created user.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;sudo &lt;/span&gt;apt &lt;span class="nb"&gt;install &lt;/span&gt;htop git build-essential cmake libreadline-dev zlib1g-dev flex bison libicu-dev pkgconf vim &lt;span class="nt"&gt;--yes&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This command installs various software and libraries needed to compile and run PostgreSQL. These include a text editor (vim), version control system (git), essential compilation tools (build-essential, cmake), a couple of libraries for handling compressed data (zlib1g-dev), text parsing (flex, bison), international components for Unicode (libicu-dev), and others.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Installing PostgreSQL&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;Now that our system is prepared, we can download the PostgreSQL source code, configure it, and install it.&lt;/p&gt;

&lt;p&gt;First, download the PostgreSQL source code from the official website and unpack it or clone from GitHub. Then navigate into the directory.&lt;/p&gt;

&lt;p&gt;Next, configure the installation with debug information and additional checks:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;./configure &lt;span class="se"&gt;\&lt;/span&gt;
    &lt;span class="nt"&gt;--enable-debug&lt;/span&gt; &lt;span class="nt"&gt;--enable-cassert&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
    &lt;span class="nv"&gt;CFLAGS&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"-ggdb -Og -fno-omit-frame-pointer"&lt;/span&gt; 
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This command configures the source code to include debug information and enable assertion checks. The CFLAGS part sets compiler options to include debugging information in the executables (which helps when you need to debug something), disable optimizations (-Og), and not omit the frame pointer, which also helps with debugging.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;make &lt;span class="nb"&gt;install&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This command compiles the source code and installs the resulting binaries.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;mkdir&lt;/span&gt; &lt;span class="nt"&gt;-p&lt;/span&gt; /usr/local/pgsql/data
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This command creates a directory for the database files.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;chown&lt;/span&gt; &amp;lt;username&amp;gt; /usr/local/pgsql/data
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This command changes the ownership of the data directory to the new user we created earlier.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;su - &amp;lt;username&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This command switches the current user to the new user.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Setting Environment Variables&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;Add these lines to your &lt;code&gt;.profile&lt;/code&gt; file, typically located in your home directory (&lt;code&gt;~/.profile&lt;/code&gt;):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;LD_LIBRARY_PATH&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;/usr/local/pgsql/lib
&lt;span class="nb"&gt;export &lt;/span&gt;LD_LIBRARY_PATH
&lt;span class="nb"&gt;export &lt;/span&gt;&lt;span class="nv"&gt;PATH&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;/usr/local/pgsql/bin:&lt;span class="nv"&gt;$PATH&lt;/span&gt;
&lt;span class="nb"&gt;export &lt;/span&gt;&lt;span class="nv"&gt;DATA&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;/usr/local/pgsql/data
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;These commands set environment variables so that the system knows where to find the PostgreSQL executables and libraries, as well as where the data directory is.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Initializing the Database&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;Finally, let's initialize the database and start it up.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;initdb &lt;span class="nt"&gt;-D&lt;/span&gt; &lt;span class="nv"&gt;$DATA&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This command initializes the PostgreSQL database in the directory specified by the &lt;code&gt;DATA&lt;/code&gt; environment variable.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;pg_ctl &lt;span class="nt"&gt;-D&lt;/span&gt; &lt;span class="nv"&gt;$DATA&lt;/span&gt; start
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This command starts the PostgreSQL database.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;createdb &lt;span class="nb"&gt;test&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This command creates a new database named &lt;code&gt;test&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;psql &lt;span class="nb"&gt;test&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This command connects to the new &lt;code&gt;test&lt;/code&gt; database with the &lt;code&gt;psql&lt;/code&gt; client, and you're ready to start using PostgreSQL!&lt;/p&gt;

&lt;p&gt;Conclusion:&lt;/p&gt;

&lt;p&gt;Congratulations! You've successfully installed PostgreSQL from the source. This setup gives you full control over the configuration and enables debugging, which can be particularly helpful if you're developing an extension like Apache AGE or diving deeper into the PostgreSQL internals. Now you're ready to start creating and managing your databases!&lt;/p&gt;




&lt;p&gt;Remember, when working directly with source installations, you have more control, but it also requires more responsibility for maintenance and updates. For production environments, it is generally recommended to use version-controlled packages provided by your operating system or trusted third-party repositories unless you have a good reason to compile from source.&lt;/p&gt;




&lt;p&gt;I make these posts in order to guide people into the development of a new technology. If you find any misleading information, I urge you to comment below so I can fix it. Thanks!&lt;/p&gt;




&lt;p&gt;Check Apache AGE: &lt;a href="https://age.apache.org/"&gt;https://age.apache.org/&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Overview — Apache AGE master documentation: &lt;a href="https://age.apache.org/age-manual/master/intro/overview.html"&gt;https://age.apache.org/age-manual/master/intro/overview.html&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;GitHub - apache/age: &lt;a href="https://github.com/apache/age"&gt;https://github.com/apache/age&lt;/a&gt;&lt;/p&gt;

</description>
    </item>
    <item>
      <title>How to Set Up a Developer Environment for Apache AGE using Docker</title>
      <dc:creator>Marco Aurélio Silva de Souza Júnior</dc:creator>
      <pubDate>Fri, 28 Jul 2023 13:16:47 +0000</pubDate>
      <link>https://dev.to/markgomer/how-to-set-up-a-developer-environment-for-apache-age-using-docker-6fe</link>
      <guid>https://dev.to/markgomer/how-to-set-up-a-developer-environment-for-apache-age-using-docker-6fe</guid>
      <description>&lt;p&gt;This is a guide on setting up your developer environment for Apache AGE using Docker on WSL. Docker simplifies your workflow and enhances your productivity. It allows you to create, deploy, and run applications by using containers. It will be helpful if you need to work on many versions of a software, like postgres.&lt;/p&gt;

&lt;p&gt;Let's go into the steps!&lt;/p&gt;

&lt;h2&gt;
  
  
  Pre-requisites
&lt;/h2&gt;

&lt;p&gt;This short tutorial was built using WSL2, with integrated docker.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 1: Create AGE Fork and Clone PostgreSQL
&lt;/h2&gt;

&lt;p&gt;On your host OS, clone your own fork of Apache AGE and clone postgres in two side-by-side folders.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 2: Get Base Image and Install Build Essentials
&lt;/h2&gt;

&lt;p&gt;I like using the image debian:stable-slim, as it is very lightweight. You can get it by pulling from docker hub:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;docker run debian:stable-slim
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Start by running a Docker container with the command:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;docker run &lt;span class="nt"&gt;--name&lt;/span&gt; &amp;lt;new_image_name&amp;gt; &lt;span class="nt"&gt;-h&lt;/span&gt; &amp;lt;new_tag&amp;gt; &lt;span class="nt"&gt;-e&lt;/span&gt; &lt;span class="nv"&gt;LANG&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;C.UTF-8 &lt;span class="nt"&gt;-it&lt;/span&gt; debian:stable-slim /bin/bash &lt;span class="nt"&gt;-l&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Next, we need to update our software packages and install the essential ones. Run these commands on the terminal inside the container, which just opened:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;apt update &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; apt upgrade &lt;span class="nt"&gt;--yes&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; apt &lt;span class="nb"&gt;install sudo &lt;/span&gt;locales &lt;span class="nt"&gt;--yes&lt;/span&gt;
dpkg-reconfigure tzdata
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now, we'll create a new user and give them sudo permissions. Replace &lt;code&gt;&amp;lt;your_username&amp;gt;&lt;/code&gt; with your chosen username:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;adduser &amp;lt;your_username&amp;gt;
&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"&amp;lt;your_username&amp;gt; ALL=PASSWD: ALL"&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; /etc/sudoers.d/&amp;lt;your_username&amp;gt;
su - &amp;lt;your_username&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Lastly, we need to install some necessary tools. Run:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;sudo &lt;/span&gt;apt &lt;span class="nb"&gt;install &lt;/span&gt;htop git build-essential cmake libreadline-dev zlib1g-dev flex bison libicu-dev pkgconf vim &lt;span class="nt"&gt;--yes&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Step 3: Clone Image and Delete the Old One
&lt;/h2&gt;

&lt;p&gt;To create a new Docker image from changes made to the current container, run:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;docker image &lt;span class="nb"&gt;ls
&lt;/span&gt;docker commit debian:stable-slim &amp;lt;new_image_name:new_tag&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then, you can remove the old container using:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;docker &lt;span class="nb"&gt;rm &lt;/span&gt;debian:stable-slim
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The newly created image will serve as your base to create other containers with different versions of postgres.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 4: Run the Container
&lt;/h2&gt;

&lt;p&gt;Finally, we can run our new container. Make sure to replace the path placeholders with the actual source and destination paths for AGE:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;docker run &lt;span class="se"&gt;\&lt;/span&gt;
    &lt;span class="nt"&gt;--name&lt;/span&gt; &amp;lt;new_container_name&amp;gt; &lt;span class="nt"&gt;-h&lt;/span&gt; &amp;lt;new_host_name&amp;gt; &lt;span class="se"&gt;\&lt;/span&gt;
    &lt;span class="nt"&gt;-v&lt;/span&gt; path/to/age/source:path/to/age/destination/inside/container &lt;span class="se"&gt;\&lt;/span&gt;
    &lt;span class="nt"&gt;-it&lt;/span&gt; &amp;lt;new_image_name&amp;gt;:&amp;lt;&lt;span class="nb"&gt;hostname&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; /bin/bash
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Congrats! You've now set up your developer environment for Apache AGE using Docker. This environment will be isolated from the other parts of your system, which helps to keep your workstation clean and organized.&lt;/p&gt;

&lt;p&gt;Keep in mind that Docker is an extensive platform, and there's a lot more to learn. However, understanding these basics will significantly improve your workflow as a developer. &lt;/p&gt;




&lt;p&gt;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!&lt;/p&gt;




&lt;p&gt;Check Apache AGE: &lt;a href="https://age.apache.org/"&gt;https://age.apache.org/&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Overview — Apache AGE master documentation: &lt;a href="https://age.apache.org/age-manual/master/intro/overview.html"&gt;https://age.apache.org/age-manual/master/intro/overview.html&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;GitHub - apache/age: &lt;a href="https://github.com/apache/age"&gt;https://github.com/apache/age&lt;/a&gt;&lt;/p&gt;

</description>
      <category>apacheage</category>
      <category>postgres</category>
      <category>docker</category>
    </item>
    <item>
      <title>Enhancing the create_complete_graph Function in Apache AGE</title>
      <dc:creator>Marco Aurélio Silva de Souza Júnior</dc:creator>
      <pubDate>Thu, 27 Jul 2023 13:27:38 +0000</pubDate>
      <link>https://dev.to/markgomer/enhancing-the-createcompletegraph-function-in-apache-age-fj7</link>
      <guid>https://dev.to/markgomer/enhancing-the-createcompletegraph-function-in-apache-age-fj7</guid>
      <description>&lt;p&gt;In this blog post, we're going to discuss an upgrade to the &lt;code&gt;create_complete_graph&lt;/code&gt; function in Apache AGE, continuing our series. This function generates a complete graph with the given parameters, such as the graph name, number of nodes, and edge label. We'll be enhancing the function to add support for pre-modeled starting properties when creating nodes and edges.&lt;/p&gt;

&lt;p&gt;To understand this modification, let's first dive into the &lt;code&gt;create_complete_graph&lt;/code&gt; function in its initial state. The function takes in the following parameters:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;'graph_name': The name of the graph.&lt;/li&gt;
&lt;li&gt;'no_of_nodes': The number of nodes to create.&lt;/li&gt;
&lt;li&gt;'edge_label': The label for the edges.&lt;/li&gt;
&lt;li&gt;'node_label': The label for the nodes (optional).&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;In the existing code, node properties and edge properties are initialized as empty by default:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight c"&gt;&lt;code&gt;&lt;span class="n"&gt;agtype&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;props&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;create_empty_agtype&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then, these empty properties are passed to both &lt;code&gt;insert_vertex_simple&lt;/code&gt; and &lt;code&gt;insert_edge_simple&lt;/code&gt; functions while creating vertices and edges.&lt;/p&gt;

&lt;h2&gt;
  
  
  Modifications
&lt;/h2&gt;

&lt;p&gt;Now, we'll modify the function to accept two additional parameters: 'edge_properties' and 'node_properties'. This will allow us to provide initial properties for edges and nodes while creating them.&lt;/p&gt;

&lt;p&gt;Here are the steps to implement this enhancement:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Add Parameters:&lt;/strong&gt; First, we need to add two more parameters in the &lt;code&gt;age--1.3.0.sql&lt;/code&gt; file:
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="k"&gt;CREATE&lt;/span&gt; &lt;span class="k"&gt;FUNCTION&lt;/span&gt; &lt;span class="n"&gt;ag_catalog&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;create_complete_graph&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;graph_name&lt;/span&gt; &lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; 
    &lt;span class="n"&gt;number_of_nodes&lt;/span&gt; &lt;span class="nb"&gt;int&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; 
    &lt;span class="n"&gt;edge_label&lt;/span&gt; &lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; 
    &lt;span class="n"&gt;edge_properties&lt;/span&gt; &lt;span class="n"&gt;agtype&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;NULL&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;node_label&lt;/span&gt; &lt;span class="n"&gt;name&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;NULL&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;node_properties&lt;/span&gt; &lt;span class="n"&gt;agtype&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;NULL&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;RETURNS&lt;/span&gt; &lt;span class="n"&gt;void&lt;/span&gt;
&lt;span class="k"&gt;LANGUAGE&lt;/span&gt; &lt;span class="k"&gt;c&lt;/span&gt;
&lt;span class="k"&gt;CALLED&lt;/span&gt; &lt;span class="k"&gt;ON&lt;/span&gt; &lt;span class="k"&gt;NULL&lt;/span&gt; &lt;span class="k"&gt;INPUT&lt;/span&gt;
&lt;span class="n"&gt;PARALLEL&lt;/span&gt; &lt;span class="n"&gt;SAFE&lt;/span&gt;
&lt;span class="k"&gt;AS&lt;/span&gt; &lt;span class="s1"&gt;'MODULE_PATHNAME'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Declare Properties:&lt;/strong&gt; Next, declare two &lt;code&gt;agtype&lt;/code&gt; variables, one for &lt;code&gt;edge_properties&lt;/code&gt; and one for &lt;code&gt;node_properties&lt;/code&gt;. Initialize them to &lt;code&gt;NULL&lt;/code&gt;.
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight c"&gt;&lt;code&gt;&lt;span class="n"&gt;agtype&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;edge_properties&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;NULL&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="n"&gt;agtype&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;node_properties&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;NULL&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Assign Properties:&lt;/strong&gt; Within the function, we will assign values to &lt;code&gt;edge_properties&lt;/code&gt; and &lt;code&gt;node_properties&lt;/code&gt; only if they are not NULL.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;For &lt;code&gt;edge_properties&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight c"&gt;&lt;code&gt;&lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="n"&gt;PG_ARGISNULL&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;edge_properties&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;agtype&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="n"&gt;PG_GETARG_ARRAYTYPE_P&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;For &lt;code&gt;node_properties&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight c"&gt;&lt;code&gt;&lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="n"&gt;PG_ARGISNULL&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;node_properties&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;agtype&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="n"&gt;PG_GETARG_ARRAYTYPE_P&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Modify Vertex and Edge Creation:&lt;/strong&gt; Replace the &lt;code&gt;props&lt;/code&gt; variable in &lt;code&gt;insert_vertex_simple&lt;/code&gt; and &lt;code&gt;insert_edge_simple&lt;/code&gt; function calls with &lt;code&gt;node_properties&lt;/code&gt; and &lt;code&gt;edge_properties&lt;/code&gt; respectively.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;For vertex creation:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight c"&gt;&lt;code&gt;&lt;span class="n"&gt;insert_vertex_simple&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;graph_id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;vtx_name_str&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;object_graph_id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;node_properties&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;For edge creation:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight c"&gt;&lt;code&gt;&lt;span class="n"&gt;insert_edge_simple&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;graph_id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;edge_name_str&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                   &lt;span class="n"&gt;object_graph_id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;start_vertex_graph_id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                   &lt;span class="n"&gt;end_vertex_graph_id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;edge_properties&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And  that's it! You have now successfully added the ability to include pre-modeled starting properties for nodes and edges in the &lt;code&gt;create_complete_graph&lt;/code&gt; function. This will allow developers to add their own properties to nodes and edges upon creation, making the function more flexible and customizable. &lt;/p&gt;

&lt;p&gt;To call the function now you can put properties as agtype in the parameters, like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="k"&gt;SELECT&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="k"&gt;FROM&lt;/span&gt; &lt;span class="n"&gt;create_complete_graph&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="s1"&gt;'test_graph'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="s1"&gt;'edges_label'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'{"edge_property":"test"}'&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;agtype&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="s1"&gt;'vertices_label'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'{"node_property":"test"}'&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;agtype&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Remember to compile the modified extension and install it in your PostgreSQL server to make use of these enhancements. &lt;/p&gt;




&lt;p&gt;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!&lt;/p&gt;




&lt;p&gt;Check Apache AGE: &lt;a href="https://age.apache.org/"&gt;https://age.apache.org/&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Overview — Apache AGE master documentation: &lt;a href="https://age.apache.org/age-manual/master/intro/overview.html"&gt;https://age.apache.org/age-manual/master/intro/overview.html&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;GitHub - apache/age: &lt;a href="https://github.com/apache/age"&gt;https://github.com/apache/age&lt;/a&gt;&lt;/p&gt;

</description>
      <category>apacheage</category>
      <category>postgres</category>
    </item>
    <item>
      <title>Setting Up pgAdmin 4 on Windows with PostgreSQL on WSL</title>
      <dc:creator>Marco Aurélio Silva de Souza Júnior</dc:creator>
      <pubDate>Mon, 24 Jul 2023 17:57:39 +0000</pubDate>
      <link>https://dev.to/markgomer/setting-up-pgadmin-4-on-windows-with-postgresql-on-wsl-9j7</link>
      <guid>https://dev.to/markgomer/setting-up-pgadmin-4-on-windows-with-postgresql-on-wsl-9j7</guid>
      <description>&lt;p&gt;In this blog post, we'll walk through the process of setting up pgAdmin 4, installed natively on Windows, to work with a PostgreSQL server running on Windows Subsystem for Linux (WSL). This guide assumes you have already installed PostgreSQL on WSL and pgAdmin 4 on your Windows system.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Step 1: Start the PostgreSQL Server on WSL&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;First, you need to start your PostgreSQL server on WSL. Use the &lt;code&gt;pg_ctl&lt;/code&gt; command followed by &lt;code&gt;-D&lt;/code&gt; and the directory of your database to start the server. The command should look something like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;pg_ctl -D &amp;lt;your database directory&amp;gt; start
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Upon running this command, you should see an output similar to the following:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;waiting for server to start....2023-07-13 12:08:01.660 -03 [4659] LOG:  starting PostgreSQL 16beta1 on x86_64-pc-linux-gnu, compiled by gcc (GCC) 13.1.1 20230429, 64-bit
2023-07-13 12:08:01.662 -03 [4659] LOG:  listening on IPv4 address "127.0.0.1", port 5432
2023-07-13 12:08:01.676 -03 [4659] LOG:  listening on Unix socket "/tmp/.s.PGSQL.5432"
2023-07-13 12:08:01.707 -03 [4662] LOG:  database system was shut down at 2023-06-30 17:18:29 -03
2023-07-13 12:08:01.738 -03 [4659] LOG:  database system is ready to accept connections
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Take note of the IPv4 address and port number where the server is listening. In this case, it's "127.0.0.1" and port "5432".&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Step 2: Add a New Server on pgAdmin&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Next, open pgAdmin and add a new server. In the "Connection" tab, enter the IPv4 address and port number you noted in the previous step into the "Host name/address" and "Port" fields, respectively.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Step 3: Specify the Maintenance Database&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The "Maintenance database" field should be filled with the name of your PostgreSQL database. If you're unsure of your database name, you can list all available databases by running the &lt;code&gt;psql --list&lt;/code&gt; command on WSL.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Step 4: Enter Your Username and Password&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The "Username" and "Password" fields should be filled with your PostgreSQL username and password, respectively. This is the same username and password you use to connect to PostgreSQL on WSL.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Step 5: Name Your Connection&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Finally, give your connection a meaningful name in the "Name" field under the "General" tab. This will help you identify this connection in the future.&lt;/p&gt;

&lt;p&gt;Once you've filled out all the necessary fields, save your new server configuration. You should now be able to connect to your PostgreSQL server on WSL using pgAdmin 4 on Windows.&lt;/p&gt;




&lt;p&gt;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!&lt;/p&gt;




&lt;p&gt;Check Apache AGE: &lt;a href="https://age.apache.org/"&gt;https://age.apache.org/&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Overview — Apache AGE master documentation: &lt;a href="https://age.apache.org/age-manual/master/intro/overview.html"&gt;https://age.apache.org/age-manual/master/intro/overview.html&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;GitHub - apache/age: &lt;a href="https://github.com/apache/age"&gt;https://github.com/apache/age&lt;/a&gt;&lt;/p&gt;

</description>
      <category>apacheage</category>
      <category>postgressql</category>
    </item>
    <item>
      <title>How to Fetch Different Kinds of Arguments in Apache AGE C-Language Functions</title>
      <dc:creator>Marco Aurélio Silva de Souza Júnior</dc:creator>
      <pubDate>Tue, 11 Jul 2023 13:18:23 +0000</pubDate>
      <link>https://dev.to/markgomer/how-to-fetch-different-kinds-of-arguments-in-apache-age-c-language-functions-3a5k</link>
      <guid>https://dev.to/markgomer/how-to-fetch-different-kinds-of-arguments-in-apache-age-c-language-functions-3a5k</guid>
      <description>&lt;p&gt;Creating a PostgreSQL extension in C, like &lt;a href="https://age.apache.org/"&gt;Apache AGE&lt;/a&gt;, allows you to execute high-performance code directly in your database. One of the challenges is passing arguments to these C functions. Here's a simple guide to fetch different kinds of arguments in a C-language function of a PostgreSQL extension.&lt;/p&gt;

&lt;p&gt;Before we start, make sure to include necessary PostgreSQL headers in your C file:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight c"&gt;&lt;code&gt;&lt;span class="cp"&gt;#include&lt;/span&gt; &lt;span class="cpf"&gt;"postgres.h"&lt;/span&gt;&lt;span class="cp"&gt;
#include&lt;/span&gt; &lt;span class="cpf"&gt;"fmgr.h"&lt;/span&gt;&lt;span class="cp"&gt;
#include&lt;/span&gt; &lt;span class="cpf"&gt;"utils/builtins.h"&lt;/span&gt;&lt;span class="cp"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;PostgreSQL provides the &lt;code&gt;fmgr&lt;/code&gt; (Function Manager) module that includes macros for dealing with arguments. &lt;/p&gt;

&lt;h3&gt;
  
  
  Handling Scalar Arguments
&lt;/h3&gt;

&lt;p&gt;For scalar arguments like integers or floats, use the &lt;code&gt;PG_GETARG_&lt;/code&gt; macros:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight c"&gt;&lt;code&gt;&lt;span class="n"&gt;PG_FUNCTION_INFO_V1&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;add_integers&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="n"&gt;Datum&lt;/span&gt;
&lt;span class="nf"&gt;add_integers&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;PG_FUNCTION_ARGS&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;int32&lt;/span&gt; &lt;span class="n"&gt;arg1&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;PG_GETARG_INT32&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;  &lt;span class="c1"&gt;// Fetches the first argument&lt;/span&gt;
    &lt;span class="n"&gt;int32&lt;/span&gt; &lt;span class="n"&gt;arg2&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;PG_GETARG_INT32&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;  &lt;span class="c1"&gt;// Fetches the second argument&lt;/span&gt;

    &lt;span class="n"&gt;PG_RETURN_INT32&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;arg1&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;arg2&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Handling String Arguments
&lt;/h3&gt;

&lt;p&gt;For text arguments, use the &lt;code&gt;PG_GETARG_TEXT_P&lt;/code&gt; macro:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight c"&gt;&lt;code&gt;&lt;span class="n"&gt;PG_FUNCTION_INFO_V1&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;echo_text&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="n"&gt;Datum&lt;/span&gt;
&lt;span class="nf"&gt;echo_text&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;PG_FUNCTION_ARGS&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;text&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;arg1&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;PG_GETARG_TEXT_P&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="kt"&gt;char&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;cstr&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;text_to_cstring&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;arg1&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="n"&gt;PG_RETURN_TEXT_P&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;cstring_to_text&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;cstr&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Handling Array Arguments
&lt;/h3&gt;

&lt;p&gt;For arrays, use the &lt;code&gt;PG_GETARG_ARRAYTYPE_P&lt;/code&gt; macro:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight c"&gt;&lt;code&gt;&lt;span class="n"&gt;PG_FUNCTION_INFO_V1&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;process_array&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="n"&gt;Datum&lt;/span&gt;
&lt;span class="nf"&gt;process_array&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;PG_FUNCTION_ARGS&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;ArrayType&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;array&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;PG_GETARG_ARRAYTYPE_P&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="c1"&gt;// Further processing...&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Handling NULL Arguments
&lt;/h3&gt;

&lt;p&gt;You can check if an argument is NULL using &lt;code&gt;PG_ARGISNULL(index)&lt;/code&gt; macro:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight c"&gt;&lt;code&gt;&lt;span class="n"&gt;PG_FUNCTION_INFO_V1&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;echo_or_default&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="n"&gt;Datum&lt;/span&gt;
&lt;span class="nf"&gt;echo_or_default&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;PG_FUNCTION_ARGS&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;PG_ARGISNULL&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
        &lt;span class="n"&gt;PG_RETURN_TEXT_P&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;cstring_to_text&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"default"&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
    &lt;span class="k"&gt;else&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;text&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;arg1&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;PG_GETARG_TEXT_P&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="kt"&gt;char&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;cstr&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;text_to_cstring&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;arg1&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

        &lt;span class="n"&gt;PG_RETURN_TEXT_P&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;cstring_to_text&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;cstr&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Concluding Remarks
&lt;/h3&gt;

&lt;p&gt;This is a basic guide to fetching arguments in PostgreSQL C functions. Depending on the argument's type, you will need to use the appropriate &lt;code&gt;PG_GETARG_&lt;/code&gt; macros. Remember to consider NULL arguments as well. By mastering these techniques, you'll be able to harness the full power of PostgreSQL C-language functions.&lt;/p&gt;

&lt;p&gt;Keep in mind that PostgreSQL's C API is vast and provides many more capabilities for dealing with complex data types, sets, and even triggering side effects on your database. Make sure to explore the &lt;a href="https://www.postgresql.org/docs/"&gt;official PostgreSQL documentation&lt;/a&gt; for a more comprehensive understanding.&lt;/p&gt;

&lt;p&gt;Note: C-language functions can offer significant performance advantages but come with risks, especially around memory management. Be sure to thoroughly test any C functions you write for your PostgreSQL database.&lt;/p&gt;




&lt;p&gt;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!&lt;/p&gt;




&lt;p&gt;Check Apache AGE: &lt;a href="https://age.apache.org/"&gt;https://age.apache.org/&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Overview — Apache AGE master documentation: &lt;a href="https://age.apache.org/age-manual/master/intro/overview.html"&gt;https://age.apache.org/age-manual/master/intro/overview.html&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;GitHub - apache/age: &lt;a href="https://github.com/apache/age"&gt;https://github.com/apache/age&lt;/a&gt;&lt;/p&gt;

</description>
      <category>apacheage</category>
      <category>postgres</category>
    </item>
    <item>
      <title>Introduction to Apache AGE - Graph Extension for PostgreSQL</title>
      <dc:creator>Marco Aurélio Silva de Souza Júnior</dc:creator>
      <pubDate>Fri, 07 Jul 2023 13:22:49 +0000</pubDate>
      <link>https://dev.to/markgomer/introduction-to-apache-age-graph-extension-for-postgresql-p2l</link>
      <guid>https://dev.to/markgomer/introduction-to-apache-age-graph-extension-for-postgresql-p2l</guid>
      <description>&lt;p&gt;As data grows more complex and interconnected, the need for efficient and effective tools to handle these relationships also expands. &lt;a href="https://age.apache.org/"&gt;Apache AGE&lt;/a&gt; (A Graph Extension) is one such tool that brings the power of graph databases to PostgreSQL. &lt;/p&gt;

&lt;h2&gt;
  
  
  What is Apache AGE?
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://github.com/apache/age"&gt;Apache AGE is an open-source project&lt;/a&gt; under Apache that provides graph database functionality to PostgreSQL. It extends the PostgreSQL capabilities, allowing it to store, query, and process graph data.&lt;/p&gt;

&lt;h2&gt;
  
  
  Benefits of Apache AGE
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Seamless Integration with PostgreSQL
&lt;/h3&gt;

&lt;p&gt;Apache AGE is a PostgreSQL extension, meaning existing PostgreSQL users can leverage AGE without changing their entire database infrastructure. It effectively adds graph functionality to an already powerful RDBMS.&lt;/p&gt;

&lt;h3&gt;
  
  
  Robust Query Language
&lt;/h3&gt;

&lt;p&gt;Apache AGE uses the openCypher Query Language, enabling users to handle complex, interrelated data queries efficiently. openCypher is a highly popular and widely adopted language in the graph database industry, and its use in Apache AGE makes the tool versatile and robust.&lt;/p&gt;

&lt;h3&gt;
  
  
  Open Source
&lt;/h3&gt;

&lt;p&gt;Apache AGE is an open-source project. This means it has a global community of developers constantly working on improving and enhancing its features. Users also benefit from extensive community support.&lt;/p&gt;

&lt;h2&gt;
  
  
  Use Cases
&lt;/h2&gt;

&lt;p&gt;Apache AGE is used in various data-intensive fields where relationship exploration is critical. Some of these include social network analysis, real-time recommendation engines, fraud detection in financial transactions, and complex network management.&lt;/p&gt;

&lt;h2&gt;
  
  
  How to Start
&lt;/h2&gt;

&lt;p&gt;Getting started with Apache AGE is easy. After installing PostgreSQL, you can add Apache AGE as an extension. AGE's comprehensive documentation and a supportive community will help you navigate this journey.&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;With data interconnectivity becoming a central part of modern application architectures, graph databases like Apache AGE are critical. By offering a seamless extension to PostgreSQL, Apache AGE is expanding the realm of possibility for developers handling complex data. With robust capabilities and an active open-source community, Apache AGE is a powerful tool for any developer's arsenal.&lt;/p&gt;




&lt;p&gt;Check Apache AGE: &lt;a href="https://age.apache.org/"&gt;https://age.apache.org/&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Overview — Apache AGE master documentation: &lt;a href="https://age.apache.org/age-manual/master/intro/overview.html"&gt;https://age.apache.org/age-manual/master/intro/overview.html&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;GitHub - apache/age: &lt;a href="https://github.com/apache/age"&gt;https://github.com/apache/age&lt;/a&gt;&lt;/p&gt;

</description>
      <category>apacheage</category>
      <category>postgres</category>
      <category>graphdatabase</category>
      <category>apache</category>
    </item>
    <item>
      <title>Apache AGE's ListGraphid</title>
      <dc:creator>Marco Aurélio Silva de Souza Júnior</dc:creator>
      <pubDate>Wed, 28 Jun 2023 14:16:48 +0000</pubDate>
      <link>https://dev.to/markgomer/apache-ages-listgraphid-1ipl</link>
      <guid>https://dev.to/markgomer/apache-ages-listgraphid-1ipl</guid>
      <description>&lt;p&gt;Greetings!&lt;/p&gt;

&lt;p&gt;In today's post, we are going to explain a simple yet vital structure in &lt;a href="https://age.apache.org/"&gt;Apache AGE&lt;/a&gt;, the PostgreSQL extension for graph databases: the &lt;code&gt;ListGraphId&lt;/code&gt; structure. The aim is to help you understand how it functions, why it is essential, and how you can iterate over it.&lt;/p&gt;

&lt;h2&gt;
  
  
  What is the &lt;code&gt;ListGraphId&lt;/code&gt; structure?
&lt;/h2&gt;

&lt;p&gt;&lt;code&gt;ListGraphId&lt;/code&gt; is a particular structure designed to store a list of nodes (vertices) in a graph. Each node is represented by a unique &lt;code&gt;graphid&lt;/code&gt;, an &lt;code&gt;int64&lt;/code&gt; identifier. &lt;/p&gt;

&lt;p&gt;The structure is defined in the &lt;a href="https://github.com/apache/age/blob/fada9c9cbe348e10593b6647d3bdb5864a719a1b/src/backend/utils/adt/age_graphid_ds.c"&gt;&lt;code&gt;age_graphid_ds.c&lt;/code&gt;&lt;/a&gt; file, which resides in the Apache AGE source code, and it looks like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight c"&gt;&lt;code&gt;&lt;span class="k"&gt;typedef&lt;/span&gt; &lt;span class="k"&gt;struct&lt;/span&gt; &lt;span class="n"&gt;ListGraphId&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;GraphIdNode&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;head&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="n"&gt;GraphIdNode&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;tail&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="n"&gt;int64&lt;/span&gt; &lt;span class="n"&gt;size&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="n"&gt;ListGraphId&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In &lt;code&gt;ListGraphId&lt;/code&gt;, &lt;code&gt;head&lt;/code&gt; points to the first node of the list, &lt;code&gt;tail&lt;/code&gt; points to the last node, and &lt;code&gt;size&lt;/code&gt; represents the total number of nodes in the list.&lt;/p&gt;

&lt;h2&gt;
  
  
  The &lt;code&gt;GraphIdNode&lt;/code&gt; Structure
&lt;/h2&gt;

&lt;p&gt;Before delving into &lt;code&gt;ListGraphId&lt;/code&gt;, let's take a quick look at the &lt;code&gt;GraphIdNode&lt;/code&gt; structure, which is the "node" of our &lt;code&gt;ListGraphId&lt;/code&gt;. Here is its definition:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight c"&gt;&lt;code&gt;&lt;span class="k"&gt;typedef&lt;/span&gt; &lt;span class="k"&gt;struct&lt;/span&gt; &lt;span class="n"&gt;GraphIdNode&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;graphid&lt;/span&gt; &lt;span class="n"&gt;id&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="k"&gt;struct&lt;/span&gt; &lt;span class="n"&gt;GraphIdNode&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;next&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="n"&gt;GraphIdNode&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In &lt;code&gt;GraphIdNode&lt;/code&gt;, &lt;code&gt;id&lt;/code&gt; is the unique identifier (&lt;code&gt;graphid&lt;/code&gt;) of a graph node (vertex), and &lt;code&gt;next&lt;/code&gt; is a pointer to the next node in the list. Simple, isn't it?&lt;/p&gt;

&lt;h2&gt;
  
  
  Why &lt;code&gt;ListGraphId&lt;/code&gt;?
&lt;/h2&gt;

&lt;p&gt;You might wonder, why go through the trouble of creating a structure like &lt;code&gt;ListGraphId&lt;/code&gt; when PostgreSQL has a &lt;code&gt;List&lt;/code&gt; structure? The reason is quite straightforward. PostgreSQL's &lt;code&gt;List&lt;/code&gt; structure does not directly support &lt;code&gt;int64&lt;/code&gt; data types, which are used for graph vertex identifiers (&lt;code&gt;graphid&lt;/code&gt;). Therefore, &lt;code&gt;ListGraphId&lt;/code&gt; was created as a more suitable alternative for handling lists of &lt;code&gt;graphid&lt;/code&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Iterating over &lt;code&gt;ListGraphId&lt;/code&gt;
&lt;/h2&gt;

&lt;p&gt;Now let's dive into how to iterate over &lt;code&gt;ListGraphId&lt;/code&gt;. Given its linked-list nature, we can employ a basic linked-list traversal technique.&lt;/p&gt;

&lt;p&gt;Here is a simple function that prints all &lt;code&gt;graphid&lt;/code&gt; in a &lt;code&gt;ListGraphId&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight c"&gt;&lt;code&gt;&lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;print_graph_ids&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ListGraphId&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;listgraphid&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;GraphIdNode&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;curr_node&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="cm"&gt;/* Start from the head node */&lt;/span&gt;
    &lt;span class="k"&gt;for&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;curr_node&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;listgraphid&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;head&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; 
        &lt;span class="n"&gt;curr_node&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="nb"&gt;NULL&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; 
        &lt;span class="n"&gt;curr_node&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;curr_node&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;next&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;printf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"%lld&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;curr_node&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;id&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In the &lt;code&gt;print_graph_ids&lt;/code&gt; function, we start with the &lt;code&gt;head&lt;/code&gt; node of the &lt;code&gt;ListGraphId&lt;/code&gt; and follow the &lt;code&gt;next&lt;/code&gt; pointers until we reach the end of the list (&lt;code&gt;NULL&lt;/code&gt;). At each node, we print out the &lt;code&gt;graphid&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;And voila, you've successfully iterated over a &lt;code&gt;ListGraphId&lt;/code&gt; structure.&lt;/p&gt;

&lt;h2&gt;
  
  
  Wrapping Up
&lt;/h2&gt;

&lt;p&gt;Understanding the &lt;code&gt;ListGraphId&lt;/code&gt; structure and how to iterate over it is a crucial step for anyone looking to dive deeper into Apache AGE's internals or working on more advanced graph database manipulations with this extension.&lt;/p&gt;

&lt;p&gt;This simple yet effective data structure forms the basis for more advanced operations and techniques in Apache AGE. In the coming blog posts, we'll explore more about these features and continue our journey into graph databases.&lt;/p&gt;




&lt;p&gt;I hope this clarifies the &lt;code&gt;ListGraphId&lt;/code&gt; structure's purpose and usage in Apache AGE. Do you have any questions or is there anything else you want to know? Please feel free to comment below.&lt;/p&gt;




&lt;p&gt;Check Apache AGE: &lt;a href="https://age.apache.org/"&gt;https://age.apache.org/&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Overview — Apache AGE master documentation: &lt;a href="https://age.apache.org/age-manual/master/intro/overview.html"&gt;https://age.apache.org/age-manual/master/intro/overview.html&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;GitHub - apache/age: &lt;a href="https://github.com/apache/age"&gt;https://github.com/apache/age&lt;/a&gt;&lt;/p&gt;

</description>
      <category>apacheage</category>
      <category>postgres</category>
      <category>apache</category>
      <category>graphdatabase</category>
    </item>
    <item>
      <title>Refactoring The Create Barbell Graph Function</title>
      <dc:creator>Marco Aurélio Silva de Souza Júnior</dc:creator>
      <pubDate>Tue, 27 Jun 2023 14:32:59 +0000</pubDate>
      <link>https://dev.to/markgomer/refactoring-the-create-barbell-graph-function-cel</link>
      <guid>https://dev.to/markgomer/refactoring-the-create-barbell-graph-function-cel</guid>
      <description>&lt;p&gt;On our last post for the source code tour of Apache AGE series, we implemented a function to generate a Barbell graph, and here is the result of it on &lt;a href="https://github.com/apache/age/blob/d3a3bd5d0c3dd632588ef88c7d1e450cbfa9d14b/src/backend/utils/graph_generation.c#L257"&gt;AGE's GitHub repository&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;But I thought it got a little hard to understand this function, as it has lots of steps just to create some vertexes and edges. &lt;/p&gt;

&lt;p&gt;So let's refactor this function, implementing smaller helper functions in order to streamline the creation of vertexes and edges, therefore making it easier to read and get other kinds of pre-modeled graphs done.&lt;/p&gt;




&lt;p&gt;First, let's put together in a struct every component we need to build nodes and edges:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight c"&gt;&lt;code&gt;&lt;span class="k"&gt;typedef&lt;/span&gt; &lt;span class="k"&gt;struct&lt;/span&gt; &lt;span class="n"&gt;graph_components&lt;/span&gt; 
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;Oid&lt;/span&gt; &lt;span class="n"&gt;graph_oid&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="kt"&gt;char&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;graph_name&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="n"&gt;int32&lt;/span&gt; &lt;span class="n"&gt;graph_size&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="kt"&gt;char&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;vertex_label&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="n"&gt;int32&lt;/span&gt; &lt;span class="n"&gt;vertex_label_id&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="n"&gt;agtype&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;vertex_properties&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="n"&gt;Oid&lt;/span&gt; &lt;span class="n"&gt;vtx_seq_id&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="kt"&gt;char&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;edge_label&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="n"&gt;int32&lt;/span&gt; &lt;span class="n"&gt;edge_label_id&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="n"&gt;agtype&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;edge_properties&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="n"&gt;Oid&lt;/span&gt; &lt;span class="n"&gt;edge_seq_id&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="n"&gt;graph_components&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;p&gt;There are too many error checks inside the function and it got messy, let's put it inside a function:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight c"&gt;&lt;code&gt;&lt;span class="k"&gt;static&lt;/span&gt; &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;validate_barbell_function_args&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;PG_FUNCTION_ARGS&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;PG_ARGISNULL&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;ereport&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ERROR&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;errcode&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ERRCODE_INVALID_PARAMETER_VALUE&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
                        &lt;span class="n"&gt;errmsg&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Graph name cannot be NULL"&lt;/span&gt;&lt;span class="p"&gt;)));&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;PG_ARGISNULL&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="n"&gt;PG_GETARG_INT32&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;ereport&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ERROR&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;errcode&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ERRCODE_INVALID_PARAMETER_VALUE&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
                &lt;span class="n"&gt;errmsg&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Graph size cannot be NULL or lower than 3"&lt;/span&gt;&lt;span class="p"&gt;)));&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;PG_ARGISNULL&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="n"&gt;PG_GETARG_INT32&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt; &lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;ereport&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ERROR&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;errcode&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ERRCODE_INVALID_PARAMETER_VALUE&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
                &lt;span class="n"&gt;errmsg&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Bridge size cannot be NULL or lower than 0"&lt;/span&gt;&lt;span class="p"&gt;)));&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;PG_ARGISNULL&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;ereport&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ERROR&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;errcode&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ERRCODE_INVALID_PARAMETER_VALUE&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
                &lt;span class="n"&gt;errmsg&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"edge label cannot be NULL"&lt;/span&gt;&lt;span class="p"&gt;)));&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="n"&gt;PG_ARGISNULL&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="n"&gt;PG_ARGISNULL&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt;
        &lt;span class="n"&gt;strcmp&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;NameStr&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;PG_GETARG_NAME&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;))),&lt;/span&gt; 
               &lt;span class="n"&gt;NameStr&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;PG_GETARG_NAME&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;))))&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;ereport&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ERROR&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;errcode&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ERRCODE_INVALID_PARAMETER_VALUE&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
                &lt;span class="n"&gt;errmsg&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"vertex and edge labels cannot be the same"&lt;/span&gt;&lt;span class="p"&gt;)));&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now we just call it with &lt;code&gt;validate_barbell_function_args(fcinfo);&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;fcinfo&lt;/code&gt; is the structure &lt;code&gt;FunctionCallInfo&lt;/code&gt; referenced by the macro &lt;code&gt;PG_FUNCTION_ARGS&lt;/code&gt;, which contains all the arguments passed to the function.&lt;/p&gt;

&lt;p&gt;Our main function is looking like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight c"&gt;&lt;code&gt;&lt;span class="n"&gt;PG_FUNCTION_INFO_V1&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;age_create_barbell_graph&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="n"&gt;Datum&lt;/span&gt; &lt;span class="nf"&gt;age_create_barbell_graph&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;PG_FUNCTION_ARGS&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; 
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;validate_barbell_function_args&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;fcinfo&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="n"&gt;PG_RETURN_VOID&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;p&gt;Now that we know the arguments are valid, let's process them and put them inside our &lt;code&gt;graph_components&lt;/code&gt; struct, which we will initialize in the main function now, just calling it &lt;code&gt;graph&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight c"&gt;&lt;code&gt;&lt;span class="n"&gt;PG_FUNCTION_INFO_V1&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;age_create_barbell_graph&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="n"&gt;Datum&lt;/span&gt; &lt;span class="nf"&gt;age_create_barbell_graph&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;PG_FUNCTION_ARGS&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; 
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;struct&lt;/span&gt; &lt;span class="n"&gt;graph_components&lt;/span&gt; &lt;span class="n"&gt;graph&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="n"&gt;validate_barbell_function_args&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;fcinfo&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="n"&gt;process_arguments&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;fcinfo&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;graph&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="n"&gt;PG_RETURN_VOID&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight c"&gt;&lt;code&gt;&lt;span class="k"&gt;static&lt;/span&gt; &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;process_arguments&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;PG_FUNCTION_ARGS&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;graph_components&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;graph&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;graph&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;graph_name&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;NameStr&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;PG_GETARG_NAME&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)));&lt;/span&gt;
    &lt;span class="n"&gt;graph&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;graph_size&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;PG_GETARG_INT32&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;PG_ARGISNULL&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;    &lt;span class="n"&gt;graph&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;vertex_label&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;AG_DEFAULT_LABEL_VERTEX&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="k"&gt;else&lt;/span&gt;                    &lt;span class="n"&gt;graph&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;vertex_label&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;NameStr&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;PG_GETARG_NAME&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;)));&lt;/span&gt;

    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;PG_ARGISNULL&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;    &lt;span class="n"&gt;graph&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;vertex_properties&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;create_empty_agtype&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
    &lt;span class="k"&gt;else&lt;/span&gt;                    &lt;span class="n"&gt;graph&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;vertex_properties&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;agtype&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="p"&gt;)(&lt;/span&gt;&lt;span class="n"&gt;PG_GETARG_DATUM&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;

    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;PG_ARGISNULL&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;    &lt;span class="n"&gt;graph&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;edge_label&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;AG_DEFAULT_LABEL_EDGE&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="k"&gt;else&lt;/span&gt;                    &lt;span class="n"&gt;graph&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;edge_label&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;NameStr&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;PG_GETARG_NAME&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;)));&lt;/span&gt;

    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;PG_ARGISNULL&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;6&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;    &lt;span class="n"&gt;graph&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;edge_properties&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;create_empty_agtype&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
    &lt;span class="k"&gt;else&lt;/span&gt;                    &lt;span class="n"&gt;graph&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;edge_properties&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;agtype&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="p"&gt;)(&lt;/span&gt;&lt;span class="n"&gt;PG_GETARG_DATUM&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;6&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Here we fetch the arguments with &lt;code&gt;PG_GETARG&lt;/code&gt;  with the type we expect and convert them to the type we need. For example, we need the graph_name as a &lt;code&gt;char*&lt;/code&gt;, but we receive it as a &lt;code&gt;Name&lt;/code&gt;, so we convert it directly with the command &lt;code&gt;NameStr(*(PG_GETARG_NAME(0)))&lt;/code&gt; - note that &lt;code&gt;0&lt;/code&gt; is because it's the first parameter.&lt;/p&gt;




&lt;p&gt;Now we can build our two complete graphs, but first let's change the &lt;code&gt;create_complete_graph&lt;/code&gt; function to make it return the &lt;code&gt;graph_id&lt;/code&gt; of the first / last created node:&lt;/p&gt;

&lt;p&gt;We just change the last line of the function from &lt;code&gt;PG_RETURN_VOID();&lt;/code&gt; to&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight c"&gt;&lt;code&gt;&lt;span class="n"&gt;PG_RETURN_DATUM&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;GRAPHID_GET_DATUM&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;end_vertex_graph_id&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And on the &lt;code&gt;age--1.3.0.sql&lt;/code&gt; file, on &lt;code&gt;create_complete_graph&lt;/code&gt; function, we change &lt;code&gt;RETURN void&lt;/code&gt; to &lt;code&gt;RETURN graphid&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="k"&gt;CREATE&lt;/span&gt; &lt;span class="k"&gt;FUNCTION&lt;/span&gt; &lt;span class="n"&gt;ag_catalog&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;create_complete_graph&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;graph_name&lt;/span&gt; &lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;nodes&lt;/span&gt; &lt;span class="nb"&gt;int&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;edge_label&lt;/span&gt; &lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;node_label&lt;/span&gt; &lt;span class="n"&gt;name&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;NULL&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;RETURNS&lt;/span&gt; &lt;span class="n"&gt;graphid&lt;/span&gt;   &lt;span class="c1"&gt;-- change here!!!&lt;/span&gt;
&lt;span class="k"&gt;LANGUAGE&lt;/span&gt; &lt;span class="k"&gt;c&lt;/span&gt;
&lt;span class="k"&gt;CALLED&lt;/span&gt; &lt;span class="k"&gt;ON&lt;/span&gt; &lt;span class="k"&gt;NULL&lt;/span&gt; &lt;span class="k"&gt;INPUT&lt;/span&gt;
&lt;span class="n"&gt;PARALLEL&lt;/span&gt; &lt;span class="n"&gt;SAFE&lt;/span&gt;
&lt;span class="k"&gt;AS&lt;/span&gt; &lt;span class="s1"&gt;'MODULE_PATHNAME'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now back to &lt;code&gt;graph_generation.c&lt;/code&gt; file, we create two variables to store a graphid of a node from each complete graph, so we can connect them with a bridge later, then we store the returning value of &lt;code&gt;create_complete_graph&lt;/code&gt; in these variables:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight c"&gt;&lt;code&gt;&lt;span class="n"&gt;Datum&lt;/span&gt; &lt;span class="n"&gt;root1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;root2&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="c1"&gt;// create two separate complete graphs&lt;/span&gt;
&lt;span class="n"&gt;root1&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;DirectFunctionCall4&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;create_complete_graph&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; 
                            &lt;span class="n"&gt;CStringGetDatum&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;graph&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;graph_name&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; 
                            &lt;span class="n"&gt;Int32GetDatum&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;graph&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;graph_size&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
                            &lt;span class="n"&gt;CStringGetDatum&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;graph&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;edge_label&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; 
                            &lt;span class="n"&gt;CStringGetDatum&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;graph&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;vertex_label&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
&lt;span class="n"&gt;root2&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;DirectFunctionCall4&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;create_complete_graph&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; 
                            &lt;span class="n"&gt;CStringGetDatum&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;graph&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;graph_name&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; 
                            &lt;span class="n"&gt;Int32GetDatum&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;graph&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;graph_size&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
                            &lt;span class="n"&gt;CStringGetDatum&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;graph&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;edge_label&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; 
                            &lt;span class="n"&gt;CStringGetDatum&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;graph&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;vertex_label&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;With this we already have two complete graphs disconnected from each other.&lt;/p&gt;




&lt;p&gt;Now let's build a bridge of &lt;code&gt;n&lt;/code&gt; nodes connecting each complete graph.&lt;/p&gt;

&lt;p&gt;But to build nodes and edges, we need to fetch its label and sequential id's. Let's make a function to each of them:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight c"&gt;&lt;code&gt;&lt;span class="k"&gt;static&lt;/span&gt; &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;fetch_label_ids&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;graph_components&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;graph&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; 
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;graph&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;graph_oid&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;get_graph_oid&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;graph&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;graph_name&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="n"&gt;graph&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;vertex_label_id&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; 
        &lt;span class="n"&gt;get_label_id&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;graph&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;vertex_label&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; 
                     &lt;span class="n"&gt;graph&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;graph_oid&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="n"&gt;graph&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;edge_label_id&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; 
        &lt;span class="n"&gt;get_label_id&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;graph&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;edge_label&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; 
                     &lt;span class="n"&gt;graph&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;graph_oid&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight c"&gt;&lt;code&gt;&lt;span class="k"&gt;static&lt;/span&gt; &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;fetch_seq_ids&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;graph_components&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;graph&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;graph_cache_data&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;graph_cache&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="n"&gt;label_cache_data&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;vtx_cache&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="n"&gt;label_cache_data&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;edge_cache&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="n"&gt;graph_cache&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;search_graph_name_cache&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;graph&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;graph_name&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="n"&gt;vtx_cache&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;search_label_name_graph_cache&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;graph&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;vertex_label&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                                              &lt;span class="n"&gt;graph&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;graph_oid&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="n"&gt;edge_cache&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;search_label_name_graph_cache&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;graph&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;edge_label&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                                               &lt;span class="n"&gt;graph&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;graph_oid&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="n"&gt;graph&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;vtx_seq_id&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; 
        &lt;span class="n"&gt;get_relname_relid&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;NameStr&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;vtx_cache&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;seq_name&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
                          &lt;span class="n"&gt;graph_cache&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;namespace&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="n"&gt;graph&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;edge_seq_id&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; 
        &lt;span class="n"&gt;get_relname_relid&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;NameStr&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;edge_cache&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;seq_name&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
                          &lt;span class="n"&gt;graph_cache&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;namespace&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now we call these functions inside the main &lt;code&gt;create_barbell&lt;/code&gt; function, passing the address of the graph struct :&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight c"&gt;&lt;code&gt;&lt;span class="n"&gt;PG_FUNCTION_INFO_V1&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;age_create_barbell_graph&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="n"&gt;Datum&lt;/span&gt; &lt;span class="nf"&gt;age_create_barbell_graph&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;PG_FUNCTION_ARGS&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; 
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;struct&lt;/span&gt; &lt;span class="n"&gt;graph_components&lt;/span&gt; &lt;span class="n"&gt;graph&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="n"&gt;Datum&lt;/span&gt; &lt;span class="n"&gt;root1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;root2&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="n"&gt;validate_barbell_function_args&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;fcinfo&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="n"&gt;initialize_graph&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;fcinfo&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;graph&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="c1"&gt;// create two separate complete graphs&lt;/span&gt;
    &lt;span class="n"&gt;root1&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;DirectFunctionCall4&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;create_complete_graph&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; 
                                &lt;span class="n"&gt;CStringGetDatum&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;graph&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;graph_name&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; 
                                &lt;span class="n"&gt;Int32GetDatum&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;graph&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;graph_size&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
                                &lt;span class="n"&gt;CStringGetDatum&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;graph&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;edge_label&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; 
                                &lt;span class="n"&gt;CStringGetDatum&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;graph&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;vertex_label&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
    &lt;span class="n"&gt;root2&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;DirectFunctionCall4&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;create_complete_graph&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; 
                                &lt;span class="n"&gt;CStringGetDatum&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;graph&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;graph_name&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; 
                                &lt;span class="n"&gt;Int32GetDatum&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;graph&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;graph_size&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
                                &lt;span class="n"&gt;CStringGetDatum&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;graph&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;edge_label&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; 
                                &lt;span class="n"&gt;CStringGetDatum&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;graph&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;vertex_label&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;

    &lt;span class="n"&gt;fetch_label_ids&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;graph&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="n"&gt;fetch_seq_ids&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;graph&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="n"&gt;PG_RETURN_VOID&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;p&gt;Now let's connect these graphs already. We will make three functions to do this, &lt;code&gt;create_vertex&lt;/code&gt;, &lt;code&gt;connect_vertexes_by_graphid&lt;/code&gt; and &lt;code&gt;insert_bridge&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight c"&gt;&lt;code&gt;&lt;span class="k"&gt;static&lt;/span&gt; &lt;span class="n"&gt;graphid&lt;/span&gt; &lt;span class="nf"&gt;create_vertex&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;graph_components&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;graph&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;next_index&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="n"&gt;graphid&lt;/span&gt; &lt;span class="n"&gt;new_graph_id&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; 

    &lt;span class="n"&gt;next_index&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;nextval_internal&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;graph&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;vtx_seq_id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nb"&gt;true&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="n"&gt;new_graph_id&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;make_graphid&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;graph&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;vertex_label_id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; 
                                &lt;span class="n"&gt;next_index&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="n"&gt;insert_vertex_simple&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;graph&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;graph_oid&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                         &lt;span class="n"&gt;graph&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;vertex_label&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                         &lt;span class="n"&gt;new_graph_id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                         &lt;span class="n"&gt;create_empty_agtype&lt;/span&gt;&lt;span class="p"&gt;());&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;new_graph_id&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt; 


&lt;span class="k"&gt;static&lt;/span&gt; &lt;span class="n"&gt;graphid&lt;/span&gt; &lt;span class="nf"&gt;connect_vertexes_by_graphid&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;graph_components&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;graph&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; 
                                           &lt;span class="n"&gt;graphid&lt;/span&gt; &lt;span class="n"&gt;out_vtx&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                                           &lt;span class="n"&gt;graphid&lt;/span&gt; &lt;span class="n"&gt;in_vtx&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;nextval&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="n"&gt;graphid&lt;/span&gt; &lt;span class="n"&gt;new_graphid&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; 

    &lt;span class="n"&gt;nextval&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;nextval_internal&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;graph&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;edge_seq_id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nb"&gt;true&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="n"&gt;new_graphid&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;make_graphid&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;graph&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;edge_label_id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;nextval&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="n"&gt;insert_edge_simple&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;graph&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;graph_oid&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                       &lt;span class="n"&gt;graph&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;edge_label&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                       &lt;span class="n"&gt;new_graphid&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;out_vtx&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;in_vtx&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                       &lt;span class="n"&gt;create_empty_agtype&lt;/span&gt;&lt;span class="p"&gt;());&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;new_graphid&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;


&lt;span class="k"&gt;static&lt;/span&gt; &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;insert_bridge&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;graph_components&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;graph&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;graphid&lt;/span&gt; &lt;span class="n"&gt;beginning&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; 
                          &lt;span class="n"&gt;graphid&lt;/span&gt; &lt;span class="n"&gt;end&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;int32&lt;/span&gt; &lt;span class="n"&gt;bridge_size&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; 
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;graphid&lt;/span&gt; &lt;span class="n"&gt;current_graphid&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="n"&gt;graphid&lt;/span&gt; &lt;span class="n"&gt;prior_graphid&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="n"&gt;prior_graphid&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;end&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;bridge_size&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="o"&gt;++&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;current_graphid&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;create_vertex&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;graph&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="n"&gt;connect_vertexes_by_graphid&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;graph&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;prior_graphid&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;current_graphid&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="n"&gt;prior_graphid&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;current_graphid&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="c1"&gt;// connect prior vertex to last index&lt;/span&gt;
    &lt;span class="n"&gt;connect_vertexes_by_graphid&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;graph&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;prior_graphid&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;beginning&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;With this made, we just fetch the bridge size from the function arguments and call &lt;code&gt;insert_bridge&lt;/code&gt;, which will make our main function look like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight c"&gt;&lt;code&gt;&lt;span class="n"&gt;PG_FUNCTION_INFO_V1&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;age_create_barbell_graph&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="n"&gt;Datum&lt;/span&gt; &lt;span class="nf"&gt;age_create_barbell_graph&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;PG_FUNCTION_ARGS&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; 
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;struct&lt;/span&gt; &lt;span class="n"&gt;graph_components&lt;/span&gt; &lt;span class="n"&gt;graph&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="n"&gt;Datum&lt;/span&gt; &lt;span class="n"&gt;root1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;root2&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="n"&gt;int32&lt;/span&gt; &lt;span class="n"&gt;bridge_size&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="n"&gt;validate_barbell_function_args&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;fcinfo&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="n"&gt;initialize_graph&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;fcinfo&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;graph&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="c1"&gt;// create two separate complete graphs&lt;/span&gt;
    &lt;span class="n"&gt;root1&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;DirectFunctionCall4&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;create_complete_graph&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; 
                                &lt;span class="n"&gt;CStringGetDatum&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;graph&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;graph_name&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; 
                                &lt;span class="n"&gt;Int32GetDatum&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;graph&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;graph_size&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
                                &lt;span class="n"&gt;CStringGetDatum&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;graph&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;edge_label&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; 
                                &lt;span class="n"&gt;CStringGetDatum&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;graph&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;vertex_label&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
    &lt;span class="n"&gt;root2&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;DirectFunctionCall4&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;create_complete_graph&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; 
                                &lt;span class="n"&gt;CStringGetDatum&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;graph&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;graph_name&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; 
                                &lt;span class="n"&gt;Int32GetDatum&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;graph&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;graph_size&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
                                &lt;span class="n"&gt;CStringGetDatum&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;graph&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;edge_label&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; 
                                &lt;span class="n"&gt;CStringGetDatum&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;graph&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;vertex_label&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;

    &lt;span class="n"&gt;fetch_label_ids&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;graph&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="n"&gt;fetch_seq_ids&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;graph&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="c1"&gt;// connect two vertexes with a path of n vertexes&lt;/span&gt;
    &lt;span class="n"&gt;bridge_size&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;fcinfo&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;arg&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;
    &lt;span class="n"&gt;insert_bridge&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;graph&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;DATUM_GET_GRAPHID&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;root1&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; 
                  &lt;span class="n"&gt;DATUM_GET_GRAPHID&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;root2&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="n"&gt;bridge_size&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="n"&gt;PG_RETURN_DATUM&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;root1&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Also we changed the return value to be the graphid &lt;code&gt;root1&lt;/code&gt;, so it may be used to make other pre-modeled graph functions in the future.&lt;/p&gt;




&lt;p&gt;Now to call the function on &lt;code&gt;psql&lt;/code&gt; interface, we issue the command:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="k"&gt;SELECT&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="k"&gt;FROM&lt;/span&gt; &lt;span class="n"&gt;age_create_barbell_graph&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'testing_graph'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="s1"&gt;'nodeLabel'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="s1"&gt;'{}'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="s1"&gt;'edgeLabel'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="s1"&gt;'{}'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This will create a Barbell graph with two complete graphs with 5 nodes each and a bridge of 3 nodes connecting them.&lt;/p&gt;




&lt;p&gt;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!&lt;/p&gt;




&lt;p&gt;Check Apache AGE: &lt;a href="https://age.apache.org/"&gt;https://age.apache.org/&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Overview — Apache AGE master documentation: &lt;a href="https://age.apache.org/age-manual/master/intro/overview.html"&gt;https://age.apache.org/age-manual/master/intro/overview.html&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;GitHub - apache/age: &lt;a href="https://github.com/apache/age"&gt;https://github.com/apache/age&lt;/a&gt;&lt;/p&gt;

</description>
      <category>apache</category>
      <category>apacheage</category>
      <category>postgres</category>
    </item>
    <item>
      <title>Developing a Barbell Graph Function with Apache AGE</title>
      <dc:creator>Marco Aurélio Silva de Souza Júnior</dc:creator>
      <pubDate>Thu, 22 Jun 2023 14:16:05 +0000</pubDate>
      <link>https://dev.to/markgomer/developing-a-barbell-graph-function-with-apache-age-234b</link>
      <guid>https://dev.to/markgomer/developing-a-barbell-graph-function-with-apache-age-234b</guid>
      <description>&lt;p&gt;Now that we saw how to develop a function to &lt;a href="https://dev.to/markgomer/apache-age-and-postgres-source-code-tour-understanding-the-complete-graph-function-2p4m"&gt;create a complete graph on Apache AGE&lt;/a&gt;, we are going to create a function to develop a &lt;a href="https://en.wikipedia.org/wiki/Barbell_graph"&gt;Barbell graph&lt;/a&gt; - 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. &lt;/p&gt;

&lt;p&gt;We start by declaring our function with the macro &lt;code&gt;PG_FUNCTION_INFO_V1&lt;/code&gt;. This is used in PostgreSQL to bind our C function to SQL commands. In our case, we're defining a function called &lt;code&gt;age_create_barbell_graph&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight c"&gt;&lt;code&gt;&lt;span class="n"&gt;PG_FUNCTION_INFO_V1&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;age_create_barbell_graph&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;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.&lt;/p&gt;

&lt;p&gt;Our main function is &lt;code&gt;age_create_barbell_graph&lt;/code&gt;, and it uses the &lt;code&gt;PG_FUNCTION_ARGS&lt;/code&gt; macro as a shortcut to pass arguments from SQL commands to our C function.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight c"&gt;&lt;code&gt;&lt;span class="n"&gt;Datum&lt;/span&gt; &lt;span class="n"&gt;age_create_barbell_graph&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;PG_FUNCTION_ARGS&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We need to declare all variables in the beginning of the function, otherwise it will issue an warning when compiling: &lt;code&gt;ISO C90 forbids mixed declarations and code [-Wdeclaration-after-statement]&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight c"&gt;&lt;code&gt;    &lt;span class="n"&gt;FunctionCallInfo&lt;/span&gt; &lt;span class="n"&gt;arguments&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="n"&gt;Oid&lt;/span&gt; &lt;span class="n"&gt;graph_oid&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="n"&gt;Name&lt;/span&gt; &lt;span class="n"&gt;graph_name&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="kt"&gt;char&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;graph_name_str&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="n"&gt;int64&lt;/span&gt; &lt;span class="n"&gt;start_node_index&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;end_node_index&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;nextval&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="n"&gt;Name&lt;/span&gt; &lt;span class="n"&gt;node_label_name&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;NULL&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="n"&gt;int32&lt;/span&gt; &lt;span class="n"&gt;node_label_id&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="kt"&gt;char&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;node_label_str&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="n"&gt;Name&lt;/span&gt; &lt;span class="n"&gt;edge_label_name&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="n"&gt;int32&lt;/span&gt; &lt;span class="n"&gt;edge_label_id&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="kt"&gt;char&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;edge_label_str&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="n"&gt;graphid&lt;/span&gt; &lt;span class="n"&gt;object_graph_id&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="n"&gt;graphid&lt;/span&gt; &lt;span class="n"&gt;start_node_graph_id&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="n"&gt;graphid&lt;/span&gt; &lt;span class="n"&gt;end_node_graph_id&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="n"&gt;graph_cache_data&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;graph_cache&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="n"&gt;label_cache_data&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;edge_cache&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="n"&gt;agtype&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;properties&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;NULL&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="n"&gt;arguments&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;fcinfo&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;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.&lt;br&gt;
Here we check the arguments and process it immediately after:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight c"&gt;&lt;code&gt;    &lt;span class="c1"&gt;// Checking for possible NULL arguments &lt;/span&gt;
    &lt;span class="c1"&gt;// Name graph_name&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;PG_ARGISNULL&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;ereport&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ERROR&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;errcode&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ERRCODE_INVALID_PARAMETER_VALUE&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
                        &lt;span class="n"&gt;errmsg&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Graph name cannot be NULL"&lt;/span&gt;&lt;span class="p"&gt;)));&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="n"&gt;graph_name&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;PG_GETARG_NAME&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="n"&gt;graph_name_str&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;NameStr&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;graph_name&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="c1"&gt;// int graph size (number of nodes in each complete graph)&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;PG_ARGISNULL&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="n"&gt;PG_GETARG_INT32&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;ereport&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ERROR&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;errcode&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ERRCODE_INVALID_PARAMETER_VALUE&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
                &lt;span class="n"&gt;errmsg&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Graph size cannot be NULL or lower than 3"&lt;/span&gt;&lt;span class="p"&gt;)));&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="cm"&gt;/*
     * int64 bridge_size: currently only stays at zero.
     * to do: implement bridge with variable number of nodes.
    */&lt;/span&gt; 
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;PG_ARGISNULL&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="n"&gt;PG_GETARG_INT32&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt; &lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;ereport&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ERROR&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;errcode&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ERRCODE_INVALID_PARAMETER_VALUE&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
                &lt;span class="n"&gt;errmsg&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Bridge size cannot be NULL or lower than 0"&lt;/span&gt;&lt;span class="p"&gt;)));&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="c1"&gt;// node label: if null, gets default label, which is "_ag_label_vertex"&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;PG_ARGISNULL&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; 
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;namestrcpy&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;node_label_name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;AG_DEFAULT_LABEL_VERTEX&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="k"&gt;else&lt;/span&gt; 
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;node_label_name&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;PG_GETARG_NAME&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="n"&gt;node_label_str&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;NameStr&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;node_label_name&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="cm"&gt;/* 
    * Name edge_label 
    */&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;PG_ARGISNULL&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;ereport&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ERROR&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;errcode&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ERRCODE_INVALID_PARAMETER_VALUE&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
                &lt;span class="n"&gt;errmsg&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"edge label can not be NULL"&lt;/span&gt;&lt;span class="p"&gt;)));&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="n"&gt;edge_label_name&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;PG_GETARG_NAME&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="n"&gt;edge_label_str&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;NameStr&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;edge_label_name&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We use &lt;code&gt;DirectFunctionCall4&lt;/code&gt; to call the function &lt;code&gt;create_complete_graph&lt;/code&gt; 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.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight c"&gt;&lt;code&gt;&lt;span class="n"&gt;DirectFunctionCall4&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;create_complete_graph&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;arguments&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;arg&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; 
                                               &lt;span class="n"&gt;arguments&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;arg&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
                                               &lt;span class="n"&gt;arguments&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;arg&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; 
                                               &lt;span class="n"&gt;arguments&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;arg&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;]);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We need to get the unique identifiers (&lt;code&gt;oid&lt;/code&gt;) for our graph and labels. This is done using the &lt;code&gt;get_graph_oid&lt;/code&gt; and &lt;code&gt;get_label_id&lt;/code&gt; functions.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight c"&gt;&lt;code&gt;&lt;span class="n"&gt;graph_oid&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;get_graph_oid&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;graph_name_str&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="n"&gt;node_label_id&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;get_label_id&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;node_label_str&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;graph_oid&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="n"&gt;edge_label_id&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;get_label_id&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;edge_label_str&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;graph_oid&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The graph and edge caches are then searched to provide access to necessary nodes to be connected with edges later.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight c"&gt;&lt;code&gt;&lt;span class="n"&gt;graph_cache&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;search_graph_name_cache&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;graph_name_str&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="n"&gt;edge_cache&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;search_label_name_graph_cache&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;edge_label_str&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="n"&gt;graph_oid&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We use the &lt;code&gt;get_nextval_internal&lt;/code&gt; function to get the next internal value in the graph, so a new object (node or edge) graph id can be composed.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight c"&gt;&lt;code&gt;&lt;span class="n"&gt;nextval&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;get_nextval_internal&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;graph_cache&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;edge_cache&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Finally, we use the &lt;code&gt;insert_edge_simple&lt;/code&gt; function to connect two nodes - one from each complete graph. This creates the bridge that links our two complete graphs into a Barbell Graph.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight c"&gt;&lt;code&gt;&lt;span class="n"&gt;insert_edge_simple&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;graph_oid&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;edge_label_str&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                       &lt;span class="n"&gt;object_graph_id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;start_node_graph_id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                       &lt;span class="n"&gt;end_node_graph_id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;properties&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And that's it! Our function ends by returning void using &lt;code&gt;PG_RETURN_VOID()&lt;/code&gt;, meaning it doesn't return any value. The graph is directly created in the database.&lt;/p&gt;

&lt;h2&gt;
  
  
  Including the Function in the PostgreSQL Catalog
&lt;/h2&gt;

&lt;p&gt;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 &lt;code&gt;age--1.3.0.sql&lt;/code&gt; file. This file is the SQL script that sets up the PostgreSQL functions when Apache AGE is installed.&lt;/p&gt;

&lt;p&gt;Here's the code you need to add to the &lt;code&gt;age--1.3.0.sql&lt;/code&gt; file:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="k"&gt;CREATE&lt;/span&gt; &lt;span class="k"&gt;FUNCTION&lt;/span&gt; &lt;span class="n"&gt;ag_catalog&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;age_create_barbell_graph&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;graph_name&lt;/span&gt; &lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;graph_size&lt;/span&gt; &lt;span class="nb"&gt;int&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;bridge_size&lt;/span&gt; &lt;span class="nb"&gt;int&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;node_label&lt;/span&gt; &lt;span class="n"&gt;name&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;NULL&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;node_properties&lt;/span&gt; &lt;span class="n"&gt;agtype&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;NULL&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;edge_label&lt;/span&gt; &lt;span class="n"&gt;name&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;NULL&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;edge_properties&lt;/span&gt; &lt;span class="n"&gt;agtype&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;NULL&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;RETURNS&lt;/span&gt; &lt;span class="n"&gt;void&lt;/span&gt;
&lt;span class="k"&gt;LANGUAGE&lt;/span&gt; &lt;span class="k"&gt;c&lt;/span&gt;
&lt;span class="k"&gt;CALLED&lt;/span&gt; &lt;span class="k"&gt;ON&lt;/span&gt; &lt;span class="k"&gt;NULL&lt;/span&gt; &lt;span class="k"&gt;INPUT&lt;/span&gt;
&lt;span class="n"&gt;PARALLEL&lt;/span&gt; &lt;span class="n"&gt;SAFE&lt;/span&gt;
&lt;span class="k"&gt;AS&lt;/span&gt; &lt;span class="s1"&gt;'MODULE_PATHNAME'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This &lt;code&gt;CREATE FUNCTION&lt;/code&gt; command adds our &lt;code&gt;age_create_barbell_graph&lt;/code&gt; function to the &lt;code&gt;ag_catalog&lt;/code&gt;, which is the PostgreSQL catalog for Apache AGE.&lt;/p&gt;

&lt;p&gt;The structure of the &lt;code&gt;CREATE FUNCTION&lt;/code&gt; 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 (&lt;code&gt;void&lt;/code&gt;).&lt;/p&gt;

&lt;p&gt;&lt;code&gt;LANGUAGE c&lt;/code&gt; specifies that the function is written in C.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;CALLED ON NULL INPUT&lt;/code&gt; means the function will still be called even if some of its arguments are null.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;PARALLEL SAFE&lt;/code&gt; indicates that this function can be safely run in parallel mode by PostgreSQL.&lt;/p&gt;

&lt;p&gt;Finally, &lt;code&gt;'MODULE_PATHNAME'&lt;/code&gt; is a placeholder for the shared library where the C function is located.&lt;/p&gt;

&lt;p&gt;After adding this to the &lt;code&gt;age--1.3.0.sql&lt;/code&gt; file and installing Apache AGE, PostgreSQL will recognize and be able to execute your &lt;code&gt;age_create_barbell_graph&lt;/code&gt; function. Now you can use this function to create barbell graphs directly from your SQL commands!&lt;/p&gt;

&lt;h2&gt;
  
  
  Calling the Function from the psql Interface
&lt;/h2&gt;

&lt;p&gt;Now that our function is defined and registered with PostgreSQL, let's go over how to call it from the &lt;code&gt;psql&lt;/code&gt; interface.&lt;/p&gt;

&lt;p&gt;Here are the commands to load the Apache AGE extension and set the search path:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="k"&gt;CREATE&lt;/span&gt; &lt;span class="n"&gt;EXTENSION&lt;/span&gt; &lt;span class="n"&gt;age&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;LOAD&lt;/span&gt; &lt;span class="s1"&gt;'age'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;SET&lt;/span&gt; &lt;span class="n"&gt;search_path&lt;/span&gt; &lt;span class="k"&gt;TO&lt;/span&gt; &lt;span class="n"&gt;ag_catalog&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;SET search_path TO ag_catalog;&lt;/code&gt; is setting the search path to &lt;code&gt;ag_catalog&lt;/code&gt;, the PostgreSQL catalog for Apache AGE. This means that the function we're going to call is located in this catalog.&lt;/p&gt;

&lt;p&gt;Now we can call our &lt;code&gt;age_create_barbell_graph&lt;/code&gt; function. Here's the command to do so:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="k"&gt;SELECT&lt;/span&gt; &lt;span class="n"&gt;age_create_barbell_graph&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'barbell'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="s1"&gt;'vlabel'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="k"&gt;NULL&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="s1"&gt;'elabel'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="k"&gt;NULL&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We use a &lt;code&gt;SELECT&lt;/code&gt; 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 &lt;code&gt;NULL&lt;/code&gt; for the properties of vertices and edges as we haven't defined any.&lt;/p&gt;

&lt;p&gt;As you might notice, the bridge size and properties arguments are not implemented in this function. &lt;strong&gt;That's an exercise for you&lt;/strong&gt; - try modifying the function to include these features, to further enhance the functionality and flexibility of your barbell graphs!&lt;/p&gt;

&lt;p&gt;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!&lt;/p&gt;




&lt;p&gt;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!&lt;/p&gt;




&lt;p&gt;Check Apache AGE: &lt;a href="https://age.apache.org/"&gt;https://age.apache.org/&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Overview — Apache AGE master documentation: &lt;a href="https://age.apache.org/age-manual/master/intro/overview.html"&gt;https://age.apache.org/age-manual/master/intro/overview.html&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;GitHub - apache/age: &lt;a href="https://github.com/apache/age"&gt;https://github.com/apache/age&lt;/a&gt;&lt;/p&gt;

</description>
      <category>apacheage</category>
      <category>apache</category>
      <category>postgres</category>
    </item>
    <item>
      <title>Apache AGE and Postgres Source Code Tour: Understanding the Complete Graph Function</title>
      <dc:creator>Marco Aurélio Silva de Souza Júnior</dc:creator>
      <pubDate>Tue, 13 Jun 2023 15:00:40 +0000</pubDate>
      <link>https://dev.to/markgomer/apache-age-and-postgres-source-code-tour-understanding-the-complete-graph-function-2p4m</link>
      <guid>https://dev.to/markgomer/apache-age-and-postgres-source-code-tour-understanding-the-complete-graph-function-2p4m</guid>
      <description>&lt;p&gt;In the following blog post, we are going to review a function used to create a complete graph within the Apache AGE. A complete graph is a simple undirected graph in which every pair of distinct vertices is connected by a unique edge. This will be important for the &lt;a href="https://en.wikipedia.org/wiki/Barbell_graph"&gt;Barbell Graph&lt;/a&gt; function we will be creating later.&lt;/p&gt;

&lt;p&gt;To begin, let's break down this code section by section:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Variable Declarations:&lt;/strong&gt; The function begins by declaring various variables that will be used throughout the code. These include variables for the graph ID, graph name, number of vertices, vertex and edge labels, and various cache data.
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight c"&gt;&lt;code&gt;&lt;span class="n"&gt;Oid&lt;/span&gt; &lt;span class="n"&gt;graph_id&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="n"&gt;Name&lt;/span&gt; &lt;span class="n"&gt;graph_name&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="n"&gt;int64&lt;/span&gt; &lt;span class="n"&gt;no_vertices&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="n"&gt;int64&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="n"&gt;j&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="n"&gt;vid&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;eid&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;start_vid&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;end_vid&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="p"&gt;...&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Error Handling:&lt;/strong&gt; Next, the function checks if any of the arguments (i.e., the graph name, number of nodes, and edge label) are null, and if so, throws an error.
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight c"&gt;&lt;code&gt;&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;PG_ARGISNULL&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;ereport&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ERROR&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;errcode&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ERRCODE_INVALID_PARAMETER_VALUE&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
                    &lt;span class="n"&gt;errmsg&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"graph name can not be NULL"&lt;/span&gt;&lt;span class="p"&gt;)));&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="p"&gt;...&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Argument Assignments and Conversions:&lt;/strong&gt; The function assigns argument variables and sets defaults for non-obligatory ones. It also converts names to strings for easier manipulation. If a vertex label is given as a parameter and it's the same as the edge label, the function throws an error.
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight c"&gt;&lt;code&gt;&lt;span class="n"&gt;graph_name&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;PG_GETARG_NAME&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="n"&gt;no_vertices&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;int64&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="n"&gt;PG_GETARG_INT64&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="n"&gt;edge_label_name&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;PG_GETARG_NAME&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;...&lt;/span&gt;

&lt;span class="p"&gt;...&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Graph Creation and Assertions:&lt;/strong&gt; If the graph doesn't exist, it creates an empty one. It assigns the edge and node properties, checks if the labels exist, and creates them if they don't. The function also retrieves the label IDs to be used in creating graph IDs.
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight c"&gt;&lt;code&gt;&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="n"&gt;graph_exists&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;graph_name_str&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;DirectFunctionCall1&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;create_graph&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;CStringGetDatum&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;graph_name&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="n"&gt;graph_id&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;get_graph_oid&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;graph_name_str&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;...&lt;/span&gt;

&lt;span class="p"&gt;...&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Vertices Creation:&lt;/strong&gt; The function creates vertices using the sequential ID for each vertex. For each vertex, it generates a unique ID and inserts the vertex into the graph.
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight c"&gt;&lt;code&gt;&lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;int64&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;=&lt;/span&gt;&lt;span class="n"&gt;no_vertices&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="o"&gt;++&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;   
    &lt;span class="n"&gt;vid&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;nextval_internal&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;vtx_seq_id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nb"&gt;true&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="n"&gt;object_graph_id&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;make_graphid&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;vtx_label_id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;vid&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="n"&gt;insert_vertex_simple&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="n"&gt;graph_id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="n"&gt;vtx_name_str&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="n"&gt;object_graph_id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="n"&gt;node_properties&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Edges Creation:&lt;/strong&gt; Finally, the function creates edges connecting every pair of vertices in the graph. It uses the last ID of the vertices created to create edges between all possible vertex pairs. After creating the edge, it inserts it into the graph.
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight c"&gt;&lt;code&gt;&lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;=&lt;/span&gt;&lt;span class="n"&gt;no_vertices&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="o"&gt;++&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;   
    &lt;span class="n"&gt;start_vid&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;lid&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;no_vertices&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="k"&gt;for&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;j&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="n"&gt;j&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;=&lt;/span&gt;&lt;span class="n"&gt;no_vertices&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="n"&gt;j&lt;/span&gt;&lt;span class="o"&gt;++&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;  
        &lt;span class="n"&gt;end_vid&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;lid&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;no_vertices&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="n"&gt;j&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="n"&gt;eid&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;nextval_internal&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;edge_seq_id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nb"&gt;true&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="n"&gt;object_graph_id&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;make_graphid&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;edge_label_id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;eid&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

        &lt;span class="n"&gt;start_vertex_graph_id&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;make_graphid&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;vtx_label_id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;start_vid&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="n"&gt;end_vertex_graph_id&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;make_graphid&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;vtx_label_id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;end_vid&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="n"&gt;insert_edge_simple&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;graph_id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;edge_name_str&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                        &lt;span class="n"&gt;object_graph_id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;start_vertex_graph_id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                        &lt;span class="n"&gt;end_vertex_graph_id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;edge_properties&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In summary, this function is a comprehensive example of how to create a complete graph in Apache AGE using PostgreSQL. It provides the ability to customize the graph name, number of nodes, edge label, and node properties, while ensuring that all possible edges between nodes are created. It is a robust tool that is essential in any graph database.&lt;/p&gt;

&lt;p&gt;It is a good starting point to understand how Apache AGE works.&lt;/p&gt;




&lt;p&gt;Check Apache AGE: &lt;a href="https://age.apache.org/"&gt;https://age.apache.org/&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Overview — Apache AGE master documentation. &lt;a href="https://age.apache.org/age-manual/master/intro/overview.html"&gt;https://age.apache.org/age-manual/master/intro/overview.html&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;GitHub - apache/age: &lt;a href="https://github.com/apache/age"&gt;https://github.com/apache/age&lt;/a&gt;.. &lt;/p&gt;

</description>
      <category>apacheage</category>
      <category>postgres</category>
    </item>
    <item>
      <title>Source code tour on Apache AGE &amp; Postgres - Lists</title>
      <dc:creator>Marco Aurélio Silva de Souza Júnior</dc:creator>
      <pubDate>Mon, 29 May 2023 23:06:34 +0000</pubDate>
      <link>https://dev.to/markgomer/source-code-tour-on-apache-age-postgres-lists-5048</link>
      <guid>https://dev.to/markgomer/source-code-tour-on-apache-age-postgres-lists-5048</guid>
      <description>&lt;h2&gt;
  
  
  Introduction
&lt;/h2&gt;

&lt;p&gt;In PostgreSQL, the &lt;code&gt;ListCell&lt;/code&gt; struct is a key component for implementing linked lists, which we will use frequently on our contribution to &lt;a href="https://github.com/apache/age"&gt;Apache AGE&lt;/a&gt;. You can check its implementation in &lt;a href="https://github.com/postgres/postgres/blob/REL_12_STABLE/src/include/nodes/pg_list.h"&gt;PostgreSQL's official GitHub Repository&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;This blog post provides a concise overview of the &lt;code&gt;ListCell&lt;/code&gt; struct, its purpose, and significance, along with an example of iterating over a &lt;code&gt;List&lt;/code&gt; using &lt;code&gt;ListCell&lt;/code&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  The ListCell Struct:
&lt;/h3&gt;

&lt;p&gt;The &lt;code&gt;ListCell&lt;/code&gt; struct, defined in &lt;code&gt;pg_list.h&lt;/code&gt;, has two members:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;next&lt;/code&gt;: a pointer to the next &lt;code&gt;ListCell&lt;/code&gt; in the linked list, enabling traversal.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;data&lt;/code&gt;: a &lt;code&gt;void&lt;/code&gt; pointer to store the actual data in each &lt;code&gt;ListCell&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Iterating over a List using ListCell:
&lt;/h2&gt;

&lt;p&gt;Let's consider an example of iterating over a list using &lt;code&gt;ListCell&lt;/code&gt;. Assume we have a &lt;code&gt;List&lt;/code&gt; of integers, and we want to print each element:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight c"&gt;&lt;code&gt;&lt;span class="n"&gt;List&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;myList&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// Assume we have a List containing integers&lt;/span&gt;

&lt;span class="n"&gt;ListCell&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;cell&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="n"&gt;foreach&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;cell&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;myList&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;value&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="n"&gt;lfirst&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;cell&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="n"&gt;printf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"%d&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;value&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In this example, we declare a &lt;code&gt;ListCell&lt;/code&gt; pointer &lt;code&gt;cell&lt;/code&gt; and use the &lt;code&gt;foreach&lt;/code&gt; macro provided by PostgreSQL to iterate over the &lt;code&gt;myList&lt;/code&gt;. Within the loop, we extract the integer value stored in each &lt;code&gt;ListCell&lt;/code&gt; using &lt;code&gt;lfirst&lt;/code&gt;, which returns a &lt;code&gt;void&lt;/code&gt; pointer. We then cast it to an &lt;code&gt;int&lt;/code&gt; pointer and dereference it to obtain the actual value, which we print.&lt;/p&gt;




&lt;p&gt;The &lt;code&gt;ListCell&lt;/code&gt; struct is a vital component of PostgreSQL's linked list implementation. It facilitates the creation and manipulation of dynamic lists throughout the PostgreSQL source code, showcasing the system's flexibility and versatility. By utilizing &lt;code&gt;ListCell&lt;/code&gt; and its associated macros, such as &lt;code&gt;foreach&lt;/code&gt;, iterating over lists becomes straightforward and efficient.&lt;/p&gt;

&lt;p&gt;Please note that this condensed blog post provides a high-level overview of the &lt;code&gt;ListCell&lt;/code&gt; struct and an example of iteration. For more detailed information, refer to the official PostgreSQL documentation and source code.&lt;/p&gt;




&lt;ul&gt;
&lt;li&gt;Apache AGE. &lt;a href="https://age.apache.org/"&gt;https://age.apache.org/&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;GitHub - apache/age - &lt;a href="https://github.com/apache/age"&gt;https://github.com/apache/age&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>apacheage</category>
      <category>postgres</category>
    </item>
  </channel>
</rss>
